Normalized line endings
This commit is contained in:
240
CHANGELOG.txt
240
CHANGELOG.txt
@ -1,120 +1,120 @@
|
|||||||
Changes for PolyVox version 0.3
|
Changes for PolyVox version 0.3
|
||||||
===============================
|
===============================
|
||||||
This release has focused on... (some introduction here).
|
This release has focused on... (some introduction here).
|
||||||
|
|
||||||
This line was added just for testing.
|
This line was added just for testing.
|
||||||
|
|
||||||
Voxel access
|
Voxel access
|
||||||
------------
|
------------
|
||||||
The getVoxelAt() and setVoxelAt() functions have been deprecated and replaced by getVoxel() and setVoxel(). These new functions provide more control over how edge cases are handled and can potentially be faster as well. Please see the 'Volumes' section of the user manual for more information about how voxel access should be performed.
|
The getVoxelAt() and setVoxelAt() functions have been deprecated and replaced by getVoxel() and setVoxel(). These new functions provide more control over how edge cases are handled and can potentially be faster as well. Please see the 'Volumes' section of the user manual for more information about how voxel access should be performed.
|
||||||
|
|
||||||
LargeVolume
|
LargeVolume
|
||||||
-----------
|
-----------
|
||||||
Behaviour and interface of the LargeVolume has changed significantly and code which uses it will certainly need to be updated. Plese see the LargeVolume API docs for full details of how it now works.
|
Behaviour and interface of the LargeVolume has changed significantly and code which uses it will certainly need to be updated. Plese see the LargeVolume API docs for full details of how it now works.
|
||||||
|
|
||||||
It is now possible to provide custom compressors for the data which is stored in a LargeVolume. Two compressor implementation are provided with PolyVox - RLECompressor which is suitable for cubic-style terrain, and MinizCompressor which uses the 'miniz' zlib implementation for smooth terrain or general purpose use. Users can provide their own implementation of the compressor interface if they wish.
|
It is now possible to provide custom compressors for the data which is stored in a LargeVolume. Two compressor implementation are provided with PolyVox - RLECompressor which is suitable for cubic-style terrain, and MinizCompressor which uses the 'miniz' zlib implementation for smooth terrain or general purpose use. Users can provide their own implementation of the compressor interface if they wish.
|
||||||
|
|
||||||
Note that the setCompressionEnabled() functionality has been removed and a compressor must always be provided when constructing the volume. The ability to disable compression was of questionable benefit and was complicating the logic in the code.
|
Note that the setCompressionEnabled() functionality has been removed and a compressor must always be provided when constructing the volume. The ability to disable compression was of questionable benefit and was complicating the logic in the code.
|
||||||
|
|
||||||
The LargeVolume also supports custom paging code which can be supplied by providing a subclass of Pager and implementing the relevant methods. This replaces the dataRequiredHandler() and dataOverflowHandler() functions.
|
The LargeVolume also supports custom paging code which can be supplied by providing a subclass of Pager and implementing the relevant methods. This replaces the dataRequiredHandler() and dataOverflowHandler() functions.
|
||||||
|
|
||||||
These changes regarding compression and paging have also affected the LargeVolume constructors(s). Please see the API docs to see how they look now.
|
These changes regarding compression and paging have also affected the LargeVolume constructors(s). Please see the API docs to see how they look now.
|
||||||
|
|
||||||
Error Handling
|
Error Handling
|
||||||
--------------
|
--------------
|
||||||
PolyVox now has it's own POLYVOX_ASSERT() macro rather than using the standard assert(). This has some advantages such as allowing a message to be printed and providing file/line information, and it is also possible to enable/disable it independantly of whether you are making a debug or release build.
|
PolyVox now has it's own POLYVOX_ASSERT() macro rather than using the standard assert(). This has some advantages such as allowing a message to be printed and providing file/line information, and it is also possible to enable/disable it independantly of whether you are making a debug or release build.
|
||||||
|
|
||||||
A simple logging system has also been added, and the output can be redirected by user code.
|
A simple logging system has also been added, and the output can be redirected by user code.
|
||||||
|
|
||||||
Please see the 'Error Handling' section of the user manual for more information about these changes.
|
Please see the 'Error Handling' section of the user manual for more information about these changes.
|
||||||
|
|
||||||
Volume wrap modes
|
Volume wrap modes
|
||||||
-----------------
|
-----------------
|
||||||
This release has seen a overhaul of the way PolyVox handles voxel positions which are outside of the volume. It used to be the case that you could specify a border value which would be returned whenever an out-of-volume access was performed, but this was not flexible enough for all use cases. You can now choose between different wrapping modes (border, clamp, etc) and apply them to both the volume itself or to samplers. If you have multiple samplers pointing at the same volume then you can choose to have different wrap modes for each of them.
|
This release has seen a overhaul of the way PolyVox handles voxel positions which are outside of the volume. It used to be the case that you could specify a border value which would be returned whenever an out-of-volume access was performed, but this was not flexible enough for all use cases. You can now choose between different wrapping modes (border, clamp, etc) and apply them to both the volume itself or to samplers. If you have multiple samplers pointing at the same volume then you can choose to have different wrap modes for each of them.
|
||||||
|
|
||||||
Within the Volume class the getVoxelAt() and setBorderValue() functions have been deprecated. Please see the 'Volumes' section of the user manual for more information about how voxel access should now be performed.
|
Within the Volume class the getVoxelAt() and setBorderValue() functions have been deprecated. Please see the 'Volumes' section of the user manual for more information about how voxel access should now be performed.
|
||||||
|
|
||||||
Various algorithms have also been updated to allow wrap modes to be specified when executing them.
|
Various algorithms have also been updated to allow wrap modes to be specified when executing them.
|
||||||
|
|
||||||
Region class
|
Region class
|
||||||
------------
|
------------
|
||||||
The Region class has been tidied up and enhanced with new functionality. It now contains functions for growing and shrinking regions, as well as 'accumulate()' functions which ensure the Region contains a given point. The concept of an invalid region has also been introduced - this is one whose lower corner is greater than it's upper corner.
|
The Region class has been tidied up and enhanced with new functionality. It now contains functions for growing and shrinking regions, as well as 'accumulate()' functions which ensure the Region contains a given point. The concept of an invalid region has also been introduced - this is one whose lower corner is greater than it's upper corner.
|
||||||
|
|
||||||
Vector class
|
Vector class
|
||||||
------------
|
------------
|
||||||
The Vector class has been tidied up. Most notably it now makes use of an 'OperationType' which is used for internal calculations and some results. The documentation has also been updated.
|
The Vector class has been tidied up. Most notably it now makes use of an 'OperationType' which is used for internal calculations and some results. The documentation has also been updated.
|
||||||
|
|
||||||
Deprecated functionality
|
Deprecated functionality
|
||||||
------------------------
|
------------------------
|
||||||
Vector::operator<() has been deprecated. It was only present to allow Vectors to be used as the key to an std::map, but it makes more sense for this to be specified seperatly as a std::map comparison function. This is now done in the OpenGLExample (search for VectorCompare).
|
Vector::operator<() has been deprecated. It was only present to allow Vectors to be used as the key to an std::map, but it makes more sense for this to be specified seperatly as a std::map comparison function. This is now done in the OpenGLExample (search for VectorCompare).
|
||||||
|
|
||||||
getVoxelAt() and setBorderValue() have been deprecated in the Volume class. See the section of this file on 'Volume wrap modes' for details.
|
getVoxelAt() and setBorderValue() have been deprecated in the Volume class. See the section of this file on 'Volume wrap modes' for details.
|
||||||
|
|
||||||
Removed functionality
|
Removed functionality
|
||||||
--------------------
|
--------------------
|
||||||
Functionality deprecated for the previous release has now been removed. This includes:
|
Functionality deprecated for the previous release has now been removed. This includes:
|
||||||
|
|
||||||
- Region::getWidth() and related functions. You should now use Region::getWidthInVoxels() or Region::getWidthInCells.
|
- Region::getWidth() and related functions. You should now use Region::getWidthInVoxels() or Region::getWidthInCells.
|
||||||
- The MeshDecimator. We don't have a direct replacement for this so you should consider an alternative such as downsampling the volume or using an external mesh processing library.
|
- The MeshDecimator. We don't have a direct replacement for this so you should consider an alternative such as downsampling the volume or using an external mesh processing library.
|
||||||
- The SimpleInterface. This was primarily for the bindings, and we are making other efforts to get those working.
|
- The SimpleInterface. This was primarily for the bindings, and we are making other efforts to get those working.
|
||||||
- Serialisation. You should implement any required serialisation yourself.
|
- Serialisation. You should implement any required serialisation yourself.
|
||||||
- This had a number of problems and was a little too high-level for PolyVox. You should implement change tracking yourself.
|
- This had a number of problems and was a little too high-level for PolyVox. You should implement change tracking yourself.
|
||||||
|
|
||||||
|
|
||||||
Changes for PolyVox version 0.2
|
Changes for PolyVox version 0.2
|
||||||
===============================
|
===============================
|
||||||
This is the first revision for which we have produced a changelog, as we are now trying to streamline our development and release process. Hence this changelog entry is not going to be as structured as we hope they will be in the future. We're writing it from memory, rather than having carefully kept track of all the relevant changes as we made them.
|
This is the first revision for which we have produced a changelog, as we are now trying to streamline our development and release process. Hence this changelog entry is not going to be as structured as we hope they will be in the future. We're writing it from memory, rather than having carefully kept track of all the relevant changes as we made them.
|
||||||
|
|
||||||
Deprecated functionality
|
Deprecated functionality
|
||||||
------------------------
|
------------------------
|
||||||
The following functionality is considered deprecated in this release of PolyVox and will probably be removed in future versions.
|
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.
|
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.
|
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.
|
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.
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
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.
|
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
|
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 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.
|
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
|
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 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.
|
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.
|
Usage of the new raycasting is demonstrated by a unit test.
|
||||||
|
|
||||||
Changes to AmbientOcclusionCalculator
|
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.
|
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
|
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.
|
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
|
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.
|
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.
|
||||||
|
246
CMakeLists.txt
246
CMakeLists.txt
@ -1,123 +1,123 @@
|
|||||||
# Copyright (c) 2007-2012 Matt Williams
|
# Copyright (c) 2007-2012 Matt Williams
|
||||||
# Copyright (c) 2007-2012 David Williams
|
# Copyright (c) 2007-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6)
|
||||||
|
|
||||||
PROJECT(PolyVox)
|
PROJECT(PolyVox)
|
||||||
|
|
||||||
SET(POLYVOX_VERSION_MAJOR "0")
|
SET(POLYVOX_VERSION_MAJOR "0")
|
||||||
SET(POLYVOX_VERSION_MINOR "2")
|
SET(POLYVOX_VERSION_MINOR "2")
|
||||||
SET(POLYVOX_VERSION_PATCH "1")
|
SET(POLYVOX_VERSION_PATCH "1")
|
||||||
SET(POLYVOX_VERSION "${POLYVOX_VERSION_MAJOR}.${POLYVOX_VERSION_MINOR}.${POLYVOX_VERSION_PATCH}" CACHE STRING "PolyVox version")
|
SET(POLYVOX_VERSION "${POLYVOX_VERSION_MAJOR}.${POLYVOX_VERSION_MINOR}.${POLYVOX_VERSION_PATCH}" CACHE STRING "PolyVox version")
|
||||||
MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
MARK_AS_ADVANCED(FORCE POLYVOX_VERSION)
|
||||||
|
|
||||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
FIND_PACKAGE(Doxygen)
|
FIND_PACKAGE(Doxygen)
|
||||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
||||||
|
|
||||||
SET(LIBRARY_TYPE "DYNAMIC" CACHE STRING "Should the library be STATIC or DYNAMIC")
|
SET(LIBRARY_TYPE "DYNAMIC" CACHE STRING "Should the library be STATIC or DYNAMIC")
|
||||||
SET_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
SET_PROPERTY(CACHE LIBRARY_TYPE PROPERTY STRINGS DYNAMIC STATIC)
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
SET(LIBRARY_TYPE "STATIC")
|
SET(LIBRARY_TYPE "STATIC")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Qt is required for building the tests, the example and optionally for bundling the documentation
|
# Qt is required for building the tests, the example and optionally for bundling the documentation
|
||||||
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtOpenGL QtTest)
|
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtOpenGL QtTest)
|
||||||
INCLUDE(${QT_USE_FILE})
|
INCLUDE(${QT_USE_FILE})
|
||||||
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
||||||
set_package_info(Doxygen "API documentation generator" http://www.doxygen.org "Building the API documentation")
|
set_package_info(Doxygen "API documentation generator" http://www.doxygen.org "Building the API documentation")
|
||||||
set_package_info(Qt4 "C++ framework" http://qt-project.org "Building the examples and tests")
|
set_package_info(Qt4 "C++ framework" http://qt-project.org "Building the examples and tests")
|
||||||
else()
|
else()
|
||||||
set_package_properties(Doxygen PROPERTIES URL http://www.doxygen.org DESCRIPTION "API documentation generator" TYPE OPTIONAL PURPOSE "Building the API documentation")
|
set_package_properties(Doxygen PROPERTIES URL http://www.doxygen.org DESCRIPTION "API documentation generator" TYPE OPTIONAL PURPOSE "Building the API documentation")
|
||||||
set_package_properties(Qt4 PROPERTIES DESCRIPTION "C++ framework" URL http://qt-project.org)
|
set_package_properties(Qt4 PROPERTIES DESCRIPTION "C++ framework" URL http://qt-project.org)
|
||||||
set_package_properties(Qt4 PROPERTIES TYPE RECOMMENDED PURPOSE "Building the examples")
|
set_package_properties(Qt4 PROPERTIES TYPE RECOMMENDED PURPOSE "Building the examples")
|
||||||
set_package_properties(Qt4 PROPERTIES TYPE OPTIONAL PURPOSE "Building the tests")
|
set_package_properties(Qt4 PROPERTIES TYPE OPTIONAL PURPOSE "Building the tests")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
IF(CMAKE_COMPILER_IS_GNUCXX) #Maybe "OR MINGW"
|
IF(CMAKE_COMPILER_IS_GNUCXX) #Maybe "OR MINGW"
|
||||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||||
ENDIF()
|
ENDIF()
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
ADD_DEFINITIONS(-std=c++0x) #Enable C++0x mode
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(library)
|
ADD_SUBDIRECTORY(library)
|
||||||
|
|
||||||
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
OPTION(ENABLE_EXAMPLES "Should the examples be built" ON)
|
||||||
IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND)
|
IF(ENABLE_EXAMPLES AND QT_QTOPENGL_FOUND)
|
||||||
ADD_SUBDIRECTORY(examples/common)
|
ADD_SUBDIRECTORY(examples/common)
|
||||||
ADD_SUBDIRECTORY(examples/Basic)
|
ADD_SUBDIRECTORY(examples/Basic)
|
||||||
ADD_SUBDIRECTORY(examples/Paging)
|
ADD_SUBDIRECTORY(examples/Paging)
|
||||||
ADD_SUBDIRECTORY(examples/OpenGL)
|
ADD_SUBDIRECTORY(examples/OpenGL)
|
||||||
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
ADD_SUBDIRECTORY(examples/SmoothLOD)
|
||||||
ADD_SUBDIRECTORY(examples/DecodeOnGPU)
|
ADD_SUBDIRECTORY(examples/DecodeOnGPU)
|
||||||
ADD_SUBDIRECTORY(examples/Python)
|
ADD_SUBDIRECTORY(examples/Python)
|
||||||
SET(BUILD_EXAMPLES ON)
|
SET(BUILD_EXAMPLES ON)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_EXAMPLES OFF)
|
SET(BUILD_EXAMPLES OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
INCLUDE(Packaging.cmake)
|
INCLUDE(Packaging.cmake)
|
||||||
|
|
||||||
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
OPTION(ENABLE_TESTS "Should the tests be built" ON)
|
||||||
IF(ENABLE_TESTS AND QT_QTTEST_FOUND)
|
IF(ENABLE_TESTS AND QT_QTTEST_FOUND)
|
||||||
INCLUDE(CTest)
|
INCLUDE(CTest)
|
||||||
MARK_AS_ADVANCED(FORCE BUILD_TESTING)
|
MARK_AS_ADVANCED(FORCE BUILD_TESTING)
|
||||||
ADD_SUBDIRECTORY(tests)
|
ADD_SUBDIRECTORY(tests)
|
||||||
SET(BUILD_TESTS ON)
|
SET(BUILD_TESTS ON)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_TESTS OFF)
|
SET(BUILD_TESTS OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
#Check if we will building _and_ bundling the docs
|
#Check if we will building _and_ bundling the docs
|
||||||
IF(DOXYGEN_FOUND AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
IF(DOXYGEN_FOUND AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
SET(BUILD_AND_BUNDLE_DOCS ON)
|
SET(BUILD_AND_BUNDLE_DOCS ON)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(BUILD_AND_BUNDLE_DOCS OFF)
|
SET(BUILD_AND_BUNDLE_DOCS OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
ADD_SUBDIRECTORY(documentation)
|
ADD_SUBDIRECTORY(documentation)
|
||||||
|
|
||||||
add_feature_info("Examples" BUILD_EXAMPLES "Examples of PolyVox usage")
|
add_feature_info("Examples" BUILD_EXAMPLES "Examples of PolyVox usage")
|
||||||
add_feature_info("Tests" BUILD_TESTS "Unit tests")
|
add_feature_info("Tests" BUILD_TESTS "Unit tests")
|
||||||
add_feature_info("Bindings" BUILD_BINDINGS "SWIG bindings")
|
add_feature_info("Bindings" BUILD_BINDINGS "SWIG bindings")
|
||||||
add_feature_info("API docs" DOXYGEN_FOUND "HTML documentation of the API")
|
add_feature_info("API docs" DOXYGEN_FOUND "HTML documentation of the API")
|
||||||
add_feature_info("Qt Help" BUILD_AND_BUNDLE_DOCS "API docs in Qt Help format")
|
add_feature_info("Qt Help" BUILD_AND_BUNDLE_DOCS "API docs in Qt Help format")
|
||||||
add_feature_info("Manual" BUILD_MANUAL "HTML user's manual")
|
add_feature_info("Manual" BUILD_MANUAL "HTML user's manual")
|
||||||
|
|
||||||
feature_summary(WHAT ALL)
|
feature_summary(WHAT ALL)
|
||||||
|
|
||||||
# Option summary
|
# Option summary
|
||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
MESSAGE(STATUS "Summary")
|
MESSAGE(STATUS "Summary")
|
||||||
MESSAGE(STATUS "-------")
|
MESSAGE(STATUS "-------")
|
||||||
MESSAGE(STATUS "Library type: " ${LIBRARY_TYPE})
|
MESSAGE(STATUS "Library type: " ${LIBRARY_TYPE})
|
||||||
MESSAGE(STATUS "Build examples: " ${BUILD_EXAMPLES})
|
MESSAGE(STATUS "Build examples: " ${BUILD_EXAMPLES})
|
||||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||||
MESSAGE(STATUS "Build bindings: " ${BUILD_BINDINGS})
|
MESSAGE(STATUS "Build bindings: " ${BUILD_BINDINGS})
|
||||||
MESSAGE(STATUS "API Docs available: " ${DOXYGEN_FOUND})
|
MESSAGE(STATUS "API Docs available: " ${DOXYGEN_FOUND})
|
||||||
MESSAGE(STATUS " - Qt Help bundling: " ${BUILD_AND_BUNDLE_DOCS})
|
MESSAGE(STATUS " - Qt Help bundling: " ${BUILD_AND_BUNDLE_DOCS})
|
||||||
MESSAGE(STATUS "Build manual: " ${BUILD_MANUAL})
|
MESSAGE(STATUS "Build manual: " ${BUILD_MANUAL})
|
||||||
MESSAGE(STATUS "")
|
MESSAGE(STATUS "")
|
||||||
|
12
CREDITS.txt
12
CREDITS.txt
@ -1,7 +1,7 @@
|
|||||||
David Williams - Lead programmer.
|
David Williams - Lead programmer.
|
||||||
Matthew Williams - Linux port, build system, support and maintenance.
|
Matthew Williams - Linux port, build system, support and maintenance.
|
||||||
Oliver Schneider - Very large Volumes
|
Oliver Schneider - Very large Volumes
|
||||||
|
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
----------------
|
----------------
|
||||||
PolyVox uses the 'miniz' for data compression. 'miniz' is public domain software and does not affect the license of PolyVox or of code using PolyVox. More details here: http://code.google.com/p/miniz/
|
PolyVox uses the 'miniz' for data compression. 'miniz' is public domain software and does not affect the license of PolyVox or of code using PolyVox. More details here: http://code.google.com/p/miniz/
|
@ -1,28 +1,28 @@
|
|||||||
# Copyright (c) 2010-2012 Matt Williams
|
# Copyright (c) 2010-2012 Matt Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
set(CTEST_PROJECT_NAME "PolyVox")
|
set(CTEST_PROJECT_NAME "PolyVox")
|
||||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
|
set(CTEST_NIGHTLY_START_TIME "00:00:00 GMT")
|
||||||
|
|
||||||
set(CTEST_DROP_METHOD "http")
|
set(CTEST_DROP_METHOD "http")
|
||||||
set(CTEST_DROP_SITE "my.cdash.org")
|
set(CTEST_DROP_SITE "my.cdash.org")
|
||||||
set(CTEST_DROP_LOCATION "/submit.php?project=PolyVox")
|
set(CTEST_DROP_LOCATION "/submit.php?project=PolyVox")
|
||||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||||
|
258
INSTALL.txt
258
INSTALL.txt
@ -1,129 +1,129 @@
|
|||||||
****************
|
****************
|
||||||
Building PolyVox
|
Building PolyVox
|
||||||
****************
|
****************
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
To build PolyVox you need:
|
To build PolyVox you need:
|
||||||
|
|
||||||
* `CMake <http://cmake.org>`_ 2.8.3 or greater
|
* `CMake <http://cmake.org>`_ 2.8.3 or greater
|
||||||
* A C++ compiler with support for some C++0x features (GCC 4.3 or VC 2010 seem to work)
|
* A C++ compiler with support for some C++0x features (GCC 4.3 or VC 2010 seem to work)
|
||||||
|
|
||||||
With the following optional packages:
|
With the following optional packages:
|
||||||
|
|
||||||
* `Qt <http://qt.nokia.com>`_ for building the tests and the example applications
|
* `Qt <http://qt.nokia.com>`_ for building the tests and the example applications
|
||||||
* ``qcollectiongenerator`` which comes with Qt Assistant is used for bundling the docs for installation
|
* ``qcollectiongenerator`` which comes with Qt Assistant is used for bundling the docs for installation
|
||||||
* `Doxygen <http://doxygen.org>`_ for building the documentation. Version 1.5.7 is needed to build the Qt Assistant docs. 1.7.0 or greater is recommended
|
* `Doxygen <http://doxygen.org>`_ for building the documentation. Version 1.5.7 is needed to build the Qt Assistant docs. 1.7.0 or greater is recommended
|
||||||
* `Python <http://python.org>`_, `Sphinx <http://sphinx.pocoo.org>`_ and `PyParsing <http://pyparsing.wikispaces.com/>`_ for generating the PolyVox manual in HTML
|
* `Python <http://python.org>`_, `Sphinx <http://sphinx.pocoo.org>`_ and `PyParsing <http://pyparsing.wikispaces.com/>`_ for generating the PolyVox manual in HTML
|
||||||
* `Python development libraries <http://python.org>`_, `SWIG <http://swig.org/>`_ for generating the Python bindings
|
* `Python development libraries <http://python.org>`_, `SWIG <http://swig.org/>`_ for generating the Python bindings
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Navigate to the PolyVox source directory (the directory containing ``INSTALL.txt`` etc.) with and then enter the build directory with::
|
Navigate to the PolyVox source directory (the directory containing ``INSTALL.txt`` etc.) with and then enter the build directory with::
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
CMake
|
CMake
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Now, we use CMake to generate the makefiles with::
|
Now, we use CMake to generate the makefiles with::
|
||||||
|
|
||||||
cmake ..
|
cmake ..
|
||||||
|
|
||||||
The ``..`` tells CMake to look in the parent directory for the source.
|
The ``..`` tells CMake to look in the parent directory for the source.
|
||||||
|
|
||||||
By default this will set it to be installed in ``/usr/local`` so if you want to install it elsewhere, set the ``CMAKE_INSTALL_PREFIX`` variable to the path you want to install to.
|
By default this will set it to be installed in ``/usr/local`` so if you want to install it elsewhere, set the ``CMAKE_INSTALL_PREFIX`` variable to the path you want to install to.
|
||||||
|
|
||||||
You can set CMake variables by passing ``-D<variable>:<type>=<value>`` to the ``cmake`` command (the ``:<type>`` part is optional but recommended). For example, to set the install prefix, pass::
|
You can set CMake variables by passing ``-D<variable>:<type>=<value>`` to the ``cmake`` command (the ``:<type>`` part is optional but recommended). For example, to set the install prefix, pass::
|
||||||
|
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH=/whatever/you/want
|
-DCMAKE_INSTALL_PREFIX:PATH=/whatever/you/want
|
||||||
|
|
||||||
The other available settings for PolyVox are:
|
The other available settings for PolyVox are:
|
||||||
|
|
||||||
``ENABLE_EXAMPLES`` (``ON`` or ``OFF``)
|
``ENABLE_EXAMPLES`` (``ON`` or ``OFF``)
|
||||||
Build the example applications that come with PolyVox. Defaults to ``ON``.
|
Build the example applications that come with PolyVox. Defaults to ``ON``.
|
||||||
|
|
||||||
``ENABLE_TESTS`` (``ON`` or ``OFF``)
|
``ENABLE_TESTS`` (``ON`` or ``OFF``)
|
||||||
Build the test applications that come with PolyVox. Running the tests is detailed in the next section. Defaults to ``ON``.
|
Build the test applications that come with PolyVox. Running the tests is detailed in the next section. Defaults to ``ON``.
|
||||||
|
|
||||||
``ENABLE_BINDINGS`` (``ON`` or ``OFF``)
|
``ENABLE_BINDINGS`` (``ON`` or ``OFF``)
|
||||||
Should the Python bindings to PolyVox be built. This requires the Python development libraries and SWIG to be installed. Defaults to ``ON``.
|
Should the Python bindings to PolyVox be built. This requires the Python development libraries and SWIG to be installed. Defaults to ``ON``.
|
||||||
|
|
||||||
``LIBRARY_TYPE`` (``DYNAMIC`` or ``STATIC``)
|
``LIBRARY_TYPE`` (``DYNAMIC`` or ``STATIC``)
|
||||||
Choose whether static (``.a``) or dynamic libraries (``.so``) should be built. On Linux ``DYNAMIC`` is the default and on Windows ``STATIC`` is the default.
|
Choose whether static (``.a``) or dynamic libraries (``.so``) should be built. On Linux ``DYNAMIC`` is the default and on Windows ``STATIC`` is the default.
|
||||||
|
|
||||||
``CMAKE_BUILD_TYPE`` (``Debug``, ``Release``, ``RelWithDebInfo`` or ``MinSizeRel``)
|
``CMAKE_BUILD_TYPE`` (``Debug``, ``Release``, ``RelWithDebInfo`` or ``MinSizeRel``)
|
||||||
String option to set the type of build. This will automatically set some compilation flags such as the optimisation level or define ``NDEBUG``.
|
String option to set the type of build. This will automatically set some compilation flags such as the optimisation level or define ``NDEBUG``.
|
||||||
|
|
||||||
For development work against the library
|
For development work against the library
|
||||||
Use ``Debug`` or ``RelWithDebInfo``
|
Use ``Debug`` or ``RelWithDebInfo``
|
||||||
|
|
||||||
For your final version
|
For your final version
|
||||||
Use ``Release``
|
Use ``Release``
|
||||||
|
|
||||||
For building packages (e.g. for Linux distributions)
|
For building packages (e.g. for Linux distributions)
|
||||||
Use ``RelWithDebInfo``
|
Use ``RelWithDebInfo``
|
||||||
|
|
||||||
Building and installing
|
Building and installing
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
Once this has completed successfully, simply run::
|
Once this has completed successfully, simply run::
|
||||||
|
|
||||||
make install
|
make install
|
||||||
|
|
||||||
and all should work.
|
and all should work.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
To run the tests you do not need to have run ``make install``. Simply run::
|
To run the tests you do not need to have run ``make install``. Simply run::
|
||||||
|
|
||||||
make
|
make
|
||||||
make test
|
make test
|
||||||
|
|
||||||
API Documentation
|
API Documentation
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
If you want to generate the API documentation, you'll need Doxygen installed. If you saw ``API Docs available: YES`` at the end of the CMake output then you're all set. To generate the docs, just run::
|
If you want to generate the API documentation, you'll need Doxygen installed. If you saw ``API Docs available: YES`` at the end of the CMake output then you're all set. To generate the docs, just run::
|
||||||
|
|
||||||
make doc
|
make doc
|
||||||
|
|
||||||
and the documentation can be browsed in plain HTML form at ``<build directory>/library/doc/html/index.html``.
|
and the documentation can be browsed in plain HTML form at ``<build directory>/library/doc/html/index.html``.
|
||||||
|
|
||||||
On top of this, if ``qcollectiongenerator`` is installed, PolyVox can also compile and install this documentation as a *Qt Help Collection* file to ``<prefix>/share/doc/packages/polyvox/qthelp/polyvox.qhc`` (this file is in the build directory as ``<build directory>/library/doc/qthelp/polyvox.qhc``). To view this file you need Qt Assistant installed. You can open it with::
|
On top of this, if ``qcollectiongenerator`` is installed, PolyVox can also compile and install this documentation as a *Qt Help Collection* file to ``<prefix>/share/doc/packages/polyvox/qthelp/polyvox.qhc`` (this file is in the build directory as ``<build directory>/library/doc/qthelp/polyvox.qhc``). To view this file you need Qt Assistant installed. You can open it with::
|
||||||
|
|
||||||
assistant -collectionFile library/doc/qthelp/polyvox.qhc
|
assistant -collectionFile library/doc/qthelp/polyvox.qhc
|
||||||
|
|
||||||
This allows indexed searching of the documentation and easier browsing.
|
This allows indexed searching of the documentation and easier browsing.
|
||||||
|
|
||||||
Manual
|
Manual
|
||||||
------
|
------
|
||||||
|
|
||||||
As well as the API documentation, PolyVox also provides a user manual. This is written using `Sphinx <http://sphinx.pocoo.org>`_ and so to convert the documentation sources to HTML requires Sphinx and Python to be installed. If these are installed and found then you will see ``Build manual: YES`` in the CMake summary output. If this is the case then just run::
|
As well as the API documentation, PolyVox also provides a user manual. This is written using `Sphinx <http://sphinx.pocoo.org>`_ and so to convert the documentation sources to HTML requires Sphinx and Python to be installed. If these are installed and found then you will see ``Build manual: YES`` in the CMake summary output. If this is the case then just run::
|
||||||
|
|
||||||
make manual
|
make manual
|
||||||
|
|
||||||
and the HTML manual will be available at ``<build directory>/documentation/index.html``.
|
and the HTML manual will be available at ``<build directory>/documentation/index.html``.
|
||||||
|
|
||||||
If you have Sphinx installed but you do not get the confirmation in the CMake output, you may need to set ``SPHINXBUILD_EXECUTABLE`` to the location of your ``sphinx-build`` executable.
|
If you have Sphinx installed but you do not get the confirmation in the CMake output, you may need to set ``SPHINXBUILD_EXECUTABLE`` to the location of your ``sphinx-build`` executable.
|
||||||
|
|
||||||
If you do not have Python and Sphinx installed and do not want to install them then the manual is just plain text (``.rst`` files) which are readable in their plain form in the ``documentation`` directory of the source distribution.
|
If you do not have Python and Sphinx installed and do not want to install them then the manual is just plain text (``.rst`` files) which are readable in their plain form in the ``documentation`` directory of the source distribution.
|
||||||
|
|
||||||
Windows
|
Windows
|
||||||
=======
|
=======
|
||||||
|
|
||||||
For information about the dependencies, CMake configuration variables and buildable targets look at the Linux build information in the section above.
|
For information about the dependencies, CMake configuration variables and buildable targets look at the Linux build information in the section above.
|
||||||
|
|
||||||
CMake
|
CMake
|
||||||
-----
|
-----
|
||||||
|
|
||||||
You need CMake installed so get the binary distribution from `CMake.org <http://cmake.org/cmake/resources/software.html>`_. Install it and run the CMake GUI.
|
You need CMake installed so get the binary distribution from `CMake.org <http://cmake.org/cmake/resources/software.html>`_. Install it and run the CMake GUI.
|
||||||
|
|
||||||
Point the source directory to the directory holding this file and the build directory to the ``build`` subdirectory. Then, click the ``Configure`` button. Click through the dialog box that appears and once you've clicked ``Finish`` you should see text appearing in the bottom text area. Once this has finished, some options will appear in the top area. The purpose of these options in detailed in the Linux→CMake section above. Once you have set these options to what you please, click ``Configure`` again. If it completes without errors then you can click ``Generate`` which will generate your compilers project files in the build directory.
|
Point the source directory to the directory holding this file and the build directory to the ``build`` subdirectory. Then, click the ``Configure`` button. Click through the dialog box that appears and once you've clicked ``Finish`` you should see text appearing in the bottom text area. Once this has finished, some options will appear in the top area. The purpose of these options in detailed in the Linux→CMake section above. Once you have set these options to what you please, click ``Configure`` again. If it completes without errors then you can click ``Generate`` which will generate your compilers project files in the build directory.
|
||||||
|
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Open the project files in your IDE and build the project as you normally would.
|
Open the project files in your IDE and build the project as you normally would.
|
||||||
|
40
LICENSE.TXT
40
LICENSE.TXT
@ -1,20 +1,20 @@
|
|||||||
Copyright (c) 2005-2012 David Williams and Matthew Williams
|
Copyright (c) 2005-2012 David Williams and Matthew Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
|
110
Packaging.cmake
110
Packaging.cmake
@ -1,55 +1,55 @@
|
|||||||
# Copyright (c) 2009-2012 Matt Williams
|
# Copyright (c) 2009-2012 Matt Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
#INCLUDE(InstallRequiredSystemLibraries)
|
#INCLUDE(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
SET(CPACK_PACKAGE_NAME "PolyVox SDK")
|
SET(CPACK_PACKAGE_NAME "PolyVox SDK")
|
||||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "PolyVox SDK")
|
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "PolyVox SDK")
|
||||||
SET(CPACK_PACKAGE_VENDOR "Thermite 3D Team")
|
SET(CPACK_PACKAGE_VENDOR "Thermite 3D Team")
|
||||||
#SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt")
|
#SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt")
|
||||||
#SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")
|
#SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt")
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${POLYVOX_VERSION_MAJOR})
|
SET(CPACK_PACKAGE_VERSION_MAJOR ${POLYVOX_VERSION_MAJOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${POLYVOX_VERSION_MINOR})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${POLYVOX_VERSION_MINOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH ${POLYVOX_VERSION_PATCH})
|
SET(CPACK_PACKAGE_VERSION_PATCH ${POLYVOX_VERSION_PATCH})
|
||||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "PolyVox SDK ${POLYVOX_VERSION}")
|
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "PolyVox SDK ${POLYVOX_VERSION}")
|
||||||
IF(WIN32 AND NOT UNIX)
|
IF(WIN32 AND NOT UNIX)
|
||||||
# There is a bug in NSIS that does not handle full unix paths properly.
|
# 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.
|
# Make sure there is at least one set of four backslashes.
|
||||||
#SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
|
#SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
|
||||||
#SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe")
|
#SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe")
|
||||||
SET(CPACK_NSIS_DISPLAY_NAME "PolyVox SDK ${POLYVOX_VERSION}")
|
SET(CPACK_NSIS_DISPLAY_NAME "PolyVox SDK ${POLYVOX_VERSION}")
|
||||||
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\thermite3d.org/phpBB/")
|
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\thermite3d.org/phpBB/")
|
||||||
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\thermite3d.org")
|
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\thermite3d.org")
|
||||||
SET(CPACK_NSIS_CONTACT "matt@milliams.com")
|
SET(CPACK_NSIS_CONTACT "matt@milliams.com")
|
||||||
SET(CPACK_NSIS_MODIFY_PATH ON)
|
SET(CPACK_NSIS_MODIFY_PATH ON)
|
||||||
ELSE(WIN32 AND NOT UNIX)
|
ELSE(WIN32 AND NOT UNIX)
|
||||||
#SET(CPACK_STRIP_FILES "bin/MyExecutable")
|
#SET(CPACK_STRIP_FILES "bin/MyExecutable")
|
||||||
#SET(CPACK_SOURCE_STRIP_FILES "")
|
#SET(CPACK_SOURCE_STRIP_FILES "")
|
||||||
ENDIF(WIN32 AND NOT UNIX)
|
ENDIF(WIN32 AND NOT UNIX)
|
||||||
#SET(CPACK_PACKAGE_EXECUTABLES "MyExecutable" "My Executable")
|
#SET(CPACK_PACKAGE_EXECUTABLES "MyExecutable" "My Executable")
|
||||||
|
|
||||||
INCLUDE(CPack)
|
INCLUDE(CPack)
|
||||||
|
|
||||||
CPACK_ADD_COMPONENT(library DISPLAY_NAME "Library" DESCRIPTION "The runtime libraries" REQUIRED)
|
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(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(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_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)
|
CPACK_ADD_COMPONENT(python DISPLAY_NAME "Python Bindings" DESCRIPTION "PolyVox bindings for the Python language" DISABLED GROUP bindings DEPENDS library)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
PolyVox - The voxel management and manipulation library
|
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 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.
|
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.
|
130
TODO.txt
130
TODO.txt
@ -1,65 +1,65 @@
|
|||||||
Discussed on forums
|
Discussed on forums
|
||||||
===================
|
===================
|
||||||
Implement RLE compressor, and use it for blocks in memory and saving to disk.
|
Implement RLE compressor, and use it for blocks in memory and saving to disk.
|
||||||
Replace shared_ptr's with intrinsic_ptrs?
|
Replace shared_ptr's with intrinsic_ptrs?
|
||||||
Make decimator work with cubic mesh
|
Make decimator work with cubic mesh
|
||||||
Raycaster.
|
Raycaster.
|
||||||
|
|
||||||
Short term
|
Short term
|
||||||
==========
|
==========
|
||||||
Sort awkward use of 'offset'
|
Sort awkward use of 'offset'
|
||||||
Replace float with uchar for material.
|
Replace float with uchar for material.
|
||||||
Mesh smoothing (surface nets?)
|
Mesh smoothing (surface nets?)
|
||||||
Mesh filters/modifiers - A 'translate' modifier?
|
Mesh filters/modifiers - A 'translate' modifier?
|
||||||
|
|
||||||
|
|
||||||
For Version 1.0
|
For Version 1.0
|
||||||
===============
|
===============
|
||||||
Implement Memory Pool
|
Implement Memory Pool
|
||||||
Clean up normal code - make normal generation a seperate pass.
|
Clean up normal code - make normal generation a seperate pass.
|
||||||
Implement mesh smoothing.
|
Implement mesh smoothing.
|
||||||
Refine interface to mesh generateion - flags structure?
|
Refine interface to mesh generateion - flags structure?
|
||||||
Refine interface to volumes and iterators.
|
Refine interface to volumes and iterators.
|
||||||
Implement block volume tidy() funtion.
|
Implement block volume tidy() funtion.
|
||||||
Remove hard-coded region size.
|
Remove hard-coded region size.
|
||||||
Seperate namespaces - PolyVoxCore, PolyVoxUtil, PolyVoxImpl
|
Seperate namespaces - PolyVoxCore, PolyVoxUtil, PolyVoxImpl
|
||||||
Move getChangedRegionGeometry() out of PolyVon and into Thermite?
|
Move getChangedRegionGeometry() out of PolyVon and into Thermite?
|
||||||
Remove/refactor IndexedSurfacePatch? Incorporate into RegionGeometry?
|
Remove/refactor IndexedSurfacePatch? Incorporate into RegionGeometry?
|
||||||
Change vertex format to ints?
|
Change vertex format to ints?
|
||||||
Check licensing, #regions, etc.
|
Check licensing, #regions, etc.
|
||||||
Decimated version of marching cubes should use less memory.
|
Decimated version of marching cubes should use less memory.
|
||||||
Unit test - compare output to reference implementation
|
Unit test - compare output to reference implementation
|
||||||
Sort awkward use of 'offset' in decimated marching cubes.
|
Sort awkward use of 'offset' in decimated marching cubes.
|
||||||
Use of LinearVolume instead of arrays.
|
Use of LinearVolume instead of arrays.
|
||||||
Add API docs
|
Add API docs
|
||||||
Add manual
|
Add manual
|
||||||
Finish OpenGL sample.
|
Finish OpenGL sample.
|
||||||
VolumeChangeTracker can be more conservitive regarding when neighbouring regions are modified.
|
VolumeChangeTracker can be more conservitive regarding when neighbouring regions are modified.
|
||||||
|
|
||||||
For Version 2.0
|
For Version 2.0
|
||||||
===============
|
===============
|
||||||
Detect detatched regions.
|
Detect detatched regions.
|
||||||
Handle mesh generation for detatched regions.
|
Handle mesh generation for detatched regions.
|
||||||
Generate ambient lighting from volume?
|
Generate ambient lighting from volume?
|
||||||
Utility function for closing outside surfaces?
|
Utility function for closing outside surfaces?
|
||||||
Consider how seperate surface should be generated for a single region.
|
Consider how seperate surface should be generated for a single region.
|
||||||
Consider transparent materials like glass.
|
Consider transparent materials like glass.
|
||||||
Allow writing meshes into volumes?
|
Allow writing meshes into volumes?
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
=============
|
=============
|
||||||
Define the following terms:
|
Define the following terms:
|
||||||
-Voxel
|
-Voxel
|
||||||
-Cell
|
-Cell
|
||||||
-Volume
|
-Volume
|
||||||
-Region
|
-Region
|
||||||
-Block
|
-Block
|
||||||
|
|
||||||
Packaging
|
Packaging
|
||||||
=========
|
=========
|
||||||
Create components for the NSIS installer (Library, bindings, examples, documentation) - Half done
|
Create components for the NSIS installer (Library, bindings, examples, documentation) - Half done
|
||||||
Add License
|
Add License
|
||||||
Add images for installer (and icons)
|
Add images for installer (and icons)
|
||||||
Set LZMA compression
|
Set LZMA compression
|
||||||
Find a way to include both debug and release builds?
|
Find a way to include both debug and release builds?
|
||||||
The .lib files should be part of the 'development' configuration?
|
The .lib files should be part of the 'development' configuration?
|
||||||
|
@ -1,49 +1,49 @@
|
|||||||
# Copyright (c) 2010-2012 Matt Williams
|
# Copyright (c) 2010-2012 Matt Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
find_program(SPHINXBUILD_EXECUTABLE sphinx-build DOC "The location of the sphinx-build executable")
|
find_program(SPHINXBUILD_EXECUTABLE sphinx-build DOC "The location of the sphinx-build executable")
|
||||||
|
|
||||||
#if(SPHINXBUILD_EXECUTABLE AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
#if(SPHINXBUILD_EXECUTABLE AND QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
if(SPHINXBUILD_EXECUTABLE)
|
if(SPHINXBUILD_EXECUTABLE)
|
||||||
message(STATUS "Found `sphinx-build` at ${SPHINXBUILD_EXECUTABLE}")
|
message(STATUS "Found `sphinx-build` at ${SPHINXBUILD_EXECUTABLE}")
|
||||||
set(BUILD_MANUAL ON PARENT_SCOPE)
|
set(BUILD_MANUAL ON PARENT_SCOPE)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.in.py ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.in.py ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY)
|
||||||
#Generates the HTML docs and the Qt help file which can be opened with "assistant -collectionFile thermite.qhc"
|
#Generates the HTML docs and the Qt help file which can be opened with "assistant -collectionFile thermite.qhc"
|
||||||
#add_custom_target(manual ${SPHINXBUILD_EXECUTABLE} -b qthelp ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} polyvox.qhcp -o polyvox.qhc)
|
#add_custom_target(manual ${SPHINXBUILD_EXECUTABLE} -b qthelp ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} polyvox.qhcp -o polyvox.qhc)
|
||||||
add_custom_target(manual
|
add_custom_target(manual
|
||||||
${SPHINXBUILD_EXECUTABLE} -b html
|
${SPHINXBUILD_EXECUTABLE} -b html
|
||||||
-c ${CMAKE_CURRENT_BINARY_DIR} #Load the conf.py from the binary dir
|
-c ${CMAKE_CURRENT_BINARY_DIR} #Load the conf.py from the binary dir
|
||||||
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Building PolyVox manual"
|
COMMENT "Building PolyVox manual"
|
||||||
)
|
)
|
||||||
add_dependencies(manual doc)
|
add_dependencies(manual doc)
|
||||||
set_target_properties(manual PROPERTIES PROJECT_LABEL "Manual") #Set label seen in IDE
|
set_target_properties(manual PROPERTIES PROJECT_LABEL "Manual") #Set label seen in IDE
|
||||||
SET_PROPERTY(TARGET manual PROPERTY FOLDER "Documentation")
|
SET_PROPERTY(TARGET manual PROPERTY FOLDER "Documentation")
|
||||||
else()
|
else()
|
||||||
if(NOT SPHINXBUILD_EXECUTABLE)
|
if(NOT SPHINXBUILD_EXECUTABLE)
|
||||||
message(STATUS "`sphinx-build` was not found. Try setting SPHINXBUILD_EXECUTABLE to its location.")
|
message(STATUS "`sphinx-build` was not found. Try setting SPHINXBUILD_EXECUTABLE to its location.")
|
||||||
endif()
|
endif()
|
||||||
if(NOT QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
if(NOT QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
message(STATUS "`qhelpgenerator` was not found. Try setting QT_QCOLLECTIONGENERATOR_EXECUTABLE to its location.")
|
message(STATUS "`qhelpgenerator` was not found. Try setting QT_QCOLLECTIONGENERATOR_EXECUTABLE to its location.")
|
||||||
endif()
|
endif()
|
||||||
set(BUILD_MANUAL OFF PARENT_SCOPE)
|
set(BUILD_MANUAL OFF PARENT_SCOPE)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
**************************
|
**************************
|
||||||
Frequently Asked Questions
|
Frequently Asked Questions
|
||||||
**************************
|
**************************
|
||||||
|
|
||||||
Should I store my environment in a single big volume or break it down into several smaller ones?
|
Should I store my environment in a single big volume or break it down into several smaller ones?
|
||||||
------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------
|
||||||
In most cases you should store you data in a single big volume, unless you are sure you understand the implications of doing otherwise.
|
In most cases you should store you data in a single big volume, unless you are sure you understand the implications of doing otherwise.
|
||||||
|
|
||||||
Most algorithms in PolyVox operate on only a single volume (the exception to this are some of the image processing algorithms which use source and destination volumes, but even they use a *single* source and a *single* destination). The reason for this is that many algorithms require fast access to the neighbours of any given voxel. As an example, the surface extractors need to look at the neighbours of a voxel in order to determine whether triangles should be generated.
|
Most algorithms in PolyVox operate on only a single volume (the exception to this are some of the image processing algorithms which use source and destination volumes, but even they use a *single* source and a *single* destination). The reason for this is that many algorithms require fast access to the neighbours of any given voxel. As an example, the surface extractors need to look at the neighbours of a voxel in order to determine whether triangles should be generated.
|
||||||
|
|
||||||
PolyVox volumes make it easy to access these neighbours, but the situation gets complex on the edge of a volume because the neighbouring voxels may not exist. It is possible to define a border value (which will be returned whenever you try to read a voxel outside the volume) but this doesn't handle all scenarios in the desired way. Often the most practical solution is to make the volume slightly larger than the data it needs to contain, and then avoid having your algorithms go right to the edge.
|
PolyVox volumes make it easy to access these neighbours, but the situation gets complex on the edge of a volume because the neighbouring voxels may not exist. It is possible to define a border value (which will be returned whenever you try to read a voxel outside the volume) but this doesn't handle all scenarios in the desired way. Often the most practical solution is to make the volume slightly larger than the data it needs to contain, and then avoid having your algorithms go right to the edge.
|
||||||
|
|
||||||
Having established that edge cases can be problematic, we can now see that storing your data as a set of adjacent volumes is undesirable because these edge cases then exist throughout the data set. This causes a lot of problems such as gaps between pieces of extracted terrain or discontinuities in the computed normals.
|
Having established that edge cases can be problematic, we can now see that storing your data as a set of adjacent volumes is undesirable because these edge cases then exist throughout the data set. This causes a lot of problems such as gaps between pieces of extracted terrain or discontinuities in the computed normals.
|
||||||
|
|
||||||
The usual reason why people attempt to break their terrain into separate volumes is so that they can perform some more advanced memory management for very big terrain, for example by only loading particular volumes into memory when they are within a certain distance from the camera. However, this kind of paging behaviour is already implemented by the LargeVolume class. The LargeVolume internally stores its data as a set of blocks, and does it in such a way that it is able to perform neighbourhood access across block boundaries. Whenever you find yourself trying to break terrain data into separate volumes you should probably use the LargeVolume instead.
|
The usual reason why people attempt to break their terrain into separate volumes is so that they can perform some more advanced memory management for very big terrain, for example by only loading particular volumes into memory when they are within a certain distance from the camera. However, this kind of paging behaviour is already implemented by the LargeVolume class. The LargeVolume internally stores its data as a set of blocks, and does it in such a way that it is able to perform neighbourhood access across block boundaries. Whenever you find yourself trying to break terrain data into separate volumes you should probably use the LargeVolume instead.
|
||||||
|
|
||||||
Note that although you should only use a single volume for your data, it is still recommended that you split the mesh data into multiple pieces so that they can be culled against the view frustum, and so that you can update the smaller pieces more quickly when you need to. You can extract meshes from different parts of the volume by passing a Region to the surface extractor.
|
Note that although you should only use a single volume for your data, it is still recommended that you split the mesh data into multiple pieces so that they can be culled against the view frustum, and so that you can update the smaller pieces more quickly when you need to. You can extract meshes from different parts of the volume by passing a Region to the surface extractor.
|
||||||
|
|
||||||
Lastly, note that there are exceptions to the 'one volume' rule. An example might be if you had a number of planets in space, in which case each planet could safely be a separate volume. These planets never touch, and so the artifacts which would occur on volume boundaries do not cause a problem.
|
Lastly, note that there are exceptions to the 'one volume' rule. An example might be if you had a number of planets in space, in which case each planet could safely be a separate volume. These planets never touch, and so the artifacts which would occur on volume boundaries do not cause a problem.
|
||||||
|
|
||||||
Can I combine smooth meshes with cubic ones?
|
Can I combine smooth meshes with cubic ones?
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
We have never attempted to do this but in theory it should be possible. One option is simply to generate two meshes (one using the MarchingCubesSurfaceExtractor and the other using the CubicSurfaceExtractor) and render them on top of each other while allowing the depth buffer to resolve the intersections. Combining these two meshes into a single mesh is likely to be difficult as they use different vertex formats and have different texturing requirements (see the document on texture mapping).
|
We have never attempted to do this but in theory it should be possible. One option is simply to generate two meshes (one using the MarchingCubesSurfaceExtractor and the other using the CubicSurfaceExtractor) and render them on top of each other while allowing the depth buffer to resolve the intersections. Combining these two meshes into a single mesh is likely to be difficult as they use different vertex formats and have different texturing requirements (see the document on texture mapping).
|
||||||
|
|
||||||
An alternative possibility may be to create a new surface extractor based on the Surface Nets (link) algorithm. The idea here is that the mesh would start with a cubic shape, but as the net was stretched it would be smoothed. The degree of smoothing could be controlled by a voxel property which could allow the full range from cubic to smooth to exist in a single mesh. As mentioned above, this may mean that some extra work has to be put into a fragment shader which is capable of texturing this kind of mesh. Come by the forums of you want to discuss this further.
|
An alternative possibility may be to create a new surface extractor based on the Surface Nets (link) algorithm. The idea here is that the mesh would start with a cubic shape, but as the net was stretched it would be smoothed. The degree of smoothing could be controlled by a voxel property which could allow the full range from cubic to smooth to exist in a single mesh. As mentioned above, this may mean that some extra work has to be put into a fragment shader which is capable of texturing this kind of mesh. Come by the forums of you want to discuss this further.
|
@ -1,48 +1,48 @@
|
|||||||
***************
|
***************
|
||||||
Level of Detail
|
Level of Detail
|
||||||
***************
|
***************
|
||||||
When the PolyVox surface extractors are applied to volume data the resulting mesh can contain a very high number of triangles. For large voxel worlds this can cause both performance and memory problems. The performance problems occur due the the load on the vertex shader which has to process a large number of vertices, and also due to the setup costs of a large number of tiny (possibly sub-pixel) triangles. The memory costs result simply from having a large amount of data which does not actually contribute to the visual appearance of the scene.
|
When the PolyVox surface extractors are applied to volume data the resulting mesh can contain a very high number of triangles. For large voxel worlds this can cause both performance and memory problems. The performance problems occur due the the load on the vertex shader which has to process a large number of vertices, and also due to the setup costs of a large number of tiny (possibly sub-pixel) triangles. The memory costs result simply from having a large amount of data which does not actually contribute to the visual appearance of the scene.
|
||||||
|
|
||||||
For these reasons it is desirable to reduce the triangle count of the meshes as far as possible, especially as meshes move away from the camera. This document describes the various approaches which are available within PolyVox to achieve this. Generally these approaches are different for cubic meshes vs smooth meshes and so we address these cases separately.
|
For these reasons it is desirable to reduce the triangle count of the meshes as far as possible, especially as meshes move away from the camera. This document describes the various approaches which are available within PolyVox to achieve this. Generally these approaches are different for cubic meshes vs smooth meshes and so we address these cases separately.
|
||||||
|
|
||||||
Cubic Meshes
|
Cubic Meshes
|
||||||
============
|
============
|
||||||
A naive implementation of a cubic surface extractor would generate a mesh containing a quad for voxel face which lies on the boundary between a solid and an empty voxel. The CubicSurfaceExtractor is indeed capable of generating such a mesh, but it also provides the option to merge adjacent quads into a single quad subject to various conditions being satisfied (e.g. the faces must have the same material). This merging process drastically reduces the amount of geometry which must be drawn but does not modify the shape of the mesh. Because of these desirable properties such merging is performed by default, but it can be disabled if necessary.
|
A naive implementation of a cubic surface extractor would generate a mesh containing a quad for voxel face which lies on the boundary between a solid and an empty voxel. The CubicSurfaceExtractor is indeed capable of generating such a mesh, but it also provides the option to merge adjacent quads into a single quad subject to various conditions being satisfied (e.g. the faces must have the same material). This merging process drastically reduces the amount of geometry which must be drawn but does not modify the shape of the mesh. Because of these desirable properties such merging is performed by default, but it can be disabled if necessary.
|
||||||
|
|
||||||
To our knowledge the only drawback of performing this quad merging is that it can create T-junctions in the resulting mesh. T-junctions are an undesirable property of mesh geometry because they can cause tiny cracks (usually just seen as flickering pixels) to occur between quads. The figure below shows a mesh before quad merging, a mesh where the merged quads have caused T-junctions, and how the resulting rendering might look (note the single pixel holes along the quad border).
|
To our knowledge the only drawback of performing this quad merging is that it can create T-junctions in the resulting mesh. T-junctions are an undesirable property of mesh geometry because they can cause tiny cracks (usually just seen as flickering pixels) to occur between quads. The figure below shows a mesh before quad merging, a mesh where the merged quads have caused T-junctions, and how the resulting rendering might look (note the single pixel holes along the quad border).
|
||||||
|
|
||||||
*Add figure here...*
|
*Add figure here...*
|
||||||
|
|
||||||
Vertices C and D are supposed to lie exactly along the line which has A and B as its end points, so in theory the mesh should be valid and should render correctly. The reason T-junctions cause a problem in practice is due to limitations of the floating point number representation. Depending on the transformations which are applied, it may be that the positions of C and/or D can not be represented precisely enough to exactly lie on the line between A and B.
|
Vertices C and D are supposed to lie exactly along the line which has A and B as its end points, so in theory the mesh should be valid and should render correctly. The reason T-junctions cause a problem in practice is due to limitations of the floating point number representation. Depending on the transformations which are applied, it may be that the positions of C and/or D can not be represented precisely enough to exactly lie on the line between A and B.
|
||||||
|
|
||||||
*Demo correct mesh. mention we don't have a solution to generate it.*
|
*Demo correct mesh. mention we don't have a solution to generate it.*
|
||||||
|
|
||||||
Whether it's a problem in practice depends on hardware precision (16/32 bit), distance from origin, number of transforms which are applied, and probably a number of other factors. We have yet to investigate.
|
Whether it's a problem in practice depends on hardware precision (16/32 bit), distance from origin, number of transforms which are applied, and probably a number of other factors. We have yet to investigate.
|
||||||
|
|
||||||
We don't currently have a real solution to this problem. In Voxeliens the borders between voxels were darkened to simulate ambient occlusion and this had the desirable side effect of making any flickering pixels very hard to see. It's also possible that anti-aliasing strategies can reduce the problem, and storing vertex positions as integers may help as well. Lastly, it may be possible to construct some kind of post-process which would repair the image where it identifies single pixel discontinuities in the depth buffer.
|
We don't currently have a real solution to this problem. In Voxeliens the borders between voxels were darkened to simulate ambient occlusion and this had the desirable side effect of making any flickering pixels very hard to see. It's also possible that anti-aliasing strategies can reduce the problem, and storing vertex positions as integers may help as well. Lastly, it may be possible to construct some kind of post-process which would repair the image where it identifies single pixel discontinuities in the depth buffer.
|
||||||
|
|
||||||
Smooth Meshes
|
Smooth Meshes
|
||||||
=============
|
=============
|
||||||
Level of detail for smooth meshes is a lot more complex than for cubic ones, and we'll admit upfront that we do not currently have a good solution to this problem. None the less, we do have a couple of partial solutions which you might be able to use or adapt for your specific scenario.
|
Level of detail for smooth meshes is a lot more complex than for cubic ones, and we'll admit upfront that we do not currently have a good solution to this problem. None the less, we do have a couple of partial solutions which you might be able to use or adapt for your specific scenario.
|
||||||
|
|
||||||
Techniques for performing level of detail on smooth meshes basically fall into two categories. The first category involves reducing the resolution of the volume data and then running the surface extractor on the smaller volume. This naturally generates a lower detail mesh which must then be scaled up to match the other meshes in the scene. The second category involves generating the mesh at full detail and then using traditional mesh simplification techniques to reduces the number of triangles. Both techniques are explored in more detail below.
|
Techniques for performing level of detail on smooth meshes basically fall into two categories. The first category involves reducing the resolution of the volume data and then running the surface extractor on the smaller volume. This naturally generates a lower detail mesh which must then be scaled up to match the other meshes in the scene. The second category involves generating the mesh at full detail and then using traditional mesh simplification techniques to reduces the number of triangles. Both techniques are explored in more detail below.
|
||||||
|
|
||||||
Volume Reduction
|
Volume Reduction
|
||||||
----------------
|
----------------
|
||||||
The VolumeResampler class can be used to copy volume data from a source region to a destination region, and it handles the resampling of the voxel values in the event that the source and destination regions are not the same size. This is exactly what we need for implementing level of detail and the principle is demonstrated by the SmoothLOD sample (see the documentation for the SmoothLOD sample for more information).
|
The VolumeResampler class can be used to copy volume data from a source region to a destination region, and it handles the resampling of the voxel values in the event that the source and destination regions are not the same size. This is exactly what we need for implementing level of detail and the principle is demonstrated by the SmoothLOD sample (see the documentation for the SmoothLOD sample for more information).
|
||||||
|
|
||||||
One of the problems with this approach is that the lower resolution mesh does not *exactly* line up with the higher resolution mesh, and this can cause cracks to be visible where the two meshes meet. The SmoothLOD sample attempts to avoid this problem by overlapping the meshes slightly but this may not be effective in all situations or from all viewpoints.
|
One of the problems with this approach is that the lower resolution mesh does not *exactly* line up with the higher resolution mesh, and this can cause cracks to be visible where the two meshes meet. The SmoothLOD sample attempts to avoid this problem by overlapping the meshes slightly but this may not be effective in all situations or from all viewpoints.
|
||||||
|
|
||||||
An alternative is the Transvoxel algorithm (link) developed by Eric Lengyel. This essentially extends the original Marching Cubes lookup table with additional entries which handle seamless transitions between LOD levels, and it is a very promising solution to level of detail for voxel terrain. At this point in time we do not have an implementation of this algorithm but work is being undertaking in the area. For the latest developments see: http://www.volumesoffun.com/phpBB3/viewtopic.php?f=2&t=338
|
An alternative is the Transvoxel algorithm (link) developed by Eric Lengyel. This essentially extends the original Marching Cubes lookup table with additional entries which handle seamless transitions between LOD levels, and it is a very promising solution to level of detail for voxel terrain. At this point in time we do not have an implementation of this algorithm but work is being undertaking in the area. For the latest developments see: http://www.volumesoffun.com/phpBB3/viewtopic.php?f=2&t=338
|
||||||
|
|
||||||
However, in all volume reduction approaches there is some uncertainty about how materials should be handled. Creating a lower resolution volume means that several voxel values from the high resolution volume need to be combined into a single value. For density values this is straightforward as a simple average gives good results, but it is not clear how this extends to material identifiers. Averaging them doesn't make sense, and it is hard to imagine an approach which would not lead to visible artifacts as LOD levels change. Perhaps the visible effects can be reduced by blending between two LOD levels, but more investigation needs to be done here.
|
However, in all volume reduction approaches there is some uncertainty about how materials should be handled. Creating a lower resolution volume means that several voxel values from the high resolution volume need to be combined into a single value. For density values this is straightforward as a simple average gives good results, but it is not clear how this extends to material identifiers. Averaging them doesn't make sense, and it is hard to imagine an approach which would not lead to visible artifacts as LOD levels change. Perhaps the visible effects can be reduced by blending between two LOD levels, but more investigation needs to be done here.
|
||||||
|
|
||||||
Mesh Simplification
|
Mesh Simplification
|
||||||
-------------------
|
-------------------
|
||||||
The other main approach is to generate the mesh at the full resolution and then reduce the number of triangles using a postprocessing step. This can draw on the large body of mesh simplification research (link to survey) and typically involves merging adjacent faces or collapsing vertices. When using this approach there are a couple of additional complications compared to the implementations which are normally seen.
|
The other main approach is to generate the mesh at the full resolution and then reduce the number of triangles using a postprocessing step. This can draw on the large body of mesh simplification research (link to survey) and typically involves merging adjacent faces or collapsing vertices. When using this approach there are a couple of additional complications compared to the implementations which are normally seen.
|
||||||
|
|
||||||
The first additional complication is that the decimation algorithm needs to preserve material boundaries so that they don't move between LOD levels. When choosing whether a particular simplification can be made (i.e deciding if one vertex can be collapsed on to another or whether two faces can be merged) a metric is usually used to determine how much the simplification would affect the visual appearance of the mesh. When working with smooth voxel meshes this metric needs to also consider the material identifiers.
|
The first additional complication is that the decimation algorithm needs to preserve material boundaries so that they don't move between LOD levels. When choosing whether a particular simplification can be made (i.e deciding if one vertex can be collapsed on to another or whether two faces can be merged) a metric is usually used to determine how much the simplification would affect the visual appearance of the mesh. When working with smooth voxel meshes this metric needs to also consider the material identifiers.
|
||||||
|
|
||||||
We also need to ensure that the metric preserves the geometric boundary of the mesh, so that no cracks are visible when a simplified mesh is place next to an original one. Maintaining this geometric boundary can be difficult, as the straightforward approach of locking the edge vertices in place will tend to limit the amount of simplification which can be performed. Alternatively, cracks can be allowed to develop if they are later hidden through the use of 'skirts' around the resulting mesh.
|
We also need to ensure that the metric preserves the geometric boundary of the mesh, so that no cracks are visible when a simplified mesh is place next to an original one. Maintaining this geometric boundary can be difficult, as the straightforward approach of locking the edge vertices in place will tend to limit the amount of simplification which can be performed. Alternatively, cracks can be allowed to develop if they are later hidden through the use of 'skirts' around the resulting mesh.
|
||||||
|
|
||||||
PolyVox used to contain code for performing simplification of the smooth voxel meshes, but unfortunately it had significant performance and functionality issues. Therefore it has been deprecated and it will be removed in a future version of the library. We will instead investigate the use of external mesh simplification libraries and OpenMesh (link) may be a good candidate here.
|
PolyVox used to contain code for performing simplification of the smooth voxel meshes, but unfortunately it had significant performance and functionality issues. Therefore it has been deprecated and it will be removed in a future version of the library. We will instead investigate the use of external mesh simplification libraries and OpenMesh (link) may be a good candidate here.
|
||||||
|
@ -1,45 +1,45 @@
|
|||||||
********
|
********
|
||||||
Lighting
|
Lighting
|
||||||
********
|
********
|
||||||
Lighting is an important part of creating a realistic scene, and fortunately most common lighting solutions can be easily applied to PolyVox meshes. In this document we describe how to implement dynamic lighting and ambient occlusion with PolyVox.
|
Lighting is an important part of creating a realistic scene, and fortunately most common lighting solutions can be easily applied to PolyVox meshes. In this document we describe how to implement dynamic lighting and ambient occlusion with PolyVox.
|
||||||
|
|
||||||
Dynamic Lighting
|
Dynamic Lighting
|
||||||
================
|
================
|
||||||
In general, any lighting solution for real-time 3D graphics should be directly applicable to PolyVox meshes.
|
In general, any lighting solution for real-time 3D graphics should be directly applicable to PolyVox meshes.
|
||||||
|
|
||||||
Normal Calculation for Smooth Meshes
|
Normal Calculation for Smooth Meshes
|
||||||
------------------------------------
|
------------------------------------
|
||||||
When working with smooth voxel terrain meshes, PolyVox provides vertex normals as part of the extracted surface mesh. A common approach for computing these normals would be to compute normals for each face in the mesh, and then compute the vertex normals as a weighted average of the normals of the faces which share it. Actually this is not the approach used by PolyVox, as PolyVox instead computes the vertex normals directly from the underlying volume data.
|
When working with smooth voxel terrain meshes, PolyVox provides vertex normals as part of the extracted surface mesh. A common approach for computing these normals would be to compute normals for each face in the mesh, and then compute the vertex normals as a weighted average of the normals of the faces which share it. Actually this is not the approach used by PolyVox, as PolyVox instead computes the vertex normals directly from the underlying volume data.
|
||||||
|
|
||||||
More specifically, PolyVox is able to compute the *gradient* of the volume data at any given point using well established image processing methods. The normalised gradient value is used as the vertex normal and in general it is smoother than the value computed by averaging neighbouring faces. Actually there are two approaches to this gradient computation known as *Central Differencing* and *Sobel Filter*. The central differencing approach is generally recommended but the Sobel filter can be used to obtain slightly smoother results but with lower performance. See the MarchingCubesSurfaceExtractor documentation for details on how to select between these (check this exists...).
|
More specifically, PolyVox is able to compute the *gradient* of the volume data at any given point using well established image processing methods. The normalised gradient value is used as the vertex normal and in general it is smoother than the value computed by averaging neighbouring faces. Actually there are two approaches to this gradient computation known as *Central Differencing* and *Sobel Filter*. The central differencing approach is generally recommended but the Sobel filter can be used to obtain slightly smoother results but with lower performance. See the MarchingCubesSurfaceExtractor documentation for details on how to select between these (check this exists...).
|
||||||
|
|
||||||
Normal Calculation for Cubic Meshes
|
Normal Calculation for Cubic Meshes
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
For cubic meshes PolyVox doesn't actually generate any vertex normals at all, and this is often a source of confusion for new users. The reason for this is that we wish to to perform per-face lighting rather than per-vertex lighting. Considering the case of a single cube, if we wanted to perform per-face lighting based on per-vertex normals then the normals cannot be shared between adjacent faces and so each vertex needs to be duplicated three times (one for each face which uses it). This means we would need 24 vertices to represent a cube which intuitively should only need eight vertices.
|
For cubic meshes PolyVox doesn't actually generate any vertex normals at all, and this is often a source of confusion for new users. The reason for this is that we wish to to perform per-face lighting rather than per-vertex lighting. Considering the case of a single cube, if we wanted to perform per-face lighting based on per-vertex normals then the normals cannot be shared between adjacent faces and so each vertex needs to be duplicated three times (one for each face which uses it). This means we would need 24 vertices to represent a cube which intuitively should only need eight vertices.
|
||||||
|
|
||||||
Therefore PolyVox does not generate per-vertex normals for cubic meshes, and as a result the cubic mesh's vertices are both smaller and less numerous. Of course, we still need a way to obtain normals for lighting calculations and so our suggestion is to compute the normals in a fragment program using the *derivative operations* which are provided by modern graphics hardware.
|
Therefore PolyVox does not generate per-vertex normals for cubic meshes, and as a result the cubic mesh's vertices are both smaller and less numerous. Of course, we still need a way to obtain normals for lighting calculations and so our suggestion is to compute the normals in a fragment program using the *derivative operations* which are provided by modern graphics hardware.
|
||||||
|
|
||||||
The description here is rather oversimplified, but the idea behind these operation is that they can tell you how much a variable has changed between two adjacent pixels. If we use our fragment world space position as the input to these derivative operations then we can obtain two vectors which lie on the surface of our face. The cross product of these then gives us a vector which is perpendicular to both and which is therefore our normal.
|
The description here is rather oversimplified, but the idea behind these operation is that they can tell you how much a variable has changed between two adjacent pixels. If we use our fragment world space position as the input to these derivative operations then we can obtain two vectors which lie on the surface of our face. The cross product of these then gives us a vector which is perpendicular to both and which is therefore our normal.
|
||||||
|
|
||||||
Further information about the derivative operations can be found in the OpenGL/Direct3D API documentation, but the implementation in code is quite simple. Firstly you need to make sure that you have access to the fragments world space position in your shader, which means you need to pass it through from the vertex shader. Then you can use the following code in your fragment shader:
|
Further information about the derivative operations can be found in the OpenGL/Direct3D API documentation, but the implementation in code is quite simple. Firstly you need to make sure that you have access to the fragments world space position in your shader, which means you need to pass it through from the vertex shader. Then you can use the following code in your fragment shader:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. sourcecode:: glsl
|
||||||
|
|
||||||
vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz));
|
vec3 worldNormal = cross(dFdy(inWorldPosition.xyz), dFdx(inWorldPosition.xyz));
|
||||||
worldNormal = normalize(worldNormal);
|
worldNormal = normalize(worldNormal);
|
||||||
|
|
||||||
**TODO: Check the normal direction**
|
**TODO: Check the normal direction**
|
||||||
|
|
||||||
Similar code can be implemented in HLSL but you may need to invert the normal due to coordinate system differences between the two APIs. Also, be aware that it may be necessary to use OpenGL ES XXX extension in order to access this derivative functionality on mobile hardware.
|
Similar code can be implemented in HLSL but you may need to invert the normal due to coordinate system differences between the two APIs. Also, be aware that it may be necessary to use OpenGL ES XXX extension in order to access this derivative functionality on mobile hardware.
|
||||||
|
|
||||||
Shadows
|
Shadows
|
||||||
-------
|
-------
|
||||||
To date we have only experimented with shadow maps as a solution to the real time shadowing problem and have found they work very well for both casting and receiving. The approach is essentially the same as for any other geometry and the usual approaches can be used for setting up the projection and for filtering the result. One PolyVox specific tip we can give is that you don't need to take account of materials when rendering into the shadow map as you always draw in black, so if you are splitting you geometry for material blending or for handling a large number of materials then you don't need to do this when rendering shadows. Using separate shadow geometry with all materials combined may decrease your batch count in this case.
|
To date we have only experimented with shadow maps as a solution to the real time shadowing problem and have found they work very well for both casting and receiving. The approach is essentially the same as for any other geometry and the usual approaches can be used for setting up the projection and for filtering the result. One PolyVox specific tip we can give is that you don't need to take account of materials when rendering into the shadow map as you always draw in black, so if you are splitting you geometry for material blending or for handling a large number of materials then you don't need to do this when rendering shadows. Using separate shadow geometry with all materials combined may decrease your batch count in this case.
|
||||||
|
|
||||||
The most widely used alternative to shadow maps is shadow volumes but we have not tested these with PolyVox. We do not expect these will provide a good solution because meshes usually require additional edge information to allow the shadow volume to be extruded from the silhouette and PolyVox does not provide this. Even if this edge information could be calculated, it would be invalidated each time the mesh changed which would make dynamic terrain more difficult.
|
The most widely used alternative to shadow maps is shadow volumes but we have not tested these with PolyVox. We do not expect these will provide a good solution because meshes usually require additional edge information to allow the shadow volume to be extruded from the silhouette and PolyVox does not provide this. Even if this edge information could be calculated, it would be invalidated each time the mesh changed which would make dynamic terrain more difficult.
|
||||||
|
|
||||||
Overall we would recommend you make use of shadow maps for dynamic shadows.
|
Overall we would recommend you make use of shadow maps for dynamic shadows.
|
||||||
|
|
||||||
Ambient Occlusion
|
Ambient Occlusion
|
||||||
=================
|
=================
|
||||||
This is an area in which we want to undertake more research in order to get effective ambient occlusion into PolyVox scenes. In the mean time SSAO has proved to be a popular solution.
|
This is an area in which we want to undertake more research in order to get effective ambient occlusion into PolyVox scenes. In the mean time SSAO has proved to be a popular solution.
|
@ -1,4 +1,4 @@
|
|||||||
=================
|
=================
|
||||||
Modifying Terrain
|
Modifying Terrain
|
||||||
=================
|
=================
|
||||||
This document has yet to be written.
|
This document has yet to be written.
|
@ -1,38 +1,38 @@
|
|||||||
*************
|
*************
|
||||||
Prerequisites
|
Prerequisites
|
||||||
*************
|
*************
|
||||||
The PolyVox library is aimed at experienced games and graphics programmers who wish to incorporate voxel environments into their applications. It is not a drop in solution, but instead provides a set of building blocks which you can use to construct a complete system. Most of the functionality could be considered quite low-level. For example, it provides mesh extractors to generate a surface from volume data but requires the application developer to handle all tasks related to scene management and rendering of such data.
|
The PolyVox library is aimed at experienced games and graphics programmers who wish to incorporate voxel environments into their applications. It is not a drop in solution, but instead provides a set of building blocks which you can use to construct a complete system. Most of the functionality could be considered quite low-level. For example, it provides mesh extractors to generate a surface from volume data but requires the application developer to handle all tasks related to scene management and rendering of such data.
|
||||||
|
|
||||||
As a result you will need a decent amount of graphics programming experience to effectively make use of the library. The purpose of this document is to highlight some of the core areas with which you will need to be familiar. In some cases we also provide links to places where you can find more information about the subject in question.
|
As a result you will need a decent amount of graphics programming experience to effectively make use of the library. The purpose of this document is to highlight some of the core areas with which you will need to be familiar. In some cases we also provide links to places where you can find more information about the subject in question.
|
||||||
|
|
||||||
You should also be aware that voxel terrain is still an open research area and has not yet seen widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you may have to do some research and experimentation yourself when trying to obtain your desired result. Please do let us know if you come up with a trick or technique which you think could benefit other users.
|
You should also be aware that voxel terrain is still an open research area and has not yet seen widespread adoption in games and simulations. There are many questions to which we do not currently know the best answer and so you may have to do some research and experimentation yourself when trying to obtain your desired result. Please do let us know if you come up with a trick or technique which you think could benefit other users.
|
||||||
|
|
||||||
Programming
|
Programming
|
||||||
===========
|
===========
|
||||||
This section describes some of the programming concepts with which you will need to be familiar:
|
This section describes some of the programming concepts with which you will need to be familiar:
|
||||||
|
|
||||||
**C++:** PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. You will need to be familiar with the basic process of building and linking against external libraries as well as setting up your development environment. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach.
|
**C++:** PolyVox is written using the C++ language and we expect this is what the majority of our users will be developing in. You will need to be familiar with the basic process of building and linking against external libraries as well as setting up your development environment. Note that you do have the option of working with other languages via the SWIG bindings but you may not have as much flexibility with this approach.
|
||||||
|
|
||||||
**Templates:** PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You shouldn't need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems.
|
**Templates:** PolyVox also makes heavy use of template programming in order to be both fast and generic, so familiarity with templates will be very useful. You shouldn't need to do much template programming yourself but an understanding of them will help you understand errors and resolve any problems.
|
||||||
|
|
||||||
**Callbacks:** Several of the algorithms in PolyVox can be customised through the use of callbacks. In general there are sensible defaults provided, but for maximum control you may wish to learn how to define you own. In general the principle is similar to the way in which callbacks are used in the STL.
|
**Callbacks:** Several of the algorithms in PolyVox can be customised through the use of callbacks. In general there are sensible defaults provided, but for maximum control you may wish to learn how to define you own. In general the principle is similar to the way in which callbacks are used in the STL.
|
||||||
|
|
||||||
Graphics Concepts
|
Graphics Concepts
|
||||||
=================
|
=================
|
||||||
Several core graphics principles will be useful in understanding and using PolyVox:
|
Several core graphics principles will be useful in understanding and using PolyVox:
|
||||||
|
|
||||||
**Volume representation:** PolyVox revolves around the idea of storing and manipulating volume data and using this as a representation of a 3d world. This is a fairly intuitive extension of traditional heightmap terrain but does require the ability to 'think in 3D'. You will need to understand that data stored in this way can become very large, and understand the idea that paging and compression can be used to combat this.
|
**Volume representation:** PolyVox revolves around the idea of storing and manipulating volume data and using this as a representation of a 3d world. This is a fairly intuitive extension of traditional heightmap terrain but does require the ability to 'think in 3D'. You will need to understand that data stored in this way can become very large, and understand the idea that paging and compression can be used to combat this.
|
||||||
|
|
||||||
**Mesh representation:** Most PolyVox projects will involve using one of the surface extractors, which output their data as index and vertex buffers. Therefore you will need to understand this representation in order to pass the data to your rendering engine or in order to perform further modifications to it. You can find out about more about this here: (ADD LINK)
|
**Mesh representation:** Most PolyVox projects will involve using one of the surface extractors, which output their data as index and vertex buffers. Therefore you will need to understand this representation in order to pass the data to your rendering engine or in order to perform further modifications to it. You can find out about more about this here: (ADD LINK)
|
||||||
|
|
||||||
**Image processing:** For certain advanced application an understanding of image processing methods can be useful. For example the process of blurring an image via a low pass filter can be used to effectively smooth out voxel terrain. There are plans to add more image processing operations to PolyVox particularly with regard to morphological operations which you might want to use to modify your environment.
|
**Image processing:** For certain advanced application an understanding of image processing methods can be useful. For example the process of blurring an image via a low pass filter can be used to effectively smooth out voxel terrain. There are plans to add more image processing operations to PolyVox particularly with regard to morphological operations which you might want to use to modify your environment.
|
||||||
|
|
||||||
Rendering
|
Rendering
|
||||||
=========
|
=========
|
||||||
**Runtime geometry creation:** PolyVox is independent of any particular graphics API which means it outputs its data using API-neutral structures such as index and vertex buffers (as mentioned above). You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology which you are using.
|
**Runtime geometry creation:** PolyVox is independent of any particular graphics API which means it outputs its data using API-neutral structures such as index and vertex buffers (as mentioned above). You will need to write the code which converts these structures into a format which your API or engine can understand. This is not a difficult task but does require some knowledge of the rendering technology which you are using.
|
||||||
|
|
||||||
**Scene management:** PolyVox is only responsible for providing you with the mesh data to be displayed, so you application or engine will need to make sensible decisions about how this data should be organised in terms of a spatial structure (octree, bounding volumes tree, etc). It will also need to provide some approach to visibility determination such as frustum culling or a more advanced approach. If you are integrating PolyVox with an existing rendering engine then you should find that many of these aspects are already handled for you.
|
**Scene management:** PolyVox is only responsible for providing you with the mesh data to be displayed, so you application or engine will need to make sensible decisions about how this data should be organised in terms of a spatial structure (octree, bounding volumes tree, etc). It will also need to provide some approach to visibility determination such as frustum culling or a more advanced approach. If you are integrating PolyVox with an existing rendering engine then you should find that many of these aspects are already handled for you.
|
||||||
|
|
||||||
**Shader programming:** The meshes which are generated by PolyVox are very basic in terms of the vertex data they provide. You get vertex positions, a material identifier, and sometimes vertex normals. It is the responsibility of application programmer to decide how to use this data to create visually interesting renderings. This means you will almost certainly want to make use of shader programs. Of course, in our texturing (LINK) and lighting (LINK) documents you will find many ideas and common solutions, but you will need strong shader programming experience to make effective use of these.
|
**Shader programming:** The meshes which are generated by PolyVox are very basic in terms of the vertex data they provide. You get vertex positions, a material identifier, and sometimes vertex normals. It is the responsibility of application programmer to decide how to use this data to create visually interesting renderings. This means you will almost certainly want to make use of shader programs. Of course, in our texturing (LINK) and lighting (LINK) documents you will find many ideas and common solutions, but you will need strong shader programming experience to make effective use of these.
|
||||||
|
|
||||||
If you don't have much experience with shader programming then there are many free resources available. The Cg Tutorial (LINK) provides a good introduction here (the concepts are applicable to other shader languages) as does the documentation for the main graphics (LINK to OpenGL docs) APIs (Link to D3D docs). there is nothing special about PolyVox meshes so you would be advised to practice development on simple meshes such as spheres and cubes before trying to apply it to the output of the mesh extractors.
|
If you don't have much experience with shader programming then there are many free resources available. The Cg Tutorial (LINK) provides a good introduction here (the concepts are applicable to other shader languages) as does the documentation for the main graphics (LINK to OpenGL docs) APIs (Link to D3D docs). there is nothing special about PolyVox meshes so you would be advised to practice development on simple meshes such as spheres and cubes before trying to apply it to the output of the mesh extractors.
|
@ -1,151 +1,151 @@
|
|||||||
***************
|
***************
|
||||||
Texture Mapping
|
Texture Mapping
|
||||||
***************
|
***************
|
||||||
The PolyVox library is only concerned with operations on volume data (such as extracting a mesh from from a volume) and deliberately avoids the issue of rendering any resulting polygon meshes. This means PolyVox is not tied to any particular graphics API or rendering engine, and makes it much easier to integrate PolyVox with existing technology, because in general a PolyVox mesh can be treated the same as any other mesh. However, the texturing of a PolyVox mesh is usually handled a little differently, and so the purpose of this document is to provide some ideas about where to start with this process.
|
The PolyVox library is only concerned with operations on volume data (such as extracting a mesh from from a volume) and deliberately avoids the issue of rendering any resulting polygon meshes. This means PolyVox is not tied to any particular graphics API or rendering engine, and makes it much easier to integrate PolyVox with existing technology, because in general a PolyVox mesh can be treated the same as any other mesh. However, the texturing of a PolyVox mesh is usually handled a little differently, and so the purpose of this document is to provide some ideas about where to start with this process.
|
||||||
|
|
||||||
This document is aimed at readers in one of two positions:
|
This document is aimed at readers in one of two positions:
|
||||||
|
|
||||||
1. You are trying to texture 'Minecraft-style' terrain with cubic blocks and a number of different materials.
|
1. You are trying to texture 'Minecraft-style' terrain with cubic blocks and a number of different materials.
|
||||||
2. You are trying to texture smooth terrain produced by the Marching Cubes (or similar) algorithm.
|
2. You are trying to texture smooth terrain produced by the Marching Cubes (or similar) algorithm.
|
||||||
|
|
||||||
These are certainly not the limit of PolyVox, and you can choose much more advanced texturing approaches if you wish. For example, in the past we have texture mapped a voxel Earth from a cube map and used an animated *procedural* texture (based on Perlin noise) for the magma at the center of the Earth. However, if you are aiming for such advanced techniques then we assume you understand the basics in this document and have enough knowledge to expand the ideas yourself. But do feel free to drop by and ask questions on our forum.
|
These are certainly not the limit of PolyVox, and you can choose much more advanced texturing approaches if you wish. For example, in the past we have texture mapped a voxel Earth from a cube map and used an animated *procedural* texture (based on Perlin noise) for the magma at the center of the Earth. However, if you are aiming for such advanced techniques then we assume you understand the basics in this document and have enough knowledge to expand the ideas yourself. But do feel free to drop by and ask questions on our forum.
|
||||||
|
|
||||||
Traditionally meshes are textured by providing a pair of UV texture coordinates for each vertex, and these UV coordinates determine which parts of a texture maps to each vertex. The process of texturing PolyVox meshes is more complex for a couple of reasons:
|
Traditionally meshes are textured by providing a pair of UV texture coordinates for each vertex, and these UV coordinates determine which parts of a texture maps to each vertex. The process of texturing PolyVox meshes is more complex for a couple of reasons:
|
||||||
|
|
||||||
1. PolyVox does not provide UV coordinates for each vertex.
|
1. PolyVox does not provide UV coordinates for each vertex.
|
||||||
2. Voxel terrain (particularly Minecraft-style) often involves many more textures than the GPU can read at a time.
|
2. Voxel terrain (particularly Minecraft-style) often involves many more textures than the GPU can read at a time.
|
||||||
|
|
||||||
By reading this document you should learn how to work around the above problems, though you will almost certainly need to follow provided links and do some further reading as we have only summarised the key ideas here.
|
By reading this document you should learn how to work around the above problems, though you will almost certainly need to follow provided links and do some further reading as we have only summarised the key ideas here.
|
||||||
|
|
||||||
Mapping textures to mesh geometry
|
Mapping textures to mesh geometry
|
||||||
=================================
|
=================================
|
||||||
The lack of UV coordinates means some lateral thinking is required in order to apply texture maps to meshes. But before we get to that, we will first try to explain the rational behind PolyVox not providing UV coordinates in the first place. This rational is different for the smooth voxel meshes vs the cubic voxel meshes.
|
The lack of UV coordinates means some lateral thinking is required in order to apply texture maps to meshes. But before we get to that, we will first try to explain the rational behind PolyVox not providing UV coordinates in the first place. This rational is different for the smooth voxel meshes vs the cubic voxel meshes.
|
||||||
|
|
||||||
Rational
|
Rational
|
||||||
--------
|
--------
|
||||||
The problem with texturing smooth voxel meshes is that the geometry can get very complex and it is not clear how the mapping between mesh geometry and a texture should be performed. In a traditional heightmap-based terrain this relationship is obvious as the texture map and heightmap simply line up directly. But for more complex shapes some form of 'UV unwrapping' is usually performed to define this relationship. This is usually done by an artist with the help of a 3D modeling package and so is a semi-automatic process, but it is time consuming and driven by the artists idea of what looks right for their particular scene. Even though fully automatic UV unwrapping is possible it is usually prohibitively slow.
|
The problem with texturing smooth voxel meshes is that the geometry can get very complex and it is not clear how the mapping between mesh geometry and a texture should be performed. In a traditional heightmap-based terrain this relationship is obvious as the texture map and heightmap simply line up directly. But for more complex shapes some form of 'UV unwrapping' is usually performed to define this relationship. This is usually done by an artist with the help of a 3D modeling package and so is a semi-automatic process, but it is time consuming and driven by the artists idea of what looks right for their particular scene. Even though fully automatic UV unwrapping is possible it is usually prohibitively slow.
|
||||||
|
|
||||||
Even if such an unwrapping were possible in a reasonable time frame, the next problem is that it would be invalidated as soon as the mesh changed. Enabling dynamic manipulation is one of the appealing factors of voxel terrain, and if this use case were discarded then the user may as well just model their terrain in an existing 3D modelling package and texture there. For these reasons we do not attempt to generate UV coordinates for smooth voxel meshes.
|
Even if such an unwrapping were possible in a reasonable time frame, the next problem is that it would be invalidated as soon as the mesh changed. Enabling dynamic manipulation is one of the appealing factors of voxel terrain, and if this use case were discarded then the user may as well just model their terrain in an existing 3D modelling package and texture there. For these reasons we do not attempt to generate UV coordinates for smooth voxel meshes.
|
||||||
|
|
||||||
The rational in the cubic case is almost the opposite. For Minecraft style terrain you want to simply line up an instance of a texture with each face of a cube, and generating the texture coordinates for this is very easy. In fact it's so easy that there's no point in doing it - the logic can instead be implemented in a shader which in turn allows the amount of data in each vertex to be reduced.
|
The rational in the cubic case is almost the opposite. For Minecraft style terrain you want to simply line up an instance of a texture with each face of a cube, and generating the texture coordinates for this is very easy. In fact it's so easy that there's no point in doing it - the logic can instead be implemented in a shader which in turn allows the amount of data in each vertex to be reduced.
|
||||||
|
|
||||||
Triplanar Texturing
|
Triplanar Texturing
|
||||||
-------------------
|
-------------------
|
||||||
The most common approach to texture mapping smooth voxel terrain is to use *triplanar texturing*. The basic idea is to project a texture along all three main axes and blend between the three texture samples according to the surface normal. As an example, suppose that we wish to write a fragment shader to apply a single texture to our terrain, and assume that we have access to both the world space position of the fragment and also its normalised surface normal. Also, note that your textures should be set to wrap because the world space position will quickly go outside the bounds of 0.0-1.0. The world space position will need to have been passed through from earlier in the pipeline while the normal can be computed using one of the approaches in the lighting (link) document. The shader code would then look something like this [footnote: code is untested as is simplified compared to real world code. hopefully it compiles, but if not it should still give you an idea of how it works]:
|
The most common approach to texture mapping smooth voxel terrain is to use *triplanar texturing*. The basic idea is to project a texture along all three main axes and blend between the three texture samples according to the surface normal. As an example, suppose that we wish to write a fragment shader to apply a single texture to our terrain, and assume that we have access to both the world space position of the fragment and also its normalised surface normal. Also, note that your textures should be set to wrap because the world space position will quickly go outside the bounds of 0.0-1.0. The world space position will need to have been passed through from earlier in the pipeline while the normal can be computed using one of the approaches in the lighting (link) document. The shader code would then look something like this [footnote: code is untested as is simplified compared to real world code. hopefully it compiles, but if not it should still give you an idea of how it works]:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. sourcecode:: glsl
|
||||||
|
|
||||||
// Take the three texture samples
|
// Take the three texture samples
|
||||||
vec4 sampleX = texture2d(inputTexture, worldSpacePos.yz); // Project along x axis
|
vec4 sampleX = texture2d(inputTexture, worldSpacePos.yz); // Project along x axis
|
||||||
vec4 sampleY = texture2d(inputTexture, worldSpacePos.xz); // Project along y axis
|
vec4 sampleY = texture2d(inputTexture, worldSpacePos.xz); // Project along y axis
|
||||||
vec4 sampleZ = texture2d(inputTexture, worldSpacePos.xy); // Project along z axis
|
vec4 sampleZ = texture2d(inputTexture, worldSpacePos.xy); // Project along z axis
|
||||||
|
|
||||||
// Blend the samples according to the normal
|
// Blend the samples according to the normal
|
||||||
vec4 blendedColour = sampleX * normal.x + sampleY * normal.y + sampleZ * normal.z;
|
vec4 blendedColour = sampleX * normal.x + sampleY * normal.y + sampleZ * normal.z;
|
||||||
|
|
||||||
Note that this approach will lead to the texture repeating once every world unit, and so in practice you may wish to scale the world space positions to make the texture appear the desired size. Also this technique can be extended to work with normal mapping though we won't go into the details here.
|
Note that this approach will lead to the texture repeating once every world unit, and so in practice you may wish to scale the world space positions to make the texture appear the desired size. Also this technique can be extended to work with normal mapping though we won't go into the details here.
|
||||||
|
|
||||||
This idea of triplanar texturing can be applied to the cubic meshes as well, and in some ways it can be considered to be even simpler. With cubic meshes the normal always points exactly along one of the main axes, and so it is not necessary to sample the texture three times nor to blend the results. Instead you can use conditional branching in the fragment shader to determine which pair of values out of {x,y,z} should be used as the texture coordinates. Something like:
|
This idea of triplanar texturing can be applied to the cubic meshes as well, and in some ways it can be considered to be even simpler. With cubic meshes the normal always points exactly along one of the main axes, and so it is not necessary to sample the texture three times nor to blend the results. Instead you can use conditional branching in the fragment shader to determine which pair of values out of {x,y,z} should be used as the texture coordinates. Something like:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. sourcecode:: glsl
|
||||||
|
|
||||||
vec4 sample = vec4(0, 0, 0, 0); // We'll fill this in below
|
vec4 sample = vec4(0, 0, 0, 0); // We'll fill this in below
|
||||||
// Assume the normal is normalised.
|
// Assume the normal is normalised.
|
||||||
if(normal.x > 0.9) // x must be one while y and z are zero
|
if(normal.x > 0.9) // x must be one while y and z are zero
|
||||||
{
|
{
|
||||||
//Project onto yz plane
|
//Project onto yz plane
|
||||||
sample = texture2D(inputTexture, worldSpacePos.yz);
|
sample = texture2D(inputTexture, worldSpacePos.yz);
|
||||||
}
|
}
|
||||||
// Now similar logic for the other two axes.
|
// Now similar logic for the other two axes.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
|
|
||||||
You might also choose to sample a different texture for each of the axes, in order to apply a different texture to each face of your cube. If so, you probably want to pack your different face textures together using an approach similar to those described later in this document for multiple material textures. Another (untested) idea would be to use the normal to select a face on a 1x1x1 cubemap, and have the cubemap face contain an index value for addressing the correct face texture. This could bypass the conditional logic above.
|
You might also choose to sample a different texture for each of the axes, in order to apply a different texture to each face of your cube. If so, you probably want to pack your different face textures together using an approach similar to those described later in this document for multiple material textures. Another (untested) idea would be to use the normal to select a face on a 1x1x1 cubemap, and have the cubemap face contain an index value for addressing the correct face texture. This could bypass the conditional logic above.
|
||||||
|
|
||||||
Using the material identifier
|
Using the material identifier
|
||||||
-----------------------------
|
-----------------------------
|
||||||
So far we have assumed that only a single material is being used for the entire voxel world, but this is seldom the case. It is common to associate a particular material with each voxel so that it can represent rock, wood, sand or any other type of material as required. The usual approach is to store a simple integer identifier with each voxel, and then map this identifier to material properties within your application.
|
So far we have assumed that only a single material is being used for the entire voxel world, but this is seldom the case. It is common to associate a particular material with each voxel so that it can represent rock, wood, sand or any other type of material as required. The usual approach is to store a simple integer identifier with each voxel, and then map this identifier to material properties within your application.
|
||||||
|
|
||||||
Both the CubicSurfaceExtractor and the MarchingCubesSurfacExtractor understand the concept of a material being associated with a voxel, and they will take this into account when generating a mesh. Specifically, they will both copy the material identifier into the vertex data of the output mesh, so you can pass it through to your shaders and use it to affect the way the surface is rendered.
|
Both the CubicSurfaceExtractor and the MarchingCubesSurfacExtractor understand the concept of a material being associated with a voxel, and they will take this into account when generating a mesh. Specifically, they will both copy the material identifier into the vertex data of the output mesh, so you can pass it through to your shaders and use it to affect the way the surface is rendered.
|
||||||
|
|
||||||
The following code snippet assumes that you have passed the material identifier to your shaders and that you can access it in the fragment shader. It then chooses which colour to draw the polygon based on this identifier:
|
The following code snippet assumes that you have passed the material identifier to your shaders and that you can access it in the fragment shader. It then chooses which colour to draw the polygon based on this identifier:
|
||||||
|
|
||||||
.. sourcecode:: glsl
|
.. sourcecode:: glsl
|
||||||
|
|
||||||
vec4 fragmentColour = vec4(1, 1, 1, 1); // Default value
|
vec4 fragmentColour = vec4(1, 1, 1, 1); // Default value
|
||||||
if(materialId < 0.5) //Avoid '==' when working with floats.
|
if(materialId < 0.5) //Avoid '==' when working with floats.
|
||||||
{
|
{
|
||||||
fragmentColour = vec4(1, 0, 0, 1) // Draw material 0 as red.
|
fragmentColour = vec4(1, 0, 0, 1) // Draw material 0 as red.
|
||||||
}
|
}
|
||||||
else if(materialId < 1.5) //Avoid '==' when working with floats.
|
else if(materialId < 1.5) //Avoid '==' when working with floats.
|
||||||
{
|
{
|
||||||
fragmentColour = vec4(0, 1, 0, 1) // Draw material 1 as green.
|
fragmentColour = vec4(0, 1, 0, 1) // Draw material 1 as green.
|
||||||
}
|
}
|
||||||
else if(materialId < 2.5) //Avoid '==' when working with floats.
|
else if(materialId < 2.5) //Avoid '==' when working with floats.
|
||||||
{
|
{
|
||||||
fragmentColour = vec4(0, 0, 1, 1) // Draw material 2 as blue.
|
fragmentColour = vec4(0, 0, 1, 1) // Draw material 2 as blue.
|
||||||
}
|
}
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
|
|
||||||
This is a very simple example, and such use of conditional branching within the shader may not be the best approach as it incurs some performance overhead and becomes unwieldy with a large number of materials. Other approaches include encoding a colour directly into the material identifier, or using the identifier as an index into a texture atlas or array.
|
This is a very simple example, and such use of conditional branching within the shader may not be the best approach as it incurs some performance overhead and becomes unwieldy with a large number of materials. Other approaches include encoding a colour directly into the material identifier, or using the identifier as an index into a texture atlas or array.
|
||||||
|
|
||||||
Note that PolyVox currently stores that material identifier for the vertex as a float, but this will probably change in the future to use the same type as is stored in the volume. It will then be up to you which type you pass to the GPU (older GPUs may not support integer values) but if you do use floats then watch out for precision issues and avoid equality comparisons.
|
Note that PolyVox currently stores that material identifier for the vertex as a float, but this will probably change in the future to use the same type as is stored in the volume. It will then be up to you which type you pass to the GPU (older GPUs may not support integer values) but if you do use floats then watch out for precision issues and avoid equality comparisons.
|
||||||
|
|
||||||
Blending between materials
|
Blending between materials
|
||||||
--------------------------
|
--------------------------
|
||||||
An additional complication when working with smooth voxel terrain is that it is usually desirable to blend smoothly between adjacent voxels with different materials. This situation does not occur with cubic meshes because the texture is considered to be per-face instead of per-vertex, and PolyVox enforces this by ensuring that all the vertices of a given face have the same material.
|
An additional complication when working with smooth voxel terrain is that it is usually desirable to blend smoothly between adjacent voxels with different materials. This situation does not occur with cubic meshes because the texture is considered to be per-face instead of per-vertex, and PolyVox enforces this by ensuring that all the vertices of a given face have the same material.
|
||||||
|
|
||||||
With a smooth mesh it is possible for each of the three vertices of any given triangle to have different material identifiers. If this is not explicitly handled then the graphics hardware will interpolate these material values across the face of the triangle. Fundamentally, the concept of interpolating between material identifiers does not make sense, because if we have (for example) 1='grass', 2='rock' and 3='sand' then it does not make sense to say rock is the average of grass and sand.
|
With a smooth mesh it is possible for each of the three vertices of any given triangle to have different material identifiers. If this is not explicitly handled then the graphics hardware will interpolate these material values across the face of the triangle. Fundamentally, the concept of interpolating between material identifiers does not make sense, because if we have (for example) 1='grass', 2='rock' and 3='sand' then it does not make sense to say rock is the average of grass and sand.
|
||||||
|
|
||||||
Correctly handling of this is a surprising difficult problem. For now, the best approach is described in our article 'Volumetric representation of virtual terrain' which appeared in Game Engine Gems Volume 1 and which is freely available through the Google Books preview here: http://books.google.com/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game%20engine%20gems&pg=PA39#v=onepage&q&f=false
|
Correctly handling of this is a surprising difficult problem. For now, the best approach is described in our article 'Volumetric representation of virtual terrain' which appeared in Game Engine Gems Volume 1 and which is freely available through the Google Books preview here: http://books.google.com/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game%20engine%20gems&pg=PA39#v=onepage&q&f=false
|
||||||
|
|
||||||
As off October 2012 we are actively researching alternative solutions to this problem though it will be some time before the results become available.
|
As off October 2012 we are actively researching alternative solutions to this problem though it will be some time before the results become available.
|
||||||
|
|
||||||
Actual implementation of these material blending approaches is left as an exercise to the reader, though it is possible that in the future we will add some utility functions to PolyVox to assist with tasks such as splitting the mesh or adding the required extra vertex attributes. Our test implementations have performed the mesh processing on the CPU before the mesh is uploaded to the graphics card, but it does seem like there is a lot of potential for implementing these approaches in the geometry shader.
|
Actual implementation of these material blending approaches is left as an exercise to the reader, though it is possible that in the future we will add some utility functions to PolyVox to assist with tasks such as splitting the mesh or adding the required extra vertex attributes. Our test implementations have performed the mesh processing on the CPU before the mesh is uploaded to the graphics card, but it does seem like there is a lot of potential for implementing these approaches in the geometry shader.
|
||||||
|
|
||||||
Storage of textures
|
Storage of textures
|
||||||
===================
|
===================
|
||||||
The other major challenge in texturing voxel based geometry is handling the large number of textures which such environments often require. As an example, a game like Minecraft has hundreds of different material types each with their own texture. The traditional approach to mesh texturing is to bind textures to *texture units* on the GPU before rendering a batch, but even modern GPUs only allow between 16-64 textures to be bound at a time. In this section we discuss various solutions to overcoming this limitation.
|
The other major challenge in texturing voxel based geometry is handling the large number of textures which such environments often require. As an example, a game like Minecraft has hundreds of different material types each with their own texture. The traditional approach to mesh texturing is to bind textures to *texture units* on the GPU before rendering a batch, but even modern GPUs only allow between 16-64 textures to be bound at a time. In this section we discuss various solutions to overcoming this limitation.
|
||||||
|
|
||||||
There are various trade offs involved, but if you are targeting hardware with support for *texture arrays* (available from OpenGL 3 and Direct3D 10 on-wards) then we can save you some time and tell you that they are almost certainly the best solution. Otherwise you have to understand the various pros and cons of the other approaches described below.
|
There are various trade offs involved, but if you are targeting hardware with support for *texture arrays* (available from OpenGL 3 and Direct3D 10 on-wards) then we can save you some time and tell you that they are almost certainly the best solution. Otherwise you have to understand the various pros and cons of the other approaches described below.
|
||||||
|
|
||||||
Separate texture units
|
Separate texture units
|
||||||
----------------------
|
----------------------
|
||||||
Before we make things unnecessarily complicated, you should consider whether you do actually need the hundreds of textures discussed earlier. If you actually only need a few textures then the simplest solution may indeed be to pass them in via different texture units. You can then select the desired textures using a series of if statements, or a switch statement if the material identifiers are integer values. There is probably some performance overhead here, but you may find it is acceptable for a small number of textures. Keep in mind that you may need to reserve some texture units for additional texture data such as normal maps or shadow maps.
|
Before we make things unnecessarily complicated, you should consider whether you do actually need the hundreds of textures discussed earlier. If you actually only need a few textures then the simplest solution may indeed be to pass them in via different texture units. You can then select the desired textures using a series of if statements, or a switch statement if the material identifiers are integer values. There is probably some performance overhead here, but you may find it is acceptable for a small number of textures. Keep in mind that you may need to reserve some texture units for additional texture data such as normal maps or shadow maps.
|
||||||
|
|
||||||
Splitting the mesh
|
Splitting the mesh
|
||||||
------------------
|
------------------
|
||||||
If your required number of textures do indeed exceed the available number of textures units then one option is to break the mesh down into a number of pieces. Let's say you have a mesh which contains one hundred different materials. As an extreme solution you could break it down into one hundred separate meshes, and for each mesh you could then bind the required single texture before drawing the geometry. Obviously this will dramatically increase the batch count of your scene and so is not recommended.
|
If your required number of textures do indeed exceed the available number of textures units then one option is to break the mesh down into a number of pieces. Let's say you have a mesh which contains one hundred different materials. As an extreme solution you could break it down into one hundred separate meshes, and for each mesh you could then bind the required single texture before drawing the geometry. Obviously this will dramatically increase the batch count of your scene and so is not recommended.
|
||||||
|
|
||||||
A more practical approach would be to break the mesh into a smaller number of pieces such that each mesh uses several textures but less than the maximum number of texture units. For example, our mesh with one hundred materials could be split into ten meshes, the first of which contains those triangles using materials 0-9, the seconds contains those triangles using materials 10-19, and so forth. There is a trade off here between the number of batches and the number of textures units used per batch.
|
A more practical approach would be to break the mesh into a smaller number of pieces such that each mesh uses several textures but less than the maximum number of texture units. For example, our mesh with one hundred materials could be split into ten meshes, the first of which contains those triangles using materials 0-9, the seconds contains those triangles using materials 10-19, and so forth. There is a trade off here between the number of batches and the number of textures units used per batch.
|
||||||
|
|
||||||
Furthermore, you could realise that although your terrain may use hundreds of different textures, any given region is likely to use only a small fraction of those. We have yet to experiment with this, but it seems if you region uses only (for example) materials 12, 47, and 231, then you could conceptually map these materials to the first three textures slots. This means that for each region you draw the mapping between material IDs and texture units would be different. This may require some complex logic in the application but could allow you to do much more with only a few texture units. We will investigate this further in the future.
|
Furthermore, you could realise that although your terrain may use hundreds of different textures, any given region is likely to use only a small fraction of those. We have yet to experiment with this, but it seems if you region uses only (for example) materials 12, 47, and 231, then you could conceptually map these materials to the first three textures slots. This means that for each region you draw the mapping between material IDs and texture units would be different. This may require some complex logic in the application but could allow you to do much more with only a few texture units. We will investigate this further in the future.
|
||||||
|
|
||||||
Texture atlases
|
Texture atlases
|
||||||
---------------
|
---------------
|
||||||
Probably the most widely used method is to pack a number of textures together into a single large texture, and to our knowledge this is the approach used by Minecraft. For example, if each of your textures are 256x256 texels, and if the maximum texture size supported by your target hardware is 4096x4096 texels, then you can pack 16 x 16 = 256 small textures into the larger one. If this isn't enough (or if your input textures are larger than 256x256) then you can also combine this approach with multiple texture units or with the mesh splitting described previously.
|
Probably the most widely used method is to pack a number of textures together into a single large texture, and to our knowledge this is the approach used by Minecraft. For example, if each of your textures are 256x256 texels, and if the maximum texture size supported by your target hardware is 4096x4096 texels, then you can pack 16 x 16 = 256 small textures into the larger one. If this isn't enough (or if your input textures are larger than 256x256) then you can also combine this approach with multiple texture units or with the mesh splitting described previously.
|
||||||
|
|
||||||
However, there are a number of problems with packing textures like this. Most obviously, it limits the size of your textures as they now have to be significantly smaller then the maximum texture size. Whether this is a problem will really depend on your application.
|
However, there are a number of problems with packing textures like this. Most obviously, it limits the size of your textures as they now have to be significantly smaller then the maximum texture size. Whether this is a problem will really depend on your application.
|
||||||
|
|
||||||
Next, it means you have to adjust your UV coordinates to correctly address a given texture inside the atlas. UV coordinates for a single texture would normally vary between 0.0 and 1.0 in both dimensions, but when packed into a texture atlas each texture uses only a small part of this range. You will need to apply offsets and scaling factors to your UV coordinates to address your texture correctly.
|
Next, it means you have to adjust your UV coordinates to correctly address a given texture inside the atlas. UV coordinates for a single texture would normally vary between 0.0 and 1.0 in both dimensions, but when packed into a texture atlas each texture uses only a small part of this range. You will need to apply offsets and scaling factors to your UV coordinates to address your texture correctly.
|
||||||
|
|
||||||
However, the biggest problem with texture atlases is that they causes problems with texture filtering and with mipmaps. The filtering problem occurs because graphics hardware usually samples the surrounding texels and performs linear interpolation to compute the colour of a given sample point, but when multiple textures are packed together these surrounding texels can actually come from a neighbouring packed texture rather than wrapping round to sample on the other side of the same packed texture. The mipmap problem occurs because for the highest mipmap levels (such as 1x1 or 2x2) multiple textures are being are being averaged together.
|
However, the biggest problem with texture atlases is that they causes problems with texture filtering and with mipmaps. The filtering problem occurs because graphics hardware usually samples the surrounding texels and performs linear interpolation to compute the colour of a given sample point, but when multiple textures are packed together these surrounding texels can actually come from a neighbouring packed texture rather than wrapping round to sample on the other side of the same packed texture. The mipmap problem occurs because for the highest mipmap levels (such as 1x1 or 2x2) multiple textures are being are being averaged together.
|
||||||
|
|
||||||
It is possible to combat these problems but the solutions are non-trivial. You will want to limit the number of miplevels which you use, and probably provide custom shader code to handle the wrapping of texture coordinates, the sampling of MIP maps, and the calculation of interpolated values. You can also try adding a border around all your packed textures, perhaps by duplicating each texture and offsetting by half its size. Even so, it's not clear to us at this point whether the the various artifacts can be completely removed. Minecraft handles it by completely disabling texture filtering and using the resulting pixelated look as part of its aesthetic.
|
It is possible to combat these problems but the solutions are non-trivial. You will want to limit the number of miplevels which you use, and probably provide custom shader code to handle the wrapping of texture coordinates, the sampling of MIP maps, and the calculation of interpolated values. You can also try adding a border around all your packed textures, perhaps by duplicating each texture and offsetting by half its size. Even so, it's not clear to us at this point whether the the various artifacts can be completely removed. Minecraft handles it by completely disabling texture filtering and using the resulting pixelated look as part of its aesthetic.
|
||||||
|
|
||||||
3D texture slices
|
3D texture slices
|
||||||
-----------------
|
-----------------
|
||||||
The idea here is similar to the texture atlas approach, but rather than packing texture side-by-side in an atlas they are instead packed as slices in a 3D texture. We haven't actually tested this but in theory it may have a couple of benefits. Firstly, it simplifies the addressing of the texture as there is no need to offset/scale the UV coordinates, and the W coordinate (the slice index) can be more easily computed from the material identifier. Secondly, a single volume texture will usually be able to hold more texels than a single 2D texture (for example, 512x512x512 is bigger than 4096x4096). Lastly, it should simplify the filtering problem as packed textures are no longer tiled and so should wrap correctly.
|
The idea here is similar to the texture atlas approach, but rather than packing texture side-by-side in an atlas they are instead packed as slices in a 3D texture. We haven't actually tested this but in theory it may have a couple of benefits. Firstly, it simplifies the addressing of the texture as there is no need to offset/scale the UV coordinates, and the W coordinate (the slice index) can be more easily computed from the material identifier. Secondly, a single volume texture will usually be able to hold more texels than a single 2D texture (for example, 512x512x512 is bigger than 4096x4096). Lastly, it should simplify the filtering problem as packed textures are no longer tiled and so should wrap correctly.
|
||||||
|
|
||||||
However, MIP mapping will probably be more complex than the texture atlas case because even the first MIP level will involve combining adjacent slices. Volume textures are also not so widely supported and may be particularly problematic on mobile hardware.
|
However, MIP mapping will probably be more complex than the texture atlas case because even the first MIP level will involve combining adjacent slices. Volume textures are also not so widely supported and may be particularly problematic on mobile hardware.
|
||||||
|
|
||||||
Texture arrays
|
Texture arrays
|
||||||
--------------
|
--------------
|
||||||
These provide the perfect solution to the problem of handling a large number of textures... at least if they are supported by your hardware. They were introduced with OpenGL 3 and Direct3D 10 but older versions of OpenGL may still be able to access the functionality via extensions. They allow you to bind an array of textures to the shader, and the advantage compared to a texture atlas is that the hardware understands that the textures are separate and so avoids the filtering and mipmapping issues. Beyond the hardware requirements, the only real limitation is that all the textures must be the same size.
|
These provide the perfect solution to the problem of handling a large number of textures... at least if they are supported by your hardware. They were introduced with OpenGL 3 and Direct3D 10 but older versions of OpenGL may still be able to access the functionality via extensions. They allow you to bind an array of textures to the shader, and the advantage compared to a texture atlas is that the hardware understands that the textures are separate and so avoids the filtering and mipmapping issues. Beyond the hardware requirements, the only real limitation is that all the textures must be the same size.
|
||||||
|
|
||||||
Bindless rendering
|
Bindless rendering
|
||||||
------------------
|
------------------
|
||||||
We don't have much to say about this option as it needs significant research, but bindless rendering is one of the new OpenGL extensions to come out of Nvidia. The idea is that it removes the abstraction of needing to 'bind' a texture to a particular texture unit, and instead allows more direct access to the texture data on the GPU. This means you can have access to a much larger number of textures from your shader. Sounds useful, but we've yet to investigate it.
|
We don't have much to say about this option as it needs significant research, but bindless rendering is one of the new OpenGL extensions to come out of Nvidia. The idea is that it removes the abstraction of needing to 'bind' a texture to a particular texture unit, and instead allows more direct access to the texture data on the GPU. This means you can have access to a much larger number of textures from your shader. Sounds useful, but we've yet to investigate it.
|
@ -1,69 +1,69 @@
|
|||||||
*********
|
*********
|
||||||
Threading
|
Threading
|
||||||
*********
|
*********
|
||||||
Modern computing hardware typically contains a large number of processors, and so users of PolyVox often want to know how they can best make use of these from their applications.
|
Modern computing hardware typically contains a large number of processors, and so users of PolyVox often want to know how they can best make use of these from their applications.
|
||||||
|
|
||||||
PolyVox does not make any guarantees about thread-safety, and does not contain any threading primitives to protect access to data structures. You can still make use of PolyVox from multiple threads, but you will have to take responsibility for enforcing thread safety yourself (e.g. by providing thread safe wrappers around the volume classes). If you do want to use PolyVox is a multi-threaded context then this document provides some tips and tricks that you might find useful.
|
PolyVox does not make any guarantees about thread-safety, and does not contain any threading primitives to protect access to data structures. You can still make use of PolyVox from multiple threads, but you will have to take responsibility for enforcing thread safety yourself (e.g. by providing thread safe wrappers around the volume classes). If you do want to use PolyVox is a multi-threaded context then this document provides some tips and tricks that you might find useful.
|
||||||
|
|
||||||
However, be aware that we do not have a lot of expertise in threading, and this is part of the reason why it is not explicitly addressed within PolyVox. If you do have more experience and believe any of this information to be misleading then please do post on the forums to discuss it.
|
However, be aware that we do not have a lot of expertise in threading, and this is part of the reason why it is not explicitly addressed within PolyVox. If you do have more experience and believe any of this information to be misleading then please do post on the forums to discuss it.
|
||||||
|
|
||||||
Volumes
|
Volumes
|
||||||
=======
|
=======
|
||||||
Volumes are a core aspect of PolyVox, and so a natural question is whether it is safe to simultaneously access a given volume from multiple threads. The answer to this is actually fairly complex and is also dependent on the type of volume which is being used.
|
Volumes are a core aspect of PolyVox, and so a natural question is whether it is safe to simultaneously access a given volume from multiple threads. The answer to this is actually fairly complex and is also dependent on the type of volume which is being used.
|
||||||
|
|
||||||
RawVolume
|
RawVolume
|
||||||
---------
|
---------
|
||||||
The RawVolume has a very simple internal structure in which the data is stored as a single array which is never moved or resized. Because of this property it is indeed safe to perform multiple simultaneous *reads* of the data from different threads. However, it is generally not safe to perform simultaneous writes from different threads, or even to write from only one thread while other threads are reading.
|
The RawVolume has a very simple internal structure in which the data is stored as a single array which is never moved or resized. Because of this property it is indeed safe to perform multiple simultaneous *reads* of the data from different threads. However, it is generally not safe to perform simultaneous writes from different threads, or even to write from only one thread while other threads are reading.
|
||||||
|
|
||||||
The reason why simultaneous writes can be problematic should be fairly obvious - if two different threads try to write to the same voxel then the result will depend on which thread writes first. But why can't we write from one thread and read from another one? The problem here is that the the CPU may implement some kind of caching mechanism and/or choose to store data in registers. If a write operation occurs before a read, then the read *may* still obtain the old value because the cache has not been updated yet. There may even be a cache for each thread (particularly if running on multiple processors).
|
The reason why simultaneous writes can be problematic should be fairly obvious - if two different threads try to write to the same voxel then the result will depend on which thread writes first. But why can't we write from one thread and read from another one? The problem here is that the the CPU may implement some kind of caching mechanism and/or choose to store data in registers. If a write operation occurs before a read, then the read *may* still obtain the old value because the cache has not been updated yet. There may even be a cache for each thread (particularly if running on multiple processors).
|
||||||
|
|
||||||
If we assume for a moment that each voxel is a simple integer, then the rules for accessing a single voxel from multiple threads are the same as the rules for accessing integers from multiple threads. There is some useful information about this available on the web, including a discussion on StackOverflow: http://stackoverflow.com/questions/4588915/can-an-integer-be-shared-between-threads-safely
|
If we assume for a moment that each voxel is a simple integer, then the rules for accessing a single voxel from multiple threads are the same as the rules for accessing integers from multiple threads. There is some useful information about this available on the web, including a discussion on StackOverflow: http://stackoverflow.com/questions/4588915/can-an-integer-be-shared-between-threads-safely
|
||||||
|
|
||||||
If nothing else, this serves to illustrate that multi-threaded access even to something as simple as an integer can be surprisingly complex and architecture dependant.
|
If nothing else, this serves to illustrate that multi-threaded access even to something as simple as an integer can be surprisingly complex and architecture dependant.
|
||||||
|
|
||||||
However, all this has been in the context of accessing a *single* voxel from multiple threads... what if we carefully design our algorithm such that different threads access different parts of the volume which never overlap? Unfortunately I don't believe this is a solution either. Caching mechanisms seldom operate on individual elements but instead tend to cache larger chunks of data on the grounds that data accesses are usually localised. So it's quite possible that accessing a given voxel will cause another voxel to be cached.
|
However, all this has been in the context of accessing a *single* voxel from multiple threads... what if we carefully design our algorithm such that different threads access different parts of the volume which never overlap? Unfortunately I don't believe this is a solution either. Caching mechanisms seldom operate on individual elements but instead tend to cache larger chunks of data on the grounds that data accesses are usually localised. So it's quite possible that accessing a given voxel will cause another voxel to be cached.
|
||||||
|
|
||||||
C++ does provide the 'volatile' keyword which can be used to ensure a variable is updated immediately (rather than being cached) but this is still not sufficient for thread safe code. It also has performance implications which we would like to avoid. More information about volatile and multitheaded programming can be found here: http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/
|
C++ does provide the 'volatile' keyword which can be used to ensure a variable is updated immediately (rather than being cached) but this is still not sufficient for thread safe code. It also has performance implications which we would like to avoid. More information about volatile and multitheaded programming can be found here: http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/
|
||||||
|
|
||||||
Lastly, note that PolyVox volumes are templatised which means the voxel type might be something other than a simple int. However we don't think this actually makes a difference given that so few guarantees are made anyway, and it should still be safe to perform multiple concurrent reads for more complex types.
|
Lastly, note that PolyVox volumes are templatised which means the voxel type might be something other than a simple int. However we don't think this actually makes a difference given that so few guarantees are made anyway, and it should still be safe to perform multiple concurrent reads for more complex types.
|
||||||
|
|
||||||
PagedVolume
|
PagedVolume
|
||||||
-----------
|
-----------
|
||||||
NOTE: The info below is based on LargeVolume, which PagedVolume has replaced. It is likely that the same limitations apply but this has not been well tested. We do intend to improve the thread safty of PagedVolume in the future.
|
NOTE: The info below is based on LargeVolume, which PagedVolume has replaced. It is likely that the same limitations apply but this has not been well tested. We do intend to improve the thread safty of PagedVolume in the future.
|
||||||
|
|
||||||
The LargeVolume provides even less thread safety than the RawVolume, in that even concurrent read operations can cause problems. The reason for this is the more complex memory management which is performed behind the scenes, and which allows pieces of volume data to be moved around and deleted. For example, a read of a single voxel may mean that the block of data associated with that voxel has to be paged in to memory, which in turn may mean that another block of data has to be paged out of memory. If second thread was halfway through reading a voxel in this second block of data then a problem will occur.
|
The LargeVolume provides even less thread safety than the RawVolume, in that even concurrent read operations can cause problems. The reason for this is the more complex memory management which is performed behind the scenes, and which allows pieces of volume data to be moved around and deleted. For example, a read of a single voxel may mean that the block of data associated with that voxel has to be paged in to memory, which in turn may mean that another block of data has to be paged out of memory. If second thread was halfway through reading a voxel in this second block of data then a problem will occur.
|
||||||
|
|
||||||
In the future we may do a more comprehensive analysis of thread safety in the LargeVolume, but for now you should assume that any multithreaded access can cause problems.
|
In the future we may do a more comprehensive analysis of thread safety in the LargeVolume, but for now you should assume that any multithreaded access can cause problems.
|
||||||
|
|
||||||
Consequences of abuse
|
Consequences of abuse
|
||||||
---------------------
|
---------------------
|
||||||
We have outlined above the rules for multithreaded access of volumes, but what actually happens if you violate these? There's a couple of things to watch out for:
|
We have outlined above the rules for multithreaded access of volumes, but what actually happens if you violate these? There's a couple of things to watch out for:
|
||||||
|
|
||||||
- As mentioned, performing unprotected writes to the volume can cause problems because the data may be copied into the CPU cache and/or registers, and so a subsequent read could retrieve the old value. This is not what you want but probably won't be fatal (i.e. it shouldn't crash). It would basically manifest itself as data corruption.
|
- As mentioned, performing unprotected writes to the volume can cause problems because the data may be copied into the CPU cache and/or registers, and so a subsequent read could retrieve the old value. This is not what you want but probably won't be fatal (i.e. it shouldn't crash). It would basically manifest itself as data corruption.
|
||||||
- If you access the LargeVolume in a multithreaded fashion then you risk trying to access data which has been removed by another thread, and in this case you will get undefined behaviour. This will probably be a crash (out of bounds access) but really anything could happen.
|
- If you access the LargeVolume in a multithreaded fashion then you risk trying to access data which has been removed by another thread, and in this case you will get undefined behaviour. This will probably be a crash (out of bounds access) but really anything could happen.
|
||||||
|
|
||||||
Surface Extraction
|
Surface Extraction
|
||||||
==================
|
==================
|
||||||
Despite the lack of thread safety built in to PolyVox, it is still possible and often desirable to make use of multiple threads for tasks such as surface extraction. Performing surface extraction does not require write access to the data, and we've already established that you can safely perform reads from different threads *provided you are not using the LargeVolume*.
|
Despite the lack of thread safety built in to PolyVox, it is still possible and often desirable to make use of multiple threads for tasks such as surface extraction. Performing surface extraction does not require write access to the data, and we've already established that you can safely perform reads from different threads *provided you are not using the LargeVolume*.
|
||||||
|
|
||||||
Combining multiple surface extraction threads with the *LargeVolume* is something we will need to experiment with in the future, to determine how it can be improved.
|
Combining multiple surface extraction threads with the *LargeVolume* is something we will need to experiment with in the future, to determine how it can be improved.
|
||||||
|
|
||||||
In the future we will expand this section to discuss how to split surface extraction across a number of threads, but for now please see Section XX of the book chapter 'Volumetric Representation of Virtual environments', available for free here: http://books.google.nl/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game+engine+gems&pg=PA39&redir_esc=y#v=onepage&q&f=false
|
In the future we will expand this section to discuss how to split surface extraction across a number of threads, but for now please see Section XX of the book chapter 'Volumetric Representation of Virtual environments', available for free here: http://books.google.nl/books?id=WNfD2u8nIlIC&lpg=PR1&dq=game+engine+gems&pg=PA39&redir_esc=y#v=onepage&q&f=false
|
||||||
|
|
||||||
GPU thread safety
|
GPU thread safety
|
||||||
=================
|
=================
|
||||||
Be aware that even if you successfully perform surface across multiple threads you still need to take care when uploading the data to the GPU. For Direct3D 9.0 and OpenGL 2.0 it is only possible to upload data from the main thread (or more accurately the one which owns the rendering context). So after you have performed your multi-threaded surface extraction you need to bring the data back to the main thread for uploading to the GPU.
|
Be aware that even if you successfully perform surface across multiple threads you still need to take care when uploading the data to the GPU. For Direct3D 9.0 and OpenGL 2.0 it is only possible to upload data from the main thread (or more accurately the one which owns the rendering context). So after you have performed your multi-threaded surface extraction you need to bring the data back to the main thread for uploading to the GPU.
|
||||||
|
|
||||||
More recent versions of the Direct3D and OpenGL APIs lift this restriction and provide means of accessing GPU resources from multiple threads. Please consult the documentation for your API for details.
|
More recent versions of the Direct3D and OpenGL APIs lift this restriction and provide means of accessing GPU resources from multiple threads. Please consult the documentation for your API for details.
|
||||||
|
|
||||||
Future work
|
Future work
|
||||||
===========
|
===========
|
||||||
Threading support is not a high priority for PolyVox because it can be implemented by the user at a higher level. However, there are a couple of areas we may investigate in the future.
|
Threading support is not a high priority for PolyVox because it can be implemented by the user at a higher level. However, there are a couple of areas we may investigate in the future.
|
||||||
|
|
||||||
Thread safe volume wrapper
|
Thread safe volume wrapper
|
||||||
--------------------------
|
--------------------------
|
||||||
It might be useful to provide a thread safe wrapper around the volume classes, and this could possibly be included in the PolyVox utilities or as a extra library. This thread safe wrapper could be templatised to work with any internal volume type, and could itself be a volume so that it can be used directly with the existing algorithms.
|
It might be useful to provide a thread safe wrapper around the volume classes, and this could possibly be included in the PolyVox utilities or as a extra library. This thread safe wrapper could be templatised to work with any internal volume type, and could itself be a volume so that it can be used directly with the existing algorithms.
|
||||||
|
|
||||||
OpenMP
|
OpenMP
|
||||||
------
|
------
|
||||||
This is a standard for extending C++ with compiler directives which allow the compiler to automatically parallelise sections of code. Most likely this could be used to parallelise some of the loops which occur in image processing tasks.
|
This is a standard for extending C++ with compiler directives which allow the compiler to automatically parallelise sections of code. Most likely this could be used to parallelise some of the loops which occur in image processing tasks.
|
@ -1,4 +1,4 @@
|
|||||||
Changelog
|
Changelog
|
||||||
#########
|
#########
|
||||||
|
|
||||||
.. include:: ../CHANGELOG.txt
|
.. include:: ../CHANGELOG.txt
|
||||||
|
@ -1,232 +1,232 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# PolyVox documentation build configuration file, created by
|
# PolyVox documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Tue Jul 6 14:46:57 2010.
|
# sphinx-quickstart on Tue Jul 6 14:46:57 2010.
|
||||||
#
|
#
|
||||||
# This file is execfile()d with the current directory set to its containing dir.
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
#
|
#
|
||||||
# Note that not all possible configuration values are present in this
|
# Note that not all possible configuration values are present in this
|
||||||
# autogenerated file.
|
# autogenerated file.
|
||||||
#
|
#
|
||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/_extensions')
|
sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/_extensions')
|
||||||
|
|
||||||
# -- General configuration -----------------------------------------------------
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
#needs_sphinx = '1.0'
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
extensions = ['sphinxcontrib.doxylink']
|
extensions = ['sphinxcontrib.doxylink']
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates']
|
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates']
|
||||||
|
|
||||||
# The suffix of source filenames.
|
# The suffix of source filenames.
|
||||||
source_suffix = '.rst'
|
source_suffix = '.rst'
|
||||||
|
|
||||||
# The encoding of source files.
|
# The encoding of source files.
|
||||||
#source_encoding = 'utf-8-sig'
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
# The master toctree document.
|
# The master toctree document.
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'PolyVox'
|
project = u'PolyVox'
|
||||||
copyright = u'2013, David Williams, Matt Williams'
|
copyright = u'2013, David Williams, Matt Williams'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '@POLYVOX_VERSION@'
|
version = '@POLYVOX_VERSION@'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '@POLYVOX_VERSION@'
|
release = '@POLYVOX_VERSION@'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
language = "en"
|
language = "en"
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
#today = ''
|
#today = ''
|
||||||
# Else, today_fmt is used as the format for a strftime call.
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
#today_fmt = '%B %d, %Y'
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
#default_role = None
|
#default_role = None
|
||||||
|
|
||||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
#add_function_parentheses = True
|
#add_function_parentheses = True
|
||||||
|
|
||||||
# If true, the current module name will be prepended to all description
|
# If true, the current module name will be prepended to all description
|
||||||
# unit titles (such as .. function::).
|
# unit titles (such as .. function::).
|
||||||
#add_module_names = True
|
#add_module_names = True
|
||||||
|
|
||||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
# output. They are ignored by default.
|
# output. They are ignored by default.
|
||||||
#show_authors = False
|
#show_authors = False
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
pygments_style = 'sphinx'
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
# A list of ignored prefixes for module index sorting.
|
# A list of ignored prefixes for module index sorting.
|
||||||
#modindex_common_prefix = []
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ---------------------------------------------------
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
html_theme = 'default'
|
html_theme = 'default'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
#html_theme_options = {}
|
#html_theme_options = {}
|
||||||
|
|
||||||
# Add any paths that contain custom themes here, relative to this directory.
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
#html_theme_path = []
|
#html_theme_path = []
|
||||||
|
|
||||||
# The name for this set of Sphinx documents. If None, it defaults to
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
# "<project> v<release> documentation".
|
# "<project> v<release> documentation".
|
||||||
#html_title = None
|
#html_title = None
|
||||||
|
|
||||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
#html_short_title = None
|
#html_short_title = None
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
# of the sidebar.
|
# of the sidebar.
|
||||||
#html_logo = None
|
#html_logo = None
|
||||||
|
|
||||||
# The name of an image file (within the static path) to use as favicon of the
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
# pixels large.
|
# pixels large.
|
||||||
#html_favicon = None
|
#html_favicon = None
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static']
|
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static']
|
||||||
|
|
||||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
# using the given strftime format.
|
# using the given strftime format.
|
||||||
#html_last_updated_fmt = '%b %d, %Y'
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
# typographically correct entities.
|
# typographically correct entities.
|
||||||
#html_use_smartypants = True
|
#html_use_smartypants = True
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
#html_sidebars = {}
|
#html_sidebars = {}
|
||||||
|
|
||||||
# Additional templates that should be rendered to pages, maps page names to
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
# template names.
|
# template names.
|
||||||
#html_additional_pages = {}
|
#html_additional_pages = {}
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#html_domain_indices = True
|
#html_domain_indices = True
|
||||||
|
|
||||||
# If false, no index is generated.
|
# If false, no index is generated.
|
||||||
#html_use_index = True
|
#html_use_index = True
|
||||||
|
|
||||||
# If true, the index is split into individual pages for each letter.
|
# If true, the index is split into individual pages for each letter.
|
||||||
#html_split_index = False
|
#html_split_index = False
|
||||||
|
|
||||||
# If true, links to the reST sources are added to the pages.
|
# If true, links to the reST sources are added to the pages.
|
||||||
#html_show_sourcelink = True
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
#html_show_sphinx = True
|
#html_show_sphinx = True
|
||||||
|
|
||||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
#html_show_copyright = True
|
#html_show_copyright = True
|
||||||
|
|
||||||
# If true, an OpenSearch description file will be output, and all pages will
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
# contain a <link> tag referring to it. The value of this option must be the
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
# base URL from which the finished HTML is served.
|
# base URL from which the finished HTML is served.
|
||||||
#html_use_opensearch = ''
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
#html_file_suffix = ''
|
#html_file_suffix = ''
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
#htmlhelp_basename = 'PolyVoxdoc'
|
#htmlhelp_basename = 'PolyVoxdoc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output --------------------------------------------------
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
# The paper size ('letter' or 'a4').
|
# The paper size ('letter' or 'a4').
|
||||||
#latex_paper_size = 'letter'
|
#latex_paper_size = 'letter'
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
#latex_font_size = '10pt'
|
#latex_font_size = '10pt'
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
('index', 'PolyVox.tex', u'PolyVox Documentation',
|
('index', 'PolyVox.tex', u'PolyVox Documentation',
|
||||||
u'David Williams, Matt Williams', 'manual'),
|
u'David Williams, Matt Williams', 'manual'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to place at the top of
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
# the title page.
|
# the title page.
|
||||||
#latex_logo = None
|
#latex_logo = None
|
||||||
|
|
||||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
# not chapters.
|
# not chapters.
|
||||||
#latex_use_parts = False
|
#latex_use_parts = False
|
||||||
|
|
||||||
# If true, show page references after internal links.
|
# If true, show page references after internal links.
|
||||||
#latex_show_pagerefs = False
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
#latex_show_urls = False
|
#latex_show_urls = False
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
# Additional stuff for the LaTeX preamble.
|
||||||
#latex_preamble = ''
|
#latex_preamble = ''
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
#latex_appendices = []
|
#latex_appendices = []
|
||||||
|
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#latex_domain_indices = True
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output --------------------------------------------
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('index', 'polyvox', u'PolyVox Documentation',
|
('index', 'polyvox', u'PolyVox Documentation',
|
||||||
[u'David Williams, Matt Williams'], 1)
|
[u'David Williams, Matt Williams'], 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
#intersphinx_mapping = {'http://docs.python.org/': None}
|
#intersphinx_mapping = {'http://docs.python.org/': None}
|
||||||
|
|
||||||
doxylink = {
|
doxylink = {
|
||||||
'polyvox' : ('@CMAKE_CURRENT_BINARY_DIR@/../library/PolyVox.tag', '../library/doc/html/') #Make this '../api/' for uploading
|
'polyvox' : ('@CMAKE_CURRENT_BINARY_DIR@/../library/PolyVox.tag', '../library/doc/html/') #Make this '../api/' for uploading
|
||||||
}
|
}
|
||||||
|
|
||||||
#This must be lowercase for QtHelp
|
#This must be lowercase for QtHelp
|
||||||
qthelp_basename = "polyvox"
|
qthelp_basename = "polyvox"
|
||||||
|
|
||||||
primary_domain = "c++"
|
primary_domain = "c++"
|
||||||
|
|
||||||
# Default higlighting scheme to use for `code-block` directives
|
# Default higlighting scheme to use for `code-block` directives
|
||||||
highlight_language = "c++"
|
highlight_language = "c++"
|
||||||
|
@ -1,41 +1,41 @@
|
|||||||
Welcome to PolyVox's documentation!
|
Welcome to PolyVox's documentation!
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
User Guide:
|
User Guide:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
install
|
install
|
||||||
principles
|
principles
|
||||||
Lighting
|
Lighting
|
||||||
TextureMapping
|
TextureMapping
|
||||||
ModifyingTerrain
|
ModifyingTerrain
|
||||||
LevelOfDetail
|
LevelOfDetail
|
||||||
Threading
|
Threading
|
||||||
ErrorHandling
|
ErrorHandling
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
tutorial1
|
tutorial1
|
||||||
python-bindings
|
python-bindings
|
||||||
|
|
||||||
Other Information:
|
Other Information:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
changelog
|
changelog
|
||||||
FAQ
|
FAQ
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
||||||
* :ref:`genindex`
|
* :ref:`genindex`
|
||||||
* :ref:`search`
|
* :ref:`search`
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
.. include:: ../INSTALL.txt
|
.. include:: ../INSTALL.txt
|
||||||
|
@ -1,155 +1,155 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
REM Command file for Sphinx documentation
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
if "%SPHINXBUILD%" == "" (
|
if "%SPHINXBUILD%" == "" (
|
||||||
set SPHINXBUILD=sphinx-build
|
set SPHINXBUILD=sphinx-build
|
||||||
)
|
)
|
||||||
set BUILDDIR=_build
|
set BUILDDIR=_build
|
||||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||||
if NOT "%PAPER%" == "" (
|
if NOT "%PAPER%" == "" (
|
||||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "" goto help
|
if "%1" == "" goto help
|
||||||
|
|
||||||
if "%1" == "help" (
|
if "%1" == "help" (
|
||||||
:help
|
:help
|
||||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||||
echo. html to make standalone HTML files
|
echo. html to make standalone HTML files
|
||||||
echo. dirhtml to make HTML files named index.html in directories
|
echo. dirhtml to make HTML files named index.html in directories
|
||||||
echo. singlehtml to make a single large HTML file
|
echo. singlehtml to make a single large HTML file
|
||||||
echo. pickle to make pickle files
|
echo. pickle to make pickle files
|
||||||
echo. json to make JSON files
|
echo. json to make JSON files
|
||||||
echo. htmlhelp to make HTML files and a HTML help project
|
echo. htmlhelp to make HTML files and a HTML help project
|
||||||
echo. qthelp to make HTML files and a qthelp project
|
echo. qthelp to make HTML files and a qthelp project
|
||||||
echo. devhelp to make HTML files and a Devhelp project
|
echo. devhelp to make HTML files and a Devhelp project
|
||||||
echo. epub to make an epub
|
echo. epub to make an epub
|
||||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||||
echo. text to make text files
|
echo. text to make text files
|
||||||
echo. man to make manual pages
|
echo. man to make manual pages
|
||||||
echo. changes to make an overview over all changed/added/deprecated items
|
echo. changes to make an overview over all changed/added/deprecated items
|
||||||
echo. linkcheck to check all external links for integrity
|
echo. linkcheck to check all external links for integrity
|
||||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "clean" (
|
if "%1" == "clean" (
|
||||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||||
del /q /s %BUILDDIR%\*
|
del /q /s %BUILDDIR%\*
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "html" (
|
if "%1" == "html" (
|
||||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "dirhtml" (
|
if "%1" == "dirhtml" (
|
||||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "singlehtml" (
|
if "%1" == "singlehtml" (
|
||||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "pickle" (
|
if "%1" == "pickle" (
|
||||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished; now you can process the pickle files.
|
echo.Build finished; now you can process the pickle files.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "json" (
|
if "%1" == "json" (
|
||||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished; now you can process the JSON files.
|
echo.Build finished; now you can process the JSON files.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "htmlhelp" (
|
if "%1" == "htmlhelp" (
|
||||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "qthelp" (
|
if "%1" == "qthelp" (
|
||||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PolyVox.qhcp
|
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PolyVox.qhcp
|
||||||
echo.To view the help file:
|
echo.To view the help file:
|
||||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PolyVox.ghc
|
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PolyVox.ghc
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "devhelp" (
|
if "%1" == "devhelp" (
|
||||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished.
|
echo.Build finished.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "epub" (
|
if "%1" == "epub" (
|
||||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "latex" (
|
if "%1" == "latex" (
|
||||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "text" (
|
if "%1" == "text" (
|
||||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "man" (
|
if "%1" == "man" (
|
||||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||||
echo.
|
echo.
|
||||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "changes" (
|
if "%1" == "changes" (
|
||||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||||
echo.
|
echo.
|
||||||
echo.The overview file is in %BUILDDIR%/changes.
|
echo.The overview file is in %BUILDDIR%/changes.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "linkcheck" (
|
if "%1" == "linkcheck" (
|
||||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||||
echo.
|
echo.
|
||||||
echo.Link check complete; look for any errors in the above output ^
|
echo.Link check complete; look for any errors in the above output ^
|
||||||
or in %BUILDDIR%/linkcheck/output.txt.
|
or in %BUILDDIR%/linkcheck/output.txt.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "doctest" (
|
if "%1" == "doctest" (
|
||||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||||
echo.
|
echo.
|
||||||
echo.Testing of doctests in the sources finished, look at the ^
|
echo.Testing of doctests in the sources finished, look at the ^
|
||||||
results in %BUILDDIR%/doctest/output.txt.
|
results in %BUILDDIR%/doctest/output.txt.
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
:end
|
:end
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
**********************
|
**********************
|
||||||
Principles of PolyVox
|
Principles of PolyVox
|
||||||
**********************
|
**********************
|
||||||
|
|
||||||
.. warning ::
|
.. warning ::
|
||||||
This section is being written and is just a skeleton for now
|
This section is being written and is just a skeleton for now
|
||||||
|
|
||||||
PolyVox provides a library for managing 3D arrays (volumes) of data (voxels). It gives you the tools to iterate through, randomly access, read and write volumes. It supports any type you'd like to represent each voxel whether it's just an ``int`` or a class which encapsulates both density and colour.
|
PolyVox provides a library for managing 3D arrays (volumes) of data (voxels). It gives you the tools to iterate through, randomly access, read and write volumes. It supports any type you'd like to represent each voxel whether it's just an ``int`` or a class which encapsulates both density and colour.
|
||||||
|
|
||||||
Once you have a volume, PolyVox provides a number of tools for turning it into something that you can pass to your rendering engine. These are called `surface extractors`.
|
Once you have a volume, PolyVox provides a number of tools for turning it into something that you can pass to your rendering engine. These are called `surface extractors`.
|
||||||
|
|
||||||
Each surface extractor needs to be told how to interperet your voxel type and that is done using...
|
Each surface extractor needs to be told how to interperet your voxel type and that is done using...
|
||||||
|
|
||||||
Link to a page describing how to write your own voxel type and link it to a surface extractor...
|
Link to a page describing how to write your own voxel type and link it to a surface extractor...
|
||||||
|
@ -1,166 +1,166 @@
|
|||||||
**********************
|
**********************
|
||||||
Tutorial 1 - Basic use
|
Tutorial 1 - Basic use
|
||||||
**********************
|
**********************
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
This tutorial covers the basic use of the PolyVox API. After reading this tutorial you should have a good idea how to create a PolyVox volume and fill it with data, extract a triangle mesh representing the surface, and render the result. This tutorial assumes you are already familiar with the basic concepts behind PolyVox (see the :doc:`principles of polyvox <principles>` document if not), and are reasonably confident with 3D graphics and C++. It also assumes you have already got PolyVox installed on your system, if this is not the case then please consult :doc:`installation guide <install>`.
|
This tutorial covers the basic use of the PolyVox API. After reading this tutorial you should have a good idea how to create a PolyVox volume and fill it with data, extract a triangle mesh representing the surface, and render the result. This tutorial assumes you are already familiar with the basic concepts behind PolyVox (see the :doc:`principles of polyvox <principles>` document if not), and are reasonably confident with 3D graphics and C++. It also assumes you have already got PolyVox installed on your system, if this is not the case then please consult :doc:`installation guide <install>`.
|
||||||
|
|
||||||
The code samples and text in this tutorial correspond directly to the BasicExample which comes with PolyVox. This example uses the Qt toolkit for window and input handling, and for providing an OpenGL context to render into. In this tutorial we will omit code which performs these tasks and will instead focus on on the PolyVox code. You can consult the `Qt documentation <http://doc.qt.nokia.com/latest/>`_ if you want more information about these other aspects of the system.
|
The code samples and text in this tutorial correspond directly to the BasicExample which comes with PolyVox. This example uses the Qt toolkit for window and input handling, and for providing an OpenGL context to render into. In this tutorial we will omit code which performs these tasks and will instead focus on on the PolyVox code. You can consult the `Qt documentation <http://doc.qt.nokia.com/latest/>`_ if you want more information about these other aspects of the system.
|
||||||
|
|
||||||
Creating a volume
|
Creating a volume
|
||||||
=================
|
=================
|
||||||
To get started, we need to include the following headers:
|
To get started, we need to include the following headers:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/SurfaceMesh.h"
|
#include "PolyVoxCore/SurfaceMesh.h"
|
||||||
#include "PolyVoxCore/SimpleVolume.h"
|
#include "PolyVoxCore/SimpleVolume.h"
|
||||||
|
|
||||||
The most fundamental construct when working with PolyVox is that of the volume. This is represented by the :polyvox:`SimpleVolume` class which stores a 3D grid of voxels. Our basic example application creates a volume with the following line of code:
|
The most fundamental construct when working with PolyVox is that of the volume. This is represented by the :polyvox:`SimpleVolume` class which stores a 3D grid of voxels. Our basic example application creates a volume with the following line of code:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
SimpleVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
|
SimpleVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
|
||||||
|
|
||||||
As can be seen, the SimpleVolume class is templated upon the voxel type. This means it is straightforward to create a volume of integers, floats, or a custom voxel type (see the :polyvox:`SimpleVolume documentation <PolyVox::SimpleVolume>` for more details). In this particular case we have created a volume in which each voxel is of type `uint8_t` which is an unsigned 8-bit integer.
|
As can be seen, the SimpleVolume class is templated upon the voxel type. This means it is straightforward to create a volume of integers, floats, or a custom voxel type (see the :polyvox:`SimpleVolume documentation <PolyVox::SimpleVolume>` for more details). In this particular case we have created a volume in which each voxel is of type `uint8_t` which is an unsigned 8-bit integer.
|
||||||
|
|
||||||
Next, we set some of the voxels in the volume to be 'solid' in order to create a large sphere in the centre of the volume. We do this with the following function call:
|
Next, we set some of the voxels in the volume to be 'solid' in order to create a large sphere in the centre of the volume. We do this with the following function call:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
createSphereInVolume(volData, 30);
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
Note that this function is part of the BasicExample (rather than being part of the PolyVox library) and is implemented as follows:
|
Note that this function is part of the BasicExample (rather than being part of the PolyVox library) and is implemented as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
void createSphereInVolume(SimpleVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(SimpleVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getDepth(); z++)
|
for (int z = 0; z < volData.getDepth(); z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < volData.getHeight(); y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x,y,z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
uint8_t uVoxelValue = 0;
|
uint8_t uVoxelValue = 0;
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new voxel value
|
//Our new voxel value
|
||||||
uVoxelValue = 255;
|
uVoxelValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, uVoxelValue);
|
volData.setVoxelAt(x, y, z, uVoxelValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
This function takes as input the :polyvox:`SimpleVolume` in which we want to create the sphere, and also a radius specifying how large we want the sphere to be. In our case we have specified a radius of 30 voxels, which will fit nicely inside our :polyvox:`SimpleVolume` of dimensions 64x64x64.
|
This function takes as input the :polyvox:`SimpleVolume` in which we want to create the sphere, and also a radius specifying how large we want the sphere to be. In our case we have specified a radius of 30 voxels, which will fit nicely inside our :polyvox:`SimpleVolume` of dimensions 64x64x64.
|
||||||
|
|
||||||
Because this is a simple example function it always places the sphere at the centre of the volume. It computes this centre by halving the dimensions of the volume as given by the functions :polyvox:`SimpleVolume::getWidth`, :polyvox:`SimpleVolume::getHeight` and :polyvox:`SimpleVolume::getDepth`. The resulting position is stored using a :polyvox:`Vector3DFloat`. This is simply a typedef from our templatised :polyvox:`Vector` class, meaning that other sizes and storage types are available if you need them.
|
Because this is a simple example function it always places the sphere at the centre of the volume. It computes this centre by halving the dimensions of the volume as given by the functions :polyvox:`SimpleVolume::getWidth`, :polyvox:`SimpleVolume::getHeight` and :polyvox:`SimpleVolume::getDepth`. The resulting position is stored using a :polyvox:`Vector3DFloat`. This is simply a typedef from our templatised :polyvox:`Vector` class, meaning that other sizes and storage types are available if you need them.
|
||||||
|
|
||||||
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel forms part of the sphere and is made solid. During surface extraction, the voxel will be considered empty if it has a value of zero, and otherwise it will be considered solid. In our case we simply set it to 255 which is the largest value a uint8_t can contain.
|
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel forms part of the sphere and is made solid. During surface extraction, the voxel will be considered empty if it has a value of zero, and otherwise it will be considered solid. In our case we simply set it to 255 which is the largest value a uint8_t can contain.
|
||||||
|
|
||||||
Extracting the surface
|
Extracting the surface
|
||||||
======================
|
======================
|
||||||
Now that we have built our volume we need to convert it into a triangle mesh for rendering. This process can be performed by the :polyvox:`CubicSurfaceExtractorWithNormals` class. An instance of the :polyvox:`CubicSurfaceExtractorWithNormals` is created as follows:
|
Now that we have built our volume we need to convert it into a triangle mesh for rendering. This process can be performed by the :polyvox:`CubicSurfaceExtractorWithNormals` class. An instance of the :polyvox:`CubicSurfaceExtractorWithNormals` is created as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
SurfaceMesh<PositionMaterialNormal> mesh;
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
CubicSurfaceExtractorWithNormals< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
CubicSurfaceExtractorWithNormals< SimpleVolume<uint8_t> > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
|
|
||||||
The :polyvox:`CubicSurfaceExtractorWithNormals` takes a pointer to the volume data, and also it needs to be told which :polyvox:`Region` of the volume the extraction should be performed on (in more advanced applications this is useful for extracting only those parts of the volume which have been modified since the last extraction). For our purpose the :polyvox:`SimpleVolume` class provides a convenient :polyvox:`SimpleVolume::getEnclosingRegion` function which returns a :polyvox:`Region` representing the whole volume. The constructor also takes a pointer to a :polyvox:`SurfaceMesh` object where it will store the result, so we need to create one of these before we can construct the :polyvox:`CubicSurfaceExtractorWithNormals`.
|
The :polyvox:`CubicSurfaceExtractorWithNormals` takes a pointer to the volume data, and also it needs to be told which :polyvox:`Region` of the volume the extraction should be performed on (in more advanced applications this is useful for extracting only those parts of the volume which have been modified since the last extraction). For our purpose the :polyvox:`SimpleVolume` class provides a convenient :polyvox:`SimpleVolume::getEnclosingRegion` function which returns a :polyvox:`Region` representing the whole volume. The constructor also takes a pointer to a :polyvox:`SurfaceMesh` object where it will store the result, so we need to create one of these before we can construct the :polyvox:`CubicSurfaceExtractorWithNormals`.
|
||||||
|
|
||||||
The actual extraction happens in the :polyvox:`CubicSurfaceExtractorWithNormals::execute` function. This means you can set up a :polyvox:`CubicSurfaceExtractorWithNormals` with the required parameters and then actually execute it later. For this example we just call it straight away.
|
The actual extraction happens in the :polyvox:`CubicSurfaceExtractorWithNormals::execute` function. This means you can set up a :polyvox:`CubicSurfaceExtractorWithNormals` with the required parameters and then actually execute it later. For this example we just call it straight away.
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
surfaceExtractor.execute();
|
surfaceExtractor.execute();
|
||||||
|
|
||||||
This fills in our :polyvox:`SurfaceMesh` object, which basically contains an index and vertex buffer representing the desired triangle mesh.
|
This fills in our :polyvox:`SurfaceMesh` object, which basically contains an index and vertex buffer representing the desired triangle mesh.
|
||||||
|
|
||||||
Note: If you like you can try swapping the :polyvox:`CubicSurfaceExtractorWithNormals` for :polyvox:`MarchingCubesSurfaceExtractor`. We have already included the relevant header, and in the BasicExample you just need to change which line in commented out. The :polyvox:`MarchingCubesSurfaceExtractor` makes use of a smooth density field and will consider a voxel to be solid if it is above a threshold of half the voxel's maximum value (so in this case that's half of 255, which is 127).
|
Note: If you like you can try swapping the :polyvox:`CubicSurfaceExtractorWithNormals` for :polyvox:`MarchingCubesSurfaceExtractor`. We have already included the relevant header, and in the BasicExample you just need to change which line in commented out. The :polyvox:`MarchingCubesSurfaceExtractor` makes use of a smooth density field and will consider a voxel to be solid if it is above a threshold of half the voxel's maximum value (so in this case that's half of 255, which is 127).
|
||||||
|
|
||||||
Rendering the surface
|
Rendering the surface
|
||||||
=====================
|
=====================
|
||||||
Rendering the surface with OpenGL is handled by the OpenGLWidget class. Again, this is not part of PolyVox, it is simply an example based on Qt and OpenGL which demonstrates how rendering can be performed. Within this class there are mainly two functions which are of interest - the OpenGLWidget::setSurfaceMeshToRender() function which constructs OpenGL buffers from our :polyvox:`SurfaceMesh` and the OpenGLWidget::paintGL() function which is called each frame to perform the rendering.
|
Rendering the surface with OpenGL is handled by the OpenGLWidget class. Again, this is not part of PolyVox, it is simply an example based on Qt and OpenGL which demonstrates how rendering can be performed. Within this class there are mainly two functions which are of interest - the OpenGLWidget::setSurfaceMeshToRender() function which constructs OpenGL buffers from our :polyvox:`SurfaceMesh` and the OpenGLWidget::paintGL() function which is called each frame to perform the rendering.
|
||||||
|
|
||||||
The OpenGLWidget::setSurfaceMeshToRender() function is implemented as follows:
|
The OpenGLWidget::setSurfaceMeshToRender() function is implemented as follows:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh)
|
void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh<PositionMaterialNormal>& surfaceMesh)
|
||||||
{
|
{
|
||||||
//Convienient access to the vertices and indices
|
//Convienient access to the vertices and indices
|
||||||
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
const vector<uint32_t>& vecIndices = surfaceMesh.getIndices();
|
||||||
const vector<PositionMaterialNormal>& vecVertices = surfaceMesh.getVertices();
|
const vector<PositionMaterialNormal>& vecVertices = surfaceMesh.getVertices();
|
||||||
|
|
||||||
//Build an OpenGL index buffer
|
//Build an OpenGL index buffer
|
||||||
glGenBuffers(1, &indexBuffer);
|
glGenBuffers(1, &indexBuffer);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||||
const GLvoid* pIndices = static_cast<const GLvoid*>(&(vecIndices[0]));
|
const GLvoid* pIndices = static_cast<const GLvoid*>(&(vecIndices[0]));
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
//Build an OpenGL vertex buffer
|
//Build an OpenGL vertex buffer
|
||||||
glGenBuffers(1, &vertexBuffer);
|
glGenBuffers(1, &vertexBuffer);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
const GLvoid* pVertices = static_cast<const GLvoid*>(&(vecVertices[0]));
|
const GLvoid* pVertices = static_cast<const GLvoid*>(&(vecVertices[0]));
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
m_uBeginIndex = 0;
|
m_uBeginIndex = 0;
|
||||||
m_uEndIndex = vecIndices.size();
|
m_uEndIndex = vecIndices.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
We begin by obtaining direct access to the index and vertex buffer in the :polyvox:`SurfaceMesh` class in order to make the following code slightly cleaner. Both the :polyvox:`SurfaceMesh::getIndices` and :polyvox:`SurfaceMesh::getVertices` functions return an std::vector containing the relevant data.
|
We begin by obtaining direct access to the index and vertex buffer in the :polyvox:`SurfaceMesh` class in order to make the following code slightly cleaner. Both the :polyvox:`SurfaceMesh::getIndices` and :polyvox:`SurfaceMesh::getVertices` functions return an std::vector containing the relevant data.
|
||||||
|
|
||||||
The OpenGL functions which are called to construct the index and vertex buffer are best explained by the OpenGL documentation. In both cases we are making an exact copy of the data stored in the :polyvox:`SurfaceMesh`.
|
The OpenGL functions which are called to construct the index and vertex buffer are best explained by the OpenGL documentation. In both cases we are making an exact copy of the data stored in the :polyvox:`SurfaceMesh`.
|
||||||
|
|
||||||
The begin and end indices are used in the OpenGLWidget::paintGL() to control what part of the index buffer is actually rendered. For this simple example we will render the whole buffer from '0' to 'vecIndices.size()'.
|
The begin and end indices are used in the OpenGLWidget::paintGL() to control what part of the index buffer is actually rendered. For this simple example we will render the whole buffer from '0' to 'vecIndices.size()'.
|
||||||
|
|
||||||
With the OpenGL index and vertex buffers set up, we can now look at the code which is called each frame to render them:
|
With the OpenGL index and vertex buffers set up, we can now look at the code which is called each frame to render them:
|
||||||
|
|
||||||
.. sourcecode:: c++
|
.. sourcecode:: c++
|
||||||
|
|
||||||
void OpenGLWidget::paintGL()
|
void OpenGLWidget::paintGL()
|
||||||
{
|
{
|
||||||
//Clear the screen
|
//Clear the screen
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
//Set up the viewing transformation
|
//Set up the viewing transformation
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back
|
glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back
|
||||||
glRotatef(-m_xRotation, 0.0f, 1.0f, 0.0f);
|
glRotatef(-m_xRotation, 0.0f, 1.0f, 0.0f);
|
||||||
glRotatef(-m_yRotation, 1.0f, 0.0f, 0.0f);
|
glRotatef(-m_yRotation, 1.0f, 0.0f, 0.0f);
|
||||||
glTranslatef(-32.0f,-32.0f,-32.0f); //Centre volume and move back
|
glTranslatef(-32.0f,-32.0f,-32.0f); //Centre volume and move back
|
||||||
|
|
||||||
//Bind the index buffer
|
//Bind the index buffer
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||||
|
|
||||||
//Bind the vertex buffer
|
//Bind the vertex buffer
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0);
|
glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0);
|
||||||
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12);
|
glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12);
|
||||||
|
|
||||||
glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0);
|
glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
//Error checking code here...
|
//Error checking code here...
|
||||||
}
|
}
|
||||||
|
|
||||||
Again, the explanation of this code is best left to the OpenGL documentation. Note that is is called automatically by Qt each time the display needs to be updated.
|
Again, the explanation of this code is best left to the OpenGL documentation. Note that is is called automatically by Qt each time the display needs to be updated.
|
@ -1,74 +1,74 @@
|
|||||||
# Copyright (c) 2010-2012 David Williams
|
# Copyright (c) 2010-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(BasicExample)
|
PROJECT(BasicExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL REQUIRED)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
||||||
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
#This will include the shader files inside the compiled binary
|
||||||
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(BasicExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(BasicExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(BasicExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(BasicExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET BasicExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS BasicExample
|
INSTALL(TARGETS BasicExample
|
||||||
RUNTIME DESTINATION Examples/OpenGL/bin
|
RUNTIME DESTINATION Examples/OpenGL/bin
|
||||||
LIBRARY DESTINATION Examples/OpenGL/lib
|
LIBRARY DESTINATION Examples/OpenGL/lib
|
||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
COMPONENT example
|
||||||
)
|
)
|
||||||
|
|
||||||
#.dlls should be installed in shared builds.
|
#.dlls should be installed in shared builds.
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
|
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,95 +1,95 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getDepth(); z++)
|
for (int z = 0; z < volData.getDepth(); z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < volData.getHeight(); y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x,y,z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
uint8_t uVoxelValue = 0;
|
uint8_t uVoxelValue = 0;
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new voxel value
|
//Our new voxel value
|
||||||
uVoxelValue = 255;
|
uVoxelValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, uVoxelValue);
|
volData.setVoxelAt(x, y, z, uVoxelValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//Create an empty volume and then place a sphere in it
|
||||||
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
createSphereInVolume(volData, 30);
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
// Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see.
|
// Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see.
|
||||||
auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
||||||
//auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
//auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
||||||
|
|
||||||
// The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to
|
// The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to
|
||||||
// decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code.
|
// decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code.
|
||||||
auto decodedMesh = decodeMesh(mesh);
|
auto decodedMesh = decodeMesh(mesh);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.addMesh(decodedMesh);
|
openGLWidget.addMesh(decodedMesh);
|
||||||
//openGLWidget.addMesh(mesh2);
|
//openGLWidget.addMesh(mesh2);
|
||||||
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
@ -1,75 +1,75 @@
|
|||||||
# Copyright (c) 2010-2012 David Williams
|
# Copyright (c) 2010-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(DecodeOnGPUExample)
|
PROJECT(DecodeOnGPUExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL REQUIRED)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
||||||
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
#This will include the shader files inside the compiled binary
|
||||||
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
QT4_ADD_RESOURCES(DECODE_RESOURCES_RCC decode.qrc)
|
QT4_ADD_RESOURCES(DECODE_RESOURCES_RCC decode.qrc)
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} decode.qrc ${DECODE_RESOURCES_RCC})
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} decode.qrc ${DECODE_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${DECODE_RESOURCES_RCC})
|
ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${DECODE_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(DecodeOnGPUExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(DecodeOnGPUExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(DecodeOnGPUExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(DecodeOnGPUExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET DecodeOnGPUExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET DecodeOnGPUExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS DecodeOnGPUExample
|
INSTALL(TARGETS DecodeOnGPUExample
|
||||||
RUNTIME DESTINATION Examples/OpenGL/bin
|
RUNTIME DESTINATION Examples/OpenGL/bin
|
||||||
LIBRARY DESTINATION Examples/OpenGL/lib
|
LIBRARY DESTINATION Examples/OpenGL/lib
|
||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
COMPONENT example
|
||||||
)
|
)
|
||||||
|
|
||||||
#.dlls should be installed in shared builds.
|
#.dlls should be installed in shared builds.
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
|
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,167 +1,167 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getDepth(); z++)
|
for (int z = 0; z < volData.getDepth(); z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < volData.getHeight(); y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x,y,z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
uint8_t uVoxelValue = 0;
|
uint8_t uVoxelValue = 0;
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new voxel value
|
//Our new voxel value
|
||||||
uVoxelValue = 255;
|
uVoxelValue = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, uVoxelValue);
|
volData.setVoxelAt(x, y, z, uVoxelValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
||||||
{
|
{
|
||||||
// Convienient access to the vertices and indices
|
// Convienient access to the vertices and indices
|
||||||
const auto& vecIndices = surfaceMesh.getIndices();
|
const auto& vecIndices = surfaceMesh.getIndices();
|
||||||
const auto& vecVertices = surfaceMesh.getVertices();
|
const auto& vecVertices = surfaceMesh.getVertices();
|
||||||
|
|
||||||
// This struct holds the OpenGL properties (buffer handles, etc) which will be used
|
// This struct holds the OpenGL properties (buffer handles, etc) which will be used
|
||||||
// to render our mesh. We copy the data from the PolyVox mesh into this structure.
|
// to render our mesh. We copy the data from the PolyVox mesh into this structure.
|
||||||
OpenGLMeshData meshData;
|
OpenGLMeshData meshData;
|
||||||
|
|
||||||
// Create the VAO for the mesh
|
// Create the VAO for the mesh
|
||||||
glGenVertexArrays(1, &(meshData.vertexArrayObject));
|
glGenVertexArrays(1, &(meshData.vertexArrayObject));
|
||||||
glBindVertexArray(meshData.vertexArrayObject);
|
glBindVertexArray(meshData.vertexArrayObject);
|
||||||
|
|
||||||
// The GL_ARRAY_BUFFER will contain the list of vertex positions
|
// The GL_ARRAY_BUFFER will contain the list of vertex positions
|
||||||
glGenBuffers(1, &(meshData.vertexBuffer));
|
glGenBuffers(1, &(meshData.vertexBuffer));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
// and GL_ELEMENT_ARRAY_BUFFER will contain the indices
|
// and GL_ELEMENT_ARRAY_BUFFER will contain the indices
|
||||||
glGenBuffers(1, &(meshData.indexBuffer));
|
glGenBuffers(1, &(meshData.indexBuffer));
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), vecIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
// Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out
|
// Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out
|
||||||
glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions
|
glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions
|
||||||
glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedPosition))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type)
|
glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedPosition))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type)
|
||||||
|
|
||||||
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor
|
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor
|
||||||
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the
|
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the
|
||||||
// shader. This is mostly just to simplify this example code - in a real application you will know whether your
|
// shader. This is mostly just to simplify this example code - in a real application you will know whether your
|
||||||
// chosen surface extractor generates normals and can skip uploading them if not.
|
// chosen surface extractor generates normals and can skip uploading them if not.
|
||||||
glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals.
|
glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals.
|
||||||
glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedNormal)));
|
glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, encodedNormal)));
|
||||||
|
|
||||||
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code
|
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code
|
||||||
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here.
|
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here.
|
||||||
glEnableVertexAttribArray(2); //We're talking about shader attribute '2'
|
glEnableVertexAttribArray(2); //We're talking about shader attribute '2'
|
||||||
GLint size = (std::min)(sizeof(uint8_t), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type)
|
GLint size = (std::min)(sizeof(uint8_t), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type)
|
||||||
glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, data)));
|
glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, data)));
|
||||||
|
|
||||||
// We're done uploading and can now unbind.
|
// We're done uploading and can now unbind.
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
// A few additional properties can be copied across for use during rendering.
|
// A few additional properties can be copied across for use during rendering.
|
||||||
meshData.noOfIndices = vecIndices.size();
|
meshData.noOfIndices = vecIndices.size();
|
||||||
meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ());
|
meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ());
|
||||||
meshData.scale = scale;
|
meshData.scale = scale;
|
||||||
|
|
||||||
// Set 16 or 32-bit index buffer size.
|
// Set 16 or 32-bit index buffer size.
|
||||||
meshData.indexType = sizeof(PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
meshData.indexType = sizeof(PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||||
|
|
||||||
return meshData;
|
return meshData;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/decode.vert"))
|
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/decode.vert"))
|
||||||
{
|
{
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag"))
|
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag"))
|
||||||
{
|
{
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
openGLWidget.setShader(shader);
|
openGLWidget.setShader(shader);
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//Create an empty volume and then place a sphere in it
|
||||||
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
createSphereInVolume(volData, 30);
|
createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
// Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see.
|
// Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see.
|
||||||
//auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
//auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion());
|
||||||
auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion());
|
||||||
|
|
||||||
// The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to
|
// The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to
|
||||||
// decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code.
|
// decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code.
|
||||||
//auto decodedMesh = decodeMesh(mesh);
|
//auto decodedMesh = decodeMesh(mesh);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
OpenGLMeshData meshData = buildOpenGLMeshData(mesh);
|
OpenGLMeshData meshData = buildOpenGLMeshData(mesh);
|
||||||
openGLWidget.addMeshData(meshData);
|
openGLWidget.addMeshData(meshData);
|
||||||
|
|
||||||
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
@ -1,77 +1,77 @@
|
|||||||
# Copyright (c) 2010-2012 David Williams
|
# Copyright (c) 2010-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(OpenGLExample)
|
PROJECT(OpenGLExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
Shapes.cpp
|
Shapes.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
Shapes.h
|
Shapes.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL REQUIRED)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
||||||
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
#This will include the shader files inside the compiled binary
|
||||||
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
QT4_ADD_RESOURCES(OPENGLEXAMPLE_RESOURCES_RCC openglexample.qrc)
|
QT4_ADD_RESOURCES(OPENGLEXAMPLE_RESOURCES_RCC openglexample.qrc)
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} openglexample.qrc ${OPENGLEXAMPLE_RESOURCES_RCC})
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} openglexample.qrc ${OPENGLEXAMPLE_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGLEXAMPLE_RESOURCES_RCC})
|
ADD_EXECUTABLE(OpenGLExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${OPENGLEXAMPLE_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(OpenGLExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(OpenGLExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(OpenGLExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(OpenGLExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET OpenGLExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS OpenGLExample
|
INSTALL(TARGETS OpenGLExample
|
||||||
RUNTIME DESTINATION Examples/OpenGL/bin
|
RUNTIME DESTINATION Examples/OpenGL/bin
|
||||||
LIBRARY DESTINATION Examples/OpenGL/lib
|
LIBRARY DESTINATION Examples/OpenGL/lib
|
||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
COMPONENT example
|
||||||
)
|
)
|
||||||
|
|
||||||
#.dlls should be installed in shared builds.
|
#.dlls should be installed in shared builds.
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
|
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,73 +1,73 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(PagedVolume<MaterialDensityPair88>& volData, float fRadius, uint8_t uValue)
|
void createSphereInVolume(PagedVolume<MaterialDensityPair88>& volData, float fRadius, uint8_t uValue)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast<int32_t>(2);
|
Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast<int32_t>(2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getDepth(); z++)
|
for (int z = 0; z < volData.getDepth(); z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < volData.getHeight(); y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DInt32 v3dCurrentPos(x,y,z);
|
Vector3DInt32 v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
double fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
double fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center
|
//If the current voxel is less than 'radius' units from the center
|
||||||
//then we make it solid, otherwise we make it empty space.
|
//then we make it solid, otherwise we make it empty space.
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity()));
|
volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createCubeInVolume(PagedVolume<MaterialDensityPair88>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
void createCubeInVolume(PagedVolume<MaterialDensityPair88>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
|
||||||
{
|
{
|
||||||
uint8_t maxDen = MaterialDensityPair88::getMaxDensity();
|
uint8_t maxDen = MaterialDensityPair88::getMaxDensity();
|
||||||
uint8_t minDen = MaterialDensityPair88::getMinDensity();
|
uint8_t minDen = MaterialDensityPair88::getMinDensity();
|
||||||
//This three-level for loop iterates over every voxel between the specified corners
|
//This three-level for loop iterates over every voxel between the specified corners
|
||||||
for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++)
|
for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
for (int y = lowerCorner.getY(); y <= upperCorner.getY(); y++)
|
for (int y = lowerCorner.getY(); y <= upperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++)
|
for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen));
|
volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,33 +1,33 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __OpenGLExample_Shapes_H__
|
#ifndef __OpenGLExample_Shapes_H__
|
||||||
#define __OpenGLExample_Shapes_H__
|
#define __OpenGLExample_Shapes_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
|
|
||||||
void createSphereInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, float fRadius, uint8_t uValue);
|
void createSphereInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, float fRadius, uint8_t uValue);
|
||||||
void createCubeInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
void createCubeInVolume(PolyVox::LargeVolume<PolyVox::MaterialDensityPair88>& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue);
|
||||||
|
|
||||||
#endif //__OpenGLExample_Shapes_H__
|
#endif //__OpenGLExample_Shapes_H__
|
@ -1,146 +1,146 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/FilePager.h"
|
#include "PolyVoxCore/FilePager.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
#include "PolyVoxCore/LowPassFilter.h"
|
#include "PolyVoxCore/LowPassFilter.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVoxCore/RawVolume.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/Impl/Utility.h"
|
#include "PolyVoxCore/Impl/Utility.h"
|
||||||
|
|
||||||
#include "Shapes.h"
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h> // Standard Header For Most Programs
|
#include <windows.h> // Standard Header For Most Programs
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
|
||||||
//Some namespaces we need
|
//Some namespaces we need
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const int32_t g_uVolumeSideLength = 128;
|
const int32_t g_uVolumeSideLength = 128;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FilePager<MaterialDensityPair88>* pager = new FilePager<MaterialDensityPair88>(".");
|
FilePager<MaterialDensityPair88>* pager = new FilePager<MaterialDensityPair88>(".");
|
||||||
PagedVolume<MaterialDensityPair88> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)), pager);
|
PagedVolume<MaterialDensityPair88> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)), pager);
|
||||||
|
|
||||||
//Make our volume contain a sphere in the center.
|
//Make our volume contain a sphere in the center.
|
||||||
int32_t minPos = 0;
|
int32_t minPos = 0;
|
||||||
int32_t midPos = g_uVolumeSideLength / 2;
|
int32_t midPos = g_uVolumeSideLength / 2;
|
||||||
int32_t maxPos = g_uVolumeSideLength - 1;
|
int32_t maxPos = g_uVolumeSideLength - 1;
|
||||||
|
|
||||||
cout << "Creating sphere 1" << std::endl;
|
cout << "Creating sphere 1" << std::endl;
|
||||||
createSphereInVolume(volData, 60.0f, 5);
|
createSphereInVolume(volData, 60.0f, 5);
|
||||||
cout << "Creating sphere 2" << std::endl;
|
cout << "Creating sphere 2" << std::endl;
|
||||||
createSphereInVolume(volData, 50.0f, 4);
|
createSphereInVolume(volData, 50.0f, 4);
|
||||||
cout << "Creating sphere 3" << std::endl;
|
cout << "Creating sphere 3" << std::endl;
|
||||||
createSphereInVolume(volData, 40.0f, 3);
|
createSphereInVolume(volData, 40.0f, 3);
|
||||||
cout << "Creating sphere 4" << std::endl;
|
cout << "Creating sphere 4" << std::endl;
|
||||||
createSphereInVolume(volData, 30.0f, 2);
|
createSphereInVolume(volData, 30.0f, 2);
|
||||||
cout << "Creating sphere 5" << std::endl;
|
cout << "Creating sphere 5" << std::endl;
|
||||||
createSphereInVolume(volData, 20.0f, 1);
|
createSphereInVolume(volData, 20.0f, 1);
|
||||||
|
|
||||||
cout << "Creating cubes" << std::endl;
|
cout << "Creating cubes" << std::endl;
|
||||||
createCubeInVolume(volData, Vector3DInt32(minPos, minPos, minPos), Vector3DInt32(midPos-1, midPos-1, midPos-1), 0);
|
createCubeInVolume(volData, Vector3DInt32(minPos, minPos, minPos), Vector3DInt32(midPos-1, midPos-1, midPos-1), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos+1, midPos+1, minPos), Vector3DInt32(maxPos, maxPos, midPos-1), 0);
|
createCubeInVolume(volData, Vector3DInt32(midPos+1, midPos+1, minPos), Vector3DInt32(maxPos, maxPos, midPos-1), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos+1, minPos, midPos+1), Vector3DInt32(maxPos, midPos-1, maxPos), 0);
|
createCubeInVolume(volData, Vector3DInt32(midPos+1, minPos, midPos+1), Vector3DInt32(maxPos, midPos-1, maxPos), 0);
|
||||||
createCubeInVolume(volData, Vector3DInt32(minPos, midPos+1, midPos+1), Vector3DInt32(midPos-1, maxPos, maxPos), 0);
|
createCubeInVolume(volData, Vector3DInt32(minPos, midPos+1, midPos+1), Vector3DInt32(midPos-1, maxPos, maxPos), 0);
|
||||||
|
|
||||||
createCubeInVolume(volData, Vector3DInt32(1, midPos-10, midPos-10), Vector3DInt32(maxPos-1, midPos+10, midPos+10), MaterialDensityPair44::getMaxDensity());
|
createCubeInVolume(volData, Vector3DInt32(1, midPos-10, midPos-10), Vector3DInt32(maxPos-1, midPos+10, midPos+10), MaterialDensityPair44::getMaxDensity());
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), MaterialDensityPair44::getMaxDensity());
|
createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), MaterialDensityPair44::getMaxDensity());
|
||||||
createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), MaterialDensityPair44::getMaxDensity());
|
createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), MaterialDensityPair44::getMaxDensity());
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
|
|
||||||
|
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
QSharedPointer<QGLShaderProgram> shader(new QGLShaderProgram);
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/openglexample.vert"))
|
if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/openglexample.vert"))
|
||||||
{
|
{
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/openglexample.frag"))
|
if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/openglexample.frag"))
|
||||||
{
|
{
|
||||||
std::cerr << shader->log().toStdString() << std::endl;
|
std::cerr << shader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
openGLWidget.setShader(shader);
|
openGLWidget.setShader(shader);
|
||||||
|
|
||||||
QTime time;
|
QTime time;
|
||||||
time.start();
|
time.start();
|
||||||
//openGLWidget.setVolume(&volData);
|
//openGLWidget.setVolume(&volData);
|
||||||
cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl;
|
cout << endl << "Time taken = " << time.elapsed() / 1000.0f << "s" << endl << endl;
|
||||||
|
|
||||||
const int32_t extractedRegionSize = 32;
|
const int32_t extractedRegionSize = 32;
|
||||||
int meshCounter = 0;
|
int meshCounter = 0;
|
||||||
|
|
||||||
for (int32_t z = 0; z < volData.getDepth(); z += extractedRegionSize)
|
for (int32_t z = 0; z < volData.getDepth(); z += extractedRegionSize)
|
||||||
{
|
{
|
||||||
for (int32_t y = 0; y < volData.getHeight(); y += extractedRegionSize)
|
for (int32_t y = 0; y < volData.getHeight(); y += extractedRegionSize)
|
||||||
{
|
{
|
||||||
for (int32_t x = 0; x < volData.getWidth(); x += extractedRegionSize)
|
for (int32_t x = 0; x < volData.getWidth(); x += extractedRegionSize)
|
||||||
{
|
{
|
||||||
// Specify the region to extract based on a starting position and the desired region sze.
|
// Specify the region to extract based on a starting position and the desired region sze.
|
||||||
PolyVox::Region regToExtract(x, y, z, x + extractedRegionSize, y + extractedRegionSize, z + extractedRegionSize);
|
PolyVox::Region regToExtract(x, y, z, x + extractedRegionSize, y + extractedRegionSize, z + extractedRegionSize);
|
||||||
|
|
||||||
// If you uncomment this line you will be able to see that the volume is rendered as multiple seperate meshes.
|
// If you uncomment this line you will be able to see that the volume is rendered as multiple seperate meshes.
|
||||||
//regToExtract.shrink(1);
|
//regToExtract.shrink(1);
|
||||||
|
|
||||||
// Perform the extraction for this region of the volume
|
// Perform the extraction for this region of the volume
|
||||||
auto mesh = extractMarchingCubesMesh(&volData, regToExtract);
|
auto mesh = extractMarchingCubesMesh(&volData, regToExtract);
|
||||||
|
|
||||||
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
auto decodedMesh = decodeMesh(mesh);
|
auto decodedMesh = decodeMesh(mesh);
|
||||||
|
|
||||||
// Pass the surface to the OpenGL window. Note that we are also passing an offset in this multi-mesh example. This is because
|
// Pass the surface to the OpenGL window. Note that we are also passing an offset in this multi-mesh example. This is because
|
||||||
// the surface extractors return a mesh with 'local space' positions to reduce storage requirements and precision problems.
|
// the surface extractors return a mesh with 'local space' positions to reduce storage requirements and precision problems.
|
||||||
openGLWidget.addMesh(decodedMesh, decodedMesh.getOffset());
|
openGLWidget.addMesh(decodedMesh, decodedMesh.getOffset());
|
||||||
|
|
||||||
meshCounter++;
|
meshCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "Rendering volume as " << meshCounter << " seperate meshes" << endl;
|
cout << "Rendering volume as " << meshCounter << " seperate meshes" << endl;
|
||||||
|
|
||||||
|
|
||||||
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,79 +1,79 @@
|
|||||||
# Copyright (c) 2010-2012 David Williams
|
# Copyright (c) 2010-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(PagingExample)
|
PROJECT(PagingExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
Perlin.cpp
|
Perlin.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
Perlin.h
|
Perlin.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL REQUIRED)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
||||||
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
#This will include the shader files inside the compiled binary
|
||||||
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(PagingExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(PagingExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(PagingExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
SET_TARGET_PROPERTIES(PagingExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(PagingExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET PagingExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
configure_file(../common/example.vert example.vert COPYONLY)
|
configure_file(../common/example.vert example.vert COPYONLY)
|
||||||
configure_file(../common/example.frag example.frag COPYONLY)
|
configure_file(../common/example.frag example.frag COPYONLY)
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS PagingExample
|
INSTALL(TARGETS PagingExample
|
||||||
RUNTIME DESTINATION Examples/OpenGL/bin
|
RUNTIME DESTINATION Examples/OpenGL/bin
|
||||||
LIBRARY DESTINATION Examples/OpenGL/lib
|
LIBRARY DESTINATION Examples/OpenGL/lib
|
||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
COMPONENT example
|
||||||
)
|
)
|
||||||
|
|
||||||
#.dlls should be installed in shared builds.
|
#.dlls should be installed in shared builds.
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
|
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,265 +1,265 @@
|
|||||||
// Code from http://www.flipcode.com/archives/Perlin_Noise_Class.shtml
|
// Code from http://www.flipcode.com/archives/Perlin_Noise_Class.shtml
|
||||||
// This is only in PolyVox for the purpose of the examples. It was not written by
|
// This is only in PolyVox for the purpose of the examples. It was not written by
|
||||||
// the PolyVox authors and cannot be assumed to be under the same license as PolyVox.
|
// the PolyVox authors and cannot be assumed to be under the same license as PolyVox.
|
||||||
|
|
||||||
/* coherent noise function over 1, 2 or 3 dimensions */
|
/* coherent noise function over 1, 2 or 3 dimensions */
|
||||||
/* (copyright Ken Perlin) */
|
/* (copyright Ken Perlin) */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "Perlin.h"
|
#include "Perlin.h"
|
||||||
|
|
||||||
#define B SAMPLE_SIZE
|
#define B SAMPLE_SIZE
|
||||||
#define BM (SAMPLE_SIZE-1)
|
#define BM (SAMPLE_SIZE-1)
|
||||||
|
|
||||||
#define N 0x1000
|
#define N 0x1000
|
||||||
#define NP 12 /* 2^N */
|
#define NP 12 /* 2^N */
|
||||||
#define NM 0xfff
|
#define NM 0xfff
|
||||||
|
|
||||||
#define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
|
#define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
|
||||||
#define lerp(t, a, b) ( a + t * (b - a) )
|
#define lerp(t, a, b) ( a + t * (b - a) )
|
||||||
|
|
||||||
#define setup(i,b0,b1,r0,r1)\
|
#define setup(i,b0,b1,r0,r1)\
|
||||||
t = vec[i] + N;\
|
t = vec[i] + N;\
|
||||||
b0 = ((int)t) & BM;\
|
b0 = ((int)t) & BM;\
|
||||||
b1 = (b0+1) & BM;\
|
b1 = (b0+1) & BM;\
|
||||||
r0 = t - (int)t;\
|
r0 = t - (int)t;\
|
||||||
r1 = r0 - 1.0f;
|
r1 = r0 - 1.0f;
|
||||||
|
|
||||||
float Perlin::noise1(float arg)
|
float Perlin::noise1(float arg)
|
||||||
{
|
{
|
||||||
int bx0, bx1;
|
int bx0, bx1;
|
||||||
float rx0, rx1, sx, t, u, v, vec[1];
|
float rx0, rx1, sx, t, u, v, vec[1];
|
||||||
|
|
||||||
vec[0] = arg;
|
vec[0] = arg;
|
||||||
|
|
||||||
if (mStart)
|
if (mStart)
|
||||||
{
|
{
|
||||||
srand(mSeed);
|
srand(mSeed);
|
||||||
mStart = false;
|
mStart = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0, bx0,bx1, rx0,rx1);
|
setup(0, bx0,bx1, rx0,rx1);
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
|
|
||||||
u = rx0 * g1[ p[ bx0 ] ];
|
u = rx0 * g1[ p[ bx0 ] ];
|
||||||
v = rx1 * g1[ p[ bx1 ] ];
|
v = rx1 * g1[ p[ bx1 ] ];
|
||||||
|
|
||||||
return lerp(sx, u, v);
|
return lerp(sx, u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Perlin::noise2(float vec[2])
|
float Perlin::noise2(float vec[2])
|
||||||
{
|
{
|
||||||
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
||||||
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (mStart)
|
if (mStart)
|
||||||
{
|
{
|
||||||
srand(mSeed);
|
srand(mSeed);
|
||||||
mStart = false;
|
mStart = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0,bx0,bx1,rx0,rx1);
|
setup(0,bx0,bx1,rx0,rx1);
|
||||||
setup(1,by0,by1,ry0,ry1);
|
setup(1,by0,by1,ry0,ry1);
|
||||||
|
|
||||||
i = p[bx0];
|
i = p[bx0];
|
||||||
j = p[bx1];
|
j = p[bx1];
|
||||||
|
|
||||||
b00 = p[i + by0];
|
b00 = p[i + by0];
|
||||||
b10 = p[j + by0];
|
b10 = p[j + by0];
|
||||||
b01 = p[i + by1];
|
b01 = p[i + by1];
|
||||||
b11 = p[j + by1];
|
b11 = p[j + by1];
|
||||||
|
|
||||||
sx = s_curve(rx0);
|
sx = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
|
|
||||||
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
|
||||||
|
|
||||||
q = g2[b00];
|
q = g2[b00];
|
||||||
u = at2(rx0,ry0);
|
u = at2(rx0,ry0);
|
||||||
q = g2[b10];
|
q = g2[b10];
|
||||||
v = at2(rx1,ry0);
|
v = at2(rx1,ry0);
|
||||||
a = lerp(sx, u, v);
|
a = lerp(sx, u, v);
|
||||||
|
|
||||||
q = g2[b01];
|
q = g2[b01];
|
||||||
u = at2(rx0,ry1);
|
u = at2(rx0,ry1);
|
||||||
q = g2[b11];
|
q = g2[b11];
|
||||||
v = at2(rx1,ry1);
|
v = at2(rx1,ry1);
|
||||||
b = lerp(sx, u, v);
|
b = lerp(sx, u, v);
|
||||||
|
|
||||||
return lerp(sy, a, b);
|
return lerp(sy, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Perlin::noise3(float vec[3])
|
float Perlin::noise3(float vec[3])
|
||||||
{
|
{
|
||||||
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
||||||
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (mStart)
|
if (mStart)
|
||||||
{
|
{
|
||||||
srand(mSeed);
|
srand(mSeed);
|
||||||
mStart = false;
|
mStart = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(0, bx0,bx1, rx0,rx1);
|
setup(0, bx0,bx1, rx0,rx1);
|
||||||
setup(1, by0,by1, ry0,ry1);
|
setup(1, by0,by1, ry0,ry1);
|
||||||
setup(2, bz0,bz1, rz0,rz1);
|
setup(2, bz0,bz1, rz0,rz1);
|
||||||
|
|
||||||
i = p[ bx0 ];
|
i = p[ bx0 ];
|
||||||
j = p[ bx1 ];
|
j = p[ bx1 ];
|
||||||
|
|
||||||
b00 = p[ i + by0 ];
|
b00 = p[ i + by0 ];
|
||||||
b10 = p[ j + by0 ];
|
b10 = p[ j + by0 ];
|
||||||
b01 = p[ i + by1 ];
|
b01 = p[ i + by1 ];
|
||||||
b11 = p[ j + by1 ];
|
b11 = p[ j + by1 ];
|
||||||
|
|
||||||
t = s_curve(rx0);
|
t = s_curve(rx0);
|
||||||
sy = s_curve(ry0);
|
sy = s_curve(ry0);
|
||||||
sz = s_curve(rz0);
|
sz = s_curve(rz0);
|
||||||
|
|
||||||
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
||||||
|
|
||||||
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
|
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
|
||||||
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
|
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
|
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
|
||||||
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
|
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
c = lerp(sy, a, b);
|
c = lerp(sy, a, b);
|
||||||
|
|
||||||
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
|
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
|
||||||
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
|
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
|
||||||
a = lerp(t, u, v);
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
|
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
|
||||||
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
|
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
|
||||||
b = lerp(t, u, v);
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
d = lerp(sy, a, b);
|
d = lerp(sy, a, b);
|
||||||
|
|
||||||
return lerp(sz, c, d);
|
return lerp(sz, c, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perlin::normalize2(float v[2])
|
void Perlin::normalize2(float v[2])
|
||||||
{
|
{
|
||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
|
s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
s = 1.0f/s;
|
s = 1.0f/s;
|
||||||
v[0] = v[0] * s;
|
v[0] = v[0] * s;
|
||||||
v[1] = v[1] * s;
|
v[1] = v[1] * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perlin::normalize3(float v[3])
|
void Perlin::normalize3(float v[3])
|
||||||
{
|
{
|
||||||
float s;
|
float s;
|
||||||
|
|
||||||
s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
s = 1.0f/s;
|
s = 1.0f/s;
|
||||||
|
|
||||||
v[0] = v[0] * s;
|
v[0] = v[0] * s;
|
||||||
v[1] = v[1] * s;
|
v[1] = v[1] * s;
|
||||||
v[2] = v[2] * s;
|
v[2] = v[2] * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perlin::init(void)
|
void Perlin::init(void)
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
for (i = 0 ; i < B ; i++)
|
for (i = 0 ; i < B ; i++)
|
||||||
{
|
{
|
||||||
p[i] = i;
|
p[i] = i;
|
||||||
g1[i] = (float)((rand() % (B + B)) - B) / B;
|
g1[i] = (float)((rand() % (B + B)) - B) / B;
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[i][j] = (float)((rand() % (B + B)) - B) / B;
|
g2[i][j] = (float)((rand() % (B + B)) - B) / B;
|
||||||
normalize2(g2[i]);
|
normalize2(g2[i]);
|
||||||
for (j = 0 ; j < 3 ; j++)
|
for (j = 0 ; j < 3 ; j++)
|
||||||
g3[i][j] = (float)((rand() % (B + B)) - B) / B;
|
g3[i][j] = (float)((rand() % (B + B)) - B) / B;
|
||||||
normalize3(g3[i]);
|
normalize3(g3[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (--i)
|
while (--i)
|
||||||
{
|
{
|
||||||
k = p[i];
|
k = p[i];
|
||||||
p[i] = p[j = rand() % B];
|
p[i] = p[j = rand() % B];
|
||||||
p[j] = k;
|
p[j] = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < B + 2 ; i++)
|
for (i = 0 ; i < B + 2 ; i++)
|
||||||
{
|
{
|
||||||
p[B + i] = p[i];
|
p[B + i] = p[i];
|
||||||
g1[B + i] = g1[i];
|
g1[B + i] = g1[i];
|
||||||
for (j = 0 ; j < 2 ; j++)
|
for (j = 0 ; j < 2 ; j++)
|
||||||
g2[B + i][j] = g2[i][j];
|
g2[B + i][j] = g2[i][j];
|
||||||
for (j = 0 ; j < 3 ; j++)
|
for (j = 0 ; j < 3 ; j++)
|
||||||
g3[B + i][j] = g3[i][j];
|
g3[B + i][j] = g3[i][j];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float Perlin::perlin_noise_2D(float vec[2])
|
float Perlin::perlin_noise_2D(float vec[2])
|
||||||
{
|
{
|
||||||
int terms = mOctaves;
|
int terms = mOctaves;
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
float amp = mAmplitude;
|
float amp = mAmplitude;
|
||||||
|
|
||||||
vec[0]*=mFrequency;
|
vec[0]*=mFrequency;
|
||||||
vec[1]*=mFrequency;
|
vec[1]*=mFrequency;
|
||||||
|
|
||||||
for( int i=0; i<terms; i++ )
|
for( int i=0; i<terms; i++ )
|
||||||
{
|
{
|
||||||
result += noise2(vec)*amp;
|
result += noise2(vec)*amp;
|
||||||
vec[0] *= 2.0f;
|
vec[0] *= 2.0f;
|
||||||
vec[1] *= 2.0f;
|
vec[1] *= 2.0f;
|
||||||
amp*=0.5f;
|
amp*=0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Perlin::perlin_noise_3D(float vec[3])
|
float Perlin::perlin_noise_3D(float vec[3])
|
||||||
{
|
{
|
||||||
int terms = mOctaves;
|
int terms = mOctaves;
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
float amp = mAmplitude;
|
float amp = mAmplitude;
|
||||||
|
|
||||||
vec[0]*=mFrequency;
|
vec[0]*=mFrequency;
|
||||||
vec[1]*=mFrequency;
|
vec[1]*=mFrequency;
|
||||||
vec[2]*=mFrequency;
|
vec[2]*=mFrequency;
|
||||||
|
|
||||||
for( int i=0; i<terms; i++ )
|
for( int i=0; i<terms; i++ )
|
||||||
{
|
{
|
||||||
result += noise3(vec)*amp;
|
result += noise3(vec)*amp;
|
||||||
vec[0] *= 2.0f;
|
vec[0] *= 2.0f;
|
||||||
vec[1] *= 2.0f;
|
vec[1] *= 2.0f;
|
||||||
vec[2] *= 2.0f;
|
vec[2] *= 2.0f;
|
||||||
amp*=0.5f;
|
amp*=0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Perlin::Perlin(int octaves,float freq,float amp,int seed)
|
Perlin::Perlin(int octaves,float freq,float amp,int seed)
|
||||||
{
|
{
|
||||||
mOctaves = octaves;
|
mOctaves = octaves;
|
||||||
mFrequency = freq;
|
mFrequency = freq;
|
||||||
mAmplitude = amp;
|
mAmplitude = amp;
|
||||||
mSeed = seed;
|
mSeed = seed;
|
||||||
mStart = true;
|
mStart = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,64 +1,64 @@
|
|||||||
// Code from http://www.flipcode.com/archives/Perlin_Noise_Class.shtml
|
// Code from http://www.flipcode.com/archives/Perlin_Noise_Class.shtml
|
||||||
// This is only in PolyVox for the purpose of the examples. It was not written by
|
// This is only in PolyVox for the purpose of the examples. It was not written by
|
||||||
// the PolyVox authors and cannot be assumed to be under the same license as PolyVox.
|
// the PolyVox authors and cannot be assumed to be under the same license as PolyVox.
|
||||||
|
|
||||||
#ifndef PERLIN_H_
|
#ifndef PERLIN_H_
|
||||||
|
|
||||||
#define PERLIN_H_
|
#define PERLIN_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#define SAMPLE_SIZE 1024
|
#define SAMPLE_SIZE 1024
|
||||||
|
|
||||||
class Perlin
|
class Perlin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Perlin(int octaves,float freq,float amp,int seed);
|
Perlin(int octaves,float freq,float amp,int seed);
|
||||||
|
|
||||||
|
|
||||||
float Get(float x,float y)
|
float Get(float x,float y)
|
||||||
{
|
{
|
||||||
float vec[2];
|
float vec[2];
|
||||||
vec[0] = x;
|
vec[0] = x;
|
||||||
vec[1] = y;
|
vec[1] = y;
|
||||||
return perlin_noise_2D(vec);
|
return perlin_noise_2D(vec);
|
||||||
};
|
};
|
||||||
|
|
||||||
float Get3D(float x,float y,float z)
|
float Get3D(float x,float y,float z)
|
||||||
{
|
{
|
||||||
float vec[3];
|
float vec[3];
|
||||||
vec[0] = x;
|
vec[0] = x;
|
||||||
vec[1] = y;
|
vec[1] = y;
|
||||||
vec[2] = z;
|
vec[2] = z;
|
||||||
return perlin_noise_3D(vec);
|
return perlin_noise_3D(vec);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init_perlin(int n,float p);
|
void init_perlin(int n,float p);
|
||||||
float perlin_noise_2D(float vec[2]);
|
float perlin_noise_2D(float vec[2]);
|
||||||
float perlin_noise_3D(float vec[3]);
|
float perlin_noise_3D(float vec[3]);
|
||||||
|
|
||||||
float noise1(float arg);
|
float noise1(float arg);
|
||||||
float noise2(float vec[2]);
|
float noise2(float vec[2]);
|
||||||
float noise3(float vec[3]);
|
float noise3(float vec[3]);
|
||||||
void normalize2(float v[2]);
|
void normalize2(float v[2]);
|
||||||
void normalize3(float v[3]);
|
void normalize3(float v[3]);
|
||||||
void init(void);
|
void init(void);
|
||||||
|
|
||||||
int mOctaves;
|
int mOctaves;
|
||||||
float mFrequency;
|
float mFrequency;
|
||||||
float mAmplitude;
|
float mAmplitude;
|
||||||
int mSeed;
|
int mSeed;
|
||||||
|
|
||||||
int p[SAMPLE_SIZE + SAMPLE_SIZE + 2];
|
int p[SAMPLE_SIZE + SAMPLE_SIZE + 2];
|
||||||
float g3[SAMPLE_SIZE + SAMPLE_SIZE + 2][3];
|
float g3[SAMPLE_SIZE + SAMPLE_SIZE + 2][3];
|
||||||
float g2[SAMPLE_SIZE + SAMPLE_SIZE + 2][2];
|
float g2[SAMPLE_SIZE + SAMPLE_SIZE + 2][2];
|
||||||
float g1[SAMPLE_SIZE + SAMPLE_SIZE + 2];
|
float g1[SAMPLE_SIZE + SAMPLE_SIZE + 2];
|
||||||
bool mStart;
|
bool mStart;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,186 +1,186 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
#include "Perlin.h"
|
#include "Perlin.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/MaterialDensityPair.h"
|
#include "PolyVoxCore/MaterialDensityPair.h"
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
#include "PolyVoxCore/CubicSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(PagedVolume<MaterialDensityPair44>& volData, Vector3DFloat v3dVolCenter, float fRadius)
|
void createSphereInVolume(PagedVolume<MaterialDensityPair44>& volData, Vector3DFloat v3dVolCenter, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
int iRadius = fRadius;
|
int iRadius = fRadius;
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = v3dVolCenter.getZ() - iRadius; z <= v3dVolCenter.getZ() + iRadius; z++)
|
for (int z = v3dVolCenter.getZ() - iRadius; z <= v3dVolCenter.getZ() + iRadius; z++)
|
||||||
{
|
{
|
||||||
for (int y = v3dVolCenter.getY() - iRadius; y <= v3dVolCenter.getY() + iRadius; y++)
|
for (int y = v3dVolCenter.getY() - iRadius; y <= v3dVolCenter.getY() + iRadius; y++)
|
||||||
{
|
{
|
||||||
for (int x = v3dVolCenter.getX() - iRadius; x <= v3dVolCenter.getX() + iRadius; x++)
|
for (int x = v3dVolCenter.getX() - iRadius; x <= v3dVolCenter.getX() + iRadius; x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x,y,z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
//If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new density value
|
//Our new density value
|
||||||
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
||||||
|
|
||||||
//Get the old voxel
|
//Get the old voxel
|
||||||
MaterialDensityPair44 voxel = volData.getVoxel(x,y,z);
|
MaterialDensityPair44 voxel = volData.getVoxel(x,y,z);
|
||||||
|
|
||||||
//Modify the density
|
//Modify the density
|
||||||
voxel.setDensity(uDensity);
|
voxel.setDensity(uDensity);
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, voxel);
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates data using Perlin noise.
|
* Generates data using Perlin noise.
|
||||||
*/
|
*/
|
||||||
class PerlinNoisePager : public PolyVox::PagedVolume<MaterialDensityPair44>::Pager
|
class PerlinNoisePager : public PolyVox::PagedVolume<MaterialDensityPair44>::Pager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
PerlinNoisePager()
|
PerlinNoisePager()
|
||||||
:PagedVolume<MaterialDensityPair44>::Pager()
|
:PagedVolume<MaterialDensityPair44>::Pager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~PerlinNoisePager() {};
|
virtual ~PerlinNoisePager() {};
|
||||||
|
|
||||||
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk)
|
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk)
|
||||||
{
|
{
|
||||||
Perlin perlin(2,2,1,234);
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
for(int x = region.getLowerX(); x <= region.getUpperX(); x++)
|
for(int x = region.getLowerX(); x <= region.getUpperX(); x++)
|
||||||
{
|
{
|
||||||
for(int y = region.getLowerY(); y <= region.getUpperY(); y++)
|
for(int y = region.getLowerY(); y <= region.getUpperY(); y++)
|
||||||
{
|
{
|
||||||
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
||||||
perlinVal += 1.0f;
|
perlinVal += 1.0f;
|
||||||
perlinVal *= 0.5f;
|
perlinVal *= 0.5f;
|
||||||
perlinVal *= 255;
|
perlinVal *= 255;
|
||||||
for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
|
for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++)
|
||||||
{
|
{
|
||||||
MaterialDensityPair44 voxel;
|
MaterialDensityPair44 voxel;
|
||||||
if(z < perlinVal)
|
if(z < perlinVal)
|
||||||
{
|
{
|
||||||
const int xpos = 50;
|
const int xpos = 50;
|
||||||
const int zpos = 100;
|
const int zpos = 100;
|
||||||
if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) {
|
if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) {
|
||||||
// tunnel
|
// tunnel
|
||||||
voxel.setMaterial(0);
|
voxel.setMaterial(0);
|
||||||
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
} else {
|
} else {
|
||||||
// solid
|
// solid
|
||||||
voxel.setMaterial(245);
|
voxel.setMaterial(245);
|
||||||
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
voxel.setMaterial(0);
|
voxel.setMaterial(0);
|
||||||
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15)
|
// Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15)
|
||||||
// then the valid chunk voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the
|
// then the valid chunk voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the
|
||||||
// region from the volume space position in order to get the chunk space position.
|
// region from the volume space position in order to get the chunk space position.
|
||||||
pChunk->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
pChunk->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/)
|
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/)
|
||||||
{
|
{
|
||||||
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
PerlinNoisePager* pager = new PerlinNoisePager();
|
PerlinNoisePager* pager = new PerlinNoisePager();
|
||||||
PagedVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion, pager, 64);
|
PagedVolume<MaterialDensityPair44> volData(PolyVox::Region::MaxRegion, pager, 64);
|
||||||
volData.setMemoryUsageLimit(8 * 1024 * 1024); // 8Mb
|
volData.setMemoryUsageLimit(8 * 1024 * 1024); // 8Mb
|
||||||
|
|
||||||
//createSphereInVolume(volData, 30);
|
//createSphereInVolume(volData, 30);
|
||||||
//createPerlinTerrain(volData);
|
//createPerlinTerrain(volData);
|
||||||
//createPerlinVolumeSlow(volData);
|
//createPerlinVolumeSlow(volData);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,255,255));
|
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,255,255));
|
||||||
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
volData.prefetch(reg);
|
volData.prefetch(reg);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(255,255,255));
|
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(255,255,255));
|
||||||
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
||||||
volData.flush(reg2);
|
volData.flush(reg2);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
std::cout << "Flushing entire volume" << std::endl;
|
std::cout << "Flushing entire volume" << std::endl;
|
||||||
volData.flushAll();
|
volData.flushAll();
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
//std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
auto mesh = extractCubicMesh(&volData, reg2);
|
auto mesh = extractCubicMesh(&volData, reg2);
|
||||||
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
||||||
|
|
||||||
auto decodedMesh = decodeMesh(mesh);
|
auto decodedMesh = decodeMesh(mesh);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.addMesh(decodedMesh);
|
openGLWidget.addMesh(decodedMesh);
|
||||||
|
|
||||||
openGLWidget.setViewableRegion(reg2);
|
openGLWidget.setViewableRegion(reg2);
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
# Copyright (c) 2010-2013 Matt Williams
|
# Copyright (c) 2010-2013 Matt Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
PROJECT(PythonExample)
|
PROJECT(PythonExample)
|
||||||
|
|
||||||
configure_file(PythonExample.py PythonExample.py COPYONLY)
|
configure_file(PythonExample.py PythonExample.py COPYONLY)
|
||||||
|
@ -1,77 +1,77 @@
|
|||||||
# Copyright (c) 2010-2012 David Williams
|
# Copyright (c) 2010-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(SmoothLODExample)
|
PROJECT(SmoothLODExample)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(SRC_FILES
|
SET(SRC_FILES
|
||||||
main.cpp
|
main.cpp
|
||||||
../common/OpenGLWidget.cpp
|
../common/OpenGLWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(INC_FILES
|
SET(INC_FILES
|
||||||
OpenGLWidget.h
|
OpenGLWidget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGLEW_STATIC)
|
add_definitions(-DGLEW_STATIC)
|
||||||
|
|
||||||
FIND_PACKAGE(OpenGL REQUIRED)
|
FIND_PACKAGE(OpenGL REQUIRED)
|
||||||
|
|
||||||
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
#Tell CMake the paths for OpenGL and for PolyVox (which is just relative to our current location)
|
||||||
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR} ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${GLEW_SOURCE_DIR})
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#This will include the shader files inside the compiled binary
|
#This will include the shader files inside the compiled binary
|
||||||
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
|
||||||
|
|
||||||
# Put the resources in a seperate folder in Visual Studio
|
# Put the resources in a seperate folder in Visual Studio
|
||||||
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
|
||||||
|
|
||||||
#Build
|
#Build
|
||||||
ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
ADD_EXECUTABLE(SmoothLODExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(SmoothLODExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings
|
SET_TARGET_PROPERTIES(SmoothLODExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127") #All warnings
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
TARGET_LINK_LIBRARIES(SmoothLODExample glew ${QT_LIBRARIES} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples")
|
SET_PROPERTY(TARGET SmoothLODExample PROPERTY FOLDER "Examples")
|
||||||
|
|
||||||
configure_file(../common/example.vert example.vert COPYONLY)
|
configure_file(../common/example.vert example.vert COPYONLY)
|
||||||
configure_file(../common/example.frag example.frag COPYONLY)
|
configure_file(../common/example.frag example.frag COPYONLY)
|
||||||
|
|
||||||
#Install - Only install the example in Windows
|
#Install - Only install the example in Windows
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS SmoothLODExample
|
INSTALL(TARGETS SmoothLODExample
|
||||||
RUNTIME DESTINATION Examples/OpenGL/bin
|
RUNTIME DESTINATION Examples/OpenGL/bin
|
||||||
LIBRARY DESTINATION Examples/OpenGL/lib
|
LIBRARY DESTINATION Examples/OpenGL/lib
|
||||||
ARCHIVE DESTINATION Examples/OpenGL/lib
|
ARCHIVE DESTINATION Examples/OpenGL/lib
|
||||||
COMPONENT example
|
COMPONENT example
|
||||||
)
|
)
|
||||||
|
|
||||||
#.dlls should be installed in shared builds.
|
#.dlls should be installed in shared builds.
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../release/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Release)
|
||||||
|
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxCore.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
#INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/../../debug/PolyVoxUtil.dll DESTINATION Examples/OpenGL/bin CONFIGURATIONS Debug)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,110 +1,110 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Density.h"
|
#include "PolyVoxCore/Density.h"
|
||||||
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
#include "PolyVoxCore/MarchingCubesSurfaceExtractor.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/RawVolume.h"
|
#include "PolyVoxCore/RawVolume.h"
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
#include "PolyVoxCore/VolumeResampler.h"
|
#include "PolyVoxCore/VolumeResampler.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
void createSphereInVolume(PagedVolume<uint8_t>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getDepth(); z++)
|
for (int z = 0; z < volData.getDepth(); z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < volData.getHeight(); y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getWidth(); x++)
|
for (int x = 0; x < volData.getWidth(); x++)
|
||||||
{
|
{
|
||||||
//Store our current position as a vector...
|
//Store our current position as a vector...
|
||||||
Vector3DFloat v3dCurrentPos(x,y,z);
|
Vector3DFloat v3dCurrentPos(x,y,z);
|
||||||
//And compute how far the current position is from the center of the volume
|
//And compute how far the current position is from the center of the volume
|
||||||
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
|
||||||
|
|
||||||
if(fDistToCenter <= fRadius)
|
if(fDistToCenter <= fRadius)
|
||||||
{
|
{
|
||||||
//Our new density value
|
//Our new density value
|
||||||
uint8_t uDensity = std::numeric_limits<uint8_t>::max();
|
uint8_t uDensity = std::numeric_limits<uint8_t>::max();
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Wrte the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, uDensity);
|
volData.setVoxelAt(x, y, z, uDensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//144 in the middle, (144 - 32) at the edges. Threshold of 128 is between these
|
//144 in the middle, (144 - 32) at the edges. Threshold of 128 is between these
|
||||||
//volData.setVoxelAt(x, y, z, 144 - fDistToCenter);
|
//volData.setVoxelAt(x, y, z, 144 - fDistToCenter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//Create an empty volume and then place a sphere in it
|
||||||
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
PagedVolume<uint8_t> volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
createSphereInVolume(volData, 28);
|
createSphereInVolume(volData, 28);
|
||||||
|
|
||||||
//Smooth the data - should reimplement this using LowPassFilter
|
//Smooth the data - should reimplement this using LowPassFilter
|
||||||
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
//smoothRegion<PagedVolume, Density8>(volData, volData.getEnclosingRegion());
|
||||||
|
|
||||||
RawVolume<uint8_t> volDataLowLOD(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(15, 31, 31)));
|
RawVolume<uint8_t> volDataLowLOD(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(15, 31, 31)));
|
||||||
|
|
||||||
VolumeResampler< PagedVolume<uint8_t>, RawVolume<uint8_t> > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
VolumeResampler< PagedVolume<uint8_t>, RawVolume<uint8_t> > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
||||||
volumeResampler.execute();
|
volumeResampler.execute();
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
auto meshLowLOD = extractMarchingCubesMesh(&volDataLowLOD, volDataLowLOD.getEnclosingRegion());
|
||||||
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
auto decodedMeshLowLOD = decodeMesh(meshLowLOD);
|
auto decodedMeshLowLOD = decodeMesh(meshLowLOD);
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63)));
|
auto meshHighLOD = extractMarchingCubesMesh(&volData, PolyVox::Region(Vector3DInt32(30, 0, 0), Vector3DInt32(63, 63, 63)));
|
||||||
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
// The returned mesh needs to be decoded to be appropriate for GPU rendering.
|
||||||
auto decodedMeshHighLOD = decodeMesh(meshHighLOD);
|
auto decodedMeshHighLOD = decodeMesh(meshHighLOD);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.addMesh(decodedMeshHighLOD, Vector3DInt32(30, 0, 0));
|
openGLWidget.addMesh(decodedMeshHighLOD, Vector3DInt32(30, 0, 0));
|
||||||
openGLWidget.addMesh(decodedMeshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f);
|
openGLWidget.addMesh(decodedMeshLowLOD, Vector3DInt32(0, 0, 0), 63.0f / 31.0f);
|
||||||
|
|
||||||
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
openGLWidget.setViewableRegion(volData.getEnclosingRegion());
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,196 +1,196 @@
|
|||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
//#include <QtMath>
|
//#include <QtMath>
|
||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Public functions
|
// Public functions
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
||||||
:QGLWidget(parent)
|
:QGLWidget(parent)
|
||||||
,m_viewableRegion(PolyVox::Region(0, 0, 0, 255, 255, 255))
|
,m_viewableRegion(PolyVox::Region(0, 0, 0, 255, 255, 255))
|
||||||
,m_xRotation(0)
|
,m_xRotation(0)
|
||||||
,m_yRotation(0)
|
,m_yRotation(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::setShader(QSharedPointer<QGLShaderProgram> shader)
|
void OpenGLWidget::setShader(QSharedPointer<QGLShaderProgram> shader)
|
||||||
{
|
{
|
||||||
mShader = shader;
|
mShader = shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::setViewableRegion(PolyVox::Region viewableRegion)
|
void OpenGLWidget::setViewableRegion(PolyVox::Region viewableRegion)
|
||||||
{
|
{
|
||||||
m_viewableRegion = viewableRegion;
|
m_viewableRegion = viewableRegion;
|
||||||
|
|
||||||
// The user has specifed a new viewable region
|
// The user has specifed a new viewable region
|
||||||
// so we need to regenerate our camera matrix.
|
// so we need to regenerate our camera matrix.
|
||||||
setupWorldToCameraMatrix();
|
setupWorldToCameraMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::mousePressEvent(QMouseEvent* event)
|
void OpenGLWidget::mousePressEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
// Initialise these variables which will be used when the mouse actually moves.
|
// Initialise these variables which will be used when the mouse actually moves.
|
||||||
m_CurrentMousePos = event->pos();
|
m_CurrentMousePos = event->pos();
|
||||||
m_LastFrameMousePos = m_CurrentMousePos;
|
m_LastFrameMousePos = m_CurrentMousePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::mouseMoveEvent(QMouseEvent* event)
|
void OpenGLWidget::mouseMoveEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
// Update the x and y rotations based on the mouse movement.
|
// Update the x and y rotations based on the mouse movement.
|
||||||
m_CurrentMousePos = event->pos();
|
m_CurrentMousePos = event->pos();
|
||||||
QPoint diff = m_CurrentMousePos - m_LastFrameMousePos;
|
QPoint diff = m_CurrentMousePos - m_LastFrameMousePos;
|
||||||
m_xRotation += diff.x();
|
m_xRotation += diff.x();
|
||||||
m_yRotation += diff.y();
|
m_yRotation += diff.y();
|
||||||
m_LastFrameMousePos = m_CurrentMousePos;
|
m_LastFrameMousePos = m_CurrentMousePos;
|
||||||
|
|
||||||
// The camera rotation has changed so we need to regenerate the matrix.
|
// The camera rotation has changed so we need to regenerate the matrix.
|
||||||
setupWorldToCameraMatrix();
|
setupWorldToCameraMatrix();
|
||||||
|
|
||||||
// Re-render.
|
// Re-render.
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Protected functions
|
// Protected functions
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void OpenGLWidget::initializeGL()
|
void OpenGLWidget::initializeGL()
|
||||||
{
|
{
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
if (GLEW_OK != err)
|
if (GLEW_OK != err)
|
||||||
{
|
{
|
||||||
/* Problem: glewInit failed, something is seriously wrong. */
|
/* Problem: glewInit failed, something is seriously wrong. */
|
||||||
std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl;
|
std::cout << "GLEW Error: " << glewGetErrorString(err) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Print out some information about the OpenGL implementation.
|
//Print out some information about the OpenGL implementation.
|
||||||
std::cout << "OpenGL Implementation Details:" << std::endl;
|
std::cout << "OpenGL Implementation Details:" << std::endl;
|
||||||
if(glGetString(GL_VENDOR))
|
if(glGetString(GL_VENDOR))
|
||||||
std::cout << "\tGL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
|
std::cout << "\tGL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
|
||||||
if(glGetString(GL_RENDERER))
|
if(glGetString(GL_RENDERER))
|
||||||
std::cout << "\tGL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
|
std::cout << "\tGL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
|
||||||
if(glGetString(GL_VERSION))
|
if(glGetString(GL_VERSION))
|
||||||
std::cout << "\tGL_VERSION: " << glGetString(GL_VERSION) << std::endl;
|
std::cout << "\tGL_VERSION: " << glGetString(GL_VERSION) << std::endl;
|
||||||
if(glGetString(GL_SHADING_LANGUAGE_VERSION))
|
if(glGetString(GL_SHADING_LANGUAGE_VERSION))
|
||||||
std::cout << "\tGL_SHADING_LANGUAGE_VERSION: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
|
std::cout << "\tGL_SHADING_LANGUAGE_VERSION: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
|
||||||
|
|
||||||
//Set up the clear colour
|
//Set up the clear colour
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
glClearDepth(1.0f);
|
glClearDepth(1.0f);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
glDepthRange(0.0, 1.0);
|
glDepthRange(0.0, 1.0);
|
||||||
|
|
||||||
mShader = QSharedPointer<QGLShaderProgram>(new QGLShaderProgram);
|
mShader = QSharedPointer<QGLShaderProgram>(new QGLShaderProgram);
|
||||||
|
|
||||||
// This is basically a simple fallback vertex shader which does the most basic rendering possible.
|
// This is basically a simple fallback vertex shader which does the most basic rendering possible.
|
||||||
// PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired.
|
// PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired.
|
||||||
if (!mShader->addShaderFromSourceFile(QGLShader::Vertex, ":/example.vert"))
|
if (!mShader->addShaderFromSourceFile(QGLShader::Vertex, ":/example.vert"))
|
||||||
{
|
{
|
||||||
std::cerr << mShader->log().toStdString() << std::endl;
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is basically a simple fallback fragment shader which does the most basic rendering possible.
|
// This is basically a simple fallback fragment shader which does the most basic rendering possible.
|
||||||
// PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired.
|
// PolyVox examples are able to provide their own shaders to demonstrate certain effects if desired.
|
||||||
if (!mShader->addShaderFromSourceFile(QGLShader::Fragment, ":/example.frag"))
|
if (!mShader->addShaderFromSourceFile(QGLShader::Fragment, ":/example.frag"))
|
||||||
{
|
{
|
||||||
std::cerr << mShader->log().toStdString() << std::endl;
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind the position semantic - this is defined in the vertex shader above.
|
// Bind the position semantic - this is defined in the vertex shader above.
|
||||||
mShader->bindAttributeLocation("position", 0);
|
mShader->bindAttributeLocation("position", 0);
|
||||||
|
|
||||||
// Bind the other semantics. Note that these don't actually exist in our example shader above! However, other
|
// Bind the other semantics. Note that these don't actually exist in our example shader above! However, other
|
||||||
// example shaders may choose to provide them and having the binding code here does not seem to cause any problems.
|
// example shaders may choose to provide them and having the binding code here does not seem to cause any problems.
|
||||||
mShader->bindAttributeLocation("normal", 1);
|
mShader->bindAttributeLocation("normal", 1);
|
||||||
mShader->bindAttributeLocation("material", 2);
|
mShader->bindAttributeLocation("material", 2);
|
||||||
|
|
||||||
if (!mShader->link())
|
if (!mShader->link())
|
||||||
{
|
{
|
||||||
std::cerr << mShader->log().toStdString() << std::endl;
|
std::cerr << mShader->log().toStdString() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial setup of camera.
|
// Initial setup of camera.
|
||||||
setupWorldToCameraMatrix();
|
setupWorldToCameraMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::resizeGL(int w, int h)
|
void OpenGLWidget::resizeGL(int w, int h)
|
||||||
{
|
{
|
||||||
//Setup the viewport
|
//Setup the viewport
|
||||||
glViewport(0, 0, w, h);
|
glViewport(0, 0, w, h);
|
||||||
|
|
||||||
auto aspectRatio = w / (float)h;
|
auto aspectRatio = w / (float)h;
|
||||||
float zNear = 1.0;
|
float zNear = 1.0;
|
||||||
float zFar = 1000.0;
|
float zFar = 1000.0;
|
||||||
|
|
||||||
cameraToClipMatrix.setToIdentity();
|
cameraToClipMatrix.setToIdentity();
|
||||||
cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar);
|
cameraToClipMatrix.frustum(-aspectRatio, aspectRatio, -1, 1, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::paintGL()
|
void OpenGLWidget::paintGL()
|
||||||
{
|
{
|
||||||
//Clear the screen
|
//Clear the screen
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// Our example framework only uses a single shader for the scene (for all meshes).
|
// Our example framework only uses a single shader for the scene (for all meshes).
|
||||||
mShader->bind();
|
mShader->bind();
|
||||||
|
|
||||||
// These two matrices are constant for all meshes.
|
// These two matrices are constant for all meshes.
|
||||||
mShader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix);
|
mShader->setUniformValue("worldToCameraMatrix", worldToCameraMatrix);
|
||||||
mShader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix);
|
mShader->setUniformValue("cameraToClipMatrix", cameraToClipMatrix);
|
||||||
|
|
||||||
// Iterate over each mesh which the user added to our list, and render it.
|
// Iterate over each mesh which the user added to our list, and render it.
|
||||||
for (OpenGLMeshData meshData : mMeshData)
|
for (OpenGLMeshData meshData : mMeshData)
|
||||||
{
|
{
|
||||||
//Set up the model matrrix based on provided translation and scale.
|
//Set up the model matrrix based on provided translation and scale.
|
||||||
QMatrix4x4 modelToWorldMatrix;
|
QMatrix4x4 modelToWorldMatrix;
|
||||||
modelToWorldMatrix.translate(meshData.translation);
|
modelToWorldMatrix.translate(meshData.translation);
|
||||||
modelToWorldMatrix.scale(meshData.scale);
|
modelToWorldMatrix.scale(meshData.scale);
|
||||||
mShader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix);
|
mShader->setUniformValue("modelToWorldMatrix", modelToWorldMatrix);
|
||||||
|
|
||||||
// Bind the vertex array for the current mesh
|
// Bind the vertex array for the current mesh
|
||||||
glBindVertexArray(meshData.vertexArrayObject);
|
glBindVertexArray(meshData.vertexArrayObject);
|
||||||
// Draw the mesh
|
// Draw the mesh
|
||||||
glDrawElements(GL_TRIANGLES, meshData.noOfIndices, meshData.indexType, 0);
|
glDrawElements(GL_TRIANGLES, meshData.noOfIndices, meshData.indexType, 0);
|
||||||
// Unbind the vertex array.
|
// Unbind the vertex array.
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're done with the shader for this frame.
|
// We're done with the shader for this frame.
|
||||||
mShader->release();
|
mShader->release();
|
||||||
|
|
||||||
// Check for errors.
|
// Check for errors.
|
||||||
GLenum errCode = glGetError();
|
GLenum errCode = glGetError();
|
||||||
if(errCode != GL_NO_ERROR)
|
if(errCode != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
std::cerr << "OpenGL Error: " << errCode << std::endl;
|
std::cerr << "OpenGL Error: " << errCode << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Private functions
|
// Private functions
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void OpenGLWidget::setupWorldToCameraMatrix()
|
void OpenGLWidget::setupWorldToCameraMatrix()
|
||||||
{
|
{
|
||||||
QVector3D lowerCorner(m_viewableRegion.getLowerX(), m_viewableRegion.getLowerY(), m_viewableRegion.getLowerZ());
|
QVector3D lowerCorner(m_viewableRegion.getLowerX(), m_viewableRegion.getLowerY(), m_viewableRegion.getLowerZ());
|
||||||
QVector3D upperCorner(m_viewableRegion.getUpperX(), m_viewableRegion.getUpperY(), m_viewableRegion.getUpperZ());
|
QVector3D upperCorner(m_viewableRegion.getUpperX(), m_viewableRegion.getUpperY(), m_viewableRegion.getUpperZ());
|
||||||
|
|
||||||
QVector3D centerPoint = (lowerCorner + upperCorner) * 0.5;
|
QVector3D centerPoint = (lowerCorner + upperCorner) * 0.5;
|
||||||
float fDiagonalLength = (upperCorner - lowerCorner).length();
|
float fDiagonalLength = (upperCorner - lowerCorner).length();
|
||||||
|
|
||||||
worldToCameraMatrix.setToIdentity();
|
worldToCameraMatrix.setToIdentity();
|
||||||
worldToCameraMatrix.translate(0, 0, -fDiagonalLength / 2.0f); //Move the camera back by the required amount
|
worldToCameraMatrix.translate(0, 0, -fDiagonalLength / 2.0f); //Move the camera back by the required amount
|
||||||
worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis
|
worldToCameraMatrix.rotate(m_xRotation, 0, 1, 0); //rotate around y-axis
|
||||||
worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis
|
worldToCameraMatrix.rotate(m_yRotation, 1, 0, 0); //rotate around x-axis
|
||||||
worldToCameraMatrix.translate(-centerPoint); //centre the model on the origin
|
worldToCameraMatrix.translate(-centerPoint); //centre the model on the origin
|
||||||
}
|
}
|
@ -1,160 +1,160 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __BasicExample_OpenGLWidget_H__
|
#ifndef __BasicExample_OpenGLWidget_H__
|
||||||
#define __BasicExample_OpenGLWidget_H__
|
#define __BasicExample_OpenGLWidget_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
|
|
||||||
#include "glew/glew.h"
|
#include "glew/glew.h"
|
||||||
|
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <QGLShaderProgram>
|
#include <QGLShaderProgram>
|
||||||
|
|
||||||
// This structure holds all the data required
|
// This structure holds all the data required
|
||||||
// to render one of our meshes through OpenGL.
|
// to render one of our meshes through OpenGL.
|
||||||
struct OpenGLMeshData
|
struct OpenGLMeshData
|
||||||
{
|
{
|
||||||
GLuint noOfIndices;
|
GLuint noOfIndices;
|
||||||
GLenum indexType;
|
GLenum indexType;
|
||||||
GLuint indexBuffer;
|
GLuint indexBuffer;
|
||||||
GLuint vertexBuffer;
|
GLuint vertexBuffer;
|
||||||
GLuint vertexArrayObject;
|
GLuint vertexArrayObject;
|
||||||
QVector3D translation;
|
QVector3D translation;
|
||||||
float scale;
|
float scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Our OpenGLWidget is used by all the examples to render the extracted meshes. It is
|
// Our OpenGLWidget is used by all the examples to render the extracted meshes. It is
|
||||||
// fairly specific to our needs (you probably won't want to use it in your own project)
|
// fairly specific to our needs (you probably won't want to use it in your own project)
|
||||||
// but should provide a useful illustration of how PolyVox meshes can be rendered.
|
// but should provide a useful illustration of how PolyVox meshes can be rendered.
|
||||||
class OpenGLWidget : public QGLWidget
|
class OpenGLWidget : public QGLWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
OpenGLWidget(QWidget *parent);
|
OpenGLWidget(QWidget *parent);
|
||||||
|
|
||||||
// Convert a PolyVox mesh to OpenGL index/vertex buffers. Inlined because it's templatised.
|
// Convert a PolyVox mesh to OpenGL index/vertex buffers. Inlined because it's templatised.
|
||||||
template <typename MeshType>
|
template <typename MeshType>
|
||||||
void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
void addMesh(const MeshType& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f)
|
||||||
{
|
{
|
||||||
// Convienient access to the vertices and indices
|
// Convienient access to the vertices and indices
|
||||||
const auto& vecIndices = surfaceMesh.getIndices();
|
const auto& vecIndices = surfaceMesh.getIndices();
|
||||||
const auto& vecVertices = surfaceMesh.getVertices();
|
const auto& vecVertices = surfaceMesh.getVertices();
|
||||||
|
|
||||||
// This struct holds the OpenGL properties (buffer handles, etc) which will be used
|
// This struct holds the OpenGL properties (buffer handles, etc) which will be used
|
||||||
// to render our mesh. We copy the data from the PolyVox mesh into this structure.
|
// to render our mesh. We copy the data from the PolyVox mesh into this structure.
|
||||||
OpenGLMeshData meshData;
|
OpenGLMeshData meshData;
|
||||||
|
|
||||||
// Create the VAO for the mesh
|
// Create the VAO for the mesh
|
||||||
glGenVertexArrays(1, &(meshData.vertexArrayObject));
|
glGenVertexArrays(1, &(meshData.vertexArrayObject));
|
||||||
glBindVertexArray(meshData.vertexArrayObject);
|
glBindVertexArray(meshData.vertexArrayObject);
|
||||||
|
|
||||||
// The GL_ARRAY_BUFFER will contain the list of vertex positions
|
// The GL_ARRAY_BUFFER will contain the list of vertex positions
|
||||||
glGenBuffers(1, &(meshData.vertexBuffer));
|
glGenBuffers(1, &(meshData.vertexBuffer));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(typename MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(typename MeshType::VertexType), vecVertices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
// and GL_ELEMENT_ARRAY_BUFFER will contain the indices
|
// and GL_ELEMENT_ARRAY_BUFFER will contain the indices
|
||||||
glGenBuffers(1, &(meshData.indexBuffer));
|
glGenBuffers(1, &(meshData.indexBuffer));
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshData.indexBuffer);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(typename MeshType::IndexType), vecIndices.data(), GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(typename MeshType::IndexType), vecIndices.data(), GL_STATIC_DRAW);
|
||||||
|
|
||||||
// Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out
|
// Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out
|
||||||
glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions
|
glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type)
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type)
|
||||||
|
|
||||||
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor
|
// Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor
|
||||||
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the
|
// does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the
|
||||||
// shader. This is mostly just to simplify this example code - in a real application you will know whether your
|
// shader. This is mostly just to simplify this example code - in a real application you will know whether your
|
||||||
// chosen surface extractor generates normals and can skip uploading them if not.
|
// chosen surface extractor generates normals and can skip uploading them if not.
|
||||||
glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals.
|
glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals.
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal)));
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, normal)));
|
||||||
|
|
||||||
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code
|
// Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code
|
||||||
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here.
|
// we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here.
|
||||||
glEnableVertexAttribArray(2); //We're talking about shader attribute '2'
|
glEnableVertexAttribArray(2); //We're talking about shader attribute '2'
|
||||||
GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type)
|
GLint size = (std::min)(sizeof(typename MeshType::VertexType::DataType), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type)
|
||||||
glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data)));
|
glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(typename MeshType::VertexType), (GLvoid*)(offsetof(typename MeshType::VertexType, data)));
|
||||||
|
|
||||||
// We're done uploading and can now unbind.
|
// We're done uploading and can now unbind.
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
// A few additional properties can be copied across for use during rendering.
|
// A few additional properties can be copied across for use during rendering.
|
||||||
meshData.noOfIndices = vecIndices.size();
|
meshData.noOfIndices = vecIndices.size();
|
||||||
meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ());
|
meshData.translation = QVector3D(translation.getX(), translation.getY(), translation.getZ());
|
||||||
meshData.scale = scale;
|
meshData.scale = scale;
|
||||||
|
|
||||||
// Set 16 or 32-bit index buffer size.
|
// Set 16 or 32-bit index buffer size.
|
||||||
meshData.indexType = sizeof(typename MeshType::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
meshData.indexType = sizeof(typename MeshType::IndexType) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||||
|
|
||||||
// Now add the mesh to the list of meshes to render.
|
// Now add the mesh to the list of meshes to render.
|
||||||
addMeshData(meshData);
|
addMeshData(meshData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMeshData(OpenGLMeshData meshData)
|
void addMeshData(OpenGLMeshData meshData)
|
||||||
{
|
{
|
||||||
mMeshData.push_back(meshData);
|
mMeshData.push_back(meshData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For our purposes we use a single shader for the whole volume, and
|
// For our purposes we use a single shader for the whole volume, and
|
||||||
// this example framework is only meant to show a single volume at a time
|
// this example framework is only meant to show a single volume at a time
|
||||||
void setShader(QSharedPointer<QGLShaderProgram> shader);
|
void setShader(QSharedPointer<QGLShaderProgram> shader);
|
||||||
|
|
||||||
// The viewable region can be adjusted so that this example framework can be used for different volume sizes.
|
// The viewable region can be adjusted so that this example framework can be used for different volume sizes.
|
||||||
void setViewableRegion(PolyVox::Region viewableRegion);
|
void setViewableRegion(PolyVox::Region viewableRegion);
|
||||||
|
|
||||||
// Mouse handling
|
// Mouse handling
|
||||||
void mouseMoveEvent(QMouseEvent* event);
|
void mouseMoveEvent(QMouseEvent* event);
|
||||||
void mousePressEvent(QMouseEvent* event);
|
void mousePressEvent(QMouseEvent* event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Qt OpenGL functions
|
// Qt OpenGL functions
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void resizeGL(int w, int h);
|
void resizeGL(int w, int h);
|
||||||
void paintGL();
|
void paintGL();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void setupWorldToCameraMatrix();
|
void setupWorldToCameraMatrix();
|
||||||
|
|
||||||
// Index/vertex buffer data
|
// Index/vertex buffer data
|
||||||
std::vector<OpenGLMeshData> mMeshData;
|
std::vector<OpenGLMeshData> mMeshData;
|
||||||
|
|
||||||
QSharedPointer<QGLShaderProgram> mShader;
|
QSharedPointer<QGLShaderProgram> mShader;
|
||||||
|
|
||||||
// Matrices
|
// Matrices
|
||||||
QMatrix4x4 worldToCameraMatrix;
|
QMatrix4x4 worldToCameraMatrix;
|
||||||
QMatrix4x4 cameraToClipMatrix;
|
QMatrix4x4 cameraToClipMatrix;
|
||||||
|
|
||||||
// Mouse data
|
// Mouse data
|
||||||
QPoint m_LastFrameMousePos;
|
QPoint m_LastFrameMousePos;
|
||||||
QPoint m_CurrentMousePos;
|
QPoint m_CurrentMousePos;
|
||||||
|
|
||||||
// Camera setup
|
// Camera setup
|
||||||
PolyVox::Region m_viewableRegion;
|
PolyVox::Region m_viewableRegion;
|
||||||
int m_xRotation;
|
int m_xRotation;
|
||||||
int m_yRotation;
|
int m_yRotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__BasicExample_OpenGLWidget_H__
|
#endif //__BasicExample_OpenGLWidget_H__
|
||||||
|
@ -1,73 +1,73 @@
|
|||||||
The OpenGL Extension Wrangler Library
|
The OpenGL Extension Wrangler Library
|
||||||
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
|
||||||
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
|
||||||
Copyright (C) 2002, Lev Povalahev
|
Copyright (C) 2002, Lev Povalahev
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
this list of conditions and the following disclaimer.
|
this list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
* The name of the author may be used to endorse or promote products
|
* The name of the author may be used to endorse or promote products
|
||||||
derived from this software without specific prior written permission.
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
THE POSSIBILITY OF SUCH DAMAGE.
|
THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
Mesa 3-D graphics library
|
Mesa 3-D graphics library
|
||||||
Version: 7.0
|
Version: 7.0
|
||||||
|
|
||||||
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
to deal in the Software without restriction, including without limitation
|
to deal in the Software without restriction, including without limitation
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
Software is furnished to do so, subject to the following conditions:
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2007 The Khronos Group Inc.
|
Copyright (c) 2007 The Khronos Group Inc.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and/or associated documentation files (the
|
copy of this software and/or associated documentation files (the
|
||||||
"Materials"), to deal in the Materials without restriction, including
|
"Materials"), to deal in the Materials without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Materials, and to
|
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
permit persons to whom the Materials are furnished to do so, subject to
|
permit persons to whom the Materials are furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Materials.
|
in all copies or substantial portions of the Materials.
|
||||||
|
|
||||||
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,86 +1,86 @@
|
|||||||
# Copyright (c) 2008-2012 Matt Williams
|
# Copyright (c) 2008-2012 Matt Williams
|
||||||
# Copyright (c) 2008-2012 David Williams
|
# Copyright (c) 2008-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||||
|
|
||||||
PROJECT(PolyVox)
|
PROJECT(PolyVox)
|
||||||
|
|
||||||
add_subdirectory(PolyVoxCore)
|
add_subdirectory(PolyVoxCore)
|
||||||
add_subdirectory(PolyVoxUtil)
|
add_subdirectory(PolyVoxUtil)
|
||||||
add_subdirectory(bindings)
|
add_subdirectory(bindings)
|
||||||
|
|
||||||
#Set up install paths e.g. for PolyVoxConfig.cmake
|
#Set up install paths e.g. for PolyVoxConfig.cmake
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CONFIG_FILE_DIR "CMake")
|
set(CONFIG_FILE_DIR "CMake")
|
||||||
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "PolyVoxCore/lib")
|
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "PolyVoxCore/lib")
|
||||||
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "PolyVoxUtil/lib")
|
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "PolyVoxUtil/lib")
|
||||||
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "PolyVoxCore/include")
|
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "PolyVoxCore/include")
|
||||||
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "PolyVoxUtil/include")
|
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "PolyVoxUtil/include")
|
||||||
set(PolyVox_DOC_INSTALL_DIR "PolyVox/doc")
|
set(PolyVox_DOC_INSTALL_DIR "PolyVox/doc")
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
set(CONFIG_FILE_DIR "share/PolyVox/cmake")
|
set(CONFIG_FILE_DIR "share/PolyVox/cmake")
|
||||||
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "lib")
|
set(PolyVoxCore_LIBRARY_INSTALL_DIRS "lib")
|
||||||
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "lib")
|
set(PolyVoxUtil_LIBRARY_INSTALL_DIRS "lib")
|
||||||
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "include/PolyVoxCore")
|
set(PolyVoxCore_INCLUDE_INSTALL_DIRS "include/PolyVoxCore")
|
||||||
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "include/PolyVoxUtil")
|
set(PolyVoxUtil_INCLUDE_INSTALL_DIRS "include/PolyVoxUtil")
|
||||||
set(PolyVox_DOC_INSTALL_DIR "share/doc/packages/polyvox")
|
set(PolyVox_DOC_INSTALL_DIR "share/doc/packages/polyvox")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PolyVoxConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PolyVoxConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake @ONLY)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake DESTINATION ${CONFIG_FILE_DIR} COMPONENT development)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PolyVoxConfig.cmake DESTINATION ${CONFIG_FILE_DIR} COMPONENT development)
|
||||||
|
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.css ${CMAKE_CURRENT_BINARY_DIR}/polyvox.css)
|
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.css ${CMAKE_CURRENT_BINARY_DIR}/polyvox.css)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||||
#This is just the default doc target which only runs Doxygen
|
#This is just the default doc target which only runs Doxygen
|
||||||
add_custom_target(doc
|
add_custom_target(doc
|
||||||
COMMAND ${DOXYGEN_EXECUTABLE}
|
COMMAND ${DOXYGEN_EXECUTABLE}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Building documentation"
|
COMMENT "Building documentation"
|
||||||
SOURCES Doxyfile.in polyvox.qhcp.in Mainpage.dox
|
SOURCES Doxyfile.in polyvox.qhcp.in Mainpage.dox
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
set_target_properties(doc PROPERTIES PROJECT_LABEL "API Reference") #Set label seen in IDE
|
set_target_properties(doc PROPERTIES PROJECT_LABEL "API Reference") #Set label seen in IDE
|
||||||
set_property(TARGET doc PROPERTY FOLDER "Documentation")
|
set_property(TARGET doc PROPERTY FOLDER "Documentation")
|
||||||
|
|
||||||
#If we found qcollectiongenerator then do more processing
|
#If we found qcollectiongenerator then do more processing
|
||||||
if(QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
if(QT_QCOLLECTIONGENERATOR_EXECUTABLE)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.qhcp.in ${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qhcp) #The QtHelp config file
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/polyvox.qhcp.in ${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qhcp) #The QtHelp config file
|
||||||
|
|
||||||
#We attach this command to the doc target so it will be run automatically
|
#We attach this command to the doc target so it will be run automatically
|
||||||
add_custom_command(TARGET doc POST_BUILD
|
add_custom_command(TARGET doc POST_BUILD
|
||||||
COMMAND ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} polyvox.qhcp -o polyvox.qhc
|
COMMAND ${QT_QCOLLECTIONGENERATOR_EXECUTABLE} polyvox.qhcp -o polyvox.qhc
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp
|
||||||
COMMENT "Compiling API documentation to Qt Help format"
|
COMMENT "Compiling API documentation to Qt Help format"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(FILES
|
install(FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qhc
|
${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qhc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qch
|
${CMAKE_CURRENT_BINARY_DIR}/doc/qthelp/polyvox.qch
|
||||||
DESTINATION ${PolyVox_DOC_INSTALL_DIR}/qthelp
|
DESTINATION ${PolyVox_DOC_INSTALL_DIR}/qthelp
|
||||||
COMPONENT development
|
COMPONENT development
|
||||||
OPTIONAL
|
OPTIONAL
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#add_subdirectory(bindings)
|
#add_subdirectory(bindings)
|
||||||
|
@ -1,164 +1,164 @@
|
|||||||
# Copyright (c) 2008-2012 Matt Williams
|
# Copyright (c) 2008-2012 Matt Williams
|
||||||
# Copyright (c) 2008-2012 David Williams
|
# Copyright (c) 2008-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
PROJECT(PolyVoxCore)
|
PROJECT(PolyVoxCore)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(CORE_SRC_FILES
|
SET(CORE_SRC_FILES
|
||||||
source/AStarPathfinder.cpp
|
source/AStarPathfinder.cpp
|
||||||
source/Region.cpp
|
source/Region.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(CORE_INC_FILES
|
SET(CORE_INC_FILES
|
||||||
include/PolyVoxCore/AmbientOcclusionCalculator.h
|
include/PolyVoxCore/AmbientOcclusionCalculator.h
|
||||||
include/PolyVoxCore/AmbientOcclusionCalculator.inl
|
include/PolyVoxCore/AmbientOcclusionCalculator.inl
|
||||||
include/PolyVoxCore/Array.h
|
include/PolyVoxCore/Array.h
|
||||||
include/PolyVoxCore/AStarPathfinder.h
|
include/PolyVoxCore/AStarPathfinder.h
|
||||||
include/PolyVoxCore/AStarPathfinder.inl
|
include/PolyVoxCore/AStarPathfinder.inl
|
||||||
include/PolyVoxCore/BaseVolume.h
|
include/PolyVoxCore/BaseVolume.h
|
||||||
include/PolyVoxCore/BaseVolume.inl
|
include/PolyVoxCore/BaseVolume.inl
|
||||||
include/PolyVoxCore/BaseVolumeSampler.inl
|
include/PolyVoxCore/BaseVolumeSampler.inl
|
||||||
include/PolyVoxCore/CubicSurfaceExtractor.h
|
include/PolyVoxCore/CubicSurfaceExtractor.h
|
||||||
include/PolyVoxCore/CubicSurfaceExtractor.inl
|
include/PolyVoxCore/CubicSurfaceExtractor.inl
|
||||||
include/PolyVoxCore/DefaultIsQuadNeeded.h
|
include/PolyVoxCore/DefaultIsQuadNeeded.h
|
||||||
include/PolyVoxCore/DefaultMarchingCubesController.h
|
include/PolyVoxCore/DefaultMarchingCubesController.h
|
||||||
include/PolyVoxCore/Density.h
|
include/PolyVoxCore/Density.h
|
||||||
include/PolyVoxCore/FilePager.h
|
include/PolyVoxCore/FilePager.h
|
||||||
include/PolyVoxCore/GradientEstimators.h
|
include/PolyVoxCore/GradientEstimators.h
|
||||||
include/PolyVoxCore/GradientEstimators.inl
|
include/PolyVoxCore/GradientEstimators.inl
|
||||||
include/PolyVoxCore/Interpolation.h
|
include/PolyVoxCore/Interpolation.h
|
||||||
include/PolyVoxCore/IteratorController.h
|
include/PolyVoxCore/IteratorController.h
|
||||||
include/PolyVoxCore/IteratorController.inl
|
include/PolyVoxCore/IteratorController.inl
|
||||||
include/PolyVoxCore/LargeVolume.h
|
include/PolyVoxCore/LargeVolume.h
|
||||||
include/PolyVoxCore/LowPassFilter.h
|
include/PolyVoxCore/LowPassFilter.h
|
||||||
include/PolyVoxCore/LowPassFilter.inl
|
include/PolyVoxCore/LowPassFilter.inl
|
||||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.h
|
include/PolyVoxCore/MarchingCubesSurfaceExtractor.h
|
||||||
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl
|
||||||
include/PolyVoxCore/Material.h
|
include/PolyVoxCore/Material.h
|
||||||
include/PolyVoxCore/MaterialDensityPair.h
|
include/PolyVoxCore/MaterialDensityPair.h
|
||||||
include/PolyVoxCore/Mesh.h
|
include/PolyVoxCore/Mesh.h
|
||||||
include/PolyVoxCore/Mesh.inl
|
include/PolyVoxCore/Mesh.inl
|
||||||
include/PolyVoxCore/PagedVolume.h
|
include/PolyVoxCore/PagedVolume.h
|
||||||
include/PolyVoxCore/PagedVolume.inl
|
include/PolyVoxCore/PagedVolume.inl
|
||||||
include/PolyVoxCore/PagedVolumeChunk.inl
|
include/PolyVoxCore/PagedVolumeChunk.inl
|
||||||
include/PolyVoxCore/PagedVolumeSampler.inl
|
include/PolyVoxCore/PagedVolumeSampler.inl
|
||||||
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
||||||
include/PolyVoxCore/Picking.h
|
include/PolyVoxCore/Picking.h
|
||||||
include/PolyVoxCore/Picking.inl
|
include/PolyVoxCore/Picking.inl
|
||||||
include/PolyVoxCore/RawVolume.h
|
include/PolyVoxCore/RawVolume.h
|
||||||
include/PolyVoxCore/RawVolume.inl
|
include/PolyVoxCore/RawVolume.inl
|
||||||
include/PolyVoxCore/RawVolumeSampler.inl
|
include/PolyVoxCore/RawVolumeSampler.inl
|
||||||
include/PolyVoxCore/Raycast.h
|
include/PolyVoxCore/Raycast.h
|
||||||
include/PolyVoxCore/Raycast.inl
|
include/PolyVoxCore/Raycast.inl
|
||||||
include/PolyVoxCore/Region.h
|
include/PolyVoxCore/Region.h
|
||||||
include/PolyVoxCore/SimpleVolume.h
|
include/PolyVoxCore/SimpleVolume.h
|
||||||
include/PolyVoxCore/Vector.h
|
include/PolyVoxCore/Vector.h
|
||||||
include/PolyVoxCore/Vector.inl
|
include/PolyVoxCore/Vector.inl
|
||||||
include/PolyVoxCore/Vertex.h
|
include/PolyVoxCore/Vertex.h
|
||||||
include/PolyVoxCore/VolumeResampler.h
|
include/PolyVoxCore/VolumeResampler.h
|
||||||
include/PolyVoxCore/VolumeResampler.inl
|
include/PolyVoxCore/VolumeResampler.inl
|
||||||
include/PolyVoxCore/VoxelFilters.h
|
include/PolyVoxCore/VoxelFilters.h
|
||||||
include/PolyVoxCore/VoxelFilters.inl
|
include/PolyVoxCore/VoxelFilters.inl
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(IMPL_SRC_FILES
|
SET(IMPL_SRC_FILES
|
||||||
source/Impl/ErrorHandling.cpp
|
source/Impl/ErrorHandling.cpp
|
||||||
source/Impl/Logging.cpp
|
source/Impl/Logging.cpp
|
||||||
source/Impl/MarchingCubesTables.cpp
|
source/Impl/MarchingCubesTables.cpp
|
||||||
source/Impl/RandomUnitVectors.cpp
|
source/Impl/RandomUnitVectors.cpp
|
||||||
source/Impl/RandomVectors.cpp
|
source/Impl/RandomVectors.cpp
|
||||||
source/Impl/Timer.cpp
|
source/Impl/Timer.cpp
|
||||||
source/Impl/Utility.cpp
|
source/Impl/Utility.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(IMPL_INC_FILES
|
SET(IMPL_INC_FILES
|
||||||
include/PolyVoxCore/Impl/AStarPathfinderImpl.h
|
include/PolyVoxCore/Impl/AStarPathfinderImpl.h
|
||||||
include/PolyVoxCore/Impl/Config.h
|
include/PolyVoxCore/Impl/Config.h
|
||||||
include/PolyVoxCore/Impl/ErrorHandling.h
|
include/PolyVoxCore/Impl/ErrorHandling.h
|
||||||
include/PolyVoxCore/Impl/Logging.h
|
include/PolyVoxCore/Impl/Logging.h
|
||||||
include/PolyVoxCore/Impl/MarchingCubesTables.h
|
include/PolyVoxCore/Impl/MarchingCubesTables.h
|
||||||
include/PolyVoxCore/Impl/RandomUnitVectors.h
|
include/PolyVoxCore/Impl/RandomUnitVectors.h
|
||||||
include/PolyVoxCore/Impl/RandomVectors.h
|
include/PolyVoxCore/Impl/RandomVectors.h
|
||||||
include/PolyVoxCore/Impl/Timer.h
|
include/PolyVoxCore/Impl/Timer.h
|
||||||
include/PolyVoxCore/Impl/TypeDef.h
|
include/PolyVoxCore/Impl/TypeDef.h
|
||||||
include/PolyVoxCore/Impl/Utility.h
|
include/PolyVoxCore/Impl/Utility.h
|
||||||
)
|
)
|
||||||
|
|
||||||
#NOTE: The following line should be uncommented when building shared libs.
|
#NOTE: The following line should be uncommented when building shared libs.
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Source Files" FILES ${CORE_SRC_FILES})
|
SOURCE_GROUP("Source Files" FILES ${CORE_SRC_FILES})
|
||||||
SOURCE_GROUP("Header Files" FILES ${CORE_INC_FILES})
|
SOURCE_GROUP("Header Files" FILES ${CORE_INC_FILES})
|
||||||
|
|
||||||
SOURCE_GROUP("Source Files\\Impl" FILES ${IMPL_SRC_FILES})
|
SOURCE_GROUP("Source Files\\Impl" FILES ${IMPL_SRC_FILES})
|
||||||
SOURCE_GROUP("Header Files\\Impl" FILES ${IMPL_INC_FILES})
|
SOURCE_GROUP("Header Files\\Impl" FILES ${IMPL_INC_FILES})
|
||||||
|
|
||||||
#Tell CMake the paths
|
#Tell CMake the paths
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
#Core
|
#Core
|
||||||
#Build
|
#Build
|
||||||
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
||||||
ADD_LIBRARY(PolyVoxCore STATIC ${CORE_SRC_FILES} ${CORE_INC_FILES} ${IMPL_SRC_FILES} ${IMPL_INC_FILES})
|
ADD_LIBRARY(PolyVoxCore STATIC ${CORE_SRC_FILES} ${CORE_INC_FILES} ${IMPL_SRC_FILES} ${IMPL_INC_FILES})
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
||||||
ADD_LIBRARY(PolyVoxCore SHARED ${CORE_SRC_FILES} ${CORE_INC_FILES} ${IMPL_SRC_FILES} ${IMPL_INC_FILES})
|
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")
|
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS "-DPOLYVOX_SHARED_EXPORTS")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
SET_PROPERTY(TARGET PolyVoxCore PROPERTY FOLDER "Library")
|
SET_PROPERTY(TARGET PolyVoxCore PROPERTY FOLDER "Library")
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS "/W4 /wd4251") #Disable warning on STL exports
|
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS "/W4 /wd4251") #Disable warning on STL exports
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
|
|
||||||
#Install
|
#Install
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS PolyVoxCore
|
INSTALL(TARGETS PolyVoxCore
|
||||||
RUNTIME DESTINATION PolyVoxCore/bin COMPONENT library
|
RUNTIME DESTINATION PolyVoxCore/bin COMPONENT library
|
||||||
LIBRARY DESTINATION PolyVoxCore/lib COMPONENT library
|
LIBRARY DESTINATION PolyVoxCore/lib COMPONENT library
|
||||||
ARCHIVE DESTINATION PolyVoxCore/lib COMPONENT library
|
ARCHIVE DESTINATION PolyVoxCore/lib COMPONENT library
|
||||||
)
|
)
|
||||||
|
|
||||||
#Install the core header files, including the ones in the Impl subfolder.
|
#Install the core header files, including the ones in the Impl subfolder.
|
||||||
INSTALL(DIRECTORY include DESTINATION PolyVoxCore COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
INSTALL(DIRECTORY include DESTINATION PolyVoxCore COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
||||||
|
|
||||||
#On windows, we also install the debug information. It's unfortunate that we have to hard-code
|
#On windows, we also install the debug information. It's unfortunate that we have to hard-code
|
||||||
#the 'Debug' part of the path, but CMake doesn't seem to provide a way around this. The best I
|
#the 'Debug' part of the path, but CMake doesn't seem to provide a way around this. The best I
|
||||||
#found was: http://www.cmake.org/pipermail/cmake/2007-October/016924.html (and it is a bit ugly).
|
#found was: http://www.cmake.org/pipermail/cmake/2007-October/016924.html (and it is a bit ugly).
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/PolyVoxCore.pdb DESTINATION PolyVoxCore/lib CONFIGURATIONS Debug)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/PolyVoxCore.pdb DESTINATION PolyVoxCore/lib CONFIGURATIONS Debug)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/PolyVoxCore.pdb DESTINATION PolyVoxCore/lib CONFIGURATIONS RelWithDebInfo)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/PolyVoxCore.pdb DESTINATION PolyVoxCore/lib CONFIGURATIONS RelWithDebInfo)
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
INSTALL(TARGETS PolyVoxCore
|
INSTALL(TARGETS PolyVoxCore
|
||||||
RUNTIME DESTINATION bin COMPONENT library
|
RUNTIME DESTINATION bin COMPONENT library
|
||||||
LIBRARY DESTINATION lib COMPONENT library
|
LIBRARY DESTINATION lib COMPONENT library
|
||||||
ARCHIVE DESTINATION lib COMPONENT library
|
ARCHIVE DESTINATION lib COMPONENT library
|
||||||
)
|
)
|
||||||
|
|
||||||
#Install the core header files, including the ones in the Impl subfolder.
|
#Install the core header files, including the ones in the Impl subfolder.
|
||||||
INSTALL(DIRECTORY include/ DESTINATION include/PolyVoxCore COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
INSTALL(DIRECTORY include/ DESTINATION include/PolyVoxCore COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,195 +1,195 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_AStarPathfinder_H__
|
#ifndef __PolyVox_AStarPathfinder_H__
|
||||||
#define __PolyVox_AStarPathfinder_H__
|
#define __PolyVox_AStarPathfinder_H__
|
||||||
|
|
||||||
#include "Impl/AStarPathfinderImpl.h"
|
#include "Impl/AStarPathfinderImpl.h"
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stdexcept> //For runtime_error
|
#include <stdexcept> //For runtime_error
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
const float sqrt_1 = 1.0f;
|
const float sqrt_1 = 1.0f;
|
||||||
const float sqrt_2 = 1.4143f;
|
const float sqrt_2 = 1.4143f;
|
||||||
const float sqrt_3 = 1.7321f;
|
const float sqrt_3 = 1.7321f;
|
||||||
|
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderFaces[6];
|
extern const POLYVOX_API Vector3DInt32 arrayPathfinderFaces[6];
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderEdges[12];
|
extern const POLYVOX_API Vector3DInt32 arrayPathfinderEdges[12];
|
||||||
extern const POLYVOX_API Vector3DInt32 arrayPathfinderCorners[8];
|
extern const POLYVOX_API Vector3DInt32 arrayPathfinderCorners[8];
|
||||||
|
|
||||||
/// This function provides the default method for checking whether a given voxel
|
/// This function provides the default method for checking whether a given voxel
|
||||||
/// is valid for the path computed by the AStarPathfinder.
|
/// is valid for the path computed by the AStarPathfinder.
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos);
|
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos);
|
||||||
|
|
||||||
/// Provides a configuration for the AStarPathfinder.
|
/// Provides a configuration for the AStarPathfinder.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This structure stores the AStarPathfinder%s configuration options, because this
|
/// This structure stores the AStarPathfinder%s configuration options, because this
|
||||||
/// is simpler than providing a large number of get/set properties within the
|
/// 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
|
/// 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
|
/// 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
|
/// the result. All the other option have sensible default values which can
|
||||||
/// optionally be changed for more precise control over the pathfinder's behaviour.
|
/// optionally be changed for more precise control over the pathfinder's behaviour.
|
||||||
///
|
///
|
||||||
/// \sa AStarPathfinder
|
/// \sa AStarPathfinder
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
struct AStarPathfinderParams
|
struct AStarPathfinderParams
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AStarPathfinderParams
|
AStarPathfinderParams
|
||||||
(
|
(
|
||||||
VolumeType* volData,
|
VolumeType* volData,
|
||||||
const Vector3DInt32& v3dStart,
|
const Vector3DInt32& v3dStart,
|
||||||
const Vector3DInt32& v3dEnd,
|
const Vector3DInt32& v3dEnd,
|
||||||
std::list<Vector3DInt32>* listResult,
|
std::list<Vector3DInt32>* listResult,
|
||||||
float fHBias = 1.0,
|
float fHBias = 1.0,
|
||||||
uint32_t uMaxNoOfNodes = 10000,
|
uint32_t uMaxNoOfNodes = 10000,
|
||||||
Connectivity requiredConnectivity = TwentySixConnected,
|
Connectivity requiredConnectivity = TwentySixConnected,
|
||||||
std::function<bool (const VolumeType*, const Vector3DInt32&)> funcIsVoxelValidForPath = &aStarDefaultVoxelValidator,
|
std::function<bool (const VolumeType*, const Vector3DInt32&)> funcIsVoxelValidForPath = &aStarDefaultVoxelValidator,
|
||||||
std::function<void (float)> funcProgressCallback = nullptr
|
std::function<void (float)> funcProgressCallback = nullptr
|
||||||
)
|
)
|
||||||
:volume(volData)
|
:volume(volData)
|
||||||
,start(v3dStart)
|
,start(v3dStart)
|
||||||
,end(v3dEnd)
|
,end(v3dEnd)
|
||||||
,result(listResult)
|
,result(listResult)
|
||||||
,connectivity(requiredConnectivity)
|
,connectivity(requiredConnectivity)
|
||||||
,hBias(fHBias)
|
,hBias(fHBias)
|
||||||
,maxNumberOfNodes(uMaxNoOfNodes)
|
,maxNumberOfNodes(uMaxNoOfNodes)
|
||||||
,isVoxelValidForPath(funcIsVoxelValidForPath)
|
,isVoxelValidForPath(funcIsVoxelValidForPath)
|
||||||
,progressCallback(funcProgressCallback)
|
,progressCallback(funcProgressCallback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the volume through which the AStarPathfinder must find a path.
|
/// This is the volume through which the AStarPathfinder must find a path.
|
||||||
VolumeType* volume;
|
VolumeType* volume;
|
||||||
|
|
||||||
/// The start point for the pathfinding algorithm.
|
/// The start point for the pathfinding algorithm.
|
||||||
Vector3DInt32 start;
|
Vector3DInt32 start;
|
||||||
|
|
||||||
/// The end point for the pathfinding algorithm.
|
/// The end point for the pathfinding algorithm.
|
||||||
Vector3DInt32 end;
|
Vector3DInt32 end;
|
||||||
|
|
||||||
/// The resulting path will be stored as a series of points in
|
/// The resulting path will be stored as a series of points in
|
||||||
/// this list. Any existing contents will be cleared.
|
/// this list. Any existing contents will be cleared.
|
||||||
std::list<Vector3DInt32>* result;
|
std::list<Vector3DInt32>* result;
|
||||||
|
|
||||||
/// The AStarPathfinder performs its search by examining the neighbours
|
/// The AStarPathfinder performs its search by examining the neighbours
|
||||||
/// of each voxel it encounters. This property controls the meaning of
|
/// of each voxel it encounters. This property controls the meaning of
|
||||||
/// neighbour - e.g. whether two voxels must share a face, edge, or corner.
|
/// neighbour - e.g. whether two voxels must share a face, edge, or corner.
|
||||||
Connectivity connectivity;
|
Connectivity connectivity;
|
||||||
|
|
||||||
/// For each voxel the pathfinder tracks its distance to the start (known as g())
|
/// 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
|
/// 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
|
/// 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 -
|
/// 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
|
/// 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
|
/// 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
|
/// a potentially suboptimal path but finding it more quickly. The hBias is multiplied
|
||||||
/// by the estimated h() value to control this behaviour.
|
/// by the estimated h() value to control this behaviour.
|
||||||
float hBias;
|
float hBias;
|
||||||
|
|
||||||
/// Volumes can be pretty huge (millions of voxels) and processing each one of these
|
/// 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
|
/// 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,
|
/// 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.
|
/// before giving up and throwing an exception because a path can't be found.
|
||||||
uint32_t maxNumberOfNodes;
|
uint32_t maxNumberOfNodes;
|
||||||
|
|
||||||
/// This function is called to determine whether the path can pass though a given voxel. The
|
/// 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
|
/// 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
|
/// 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.
|
/// you could check to ensure that the voxel above is empty and the voxel below is solid.
|
||||||
///
|
///
|
||||||
/// \sa aStarDefaultVoxelValidator
|
/// \sa aStarDefaultVoxelValidator
|
||||||
std::function<bool (const VolumeType*, const Vector3DInt32&)> isVoxelValidForPath;
|
std::function<bool (const VolumeType*, const Vector3DInt32&)> isVoxelValidForPath;
|
||||||
|
|
||||||
/// This function is called by the AStarPathfinder to report on its progress in getting to
|
/// 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
|
/// 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
|
/// 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
|
/// 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.
|
///for short periods of time. It may even stop increasing altogether if a path cannot be found.
|
||||||
std::function<void (float)> progressCallback;
|
std::function<void (float)> progressCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The AStarPathfinder compute a path from one point in the volume to another.
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// resulting path is usually the shortest possible, but a less optimal path can
|
||||||
/// be exchanged for reduced computation time.
|
/// be exchanged for reduced computation time.
|
||||||
///
|
///
|
||||||
/// For an excellent overview of the A* algorithm please see Amit Patel's Game
|
/// For an excellent overview of the A* algorithm please see Amit Patel's Game
|
||||||
/// Programming page here: http://theory.stanford.edu/~amitp/GameProgramming/
|
/// Programming page here: http://theory.stanford.edu/~amitp/GameProgramming/
|
||||||
/// Much of this class is based on the principles described in those pages.
|
/// 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
|
/// Usage of this class if very strightforward. You create an instance of it
|
||||||
/// by passing an instance of the AStarPathfinderParams structure to the constructor.
|
/// by passing an instance of the AStarPathfinderParams structure to the constructor.
|
||||||
/// The details of the AStarPathfinderParams and the options it provides are described
|
/// The details of the AStarPathfinderParams and the options it provides are described
|
||||||
/// in the documentation for that class.
|
/// in the documentation for that class.
|
||||||
///
|
///
|
||||||
/// Next you call the execute() function and wait for it to return. If a path is
|
/// 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
|
/// 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
|
/// the AStarPathfinderParams. If a path cannot be found then an exception of type
|
||||||
/// std::runtime_error is thrown.
|
/// std::runtime_error is thrown.
|
||||||
///
|
///
|
||||||
/// \sa AStarPathfinderParams
|
/// \sa AStarPathfinderParams
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
class AStarPathfinder
|
class AStarPathfinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AStarPathfinder(const AStarPathfinderParams<VolumeType>& params);
|
AStarPathfinder(const AStarPathfinderParams<VolumeType>& params);
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal);
|
void processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal);
|
||||||
|
|
||||||
float SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
float SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||||
float EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
float EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||||
float TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
float TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||||
float computeH(const Vector3DInt32& a, const Vector3DInt32& b);
|
float computeH(const Vector3DInt32& a, const Vector3DInt32& b);
|
||||||
uint32_t hash(uint32_t a);
|
uint32_t hash(uint32_t a);
|
||||||
|
|
||||||
//Node containers
|
//Node containers
|
||||||
AllNodesContainer allNodes;
|
AllNodesContainer allNodes;
|
||||||
OpenNodesContainer openNodes;
|
OpenNodesContainer openNodes;
|
||||||
ClosedNodesContainer closedNodes;
|
ClosedNodesContainer closedNodes;
|
||||||
|
|
||||||
//The current node
|
//The current node
|
||||||
AllNodesContainer::iterator current;
|
AllNodesContainer::iterator current;
|
||||||
|
|
||||||
float m_fProgress;
|
float m_fProgress;
|
||||||
|
|
||||||
AStarPathfinderParams<VolumeType> m_params;
|
AStarPathfinderParams<VolumeType> m_params;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/AStarPathfinder.inl"
|
#include "PolyVoxCore/AStarPathfinder.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_AStarPathfinder_H__
|
#endif //__PolyVox_AStarPathfinder_H__
|
||||||
|
@ -1,351 +1,351 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
#include "PolyVoxCore/Impl/ErrorHandling.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Using this function, a voxel is considered valid for the path if it is inside the
|
/// 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.
|
/// 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
|
/// \return true is the voxel is valid for the path
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos)
|
bool aStarDefaultVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos)
|
||||||
{
|
{
|
||||||
//Voxels are considered valid candidates for the path if they are inside the volume...
|
//Voxels are considered valid candidates for the path if they are inside the volume...
|
||||||
if(volData->getEnclosingRegion().containsPoint(v3dPos) == false)
|
if(volData->getEnclosingRegion().containsPoint(v3dPos) == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// AStarPathfinder Class
|
// AStarPathfinder Class
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
AStarPathfinder<VolumeType>::AStarPathfinder(const AStarPathfinderParams<VolumeType>& params)
|
AStarPathfinder<VolumeType>::AStarPathfinder(const AStarPathfinderParams<VolumeType>& params)
|
||||||
:m_params(params)
|
:m_params(params)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
void AStarPathfinder<VolumeType>::execute()
|
void AStarPathfinder<VolumeType>::execute()
|
||||||
{
|
{
|
||||||
//Clear any existing nodes
|
//Clear any existing nodes
|
||||||
allNodes.clear();
|
allNodes.clear();
|
||||||
openNodes.clear();
|
openNodes.clear();
|
||||||
closedNodes.clear();
|
closedNodes.clear();
|
||||||
|
|
||||||
//Clear the result
|
//Clear the result
|
||||||
m_params.result->clear();
|
m_params.result->clear();
|
||||||
|
|
||||||
//Iterators to start and end node.
|
//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 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;
|
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.
|
//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,
|
//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
|
//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
|
//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.
|
//modify other properties of the object while it is in the set.
|
||||||
Node* tempStart = const_cast<Node*>(&(*startNode));
|
Node* tempStart = const_cast<Node*>(&(*startNode));
|
||||||
tempStart->gVal = 0;
|
tempStart->gVal = 0;
|
||||||
tempStart->hVal = computeH(startNode->position, endNode->position);
|
tempStart->hVal = computeH(startNode->position, endNode->position);
|
||||||
|
|
||||||
Node* tempEnd = const_cast<Node*>(&(*endNode));
|
Node* tempEnd = const_cast<Node*>(&(*endNode));
|
||||||
tempEnd->hVal = 0.0f;
|
tempEnd->hVal = 0.0f;
|
||||||
|
|
||||||
openNodes.insert(startNode);
|
openNodes.insert(startNode);
|
||||||
|
|
||||||
float fDistStartToEnd = (endNode->position - startNode->position).length();
|
float fDistStartToEnd = (endNode->position - startNode->position).length();
|
||||||
m_fProgress = 0.0f;
|
m_fProgress = 0.0f;
|
||||||
if(m_params.progressCallback)
|
if(m_params.progressCallback)
|
||||||
{
|
{
|
||||||
m_params.progressCallback(m_fProgress);
|
m_params.progressCallback(m_fProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
while((openNodes.empty() == false) && (openNodes.getFirst() != endNode))
|
while((openNodes.empty() == false) && (openNodes.getFirst() != endNode))
|
||||||
{
|
{
|
||||||
//Move the first node from open to closed.
|
//Move the first node from open to closed.
|
||||||
current = openNodes.getFirst();
|
current = openNodes.getFirst();
|
||||||
openNodes.removeFirst();
|
openNodes.removeFirst();
|
||||||
closedNodes.insert(current);
|
closedNodes.insert(current);
|
||||||
|
|
||||||
//Update the user on our progress
|
//Update the user on our progress
|
||||||
if(m_params.progressCallback)
|
if(m_params.progressCallback)
|
||||||
{
|
{
|
||||||
const float fMinProgresIncreament = 0.001f;
|
const float fMinProgresIncreament = 0.001f;
|
||||||
float fDistCurrentToEnd = (endNode->position - current->position).length();
|
float fDistCurrentToEnd = (endNode->position - current->position).length();
|
||||||
float fDistNormalised = fDistCurrentToEnd / fDistStartToEnd;
|
float fDistNormalised = fDistCurrentToEnd / fDistStartToEnd;
|
||||||
float fProgress = 1.0f - fDistNormalised;
|
float fProgress = 1.0f - fDistNormalised;
|
||||||
if(fProgress >= m_fProgress + fMinProgresIncreament)
|
if(fProgress >= m_fProgress + fMinProgresIncreament)
|
||||||
{
|
{
|
||||||
m_fProgress = fProgress;
|
m_fProgress = fProgress;
|
||||||
m_params.progressCallback(m_fProgress);
|
m_params.progressCallback(m_fProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//The distance from one cell to another connected by face, edge, or corner.
|
//The distance from one cell to another connected by face, edge, or corner.
|
||||||
const float fFaceCost = sqrt_1;
|
const float fFaceCost = sqrt_1;
|
||||||
const float fEdgeCost = sqrt_2;
|
const float fEdgeCost = sqrt_2;
|
||||||
const float fCornerCost = sqrt_3;
|
const float fCornerCost = sqrt_3;
|
||||||
|
|
||||||
//Process the neighbours. Note the deliberate lack of 'break'
|
//Process the neighbours. Note the deliberate lack of 'break'
|
||||||
//statements, larger connectivities include smaller ones.
|
//statements, larger connectivities include smaller ones.
|
||||||
switch(m_params.connectivity)
|
switch(m_params.connectivity)
|
||||||
{
|
{
|
||||||
case TwentySixConnected:
|
case TwentySixConnected:
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[0], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[0], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[1], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[1], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[2], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[2], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[3], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[3], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[4], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[4], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[5], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[5], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[6], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[6], current->gVal + fCornerCost);
|
||||||
processNeighbour(current->position + arrayPathfinderCorners[7], current->gVal + fCornerCost);
|
processNeighbour(current->position + arrayPathfinderCorners[7], current->gVal + fCornerCost);
|
||||||
|
|
||||||
case EighteenConnected:
|
case EighteenConnected:
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 0], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 0], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 1], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 1], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 2], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 2], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 3], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 3], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 4], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 4], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 5], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 5], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 6], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 6], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 7], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 7], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 8], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 8], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[ 9], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[ 9], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[10], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[10], current->gVal + fEdgeCost);
|
||||||
processNeighbour(current->position + arrayPathfinderEdges[11], current->gVal + fEdgeCost);
|
processNeighbour(current->position + arrayPathfinderEdges[11], current->gVal + fEdgeCost);
|
||||||
|
|
||||||
case SixConnected:
|
case SixConnected:
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[0], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[0], current->gVal + fFaceCost);
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[1], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[1], current->gVal + fFaceCost);
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[2], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[2], current->gVal + fFaceCost);
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[3], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[3], current->gVal + fFaceCost);
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[4], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[4], current->gVal + fFaceCost);
|
||||||
processNeighbour(current->position + arrayPathfinderFaces[5], current->gVal + fFaceCost);
|
processNeighbour(current->position + arrayPathfinderFaces[5], current->gVal + fFaceCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allNodes.size() > m_params.maxNumberOfNodes)
|
if(allNodes.size() > m_params.maxNumberOfNodes)
|
||||||
{
|
{
|
||||||
//We've reached the specified maximum number
|
//We've reached the specified maximum number
|
||||||
//of nodes. Just give up on the search.
|
//of nodes. Just give up on the search.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((openNodes.empty()) || (openNodes.getFirst() != endNode))
|
if((openNodes.empty()) || (openNodes.getFirst() != endNode))
|
||||||
{
|
{
|
||||||
//In this case we failed to find a valid path.
|
//In this case we failed to find a valid path.
|
||||||
POLYVOX_THROW(std::runtime_error, "No path found");
|
POLYVOX_THROW(std::runtime_error, "No path found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Regarding the const_cast - normally you should not modify an object which is in an sdt::set.
|
//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,
|
//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
|
//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
|
//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.
|
//modify other properties of the object while it is in the set.
|
||||||
Node* n = const_cast<Node*>(&(*endNode));
|
Node* n = const_cast<Node*>(&(*endNode));
|
||||||
while(n != 0)
|
while(n != 0)
|
||||||
{
|
{
|
||||||
m_params.result->push_front(n->position);
|
m_params.result->push_front(n->position);
|
||||||
n = n->parent;
|
n = n->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_params.progressCallback)
|
if(m_params.progressCallback)
|
||||||
{
|
{
|
||||||
m_params.progressCallback(1.0f);
|
m_params.progressCallback(1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
void AStarPathfinder<VolumeType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
|
void AStarPathfinder<VolumeType>::processNeighbour(const Vector3DInt32& neighbourPos, float neighbourGVal)
|
||||||
{
|
{
|
||||||
bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos);
|
bool bIsVoxelValidForPath = m_params.isVoxelValidForPath(m_params.volume, neighbourPos);
|
||||||
if(!bIsVoxelValidForPath)
|
if(!bIsVoxelValidForPath)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float cost = neighbourGVal;
|
float cost = neighbourGVal;
|
||||||
|
|
||||||
std::pair<AllNodesContainer::iterator, bool> insertResult = allNodes.insert(Node(neighbourPos.getX(), neighbourPos.getY(), neighbourPos.getZ()));
|
std::pair<AllNodesContainer::iterator, bool> insertResult = allNodes.insert(Node(neighbourPos.getX(), neighbourPos.getY(), neighbourPos.getZ()));
|
||||||
AllNodesContainer::iterator neighbour = insertResult.first;
|
AllNodesContainer::iterator neighbour = insertResult.first;
|
||||||
|
|
||||||
if(insertResult.second == true) //New node, compute h.
|
if(insertResult.second == true) //New node, compute h.
|
||||||
{
|
{
|
||||||
Node* tempNeighbour = const_cast<Node*>(&(*neighbour));
|
Node* tempNeighbour = const_cast<Node*>(&(*neighbour));
|
||||||
tempNeighbour -> hVal = computeH(neighbour->position, m_params.end);
|
tempNeighbour -> hVal = computeH(neighbour->position, m_params.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenNodesContainer::iterator openIter = openNodes.find(neighbour);
|
OpenNodesContainer::iterator openIter = openNodes.find(neighbour);
|
||||||
if(openIter != openNodes.end())
|
if(openIter != openNodes.end())
|
||||||
{
|
{
|
||||||
if(cost < neighbour->gVal)
|
if(cost < neighbour->gVal)
|
||||||
{
|
{
|
||||||
openNodes.remove(openIter);
|
openNodes.remove(openIter);
|
||||||
openIter = openNodes.end();
|
openIter = openNodes.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO - Nodes could keep track of if they are in open or closed? And a pointer to where they are?
|
//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);
|
ClosedNodesContainer::iterator closedIter = closedNodes.find(neighbour);
|
||||||
if(closedIter != closedNodes.end())
|
if(closedIter != closedNodes.end())
|
||||||
{
|
{
|
||||||
if(cost < neighbour->gVal)
|
if(cost < neighbour->gVal)
|
||||||
{
|
{
|
||||||
//Probably shouldn't happen?
|
//Probably shouldn't happen?
|
||||||
closedNodes.remove(closedIter);
|
closedNodes.remove(closedIter);
|
||||||
closedIter = closedNodes.end();
|
closedIter = closedNodes.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((openIter == openNodes.end()) && (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.
|
//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,
|
//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
|
//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
|
//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.
|
//modify other properties of the object while it is in the set.
|
||||||
Node* temp = const_cast<Node*>(&(*neighbour));
|
Node* temp = const_cast<Node*>(&(*neighbour));
|
||||||
temp->gVal = cost;
|
temp->gVal = cost;
|
||||||
openNodes.insert(neighbour);
|
openNodes.insert(neighbour);
|
||||||
temp->parent = const_cast<Node*>(&(*current));
|
temp->parent = const_cast<Node*>(&(*current));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
float AStarPathfinder<VolumeType>::SixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
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.
|
//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());
|
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;
|
return faceSteps * 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
float AStarPathfinder<VolumeType>::EighteenConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
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
|
//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
|
//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.
|
//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);
|
return SixConnectedCost(a,b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
float AStarPathfinder<VolumeType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
float AStarPathfinder<VolumeType>::TwentySixConnectedCost(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||||
{
|
{
|
||||||
//Can't say I'm certain about this heuristic - if anyone has
|
//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.
|
//a better idea of what it should be then please let me know.
|
||||||
uint32_t array[3];
|
uint32_t array[3];
|
||||||
array[0] = std::abs(a.getX() - b.getX());
|
array[0] = std::abs(a.getX() - b.getX());
|
||||||
array[1] = std::abs(a.getY() - b.getY());
|
array[1] = std::abs(a.getY() - b.getY());
|
||||||
array[2] = std::abs(a.getZ() - b.getZ());
|
array[2] = std::abs(a.getZ() - b.getZ());
|
||||||
|
|
||||||
//Maybe this is better implemented directly
|
//Maybe this is better implemented directly
|
||||||
//using three compares and two swaps... but not
|
//using three compares and two swaps... but not
|
||||||
//until the profiler says so.
|
//until the profiler says so.
|
||||||
std::sort(&array[0], &array[3]);
|
std::sort(&array[0], &array[3]);
|
||||||
|
|
||||||
uint32_t cornerSteps = array[0];
|
uint32_t cornerSteps = array[0];
|
||||||
uint32_t edgeSteps = array[1] - array[0];
|
uint32_t edgeSteps = array[1] - array[0];
|
||||||
uint32_t faceSteps = array[2] - array[1];
|
uint32_t faceSteps = array[2] - array[1];
|
||||||
|
|
||||||
return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1;
|
return cornerSteps * sqrt_3 + edgeSteps * sqrt_2 + faceSteps * sqrt_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
float AStarPathfinder<VolumeType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
|
float AStarPathfinder<VolumeType>::computeH(const Vector3DInt32& a, const Vector3DInt32& b)
|
||||||
{
|
{
|
||||||
float hVal;
|
float hVal;
|
||||||
|
|
||||||
switch(m_params.connectivity)
|
switch(m_params.connectivity)
|
||||||
{
|
{
|
||||||
case TwentySixConnected:
|
case TwentySixConnected:
|
||||||
hVal = TwentySixConnectedCost(a, b);
|
hVal = TwentySixConnectedCost(a, b);
|
||||||
break;
|
break;
|
||||||
case EighteenConnected:
|
case EighteenConnected:
|
||||||
hVal = EighteenConnectedCost(a, b);
|
hVal = EighteenConnectedCost(a, b);
|
||||||
break;
|
break;
|
||||||
case SixConnected:
|
case SixConnected:
|
||||||
hVal = SixConnectedCost(a, b);
|
hVal = SixConnectedCost(a, b);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
POLYVOX_THROW(std::invalid_argument, "Connectivity parameter has an unrecognised value.");
|
POLYVOX_THROW(std::invalid_argument, "Connectivity parameter has an unrecognised value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sanity checks in debug mode. These can come out eventually, but I
|
//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.
|
//want to make sure that the heuristics I've come up with make sense.
|
||||||
POLYVOX_ASSERT((a-b).length() <= TwentySixConnectedCost(a,b), "A* heuristic error.");
|
POLYVOX_ASSERT((a-b).length() <= TwentySixConnectedCost(a,b), "A* heuristic error.");
|
||||||
POLYVOX_ASSERT(TwentySixConnectedCost(a,b) <= EighteenConnectedCost(a,b), "A* heuristic error.");
|
POLYVOX_ASSERT(TwentySixConnectedCost(a,b) <= EighteenConnectedCost(a,b), "A* heuristic error.");
|
||||||
POLYVOX_ASSERT(EighteenConnectedCost(a,b) <= SixConnectedCost(a,b), "A* heuristic error.");
|
POLYVOX_ASSERT(EighteenConnectedCost(a,b) <= SixConnectedCost(a,b), "A* heuristic error.");
|
||||||
|
|
||||||
//Apply the bias to the computed h value;
|
//Apply the bias to the computed h value;
|
||||||
hVal *= m_params.hBias;
|
hVal *= m_params.hBias;
|
||||||
|
|
||||||
//Having computed hVal, we now apply some random bias to break ties.
|
//Having computed hVal, we now apply some random bias to break ties.
|
||||||
//This needs to be deterministic on the input position. This random
|
//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
|
//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.
|
//length, and so far fewer nodes must be expanded to find the shortest path.
|
||||||
//See http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#S12
|
//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
|
//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
|
//(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
|
//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
|
//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).
|
//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 aX = (a.getX() << 16) & 0x00FF0000;
|
||||||
uint32_t aY = (a.getY() << 8) & 0x0000FF00;
|
uint32_t aY = (a.getY() << 8) & 0x0000FF00;
|
||||||
uint32_t aZ = (a.getZ() ) & 0x000000FF;
|
uint32_t aZ = (a.getZ() ) & 0x000000FF;
|
||||||
uint32_t hashVal = hash(aX | aY | aZ);
|
uint32_t hashVal = hash(aX | aY | aZ);
|
||||||
|
|
||||||
//Stop hashVal going over 65535, and divide by 1000000 to make sure it is small.
|
//Stop hashVal going over 65535, and divide by 1000000 to make sure it is small.
|
||||||
hashVal &= 0x0000FFFF;
|
hashVal &= 0x0000FFFF;
|
||||||
float fHash = hashVal / 1000000.0f;
|
float fHash = hashVal / 1000000.0f;
|
||||||
|
|
||||||
//Apply the hash and return
|
//Apply the hash and return
|
||||||
hVal += fHash;
|
hVal += fHash;
|
||||||
return hVal;
|
return hVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Robert Jenkins' 32 bit integer hash function
|
// Robert Jenkins' 32 bit integer hash function
|
||||||
// http://www.burtleburtle.net/bob/hash/integer.html
|
// http://www.burtleburtle.net/bob/hash/integer.html
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
uint32_t AStarPathfinder<VolumeType>::hash( uint32_t a)
|
uint32_t AStarPathfinder<VolumeType>::hash( uint32_t a)
|
||||||
{
|
{
|
||||||
a = (a+0x7ed55d16) + (a<<12);
|
a = (a+0x7ed55d16) + (a<<12);
|
||||||
a = (a^0xc761c23c) ^ (a>>19);
|
a = (a^0xc761c23c) ^ (a>>19);
|
||||||
a = (a+0x165667b1) + (a<<5);
|
a = (a+0x165667b1) + (a<<5);
|
||||||
a = (a+0xd3a2646c) ^ (a<<9);
|
a = (a+0xd3a2646c) ^ (a<<9);
|
||||||
a = (a+0xfd7046c5) + (a<<3);
|
a = (a+0xfd7046c5) + (a<<3);
|
||||||
a = (a^0xb55a4f09) ^ (a>>16);
|
a = (a^0xb55a4f09) ^ (a>>16);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,82 +1,82 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __AmbientOcclusionCalculator_H__
|
#ifndef __AmbientOcclusionCalculator_H__
|
||||||
#define __AmbientOcclusionCalculator_H__
|
#define __AmbientOcclusionCalculator_H__
|
||||||
|
|
||||||
#include "Impl/RandomUnitVectors.h"
|
#include "Impl/RandomUnitVectors.h"
|
||||||
#include "Impl/RandomVectors.h"
|
#include "Impl/RandomVectors.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVoxCore/Array.h"
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
#include "PolyVoxCore/Raycast.h"
|
#include "PolyVoxCore/Raycast.h"
|
||||||
|
|
||||||
//These two should not be here!
|
//These two should not be here!
|
||||||
#include "PolyVoxCore/Material.h"
|
#include "PolyVoxCore/Material.h"
|
||||||
#include "PolyVoxCore/PagedVolume.h"
|
#include "PolyVoxCore/PagedVolume.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*
|
*
|
||||||
* Ambient occlusion
|
* Ambient occlusion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename IsVoxelTransparentCallback>
|
template<typename IsVoxelTransparentCallback>
|
||||||
class AmbientOcclusionCalculatorRaycastCallback
|
class AmbientOcclusionCalculatorRaycastCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AmbientOcclusionCalculatorRaycastCallback(IsVoxelTransparentCallback isVoxelTransparentCallback) : mIsVoxelTransparentCallback(isVoxelTransparentCallback)
|
AmbientOcclusionCalculatorRaycastCallback(IsVoxelTransparentCallback isVoxelTransparentCallback) : mIsVoxelTransparentCallback(isVoxelTransparentCallback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const PagedVolume<uint8_t>::Sampler& sampler)
|
bool operator()(const PagedVolume<uint8_t>::Sampler& sampler)
|
||||||
{
|
{
|
||||||
uint8_t sample = sampler.getVoxel();
|
uint8_t sample = sampler.getVoxel();
|
||||||
bool func = mIsVoxelTransparentCallback(sample);
|
bool func = mIsVoxelTransparentCallback(sample);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsVoxelTransparentCallback mIsVoxelTransparentCallback;
|
IsVoxelTransparentCallback mIsVoxelTransparentCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: The callback needs to be a functor not a function. I haven't been
|
// 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.
|
// able to work the required template magic to get functions working as well.
|
||||||
//
|
//
|
||||||
// Matt: If you make the function take a "IsVoxelTransparentCallback&&" then
|
// Matt: If you make the function take a "IsVoxelTransparentCallback&&" then
|
||||||
// it will forward it on. Works for functors, functions and lambdas.
|
// it will forward it on. Works for functors, functions and lambdas.
|
||||||
// This will be 'perfect forwarding' using 'universal references'
|
// This will be 'perfect forwarding' using 'universal references'
|
||||||
// This will require C++11 rvalue references which is why I haven't made the
|
// This will require C++11 rvalue references which is why I haven't made the
|
||||||
// change yet.
|
// change yet.
|
||||||
|
|
||||||
/// Calculate the ambient occlusion for the volume
|
/// Calculate the ambient occlusion for the volume
|
||||||
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
||||||
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
|
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/AmbientOcclusionCalculator.inl"
|
#include "PolyVoxCore/AmbientOcclusionCalculator.inl"
|
||||||
|
|
||||||
#endif //__AmbientOcclusionCalculator_H__
|
#endif //__AmbientOcclusionCalculator_H__
|
||||||
|
@ -1,136 +1,136 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* \param volInput The volume to calculate the ambient occlusion for
|
* \param volInput The volume to calculate the ambient occlusion for
|
||||||
* \param[out] arrayResult The output of the calculator
|
* \param[out] arrayResult The output of the calculator
|
||||||
* \param region The region of the volume for which the occlusion should be calculated
|
* \param region The region of the volume for which the occlusion should be calculated
|
||||||
* \param fRayLength The length for each test ray
|
* \param fRayLength The length for each test ray
|
||||||
* \param uNoOfSamplesPerOutputElement The number of samples to calculate the occlusion
|
* \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
|
* \param isVoxelTransparentCallback A callback which takes a \a VoxelType and returns a \a bool whether the voxel is transparent
|
||||||
*/
|
*/
|
||||||
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
template<typename VolumeType, typename IsVoxelTransparentCallback>
|
||||||
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback)
|
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback)
|
||||||
{
|
{
|
||||||
//Make sure that the size of the volume is an exact multiple of the size of the array.
|
//Make sure that the size of the volume is an exact multiple of the size of the array.
|
||||||
if(volInput->getWidth() % arrayResult->getDimension(0) != 0)
|
if(volInput->getWidth() % arrayResult->getDimension(0) != 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array width.");
|
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array width.");
|
||||||
}
|
}
|
||||||
if(volInput->getHeight() % arrayResult->getDimension(1) != 0)
|
if(volInput->getHeight() % arrayResult->getDimension(1) != 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array height.");
|
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array height.");
|
||||||
}
|
}
|
||||||
if(volInput->getDepth() % arrayResult->getDimension(2) != 0)
|
if(volInput->getDepth() % arrayResult->getDimension(2) != 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array depth.");
|
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array depth.");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t uRandomUnitVectorIndex = 0;
|
uint16_t uRandomUnitVectorIndex = 0;
|
||||||
uint16_t uRandomVectorIndex = 0;
|
uint16_t uRandomVectorIndex = 0;
|
||||||
uint16_t uIndexIncreament;
|
uint16_t uIndexIncreament;
|
||||||
|
|
||||||
//Our initial indices. It doesn't matter exactly what we set here, but the code below makes
|
//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.
|
//sure they are different for different regions which helps reduce tiling patterns in the results.
|
||||||
uRandomUnitVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ();
|
uRandomUnitVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ();
|
||||||
uRandomVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ();
|
uRandomVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ();
|
||||||
|
|
||||||
//This value helps us jump around in the array a bit more, so the
|
//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.
|
//nth 'random' value isn't always followed by the n+1th 'random' value.
|
||||||
uIndexIncreament = 1;
|
uIndexIncreament = 1;
|
||||||
|
|
||||||
const int iRatioX = volInput->getWidth() / arrayResult->getDimension(0);
|
const int iRatioX = volInput->getWidth() / arrayResult->getDimension(0);
|
||||||
const int iRatioY = volInput->getHeight() / arrayResult->getDimension(1);
|
const int iRatioY = volInput->getHeight() / arrayResult->getDimension(1);
|
||||||
const int iRatioZ = volInput->getDepth() / arrayResult->getDimension(2);
|
const int iRatioZ = volInput->getDepth() / arrayResult->getDimension(2);
|
||||||
|
|
||||||
const float fRatioX = iRatioX;
|
const float fRatioX = iRatioX;
|
||||||
const float fRatioY = iRatioY;
|
const float fRatioY = iRatioY;
|
||||||
const float fRatioZ = iRatioZ;
|
const float fRatioZ = iRatioZ;
|
||||||
const Vector3DFloat v3dRatio(fRatioX, fRatioY, fRatioZ);
|
const Vector3DFloat v3dRatio(fRatioX, fRatioY, fRatioZ);
|
||||||
|
|
||||||
const float fHalfRatioX = fRatioX * 0.5f;
|
const float fHalfRatioX = fRatioX * 0.5f;
|
||||||
const float fHalfRatioY = fRatioY * 0.5f;
|
const float fHalfRatioY = fRatioY * 0.5f;
|
||||||
const float fHalfRatioZ = fRatioZ * 0.5f;
|
const float fHalfRatioZ = fRatioZ * 0.5f;
|
||||||
const Vector3DFloat v3dHalfRatio(fHalfRatioX, fHalfRatioY, fHalfRatioZ);
|
const Vector3DFloat v3dHalfRatio(fHalfRatioX, fHalfRatioY, fHalfRatioZ);
|
||||||
|
|
||||||
const Vector3DFloat v3dOffset(0.5f,0.5f,0.5f);
|
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
|
//This loop iterates over the bottom-lower-left voxel in each of the cells in the output array
|
||||||
for(uint16_t z = region.getLowerZ(); z <= region.getUpperZ(); z += iRatioZ)
|
for(uint16_t z = region.getLowerZ(); z <= region.getUpperZ(); z += iRatioZ)
|
||||||
{
|
{
|
||||||
for(uint16_t y = region.getLowerY(); y <= region.getUpperY(); y += iRatioY)
|
for(uint16_t y = region.getLowerY(); y <= region.getUpperY(); y += iRatioY)
|
||||||
{
|
{
|
||||||
for(uint16_t x = region.getLowerX(); x <= region.getUpperX(); x += iRatioX)
|
for(uint16_t x = region.getLowerX(); x <= region.getUpperX(); x += iRatioX)
|
||||||
{
|
{
|
||||||
//Compute a start position corresponding to
|
//Compute a start position corresponding to
|
||||||
//the centre of the cell in the output array.
|
//the centre of the cell in the output array.
|
||||||
Vector3DFloat v3dStart(x, y, z);
|
Vector3DFloat v3dStart(x, y, z);
|
||||||
v3dStart -= v3dOffset;
|
v3dStart -= v3dOffset;
|
||||||
v3dStart += v3dHalfRatio;
|
v3dStart += v3dHalfRatio;
|
||||||
|
|
||||||
//Keep track of how many rays did not hit anything
|
//Keep track of how many rays did not hit anything
|
||||||
uint8_t uVisibleDirections = 0;
|
uint8_t uVisibleDirections = 0;
|
||||||
|
|
||||||
for(int ct = 0; ct < uNoOfSamplesPerOutputElement; ct++)
|
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.
|
//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
|
//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.
|
Vector3DFloat v3dJitter = randomVectors[(uRandomVectorIndex += (++uIndexIncreament)) % 1019]; //Prime number helps avoid repetition on successive loops.
|
||||||
v3dJitter *= v3dHalfRatio;
|
v3dJitter *= v3dHalfRatio;
|
||||||
const Vector3DFloat v3dRayStart = v3dStart + v3dJitter;
|
const Vector3DFloat v3dRayStart = v3dStart + v3dJitter;
|
||||||
|
|
||||||
Vector3DFloat v3dRayDirection = randomUnitVectors[(uRandomUnitVectorIndex += (++uIndexIncreament)) % 1021]; //Different prime number.
|
Vector3DFloat v3dRayDirection = randomUnitVectors[(uRandomUnitVectorIndex += (++uIndexIncreament)) % 1021]; //Different prime number.
|
||||||
v3dRayDirection *= fRayLength;
|
v3dRayDirection *= fRayLength;
|
||||||
|
|
||||||
AmbientOcclusionCalculatorRaycastCallback<IsVoxelTransparentCallback> ambientOcclusionCalculatorRaycastCallback(isVoxelTransparentCallback);
|
AmbientOcclusionCalculatorRaycastCallback<IsVoxelTransparentCallback> ambientOcclusionCalculatorRaycastCallback(isVoxelTransparentCallback);
|
||||||
RaycastResult result = raycastWithDirection(volInput, v3dRayStart, v3dRayDirection, ambientOcclusionCalculatorRaycastCallback);
|
RaycastResult result = raycastWithDirection(volInput, v3dRayStart, v3dRayDirection, ambientOcclusionCalculatorRaycastCallback);
|
||||||
|
|
||||||
// Note - The performance of this could actually be improved it we exited as soon
|
// Note - The performance of this could actually be improved it we exited as soon
|
||||||
// as the ray left the volume. The raycast test has an example of how to do this.
|
// as the ray left the volume. The raycast test has an example of how to do this.
|
||||||
if(result == RaycastResults::Completed)
|
if(result == RaycastResults::Completed)
|
||||||
{
|
{
|
||||||
++uVisibleDirections;
|
++uVisibleDirections;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float fVisibility;
|
float fVisibility;
|
||||||
if(uNoOfSamplesPerOutputElement == 0)
|
if(uNoOfSamplesPerOutputElement == 0)
|
||||||
{
|
{
|
||||||
//The user might request zero samples (I've done this in the past while debugging - I don't want to
|
//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.
|
//wait for ambient occlusion but I do want as valid result for rendering). Avoid the divide by zero.
|
||||||
fVisibility = 1.0f;
|
fVisibility = 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fVisibility = static_cast<float>(uVisibleDirections) / static_cast<float>(uNoOfSamplesPerOutputElement);
|
fVisibility = static_cast<float>(uVisibleDirections) / static_cast<float>(uNoOfSamplesPerOutputElement);
|
||||||
POLYVOX_ASSERT((fVisibility >= 0.0f) && (fVisibility <= 1.0f), "Visibility value out of range.");
|
POLYVOX_ASSERT((fVisibility >= 0.0f) && (fVisibility <= 1.0f), "Visibility value out of range.");
|
||||||
}
|
}
|
||||||
|
|
||||||
(*arrayResult)(z / iRatioZ, y / iRatioY, x / iRatioX) = static_cast<uint8_t>(255.0f * fVisibility);
|
(*arrayResult)(z / iRatioZ, y / iRatioY, x / iRatioX) = static_cast<uint8_t>(255.0f * fVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,193 +1,193 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-20014 David Williams
|
Copyright (c) 2005-20014 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Array_H__
|
#ifndef __PolyVox_Array_H__
|
||||||
#define __PolyVox_Array_H__
|
#define __PolyVox_Array_H__
|
||||||
|
|
||||||
#include <PolyVoxCore/Impl/ErrorHandling.h>
|
#include <PolyVoxCore/Impl/ErrorHandling.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template <uint32_t noOfDims, typename ElementType>
|
template <uint32_t noOfDims, typename ElementType>
|
||||||
class Array
|
class Array
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Array(uint32_t width)
|
Array(uint32_t width)
|
||||||
:m_pElements(0)
|
:m_pElements(0)
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 1, "This constructor can only be used with a one-dimensional array");
|
static_assert(noOfDims == 1, "This constructor can only be used with a one-dimensional array");
|
||||||
|
|
||||||
m_uDimensions[0] = width;
|
m_uDimensions[0] = width;
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array(uint32_t width, uint32_t height)
|
Array(uint32_t width, uint32_t height)
|
||||||
:m_pElements(0)
|
:m_pElements(0)
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 2, "This constructor can only be used with a two-dimensional array");
|
static_assert(noOfDims == 2, "This constructor can only be used with a two-dimensional array");
|
||||||
|
|
||||||
m_uDimensions[0] = width;
|
m_uDimensions[0] = width;
|
||||||
m_uDimensions[1] = height;
|
m_uDimensions[1] = height;
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array(uint32_t width, uint32_t height, uint32_t depth)
|
Array(uint32_t width, uint32_t height, uint32_t depth)
|
||||||
:m_pElements(0)
|
:m_pElements(0)
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 3, "This constructor can only be used with a three-dimensional array");
|
static_assert(noOfDims == 3, "This constructor can only be used with a three-dimensional array");
|
||||||
|
|
||||||
m_uDimensions[0] = width;
|
m_uDimensions[0] = width;
|
||||||
m_uDimensions[1] = height;
|
m_uDimensions[1] = height;
|
||||||
m_uDimensions[2] = depth;
|
m_uDimensions[2] = depth;
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are deleted to avoid accidental copying.
|
// These are deleted to avoid accidental copying.
|
||||||
Array<noOfDims, ElementType>(const Array<noOfDims, ElementType>&) = delete;
|
Array<noOfDims, ElementType>(const Array<noOfDims, ElementType>&) = delete;
|
||||||
Array<noOfDims, ElementType>& operator=(const Array<noOfDims, ElementType>&) = delete;
|
Array<noOfDims, ElementType>& operator=(const Array<noOfDims, ElementType>&) = delete;
|
||||||
|
|
||||||
~Array()
|
~Array()
|
||||||
{
|
{
|
||||||
delete[] m_pElements;
|
delete[] m_pElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType& operator()(uint32_t x) const
|
ElementType& operator()(uint32_t x) const
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 1, "This accessor can only be used with a one-dimensional array");
|
static_assert(noOfDims == 1, "This accessor can only be used with a one-dimensional array");
|
||||||
POLYVOX_ASSERT(x < m_uDimensions[0], "Array access is out-of-range.");
|
POLYVOX_ASSERT(x < m_uDimensions[0], "Array access is out-of-range.");
|
||||||
return m_pElements[x];
|
return m_pElements[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType& operator()(uint32_t x, uint32_t y) const
|
ElementType& operator()(uint32_t x, uint32_t y) const
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 2, "This accessor can only be used with a two-dimensional array");
|
static_assert(noOfDims == 2, "This accessor can only be used with a two-dimensional array");
|
||||||
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1], "Array access is out-of-range.");
|
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1], "Array access is out-of-range.");
|
||||||
return m_pElements[y * m_uDimensions[0] + x];
|
return m_pElements[y * m_uDimensions[0] + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType& operator()(uint32_t x, uint32_t y, uint32_t z) const
|
ElementType& operator()(uint32_t x, uint32_t y, uint32_t z) const
|
||||||
{
|
{
|
||||||
static_assert(noOfDims == 3, "This accessor can only be used with a three-dimensional array");
|
static_assert(noOfDims == 3, "This accessor can only be used with a three-dimensional array");
|
||||||
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1] && z < m_uDimensions[2], "Array access is out-of-range.");
|
POLYVOX_ASSERT(x < m_uDimensions[0] && y < m_uDimensions[1] && z < m_uDimensions[2], "Array access is out-of-range.");
|
||||||
return m_pElements[z * m_uDimensions[0] * m_uDimensions[1] + y * m_uDimensions[0] + x];
|
return m_pElements[z * m_uDimensions[0] * m_uDimensions[1] + y * m_uDimensions[0] + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getDimension(uint32_t dimension)
|
uint32_t getDimension(uint32_t dimension)
|
||||||
{
|
{
|
||||||
return m_uDimensions[dimension];
|
return m_uDimensions[dimension];
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType* getRawData()
|
ElementType* getRawData()
|
||||||
{
|
{
|
||||||
return m_pElements;
|
return m_pElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getNoOfElements()
|
uint32_t getNoOfElements()
|
||||||
{
|
{
|
||||||
return m_uNoOfElements;
|
return m_uNoOfElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Array& other)
|
void swap(Array& other)
|
||||||
{
|
{
|
||||||
ElementType* temp = other.m_pElements;
|
ElementType* temp = other.m_pElements;
|
||||||
other.m_pElements = m_pElements;
|
other.m_pElements = m_pElements;
|
||||||
m_pElements = temp;
|
m_pElements = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void initialize(void)
|
void initialize(void)
|
||||||
{
|
{
|
||||||
// Calculate the total number of elements in the array.
|
// Calculate the total number of elements in the array.
|
||||||
m_uNoOfElements = 1;
|
m_uNoOfElements = 1;
|
||||||
for (uint32_t i = 0; i < noOfDims; i++)
|
for (uint32_t i = 0; i < noOfDims; i++)
|
||||||
{
|
{
|
||||||
m_uNoOfElements *= m_uDimensions[i];
|
m_uNoOfElements *= m_uDimensions[i];
|
||||||
}
|
}
|
||||||
m_pElements = new ElementType[m_uNoOfElements];
|
m_pElements = new ElementType[m_uNoOfElements];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t m_uDimensions[noOfDims];
|
uint32_t m_uDimensions[noOfDims];
|
||||||
uint32_t m_uNoOfElements;
|
uint32_t m_uNoOfElements;
|
||||||
ElementType* m_pElements;
|
ElementType* m_pElements;
|
||||||
};
|
};
|
||||||
|
|
||||||
///A 1D Array of floats.
|
///A 1D Array of floats.
|
||||||
typedef Array<1, float> Array1DFloat;
|
typedef Array<1, float> Array1DFloat;
|
||||||
///A 1D Array of doubles.
|
///A 1D Array of doubles.
|
||||||
typedef Array<1, double> Array1DDouble;
|
typedef Array<1, double> Array1DDouble;
|
||||||
///A 1D Array of signed 8-bit values.
|
///A 1D Array of signed 8-bit values.
|
||||||
typedef Array<1, int8_t> Array1DInt8;
|
typedef Array<1, int8_t> Array1DInt8;
|
||||||
///A 1D Array of unsigned 8-bit values.
|
///A 1D Array of unsigned 8-bit values.
|
||||||
typedef Array<1, uint8_t> Array1DUint8;
|
typedef Array<1, uint8_t> Array1DUint8;
|
||||||
///A 1D Array of signed 16-bit values.
|
///A 1D Array of signed 16-bit values.
|
||||||
typedef Array<1, int16_t> Array1DInt16;
|
typedef Array<1, int16_t> Array1DInt16;
|
||||||
///A 1D Array of unsigned 16-bit values.
|
///A 1D Array of unsigned 16-bit values.
|
||||||
typedef Array<1, uint16_t> Array1DUint16;
|
typedef Array<1, uint16_t> Array1DUint16;
|
||||||
///A 1D Array of signed 32-bit values.
|
///A 1D Array of signed 32-bit values.
|
||||||
typedef Array<1, int32_t> Array1DInt32;
|
typedef Array<1, int32_t> Array1DInt32;
|
||||||
///A 1D Array of unsigned 32-bit values.
|
///A 1D Array of unsigned 32-bit values.
|
||||||
typedef Array<1, uint32_t> Array1DUint32;
|
typedef Array<1, uint32_t> Array1DUint32;
|
||||||
|
|
||||||
///A 2D Array of floats.
|
///A 2D Array of floats.
|
||||||
typedef Array<2, float> Array2DFloat;
|
typedef Array<2, float> Array2DFloat;
|
||||||
///A 2D Array of doubles.
|
///A 2D Array of doubles.
|
||||||
typedef Array<2, double> Array2DDouble;
|
typedef Array<2, double> Array2DDouble;
|
||||||
///A 2D Array of signed 8-bit values.
|
///A 2D Array of signed 8-bit values.
|
||||||
typedef Array<2, int8_t> Array2DInt8;
|
typedef Array<2, int8_t> Array2DInt8;
|
||||||
///A 2D Array of unsigned 8-bit values.
|
///A 2D Array of unsigned 8-bit values.
|
||||||
typedef Array<2, uint8_t> Array2DUint8;
|
typedef Array<2, uint8_t> Array2DUint8;
|
||||||
///A 2D Array of signed 16-bit values.
|
///A 2D Array of signed 16-bit values.
|
||||||
typedef Array<2, int16_t> Array2DInt16;
|
typedef Array<2, int16_t> Array2DInt16;
|
||||||
///A 2D Array of unsigned 16-bit values.
|
///A 2D Array of unsigned 16-bit values.
|
||||||
typedef Array<2, uint16_t> Array2DUint16;
|
typedef Array<2, uint16_t> Array2DUint16;
|
||||||
///A 2D Array of signed 32-bit values.
|
///A 2D Array of signed 32-bit values.
|
||||||
typedef Array<2, int32_t> Array2DInt32;
|
typedef Array<2, int32_t> Array2DInt32;
|
||||||
///A 2D Array of unsigned 32-bit values.
|
///A 2D Array of unsigned 32-bit values.
|
||||||
typedef Array<2, uint32_t> Array2DUint32;
|
typedef Array<2, uint32_t> Array2DUint32;
|
||||||
|
|
||||||
///A 3D Array of floats.
|
///A 3D Array of floats.
|
||||||
typedef Array<3, float> Array3DFloat;
|
typedef Array<3, float> Array3DFloat;
|
||||||
///A 3D Array of doubles.
|
///A 3D Array of doubles.
|
||||||
typedef Array<3, double> Array3DDouble;
|
typedef Array<3, double> Array3DDouble;
|
||||||
///A 3D Array of signed 8-bit values.
|
///A 3D Array of signed 8-bit values.
|
||||||
typedef Array<3, int8_t> Array3DInt8;
|
typedef Array<3, int8_t> Array3DInt8;
|
||||||
///A 3D Array of unsigned 8-bit values.
|
///A 3D Array of unsigned 8-bit values.
|
||||||
typedef Array<3, uint8_t> Array3DUint8;
|
typedef Array<3, uint8_t> Array3DUint8;
|
||||||
///A 3D Array of signed 16-bit values.
|
///A 3D Array of signed 16-bit values.
|
||||||
typedef Array<3, int16_t> Array3DInt16;
|
typedef Array<3, int16_t> Array3DInt16;
|
||||||
///A 3D Array of unsigned 16-bit values.
|
///A 3D Array of unsigned 16-bit values.
|
||||||
typedef Array<3, uint16_t> Array3DUint16;
|
typedef Array<3, uint16_t> Array3DUint16;
|
||||||
///A 3D Array of signed 32-bit values.
|
///A 3D Array of signed 32-bit values.
|
||||||
typedef Array<3, int32_t> Array3DInt32;
|
typedef Array<3, int32_t> Array3DInt32;
|
||||||
///A 3D Array of unsigned 32-bit values.
|
///A 3D Array of unsigned 32-bit values.
|
||||||
typedef Array<3, uint32_t> Array3DUint32;
|
typedef Array<3, uint32_t> Array3DUint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__PolyVox_Array_H__
|
#endif //__PolyVox_Array_H__
|
@ -1,217 +1,217 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_BaseVolume_H__
|
#ifndef __PolyVox_BaseVolume_H__
|
||||||
#define __PolyVox_BaseVolume_H__
|
#define __PolyVox_BaseVolume_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/// The BaseVolume class provides common functionality and an interface for other volume classes to implement. You should not try to create an instance of this
|
/// The BaseVolume class provides common functionality and an interface for other volume classes to implement. You should not try to create an instance of this
|
||||||
/// class directly. Instead you should use RawVolume or PagedVolume.
|
/// class directly. Instead you should use RawVolume or PagedVolume.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// More details to come...
|
/// More details to come...
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace WrapModes
|
namespace WrapModes
|
||||||
{
|
{
|
||||||
enum WrapMode
|
enum WrapMode
|
||||||
{
|
{
|
||||||
Validate = 0,
|
Validate = 0,
|
||||||
Clamp = 1,
|
Clamp = 1,
|
||||||
Border = 2,
|
Border = 2,
|
||||||
AssumeValid = 3
|
AssumeValid = 3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
typedef WrapModes::WrapMode WrapMode;
|
typedef WrapModes::WrapMode WrapMode;
|
||||||
|
|
||||||
// Required for a trick to implement specialization of template member
|
// Required for a trick to implement specialization of template member
|
||||||
// functions in template classes. See http://stackoverflow.com/a/4951057
|
// functions in template classes. See http://stackoverflow.com/a/4951057
|
||||||
template <WrapMode W> struct WrapModeType{};
|
template <WrapMode W> struct WrapModeType{};
|
||||||
|
|
||||||
template <typename _VoxelType>
|
template <typename _VoxelType>
|
||||||
class BaseVolume
|
class BaseVolume
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef _VoxelType VoxelType;
|
typedef _VoxelType VoxelType;
|
||||||
|
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
class Sampler
|
class Sampler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sampler(DerivedVolumeType* volume);
|
Sampler(DerivedVolumeType* volume);
|
||||||
~Sampler();
|
~Sampler();
|
||||||
|
|
||||||
Vector3DInt32 getPosition(void) const;
|
Vector3DInt32 getPosition(void) const;
|
||||||
inline VoxelType getVoxel(void) const;
|
inline VoxelType getVoxel(void) const;
|
||||||
|
|
||||||
bool isCurrentPositionValid(void) const;
|
bool isCurrentPositionValid(void) const;
|
||||||
|
|
||||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||||
inline bool setVoxel(VoxelType tValue);
|
inline bool setVoxel(VoxelType tValue);
|
||||||
void setWrapMode(WrapMode eWrapMode, VoxelType tBorder = VoxelType());
|
void setWrapMode(WrapMode eWrapMode, VoxelType tBorder = VoxelType());
|
||||||
|
|
||||||
void movePositiveX(void);
|
void movePositiveX(void);
|
||||||
void movePositiveY(void);
|
void movePositiveY(void);
|
||||||
void movePositiveZ(void);
|
void movePositiveZ(void);
|
||||||
|
|
||||||
void moveNegativeX(void);
|
void moveNegativeX(void);
|
||||||
void moveNegativeY(void);
|
void moveNegativeY(void);
|
||||||
void moveNegativeZ(void);
|
void moveNegativeZ(void);
|
||||||
|
|
||||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||||
|
|
||||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||||
|
|
||||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||||
|
|
||||||
DerivedVolumeType* mVolume;
|
DerivedVolumeType* mVolume;
|
||||||
|
|
||||||
//The current position in the volume
|
//The current position in the volume
|
||||||
int32_t mXPosInVolume;
|
int32_t mXPosInVolume;
|
||||||
int32_t mYPosInVolume;
|
int32_t mYPosInVolume;
|
||||||
int32_t mZPosInVolume;
|
int32_t mZPosInVolume;
|
||||||
|
|
||||||
WrapMode m_eWrapMode;
|
WrapMode m_eWrapMode;
|
||||||
VoxelType m_tBorder;
|
VoxelType m_tBorder;
|
||||||
|
|
||||||
//Whether the current position is inside the volume
|
//Whether the current position is inside the volume
|
||||||
//FIXME - Replace these with flags
|
//FIXME - Replace these with flags
|
||||||
bool m_bIsCurrentPositionValidInX;
|
bool m_bIsCurrentPositionValidInX;
|
||||||
bool m_bIsCurrentPositionValidInY;
|
bool m_bIsCurrentPositionValidInY;
|
||||||
bool m_bIsCurrentPositionValidInZ;
|
bool m_bIsCurrentPositionValidInZ;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Gets the value used for voxels which are outside the volume
|
/// Gets the value used for voxels which are outside the volume
|
||||||
VoxelType getBorderValue(void) const;
|
VoxelType getBorderValue(void) const;
|
||||||
/// Gets a Region representing the extents of the Volume.
|
/// Gets a Region representing the extents of the Volume.
|
||||||
const Region& getEnclosingRegion(void) const;
|
const Region& getEnclosingRegion(void) const;
|
||||||
/// Gets the width of the volume in voxels.
|
/// Gets the width of the volume in voxels.
|
||||||
int32_t getWidth(void) const;
|
int32_t getWidth(void) const;
|
||||||
/// Gets the height of the volume in voxels.
|
/// Gets the height of the volume in voxels.
|
||||||
int32_t getHeight(void) const;
|
int32_t getHeight(void) const;
|
||||||
/// Gets the depth of the volume in voxels.
|
/// Gets the depth of the volume in voxels.
|
||||||
int32_t getDepth(void) const;
|
int32_t getDepth(void) const;
|
||||||
/// Gets the length of the longest side in voxels
|
/// Gets the length of the longest side in voxels
|
||||||
int32_t getLongestSideLength(void) const;
|
int32_t getLongestSideLength(void) const;
|
||||||
/// Gets the length of the shortest side in voxels
|
/// Gets the length of the shortest side in voxels
|
||||||
int32_t getShortestSideLength(void) const;
|
int32_t getShortestSideLength(void) const;
|
||||||
/// Gets the length of the diagonal in voxels
|
/// Gets the length of the diagonal in voxels
|
||||||
float getDiagonalLength(void) const;
|
float getDiagonalLength(void) const;
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const;
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||||
|
|
||||||
/// Sets the value used for voxels which are outside the volume
|
/// Sets the value used for voxels which are outside the volume
|
||||||
void setBorderValue(const VoxelType& tBorder);
|
void setBorderValue(const VoxelType& tBorder);
|
||||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||||
/// Sets the voxel at the position given by a 3D vector
|
/// Sets the voxel at the position given by a 3D vector
|
||||||
void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// 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);
|
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||||
/// Sets the voxel at the position given by a 3D vector
|
/// Sets the voxel at the position given by a 3D vector
|
||||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||||
|
|
||||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||||
uint32_t calculateSizeInBytes(void);
|
uint32_t calculateSizeInBytes(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Constructor for creating a fixed size volume.
|
/// Constructor for creating a fixed size volume.
|
||||||
BaseVolume(const Region& regValid);
|
BaseVolume(const Region& regValid);
|
||||||
|
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
BaseVolume(const BaseVolume& rhs);
|
BaseVolume(const BaseVolume& rhs);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~BaseVolume();
|
~BaseVolume();
|
||||||
|
|
||||||
/// Assignment operator
|
/// Assignment operator
|
||||||
BaseVolume& operator=(const BaseVolume& rhs);
|
BaseVolume& operator=(const BaseVolume& rhs);
|
||||||
|
|
||||||
//The size of the volume
|
//The size of the volume
|
||||||
Region m_regValidRegion;
|
Region m_regValidRegion;
|
||||||
|
|
||||||
//Some useful sizes
|
//Some useful sizes
|
||||||
int32_t m_uLongestSideLength;
|
int32_t m_uLongestSideLength;
|
||||||
int32_t m_uShortestSideLength;
|
int32_t m_uShortestSideLength;
|
||||||
float m_fDiagonalLength;
|
float m_fDiagonalLength;
|
||||||
|
|
||||||
//The border value
|
//The border value
|
||||||
VoxelType m_tBorderValue;
|
VoxelType m_tBorderValue;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/BaseVolume.inl"
|
#include "PolyVoxCore/BaseVolume.inl"
|
||||||
#include "PolyVoxCore/BaseVolumeSampler.inl"
|
#include "PolyVoxCore/BaseVolumeSampler.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_BaseVolume_H__
|
#endif //__PolyVox_BaseVolume_H__
|
||||||
|
@ -1,314 +1,314 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This is protected because you should never create a BaseVolume directly, you should instead use one of the derived classes.
|
/// This is protected because you should never create a BaseVolume directly, you should instead use one of the derived classes.
|
||||||
///
|
///
|
||||||
/// \sa RawVolume, PagedVolume
|
/// \sa RawVolume, PagedVolume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
BaseVolume<VoxelType>::BaseVolume(const Region& regValid)
|
||||||
:m_regValidRegion(regValid)
|
:m_regValidRegion(regValid)
|
||||||
,m_tBorderValue()
|
,m_tBorderValue()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
/// 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
|
/// 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.
|
/// make a copy of a volume and in this case you should look at the VolumeResampler.
|
||||||
///
|
///
|
||||||
/// \sa VolumeResampler
|
/// \sa VolumeResampler
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
BaseVolume<VoxelType>::BaseVolume(const BaseVolume<VoxelType>& /*rhs*/)
|
BaseVolume<VoxelType>::BaseVolume(const BaseVolume<VoxelType>& /*rhs*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
|
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Destroys the volume
|
/// Destroys the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
BaseVolume<VoxelType>::~BaseVolume()
|
BaseVolume<VoxelType>::~BaseVolume()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
/// 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
|
/// 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.
|
/// make a copy of a volume and in this case you should look at the VolumeResampler.
|
||||||
///
|
///
|
||||||
/// \sa VolumeResampler
|
/// \sa VolumeResampler
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/)
|
BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
|
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The border value is returned whenever an attempt is made to read a voxel which
|
/// The border value is returned whenever an attempt is made to read a voxel which
|
||||||
/// is outside the extents of the volume.
|
/// is outside the extents of the volume.
|
||||||
/// \return The value used for voxels outside of the volume
|
/// \return The value used for voxels outside of the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType BaseVolume<VoxelType>::getBorderValue(void) const
|
VoxelType BaseVolume<VoxelType>::getBorderValue(void) const
|
||||||
{
|
{
|
||||||
return m_tBorderValue;
|
return m_tBorderValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \return A Region representing the extent of the volume.
|
/// \return A Region representing the extent of the volume.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
const Region& BaseVolume<VoxelType>::getEnclosingRegion(void) const
|
const Region& BaseVolume<VoxelType>::getEnclosingRegion(void) const
|
||||||
{
|
{
|
||||||
return m_regValidRegion;
|
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.
|
/// \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()
|
/// \sa getHeight(), getDepth()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
int32_t BaseVolume<VoxelType>::getWidth(void) const
|
int32_t BaseVolume<VoxelType>::getWidth(void) const
|
||||||
{
|
{
|
||||||
return m_regValidRegion.getUpperX() - m_regValidRegion.getLowerX() + 1;
|
return m_regValidRegion.getUpperX() - m_regValidRegion.getLowerX() + 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.
|
/// \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()
|
/// \sa getWidth(), getDepth()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
int32_t BaseVolume<VoxelType>::getHeight(void) const
|
int32_t BaseVolume<VoxelType>::getHeight(void) const
|
||||||
{
|
{
|
||||||
return m_regValidRegion.getUpperY() - m_regValidRegion.getLowerY() + 1;
|
return m_regValidRegion.getUpperY() - m_regValidRegion.getLowerY() + 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.
|
/// \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()
|
/// \sa getWidth(), getHeight()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
int32_t BaseVolume<VoxelType>::getDepth(void) const
|
int32_t BaseVolume<VoxelType>::getDepth(void) const
|
||||||
{
|
{
|
||||||
return m_regValidRegion.getUpperZ() - m_regValidRegion.getLowerZ() + 1;
|
return m_regValidRegion.getUpperZ() - m_regValidRegion.getLowerZ() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \return The length of the shortest side in voxels. For example, if a volume has
|
/// \return The length of the shortest side in voxels. For example, if a volume has
|
||||||
/// dimensions 256x512x1024 this function will return 256.
|
/// dimensions 256x512x1024 this function will return 256.
|
||||||
/// \sa getLongestSideLength(), getDiagonalLength()
|
/// \sa getLongestSideLength(), getDiagonalLength()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
int32_t BaseVolume<VoxelType>::getShortestSideLength(void) const
|
int32_t BaseVolume<VoxelType>::getShortestSideLength(void) const
|
||||||
{
|
{
|
||||||
return m_uShortestSideLength;
|
return m_uShortestSideLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \return The length of the longest side in voxels. For example, if a volume has
|
/// \return The length of the longest side in voxels. For example, if a volume has
|
||||||
/// dimensions 256x512x1024 this function will return 1024.
|
/// dimensions 256x512x1024 this function will return 1024.
|
||||||
/// \sa getShortestSideLength(), getDiagonalLength()
|
/// \sa getShortestSideLength(), getDiagonalLength()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
int32_t BaseVolume<VoxelType>::getLongestSideLength(void) const
|
int32_t BaseVolume<VoxelType>::getLongestSideLength(void) const
|
||||||
{
|
{
|
||||||
return m_uLongestSideLength;
|
return m_uLongestSideLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \return The length of the diagonal in voxels. For example, if a volume has
|
/// \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)
|
/// 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.
|
/// = 1173.139. This value is computed on volume creation so retrieving it is fast.
|
||||||
/// \sa getShortestSideLength(), getLongestSideLength()
|
/// \sa getShortestSideLength(), getLongestSideLength()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
float BaseVolume<VoxelType>::getDiagonalLength(void) const
|
float BaseVolume<VoxelType>::getDiagonalLength(void) const
|
||||||
{
|
{
|
||||||
return m_fDiagonalLength;
|
return m_fDiagonalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function requires the wrap mode to be specified as a
|
/// This version of the function requires the wrap mode to be specified as a
|
||||||
/// template parameter, which can provide better performance.
|
/// template parameter, which can provide better performance.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tBorder*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tBorder*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function requires the wrap mode to be specified as a
|
/// This version of the function requires the wrap mode to be specified as a
|
||||||
/// template parameter, which can provide better performance.
|
/// template parameter, which can provide better performance.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tBorder*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tBorder*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function is provided so that the wrap mode does not need
|
/// This version of the function is provided so that the wrap mode does not need
|
||||||
/// to be specified as a template parameter, as it may be confusing to some users.
|
/// to be specified as a template parameter, as it may be confusing to some users.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function is provided so that the wrap mode does not need
|
/// This version of the function is provided so that the wrap mode does not need
|
||||||
/// to be specified as a template parameter, as it may be confusing to some users.
|
/// to be specified as a template parameter, as it may be confusing to some users.
|
||||||
/// \param v3dPos The 3D position of the voxel
|
/// \param v3dPos The 3D position of the voxel
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos The 3D position of the voxel
|
/// \param v3dPos The 3D position of the voxel
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType BaseVolume<VoxelType>::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const
|
VoxelType BaseVolume<VoxelType>::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param tBorder The value to use for voxels outside the volume.
|
/// \param tBorder The value to use for voxels outside the volume.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void BaseVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
void BaseVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
||||||
{
|
{
|
||||||
m_tBorderValue = tBorder;
|
m_tBorderValue = tBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos the \c x position of the voxel
|
/// \param uXPos the \c x position of the voxel
|
||||||
/// \param uYPos the \c y position of the voxel
|
/// \param uYPos the \c y position of the voxel
|
||||||
/// \param uZPos the \c z position of the voxel
|
/// \param uZPos the \c z position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void BaseVolume<VoxelType>::setVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/)
|
void BaseVolume<VoxelType>::setVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void BaseVolume<VoxelType>::setVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/)
|
void BaseVolume<VoxelType>::setVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos the \c x position of the voxel
|
/// \param uXPos the \c x position of the voxel
|
||||||
/// \param uYPos the \c y position of the voxel
|
/// \param uYPos the \c y position of the voxel
|
||||||
/// \param uZPos the \c z position of the voxel
|
/// \param uZPos the \c z position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \return whether the requested position is inside the volume
|
/// \return whether the requested position is inside the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool BaseVolume<VoxelType>::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/)
|
bool BaseVolume<VoxelType>::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \return whether the requested position is inside the volume
|
/// \return whether the requested position is inside the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool BaseVolume<VoxelType>::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/)
|
bool BaseVolume<VoxelType>::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Note: This function needs reviewing for accuracy...
|
/// Note: This function needs reviewing for accuracy...
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
uint32_t BaseVolume<VoxelType>::calculateSizeInBytes(void)
|
uint32_t BaseVolume<VoxelType>::calculateSizeInBytes(void)
|
||||||
{
|
{
|
||||||
return getWidth() * getHeight() * getDepth() * sizeof(VoxelType);
|
return getWidth() * getHeight() * getDepth() * sizeof(VoxelType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,366 +1,366 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Utility.h"
|
#include "PolyVoxCore/Impl/Utility.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::Sampler(DerivedVolumeType* volume)
|
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::Sampler(DerivedVolumeType* volume)
|
||||||
:mVolume(volume)
|
:mVolume(volume)
|
||||||
,mXPosInVolume(0)
|
,mXPosInVolume(0)
|
||||||
,mYPosInVolume(0)
|
,mYPosInVolume(0)
|
||||||
,mZPosInVolume(0)
|
,mZPosInVolume(0)
|
||||||
,m_eWrapMode(WrapModes::Border)
|
,m_eWrapMode(WrapModes::Border)
|
||||||
,m_tBorder()
|
,m_tBorder()
|
||||||
,m_bIsCurrentPositionValidInX(false)
|
,m_bIsCurrentPositionValidInX(false)
|
||||||
,m_bIsCurrentPositionValidInY(false)
|
,m_bIsCurrentPositionValidInY(false)
|
||||||
,m_bIsCurrentPositionValidInZ(false)
|
,m_bIsCurrentPositionValidInZ(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::~Sampler()
|
BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::~Sampler()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
Vector3DInt32 BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getPosition(void) const
|
Vector3DInt32 BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getPosition(void) const
|
||||||
{
|
{
|
||||||
return Vector3DInt32(mXPosInVolume, mYPosInVolume, mZPosInVolume);
|
return Vector3DInt32(mXPosInVolume, mYPosInVolume, mZPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxel(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxel(void) const
|
||||||
{
|
{
|
||||||
return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume, WrapModes::Validate); // FIXME - Use templatised version instead but watch for Linux compile errors.
|
return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume, WrapModes::Validate); // FIXME - Use templatised version instead but watch for Linux compile errors.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
bool inline BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::isCurrentPositionValid(void) const
|
bool inline BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::isCurrentPositionValid(void) const
|
||||||
{
|
{
|
||||||
return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ;
|
return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(const Vector3DInt32& v3dNewPos)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(const Vector3DInt32& v3dNewPos)
|
||||||
{
|
{
|
||||||
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
setPosition(v3dNewPos.getX(), v3dNewPos.getY(), v3dNewPos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(int32_t xPos, int32_t yPos, int32_t zPos)
|
||||||
{
|
{
|
||||||
mXPosInVolume = xPos;
|
mXPosInVolume = xPos;
|
||||||
mYPosInVolume = yPos;
|
mYPosInVolume = yPos;
|
||||||
mZPosInVolume = zPos;
|
mZPosInVolume = zPos;
|
||||||
|
|
||||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(xPos);
|
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(xPos);
|
||||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(yPos);
|
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(yPos);
|
||||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(zPos);
|
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(zPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
bool BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setVoxel(VoxelType tValue)
|
bool BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setVoxel(VoxelType tValue)
|
||||||
{
|
{
|
||||||
return mVolume->setVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue);
|
return mVolume->setVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setWrapMode(WrapMode eWrapMode, VoxelType tBorder)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setWrapMode(WrapMode eWrapMode, VoxelType tBorder)
|
||||||
{
|
{
|
||||||
m_eWrapMode = eWrapMode;
|
m_eWrapMode = eWrapMode;
|
||||||
m_tBorder = tBorder;
|
m_tBorder = tBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveX(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveX(void)
|
||||||
{
|
{
|
||||||
mXPosInVolume++;
|
mXPosInVolume++;
|
||||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveY(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveY(void)
|
||||||
{
|
{
|
||||||
mYPosInVolume++;
|
mYPosInVolume++;
|
||||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveZ(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::movePositiveZ(void)
|
||||||
{
|
{
|
||||||
mZPosInVolume++;
|
mZPosInVolume++;
|
||||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeX(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeX(void)
|
||||||
{
|
{
|
||||||
mXPosInVolume--;
|
mXPosInVolume--;
|
||||||
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeY(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeY(void)
|
||||||
{
|
{
|
||||||
mYPosInVolume--;
|
mYPosInVolume--;
|
||||||
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeZ(void)
|
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::moveNegativeZ(void)
|
||||||
{
|
{
|
||||||
mZPosInVolume--;
|
mZPosInVolume--;
|
||||||
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1ny1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx0py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1nx1py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1ny1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px0py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel0px1py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1ny1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px0py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1nz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1nz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py0pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py0pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume );
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1pz(void) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::peekVoxel1px1py1pz(void) const
|
||||||
{
|
{
|
||||||
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <typename DerivedVolumeType>
|
template <typename DerivedVolumeType>
|
||||||
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
VoxelType BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||||
{
|
{
|
||||||
switch(m_eWrapMode)
|
switch(m_eWrapMode)
|
||||||
{
|
{
|
||||||
case WrapModes::Validate:
|
case WrapModes::Validate:
|
||||||
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Validate, m_tBorder);
|
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Validate, m_tBorder);
|
||||||
case WrapModes::Clamp:
|
case WrapModes::Clamp:
|
||||||
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Clamp, m_tBorder);
|
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Clamp, m_tBorder);
|
||||||
case WrapModes::Border:
|
case WrapModes::Border:
|
||||||
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Border, m_tBorder);
|
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Border, m_tBorder);
|
||||||
case WrapModes::AssumeValid:
|
case WrapModes::AssumeValid:
|
||||||
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::AssumeValid, m_tBorder);
|
return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::AssumeValid, m_tBorder);
|
||||||
default:
|
default:
|
||||||
// Should never happen
|
// Should never happen
|
||||||
POLYVOX_ASSERT(false, "Invalid wrap mode");
|
POLYVOX_ASSERT(false, "Invalid wrap mode");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,158 +1,158 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_CubicSurfaceExtractor_H__
|
#ifndef __PolyVox_CubicSurfaceExtractor_H__
|
||||||
#define __PolyVox_CubicSurfaceExtractor_H__
|
#define __PolyVox_CubicSurfaceExtractor_H__
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Array.h"
|
#include "PolyVoxCore/Array.h"
|
||||||
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these?
|
||||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
#include "PolyVoxCore/DefaultIsQuadNeeded.h"
|
||||||
#include "PolyVoxCore/Mesh.h"
|
#include "PolyVoxCore/Mesh.h"
|
||||||
#include "PolyVoxCore/Vertex.h"
|
#include "PolyVoxCore/Vertex.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
#ifdef SWIG
|
#ifdef SWIG
|
||||||
struct CubicVertex
|
struct CubicVertex
|
||||||
#else
|
#else
|
||||||
template<typename _DataType>
|
template<typename _DataType>
|
||||||
struct POLYVOX_API CubicVertex
|
struct POLYVOX_API CubicVertex
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
typedef _DataType DataType;
|
typedef _DataType DataType;
|
||||||
|
|
||||||
// Each component of the position is stored as a single unsigned byte.
|
// Each component of the position is stored as a single unsigned byte.
|
||||||
// The true position is found by offseting each component by 0.5f.
|
// The true position is found by offseting each component by 0.5f.
|
||||||
Vector3DUint8 encodedPosition;
|
Vector3DUint8 encodedPosition;
|
||||||
|
|
||||||
// User data
|
// User data
|
||||||
DataType data;
|
DataType data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convienient shorthand for declaring a mesh of 'cubic' vertices
|
// Convienient shorthand for declaring a mesh of 'cubic' vertices
|
||||||
// Currently disabled because it requires GCC 4.7
|
// Currently disabled because it requires GCC 4.7
|
||||||
//template <typename VertexDataType, typename IndexType = DefaultIndexType>
|
//template <typename VertexDataType, typename IndexType = DefaultIndexType>
|
||||||
//using CubicMesh = Mesh< CubicVertex<VertexDataType>, IndexType >;
|
//using CubicMesh = Mesh< CubicVertex<VertexDataType>, IndexType >;
|
||||||
|
|
||||||
/// Decodes a position from a CubicVertex
|
/// Decodes a position from a CubicVertex
|
||||||
inline Vector3DFloat decodePosition(const Vector3DUint8& encodedPosition)
|
inline Vector3DFloat decodePosition(const Vector3DUint8& encodedPosition)
|
||||||
{
|
{
|
||||||
Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ());
|
Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ());
|
||||||
result -= 0.5f; // Apply the required offset
|
result -= 0.5f; // Apply the required offset
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering.
|
/// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering.
|
||||||
template<typename DataType>
|
template<typename DataType>
|
||||||
Vertex<DataType> decodeVertex(const CubicVertex<DataType>& cubicVertex)
|
Vertex<DataType> decodeVertex(const CubicVertex<DataType>& cubicVertex)
|
||||||
{
|
{
|
||||||
Vertex<DataType> result;
|
Vertex<DataType> result;
|
||||||
result.position = decodePosition(cubicVertex.encodedPosition);
|
result.position = decodePosition(cubicVertex.encodedPosition);
|
||||||
result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated
|
result.normal.setElements(0.0f, 0.0f, 0.0f); // Currently not calculated
|
||||||
result.data = cubicVertex.data; // Data is not encoded
|
result.data = cubicVertex.data; // Data is not encoded
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not use this class directly. Use the 'extractCubicSurface' function instead (see examples).
|
/// Do not use this class directly. Use the 'extractCubicSurface' function instead (see examples).
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
class CubicSurfaceExtractor
|
class CubicSurfaceExtractor
|
||||||
{
|
{
|
||||||
struct IndexAndMaterial
|
struct IndexAndMaterial
|
||||||
{
|
{
|
||||||
int32_t iIndex;
|
int32_t iIndex;
|
||||||
typename VolumeType::VoxelType uMaterial;
|
typename VolumeType::VoxelType uMaterial;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FaceNames
|
enum FaceNames
|
||||||
{
|
{
|
||||||
PositiveX,
|
PositiveX,
|
||||||
PositiveY,
|
PositiveY,
|
||||||
PositiveZ,
|
PositiveZ,
|
||||||
NegativeX,
|
NegativeX,
|
||||||
NegativeY,
|
NegativeY,
|
||||||
NegativeZ,
|
NegativeZ,
|
||||||
NoOfFaces
|
NoOfFaces
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Quad
|
struct Quad
|
||||||
{
|
{
|
||||||
Quad(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
|
Quad(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
|
||||||
{
|
{
|
||||||
vertices[0] = v0;
|
vertices[0] = v0;
|
||||||
vertices[1] = v1;
|
vertices[1] = v1;
|
||||||
vertices[2] = v2;
|
vertices[2] = v2;
|
||||||
vertices[3] = v3;
|
vertices[3] = v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t vertices[4];
|
uint32_t vertices[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true);
|
CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true);
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
||||||
bool performQuadMerging(std::list<Quad>& quads);
|
bool performQuadMerging(std::list<Quad>& quads);
|
||||||
bool mergeQuads(Quad& q1, Quad& q2);
|
bool mergeQuads(Quad& q1, Quad& q2);
|
||||||
|
|
||||||
IsQuadNeeded m_funcIsQuadNeededCallback;
|
IsQuadNeeded m_funcIsQuadNeededCallback;
|
||||||
|
|
||||||
//The volume data and a sampler to access it.
|
//The volume data and a sampler to access it.
|
||||||
VolumeType* m_volData;
|
VolumeType* m_volData;
|
||||||
|
|
||||||
//Information about the region we are currently processing
|
//Information about the region we are currently processing
|
||||||
Region m_regSizeInVoxels;
|
Region m_regSizeInVoxels;
|
||||||
|
|
||||||
//The surface patch we are currently filling.
|
//The surface patch we are currently filling.
|
||||||
MeshType* m_meshCurrent;
|
MeshType* m_meshCurrent;
|
||||||
|
|
||||||
//Used to avoid creating duplicate vertices.
|
//Used to avoid creating duplicate vertices.
|
||||||
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
||||||
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
||||||
|
|
||||||
//During extraction we create a number of different lists of quads. All the
|
//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.
|
//quads in a given list are in the same plane and facing in the same direction.
|
||||||
std::vector< std::list<Quad> > m_vecQuads[NoOfFaces];
|
std::vector< std::list<Quad> > m_vecQuads[NoOfFaces];
|
||||||
|
|
||||||
//Controls whether quad merging should be performed. This might be undesirable
|
//Controls whether quad merging should be performed. This might be undesirable
|
||||||
//is the user needs per-vertex attributes, or to perform per vertex lighting.
|
//is the user needs per-vertex attributes, or to perform per vertex lighting.
|
||||||
bool m_bMergeQuads;
|
bool m_bMergeQuads;
|
||||||
|
|
||||||
//This constant defines the maximum number of quads which can share a
|
//This constant defines the maximum number of quads which can share a
|
||||||
//vertex in a cubic style mesh. See the initialisation for more details.
|
//vertex in a cubic style mesh. See the initialisation for more details.
|
||||||
static const uint32_t MaxVerticesPerPosition;
|
static const uint32_t MaxVerticesPerPosition;
|
||||||
|
|
||||||
//The wrap mode
|
//The wrap mode
|
||||||
WrapMode m_eWrapMode;
|
WrapMode m_eWrapMode;
|
||||||
typename VolumeType::VoxelType m_tBorderValue;
|
typename VolumeType::VoxelType m_tBorderValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically.
|
// This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically.
|
||||||
// There are a few reasons why this might be useful to more advanced users:
|
// There are a few reasons why this might be useful to more advanced users:
|
||||||
//
|
//
|
||||||
@ -165,64 +165,64 @@ namespace PolyVox
|
|||||||
//
|
//
|
||||||
// Note: This function is called 'extractCubicMeshCustom' rather than 'extractCubicMesh' to avoid ambiguity when only three parameters
|
// Note: This function is called 'extractCubicMeshCustom' rather than 'extractCubicMesh' to avoid ambiguity when only three parameters
|
||||||
// are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts,
|
// are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts,
|
||||||
// but this is relatively complex and I haven't done it yet. Could always add it later as another overload.
|
// but this is relatively complex and I haven't done it yet. Could always add it later as another overload.
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||||
void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
{
|
{
|
||||||
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded> extractor(volData, region, result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded> extractor(volData, region, result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
||||||
extractor.execute();
|
extractor.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube
|
/// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Introduction
|
/// Introduction
|
||||||
/// ------------
|
/// ------------
|
||||||
/// 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:
|
/// 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
|
/// \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).
|
/// 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
|
/// 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.
|
/// 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.
|
/// 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
|
/// \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).
|
/// 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
|
/// 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:
|
/// 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
|
/// \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).
|
/// 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.
|
/// 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:
|
/// 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
|
/// \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 voxels from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue).
|
/// We could choose to add the quads to *both* regions, but this can cause confusion when one of the region is modified (causing the face to disappear or a new one to be created) as *both* regions need to have their mesh regenerated to correctly represent the new state of the volume data. Such pairs of coplanar quads can also cause problems with physics engines, and may prevent transparent voxels from rendering correctly. Therefore we choose to instead only add the quad to one of the the regions and we always choose the one with the greater coordinate value in the direction in which they differ. In the above example the regions differ by the 'x' component of their position, and so the quad is added to the region with the greater 'x' value (the one marked in blue).
|
||||||
///
|
///
|
||||||
/// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.*
|
/// **Note:** *This behaviour has changed recently (September 2012). Earlier versions of PolyVox tried to be smart about this problem by looking beyond the region which was being processed, but this complicated the code and didn't work very well. Ultimatly we decided to simply stick with the convention outlined above.*
|
||||||
///
|
///
|
||||||
/// 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).
|
/// 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.
|
/// 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> >
|
template<typename VolumeType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> >
|
||||||
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
Mesh<CubicVertex<typename VolumeType::VoxelType> > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true)
|
||||||
{
|
{
|
||||||
Mesh< CubicVertex<typename VolumeType::VoxelType> > result;
|
Mesh< CubicVertex<typename VolumeType::VoxelType> > result;
|
||||||
extractCubicMeshCustom(volData, region, &result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
extractCubicMeshCustom(volData, region, &result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/CubicSurfaceExtractor.inl"
|
#include "PolyVoxCore/CubicSurfaceExtractor.inl"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,310 +1,310 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/Timer.h"
|
#include "PolyVoxCore/Impl/Timer.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
// We try to avoid duplicate vertices by checking whether a vertex has already been added at a given position.
|
// 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
|
// 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
|
// 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 eight vertices with the same position but different materials. For example, this worst-case scenario
|
// at most eight vertices with the same position but different materials. For example, this worst-case scenario
|
||||||
// happens when we have a 2x2x2 group of voxels, all with different materials and some/all partially transparent.
|
// happens when we have a 2x2x2 group of voxels, all with different materials and some/all partially transparent.
|
||||||
// The vertex position at the center of this group is then going to be used by all eight voxels all with different
|
// The vertex position at the center of this group is then going to be used by all eight voxels all with different
|
||||||
// materials.
|
// materials.
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
const uint32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::MaxVerticesPerPosition = 8;
|
const uint32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::MaxVerticesPerPosition = 8;
|
||||||
|
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads)
|
CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads)
|
||||||
:m_volData(volData)
|
:m_volData(volData)
|
||||||
,m_regSizeInVoxels(region)
|
,m_regSizeInVoxels(region)
|
||||||
,m_meshCurrent(result)
|
,m_meshCurrent(result)
|
||||||
,m_bMergeQuads(bMergeQuads)
|
,m_bMergeQuads(bMergeQuads)
|
||||||
,m_eWrapMode(eWrapMode)
|
,m_eWrapMode(eWrapMode)
|
||||||
,m_tBorderValue(tBorderValue)
|
,m_tBorderValue(tBorderValue)
|
||||||
,m_previousSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
,m_previousSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
||||||
,m_currentSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
,m_currentSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition)
|
||||||
{
|
{
|
||||||
m_funcIsQuadNeededCallback = isQuadNeeded;
|
m_funcIsQuadNeededCallback = isQuadNeeded;
|
||||||
|
|
||||||
// This extractor has a limit as to how large the extracted region can be, because the vertex positions are encoded with a single byte per component.
|
// This extractor has a limit as to how large the extracted region can be, because the vertex positions are encoded with a single byte per component.
|
||||||
int32_t maxReionDimension = 256;
|
int32_t maxReionDimension = 256;
|
||||||
POLYVOX_THROW_IF(region.getWidthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
POLYVOX_THROW_IF(region.getWidthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
||||||
POLYVOX_THROW_IF(region.getHeightInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
POLYVOX_THROW_IF(region.getHeightInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
||||||
POLYVOX_THROW_IF(region.getDepthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
POLYVOX_THROW_IF(region.getDepthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
void CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::execute()
|
void CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::execute()
|
||||||
{
|
{
|
||||||
Timer timer;
|
Timer timer;
|
||||||
m_meshCurrent->clear();
|
m_meshCurrent->clear();
|
||||||
|
|
||||||
//uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2;
|
//uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2;
|
||||||
//uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2;
|
//uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2;
|
||||||
|
|
||||||
//uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition};
|
//uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition};
|
||||||
//m_previousSliceVertices.resize(arraySize);
|
//m_previousSliceVertices.resize(arraySize);
|
||||||
//m_currentSliceVertices.resize(arraySize);
|
//m_currentSliceVertices.resize(arraySize);
|
||||||
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
|
|
||||||
m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2);
|
m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2);
|
||||||
m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2);
|
m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2);
|
||||||
|
|
||||||
m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2);
|
m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2);
|
||||||
m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2);
|
m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2);
|
||||||
|
|
||||||
m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2);
|
m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2);
|
||||||
m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2);
|
m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2);
|
||||||
|
|
||||||
typename VolumeType::Sampler volumeSampler(m_volData);
|
typename VolumeType::Sampler volumeSampler(m_volData);
|
||||||
volumeSampler.setWrapMode(m_eWrapMode, m_tBorderValue);
|
volumeSampler.setWrapMode(m_eWrapMode, m_tBorderValue);
|
||||||
|
|
||||||
for(int32_t z = m_regSizeInVoxels.getLowerZ(); z <= m_regSizeInVoxels.getUpperZ(); z++)
|
for(int32_t z = m_regSizeInVoxels.getLowerZ(); z <= m_regSizeInVoxels.getUpperZ(); z++)
|
||||||
{
|
{
|
||||||
uint32_t regZ = z - m_regSizeInVoxels.getLowerZ();
|
uint32_t regZ = z - m_regSizeInVoxels.getLowerZ();
|
||||||
|
|
||||||
for(int32_t y = m_regSizeInVoxels.getLowerY(); y <= m_regSizeInVoxels.getUpperY(); y++)
|
for(int32_t y = m_regSizeInVoxels.getLowerY(); y <= m_regSizeInVoxels.getUpperY(); y++)
|
||||||
{
|
{
|
||||||
uint32_t regY = y - m_regSizeInVoxels.getLowerY();
|
uint32_t regY = y - m_regSizeInVoxels.getLowerY();
|
||||||
|
|
||||||
volumeSampler.setPosition(m_regSizeInVoxels.getLowerX(),y,z);
|
volumeSampler.setPosition(m_regSizeInVoxels.getLowerX(),y,z);
|
||||||
|
|
||||||
for(int32_t x = m_regSizeInVoxels.getLowerX(); x <= m_regSizeInVoxels.getUpperX(); x++)
|
for(int32_t x = m_regSizeInVoxels.getLowerX(); x <= m_regSizeInVoxels.getUpperX(); x++)
|
||||||
{
|
{
|
||||||
uint32_t regX = x - m_regSizeInVoxels.getLowerX();
|
uint32_t regX = x - m_regSizeInVoxels.getLowerX();
|
||||||
|
|
||||||
typename VolumeType::VoxelType material; //Filled in by callback
|
typename VolumeType::VoxelType material; //Filled in by callback
|
||||||
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
|
typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel();
|
||||||
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
|
typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz();
|
||||||
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
|
typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz();
|
||||||
typename VolumeType::VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz();
|
typename VolumeType::VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz();
|
||||||
|
|
||||||
// X
|
// X
|
||||||
if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material))
|
if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices);
|
uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3));
|
m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material))
|
if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices);
|
uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1));
|
m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Y
|
// Y
|
||||||
if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material))
|
if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3));
|
m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material))
|
if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1));
|
m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Z
|
// Z
|
||||||
if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material))
|
if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3));
|
m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material))
|
if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material))
|
||||||
{
|
{
|
||||||
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices);
|
uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices);
|
||||||
uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices);
|
||||||
|
|
||||||
m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1));
|
m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeSampler.movePositiveX();
|
volumeSampler.movePositiveX();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_previousSliceVertices.swap(m_currentSliceVertices);
|
m_previousSliceVertices.swap(m_currentSliceVertices);
|
||||||
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++)
|
for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++)
|
||||||
{
|
{
|
||||||
std::vector< std::list<Quad> >& vecListQuads = m_vecQuads[uFace];
|
std::vector< std::list<Quad> >& vecListQuads = m_vecQuads[uFace];
|
||||||
|
|
||||||
for(uint32_t slice = 0; slice < vecListQuads.size(); slice++)
|
for(uint32_t slice = 0; slice < vecListQuads.size(); slice++)
|
||||||
{
|
{
|
||||||
std::list<Quad>& listQuads = vecListQuads[slice];
|
std::list<Quad>& listQuads = vecListQuads[slice];
|
||||||
|
|
||||||
if(m_bMergeQuads)
|
if(m_bMergeQuads)
|
||||||
{
|
{
|
||||||
//Repeatedly call this function until it returns
|
//Repeatedly call this function until it returns
|
||||||
//false to indicate nothing more can be done.
|
//false to indicate nothing more can be done.
|
||||||
while(performQuadMerging(listQuads)){}
|
while(performQuadMerging(listQuads)){}
|
||||||
}
|
}
|
||||||
|
|
||||||
typename std::list<Quad>::iterator iterEnd = listQuads.end();
|
typename std::list<Quad>::iterator iterEnd = listQuads.end();
|
||||||
for(typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++)
|
for(typename std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++)
|
||||||
{
|
{
|
||||||
Quad& quad = *quadIter;
|
Quad& quad = *quadIter;
|
||||||
m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner());
|
m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner());
|
||||||
m_meshCurrent->removeUnusedVertices();
|
m_meshCurrent->removeUnusedVertices();
|
||||||
|
|
||||||
POLYVOX_LOG_TRACE("Cubic surface extraction took " << timer.elapsedTimeInMilliSeconds()
|
POLYVOX_LOG_TRACE("Cubic surface extraction took " << timer.elapsedTimeInMilliSeconds()
|
||||||
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
<< "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels()
|
||||||
<< "x" << m_regSizeInVoxels.getDepthInVoxels() << ")");
|
<< "x" << m_regSizeInVoxels.getDepthInVoxels() << ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
int32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
|
int32_t CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
|
||||||
{
|
{
|
||||||
for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++)
|
for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++)
|
||||||
{
|
{
|
||||||
IndexAndMaterial& rEntry = existingVertices(uX, uY, ct);
|
IndexAndMaterial& rEntry = existingVertices(uX, uY, ct);
|
||||||
|
|
||||||
if(rEntry.iIndex == -1)
|
if(rEntry.iIndex == -1)
|
||||||
{
|
{
|
||||||
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them.
|
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them.
|
||||||
CubicVertex<typename VolumeType::VoxelType> cubicVertex;
|
CubicVertex<typename VolumeType::VoxelType> cubicVertex;
|
||||||
cubicVertex.encodedPosition.setElements(static_cast<uint8_t>(uX), static_cast<uint8_t>(uY), static_cast<uint8_t>(uZ));
|
cubicVertex.encodedPosition.setElements(static_cast<uint8_t>(uX), static_cast<uint8_t>(uY), static_cast<uint8_t>(uZ));
|
||||||
cubicVertex.data = uMaterialIn;
|
cubicVertex.data = uMaterialIn;
|
||||||
rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex);
|
rEntry.iIndex = m_meshCurrent->addVertex(cubicVertex);
|
||||||
rEntry.uMaterial = uMaterialIn;
|
rEntry.uMaterial = uMaterialIn;
|
||||||
|
|
||||||
return rEntry.iIndex;
|
return rEntry.iIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we have an existing vertex and the material matches then we can return it.
|
//If we have an existing vertex and the material matches then we can return it.
|
||||||
if(rEntry.uMaterial == uMaterialIn)
|
if(rEntry.uMaterial == uMaterialIn)
|
||||||
{
|
{
|
||||||
return rEntry.iIndex;
|
return rEntry.iIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we exit the loop here then apparently all the slots were full but none of them matched.
|
// If we exit the loop here then apparently all the slots were full but none of them matched.
|
||||||
// This shouldn't ever happen, so if it does it is probably a bug in PolyVox. Please report it to us!
|
// This shouldn't ever happen, so if it does it is probably a bug in PolyVox. Please report it to us!
|
||||||
POLYVOX_THROW(std::runtime_error, "All slots full but no matches during cubic surface extraction. This is probably a bug in PolyVox");
|
POLYVOX_THROW(std::runtime_error, "All slots full but no matches during cubic surface extraction. This is probably a bug in PolyVox");
|
||||||
return -1; //Should never happen.
|
return -1; //Should never happen.
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::performQuadMerging(std::list<Quad>& quads)
|
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::performQuadMerging(std::list<Quad>& quads)
|
||||||
{
|
{
|
||||||
bool bDidMerge = false;
|
bool bDidMerge = false;
|
||||||
for(typename std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
for(typename std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
||||||
{
|
{
|
||||||
typename std::list<Quad>::iterator innerIter = outerIter;
|
typename std::list<Quad>::iterator innerIter = outerIter;
|
||||||
innerIter++;
|
innerIter++;
|
||||||
while(innerIter != quads.end())
|
while(innerIter != quads.end())
|
||||||
{
|
{
|
||||||
Quad& q1 = *outerIter;
|
Quad& q1 = *outerIter;
|
||||||
Quad& q2 = *innerIter;
|
Quad& q2 = *innerIter;
|
||||||
|
|
||||||
bool result = mergeQuads(q1,q2);
|
bool result = mergeQuads(q1,q2);
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
{
|
{
|
||||||
bDidMerge = true;
|
bDidMerge = true;
|
||||||
innerIter = quads.erase(innerIter);
|
innerIter = quads.erase(innerIter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
innerIter++;
|
innerIter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bDidMerge;
|
return bDidMerge;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded>
|
||||||
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::mergeQuads(Quad& q1, Quad& q2)
|
bool CubicSurfaceExtractor<VolumeType, MeshType, IsQuadNeeded>::mergeQuads(Quad& q1, Quad& q2)
|
||||||
{
|
{
|
||||||
//All four vertices of a given quad have the same data,
|
//All four vertices of a given quad have the same data,
|
||||||
//so just check that the first pair of vertices match.
|
//so just check that the first pair of vertices match.
|
||||||
if (m_meshCurrent->getVertices()[q1.vertices[0]].data == m_meshCurrent->getVertices()[q2.vertices[0]].data)
|
if (m_meshCurrent->getVertices()[q1.vertices[0]].data == m_meshCurrent->getVertices()[q2.vertices[0]].data)
|
||||||
{
|
{
|
||||||
//Now check whether quad 2 is adjacent to quad one by comparing vertices.
|
//Now check whether quad 2 is adjacent to quad one by comparing vertices.
|
||||||
//Adjacent quads must share two vertices, and the second quad could be to the
|
//Adjacent quads must share two vertices, and the second quad could be to the
|
||||||
//top, bottom, left, of right of the first one. This gives four combinations to test.
|
//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])))
|
if((q1.vertices[0] == q2.vertices[1]) && ((q1.vertices[3] == q2.vertices[2])))
|
||||||
{
|
{
|
||||||
q1.vertices[0] = q2.vertices[0];
|
q1.vertices[0] = q2.vertices[0];
|
||||||
q1.vertices[3] = q2.vertices[3];
|
q1.vertices[3] = q2.vertices[3];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if((q1.vertices[3] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[1])))
|
else if((q1.vertices[3] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[1])))
|
||||||
{
|
{
|
||||||
q1.vertices[3] = q2.vertices[3];
|
q1.vertices[3] = q2.vertices[3];
|
||||||
q1.vertices[2] = q2.vertices[2];
|
q1.vertices[2] = q2.vertices[2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if((q1.vertices[1] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[3])))
|
else if((q1.vertices[1] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[3])))
|
||||||
{
|
{
|
||||||
q1.vertices[1] = q2.vertices[1];
|
q1.vertices[1] = q2.vertices[1];
|
||||||
q1.vertices[2] = q2.vertices[2];
|
q1.vertices[2] = q2.vertices[2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if((q1.vertices[0] == q2.vertices[3]) && ((q1.vertices[1] == q2.vertices[2])))
|
else if((q1.vertices[0] == q2.vertices[3]) && ((q1.vertices[1] == q2.vertices[2])))
|
||||||
{
|
{
|
||||||
q1.vertices[0] = q2.vertices[0];
|
q1.vertices[0] = q2.vertices[0];
|
||||||
q1.vertices[1] = q2.vertices[1];
|
q1.vertices[1] = q2.vertices[1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Quads cannot be merged.
|
//Quads cannot be merged.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,52 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_DefaultIsQuadNeeded_H__
|
#ifndef __PolyVox_DefaultIsQuadNeeded_H__
|
||||||
#define __PolyVox_DefaultIsQuadNeeded_H__
|
#define __PolyVox_DefaultIsQuadNeeded_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template<typename VoxelType>
|
template<typename VoxelType>
|
||||||
class DefaultIsQuadNeeded
|
class DefaultIsQuadNeeded
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator()(VoxelType back, VoxelType front, VoxelType& materialToUse)
|
bool operator()(VoxelType back, VoxelType front, VoxelType& materialToUse)
|
||||||
{
|
{
|
||||||
if((back > 0) && (front == 0))
|
if((back > 0) && (front == 0))
|
||||||
{
|
{
|
||||||
materialToUse = static_cast<VoxelType>(back);
|
materialToUse = static_cast<VoxelType>(back);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__PolyVox_DefaultIsQuadNeeded_H__
|
#endif //__PolyVox_DefaultIsQuadNeeded_H__
|
@ -1,191 +1,191 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Density_H__
|
#ifndef __PolyVox_Density_H__
|
||||||
#define __PolyVox_Density_H__
|
#define __PolyVox_Density_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
#include "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/// This class represents a voxel storing only a density.
|
/// This class represents a voxel storing only a density.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Detailed description...
|
/// Detailed description...
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class Density
|
class Density
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Density() : m_uDensity(0) {}
|
Density() : m_uDensity(0) {}
|
||||||
|
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
Density(Type uDensity) : m_uDensity(uDensity) {}
|
Density(Type uDensity) : m_uDensity(uDensity) {}
|
||||||
|
|
||||||
// The LowPassFilter uses this to convert between normal and accumulated types.
|
// The LowPassFilter uses this to convert between normal and accumulated types.
|
||||||
/// Copy constructor with cast
|
/// Copy constructor with cast
|
||||||
template <typename CastType> explicit Density(const Density<CastType>& density)
|
template <typename CastType> explicit Density(const Density<CastType>& density)
|
||||||
{
|
{
|
||||||
m_uDensity = static_cast<Type>(density.getDensity());
|
m_uDensity = static_cast<Type>(density.getDensity());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Density& rhs) const
|
bool operator==(const Density& rhs) const
|
||||||
{
|
{
|
||||||
return (m_uDensity == rhs.m_uDensity);
|
return (m_uDensity == rhs.m_uDensity);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator!=(const Density& rhs) const
|
bool operator!=(const Density& rhs) const
|
||||||
{
|
{
|
||||||
return !(*this == rhs);
|
return !(*this == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For densities we can supply mathematical operators which behave in an intuitive way.
|
// 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
|
// 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
|
// apply an averaging filter. The ability to divide by an integer is also needed for
|
||||||
// this same purpose.
|
// this same purpose.
|
||||||
Density<Type>& operator+=(const Density<Type>& rhs)
|
Density<Type>& operator+=(const Density<Type>& rhs)
|
||||||
{
|
{
|
||||||
m_uDensity += rhs.m_uDensity;
|
m_uDensity += rhs.m_uDensity;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Density<Type>& operator-=(const Density<Type>& rhs)
|
Density<Type>& operator-=(const Density<Type>& rhs)
|
||||||
{
|
{
|
||||||
m_uDensity -= rhs.m_uDensity;
|
m_uDensity -= rhs.m_uDensity;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Density<Type>& operator/=(uint32_t rhs)
|
Density<Type>& operator/=(uint32_t rhs)
|
||||||
{
|
{
|
||||||
m_uDensity /= rhs;
|
m_uDensity /= rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \return The current density of the voxel
|
/// \return The current density of the voxel
|
||||||
Type getDensity() const { return m_uDensity; }
|
Type getDensity() const { return m_uDensity; }
|
||||||
/**
|
/**
|
||||||
* Set the density of the voxel
|
* Set the density of the voxel
|
||||||
*
|
*
|
||||||
* \param uDensity The density to set to
|
* \param uDensity The density to set to
|
||||||
*/
|
*/
|
||||||
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
||||||
|
|
||||||
/// \return The maximum allowed density of the voxel
|
/// \return The maximum allowed density of the voxel
|
||||||
static Type getMaxDensity() { return (std::numeric_limits<Type>::max)(); }
|
static Type getMaxDensity() { return (std::numeric_limits<Type>::max)(); }
|
||||||
/// \return The minimum allowed density of the voxel
|
/// \return The minimum allowed density of the voxel
|
||||||
static Type getMinDensity() { return (std::numeric_limits<Type>::min)(); }
|
static Type getMinDensity() { return (std::numeric_limits<Type>::min)(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_uDensity;
|
Type m_uDensity;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Density<Type> operator+(const Density<Type>& lhs, const Density<Type>& rhs)
|
Density<Type> operator+(const Density<Type>& lhs, const Density<Type>& rhs)
|
||||||
{
|
{
|
||||||
Density<Type> result = lhs;
|
Density<Type> result = lhs;
|
||||||
result += rhs;
|
result += rhs;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Density<Type> operator-(const Density<Type>& lhs, const Density<Type>& rhs)
|
Density<Type> operator-(const Density<Type>& lhs, const Density<Type>& rhs)
|
||||||
{
|
{
|
||||||
Density<Type> result = lhs;
|
Density<Type> result = lhs;
|
||||||
result -= rhs;
|
result -= rhs;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Density<Type> operator/(const Density<Type>& lhs, uint32_t rhs)
|
Density<Type> operator/(const Density<Type>& lhs, uint32_t rhs)
|
||||||
{
|
{
|
||||||
Density<Type> result = lhs;
|
Density<Type> result = lhs;
|
||||||
result /= rhs;
|
result /= rhs;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the predefined density types. The 8-bit types are sufficient for many purposes (including
|
// 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.
|
// most games) but 16-bit and float types do have uses particularly in medical/scientific visualisation.
|
||||||
typedef Density<uint8_t> Density8;
|
typedef Density<uint8_t> Density8;
|
||||||
typedef Density<uint16_t> Density16;
|
typedef Density<uint16_t> Density16;
|
||||||
typedef Density<uint32_t> Density32;
|
typedef Density<uint32_t> Density32;
|
||||||
typedef Density<float> DensityFloat;
|
typedef Density<float> DensityFloat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a specialisation of DefaultMarchingCubesController for the Density voxel type
|
* This is a specialisation of DefaultMarchingCubesController for the Density voxel type
|
||||||
*/
|
*/
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class DefaultMarchingCubesController< Density<Type> >
|
class DefaultMarchingCubesController< Density<Type> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Type DensityType;
|
typedef Type DensityType;
|
||||||
typedef float MaterialType;
|
typedef float MaterialType;
|
||||||
|
|
||||||
DefaultMarchingCubesController(void)
|
DefaultMarchingCubesController(void)
|
||||||
{
|
{
|
||||||
// Default to a threshold value halfway between the min and max possible values.
|
// Default to a threshold value halfway between the min and max possible values.
|
||||||
m_tThreshold = (Density<Type>::getMinDensity() + Density<Type>::getMaxDensity()) / 2;
|
m_tThreshold = (Density<Type>::getMinDensity() + Density<Type>::getMaxDensity()) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultMarchingCubesController(DensityType tThreshold)
|
DefaultMarchingCubesController(DensityType tThreshold)
|
||||||
{
|
{
|
||||||
m_tThreshold = tThreshold;
|
m_tThreshold = tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
DensityType convertToDensity(Density<Type> voxel)
|
DensityType convertToDensity(Density<Type> voxel)
|
||||||
{
|
{
|
||||||
return voxel.getDensity();
|
return voxel.getDensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialType convertToMaterial(Density<Type> /*voxel*/)
|
MaterialType convertToMaterial(Density<Type> /*voxel*/)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialType blendMaterials(Density<Type> /*a*/, Density<Type> /*b*/, float /*weight*/)
|
MaterialType blendMaterials(Density<Type> /*a*/, Density<Type> /*b*/, float /*weight*/)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DensityType getThreshold(void)
|
DensityType getThreshold(void)
|
||||||
{
|
{
|
||||||
return m_tThreshold;
|
return m_tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setThreshold(DensityType tThreshold)
|
void setThreshold(DensityType tThreshold)
|
||||||
{
|
{
|
||||||
m_tThreshold = tThreshold;
|
m_tThreshold = tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DensityType m_tThreshold;
|
DensityType m_tThreshold;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__PolyVox_Density_H__
|
#endif //__PolyVox_Density_H__
|
||||||
|
@ -1,64 +1,64 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_GradientEstimators_H__
|
#ifndef __PolyVox_GradientEstimators_H__
|
||||||
#define __PolyVox_GradientEstimators_H__
|
#define __PolyVox_GradientEstimators_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
#include "PolyVoxCore/VoxelFilters.h"
|
#include "PolyVoxCore/VoxelFilters.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
enum NormalGenerationMethod
|
enum NormalGenerationMethod
|
||||||
{
|
{
|
||||||
SIMPLE, ///<Fastest
|
SIMPLE, ///<Fastest
|
||||||
CENTRAL_DIFFERENCE,
|
CENTRAL_DIFFERENCE,
|
||||||
SOBEL,
|
SOBEL,
|
||||||
CENTRAL_DIFFERENCE_SMOOTHED,
|
CENTRAL_DIFFERENCE_SMOOTHED,
|
||||||
SOBEL_SMOOTHED ///<Smoothest
|
SOBEL_SMOOTHED ///<Smoothest
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeDecimatedCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeDecimatedCentralDifferenceGradient(typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter);
|
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter);
|
||||||
|
|
||||||
//POLYVOX_API void computeNormalsForVertices(VolumeType<uint8_t>* volumeData, Mesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
//POLYVOX_API void computeNormalsForVertices(VolumeType<uint8_t>* volumeData, Mesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
||||||
//POLYVOX_API Vector3DFloat computeNormal(VolumeType<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
//POLYVOX_API Vector3DFloat computeNormal(VolumeType<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/GradientEstimators.inl"
|
#include "PolyVoxCore/GradientEstimators.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_GradientEstimators_H__
|
#endif //__PolyVox_GradientEstimators_H__
|
||||||
|
@ -1,302 +1,302 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
Vector3DFloat computeCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
||||||
{
|
{
|
||||||
//FIXME - bitwise way of doing this?
|
//FIXME - bitwise way of doing this?
|
||||||
typename VolumeType::VoxelType voxel1nx = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1nx = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1px = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1px = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
typename VolumeType::VoxelType voxel1ny = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1ny = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1py = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1py = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
typename VolumeType::VoxelType voxel1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
return Vector3DFloat
|
return Vector3DFloat
|
||||||
(
|
(
|
||||||
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
||||||
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
||||||
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeDecimatedCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
Vector3DFloat computeDecimatedCentralDifferenceGradient(const typename VolumeType::Sampler& volIter)
|
||||||
{
|
{
|
||||||
const int32_t x = volIter.getPosition().getX();
|
const int32_t x = volIter.getPosition().getX();
|
||||||
const int32_t y = volIter.getPosition().getY();
|
const int32_t y = volIter.getPosition().getY();
|
||||||
const int32_t z = volIter.getPosition().getZ();
|
const int32_t z = volIter.getPosition().getZ();
|
||||||
|
|
||||||
//FIXME - bitwise way of doing this?
|
//FIXME - bitwise way of doing this?
|
||||||
typename VolumeType::VoxelType voxel1nx = volIter.getVoxel(x-2, y ,z ) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1nx = volIter.getVoxel(x-2, y ,z ) > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1px = volIter.getVoxel(x-2, y ,z ) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1px = volIter.getVoxel(x-2, y ,z ) > 0 ? 1: 0;
|
||||||
|
|
||||||
typename VolumeType::VoxelType voxel1ny = volIter.getVoxel(x , y-2,z ) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1ny = volIter.getVoxel(x , y-2,z ) > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1py = volIter.getVoxel(x , y-2,z ) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1py = volIter.getVoxel(x , y-2,z ) > 0 ? 1: 0;
|
||||||
|
|
||||||
typename VolumeType::VoxelType voxel1nz = volIter.getVoxel(x , y ,z-2) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1nz = volIter.getVoxel(x , y ,z-2) > 0 ? 1: 0;
|
||||||
typename VolumeType::VoxelType voxel1pz = volIter.getVoxel(x , y ,z-2) > 0 ? 1: 0;
|
typename VolumeType::VoxelType voxel1pz = volIter.getVoxel(x , y ,z-2) > 0 ? 1: 0;
|
||||||
|
|
||||||
return Vector3DFloat
|
return Vector3DFloat
|
||||||
(
|
(
|
||||||
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
static_cast<float>(voxel1nx) - static_cast<float>(voxel1px),
|
||||||
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
static_cast<float>(voxel1ny) - static_cast<float>(voxel1py),
|
||||||
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
static_cast<float>(voxel1nz) - static_cast<float>(voxel1pz)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter)
|
Vector3DFloat computeSmoothCentralDifferenceGradient(typename VolumeType::Sampler& volIter)
|
||||||
{
|
{
|
||||||
int32_t initialX = volIter.getPosition().getX();
|
int32_t initialX = volIter.getPosition().getX();
|
||||||
int32_t initialY = volIter.getPosition().getY();
|
int32_t initialY = volIter.getPosition().getY();
|
||||||
int32_t initialZ = volIter.getPosition().getZ();
|
int32_t initialZ = volIter.getPosition().getZ();
|
||||||
|
|
||||||
//FIXME - bitwise way of doing this?
|
//FIXME - bitwise way of doing this?
|
||||||
volIter.setPosition(initialX-1, initialY, initialZ);
|
volIter.setPosition(initialX-1, initialY, initialZ);
|
||||||
float voxel1nx = computeSmoothedVoxel(volIter);
|
float voxel1nx = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX+1, initialY, initialZ);
|
volIter.setPosition(initialX+1, initialY, initialZ);
|
||||||
float voxel1px = computeSmoothedVoxel(volIter);
|
float voxel1px = computeSmoothedVoxel(volIter);
|
||||||
|
|
||||||
volIter.setPosition(initialX, initialY-1, initialZ);
|
volIter.setPosition(initialX, initialY-1, initialZ);
|
||||||
float voxel1ny = computeSmoothedVoxel(volIter);
|
float voxel1ny = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX, initialY+1, initialZ);
|
volIter.setPosition(initialX, initialY+1, initialZ);
|
||||||
float voxel1py = computeSmoothedVoxel(volIter);
|
float voxel1py = computeSmoothedVoxel(volIter);
|
||||||
|
|
||||||
volIter.setPosition(initialX, initialY, initialZ-1);
|
volIter.setPosition(initialX, initialY, initialZ-1);
|
||||||
float voxel1nz = computeSmoothedVoxel(volIter);
|
float voxel1nz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX, initialY, initialZ+1);
|
volIter.setPosition(initialX, initialY, initialZ+1);
|
||||||
float voxel1pz = computeSmoothedVoxel(volIter);
|
float voxel1pz = computeSmoothedVoxel(volIter);
|
||||||
|
|
||||||
return Vector3DFloat
|
return Vector3DFloat
|
||||||
(
|
(
|
||||||
voxel1nx - voxel1px,
|
voxel1nx - voxel1px,
|
||||||
voxel1ny - voxel1py,
|
voxel1ny - voxel1py,
|
||||||
voxel1nz - voxel1pz
|
voxel1nz - voxel1pz
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter)
|
Vector3DFloat computeSobelGradient(const typename VolumeType::Sampler& volIter)
|
||||||
{
|
{
|
||||||
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
|
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} } };
|
{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 pVoxel1nx1ny1nz = volIter.peekVoxel1nx1ny1nz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1nx1ny0pz = volIter.peekVoxel1nx1ny0pz() > 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 pVoxel1nx1ny1pz = volIter.peekVoxel1nx1ny1pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1nx0py1nz = volIter.peekVoxel1nx0py1nz() > 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 pVoxel1nx0py0pz = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1nx0py1pz = volIter.peekVoxel1nx0py1pz() > 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 pVoxel1nx1py1nz = volIter.peekVoxel1nx1py1nz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1nx1py0pz = volIter.peekVoxel1nx1py0pz() > 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 pVoxel1nx1py1pz = volIter.peekVoxel1nx1py1pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
const typename VolumeType::VoxelType pVoxel0px1ny1nz = volIter.peekVoxel0px1ny1nz() > 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 pVoxel0px1ny0pz = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
const typename VolumeType::VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
const typename VolumeType::VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||||
//const VolumeType::VoxelType pVoxel0px0py0pz = volIter.peekVoxel0px0py0pz() > 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 pVoxel0px0py1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel0px1py1nz = volIter.peekVoxel0px1py1nz() > 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 pVoxel0px1py0pz = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel0px1py1pz = volIter.peekVoxel0px1py1pz() > 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 pVoxel1px1ny1nz = volIter.peekVoxel1px1ny1nz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1px1ny0pz = volIter.peekVoxel1px1ny0pz() > 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 pVoxel1px1ny1pz = volIter.peekVoxel1px1ny1pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1px0py1nz = volIter.peekVoxel1px0py1nz() > 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 pVoxel1px0py0pz = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1px0py1pz = volIter.peekVoxel1px0py1pz() > 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 pVoxel1px1py1nz = volIter.peekVoxel1px1py1nz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
const typename VolumeType::VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
||||||
const typename VolumeType::VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;
|
const typename VolumeType::VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
const int xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
const int xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||||
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
||||||
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
||||||
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
||||||
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
||||||
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
||||||
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
||||||
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
||||||
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
const int yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
const int yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||||
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
||||||
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
||||||
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
||||||
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
||||||
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
||||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
||||||
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
||||||
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
const int zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
const int zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
||||||
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
||||||
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
||||||
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
||||||
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
||||||
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
||||||
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
||||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
||||||
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
||||||
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
||||||
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
//Note: The above actually give gradients going from low density to high density.
|
//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.
|
//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));
|
return Vector3DFloat(static_cast<float>(-xGrad),static_cast<float>(-yGrad),static_cast<float>(-zGrad));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename VolumeType>
|
template<typename VolumeType>
|
||||||
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter)
|
Vector3DFloat computeSmoothSobelGradient(typename VolumeType::Sampler& volIter)
|
||||||
{
|
{
|
||||||
static const int weights[3][3][3] = { { {2,3,2}, {3,6,3}, {2,3,2} }, {
|
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} } };
|
{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 initialX = volIter.getPosition().getX();
|
||||||
int32_t initialY = volIter.getPosition().getY();
|
int32_t initialY = volIter.getPosition().getY();
|
||||||
int32_t initialZ = volIter.getPosition().getZ();
|
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-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 ); const float pVoxel1nx1ny0pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX-1, initialY-1, initialZ+1); const float pVoxel1nx1ny1pz = 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-1); const float pVoxel1nx0py1nz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX-1, initialY , initialZ ); const float pVoxel1nx0py0pz = 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 , 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-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 ); const float pVoxel1nx1py0pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX-1, initialY+1, initialZ+1); const float pVoxel1nx1py1pz = 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-1); const float pVoxel0px1ny1nz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX , initialY-1, initialZ ); const float pVoxel0px1ny0pz = 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-1, initialZ+1); const float pVoxel0px1ny1pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX , initialY , initialZ-1); const float pVoxel0px0py1nz = 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 ); const float pVoxel0px0py0pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX , initialY , initialZ+1); const float pVoxel0px0py1pz = 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-1); const float pVoxel0px1py1nz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX , initialY+1, initialZ ); const float pVoxel0px1py0pz = 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 , 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-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 ); const float pVoxel1px1ny0pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX+1, initialY-1, initialZ+1); const float pVoxel1px1ny1pz = 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-1); const float pVoxel1px0py1nz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX+1, initialY , initialZ ); const float pVoxel1px0py0pz = 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 , 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-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 ); const float pVoxel1px1py0pz = computeSmoothedVoxel(volIter);
|
||||||
volIter.setPosition(initialX+1, initialY+1, initialZ+1); const float pVoxel1px1py1pz = 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 pVoxel1nx1ny1nz = volIter.peekVoxel1nx1ny1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx1ny0pz = volIter.peekVoxel1nx1ny0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx1ny0pz = volIter.peekVoxel1nx1ny0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx1ny1pz = volIter.peekVoxel1nx1ny1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx1ny1pz = volIter.peekVoxel1nx1ny1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx0py1nz = volIter.peekVoxel1nx0py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx0py1nz = volIter.peekVoxel1nx0py1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx0py0pz = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx0py0pz = volIter.peekVoxel1nx0py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx0py1pz = volIter.peekVoxel1nx0py1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx0py1pz = volIter.peekVoxel1nx0py1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx1py1nz = volIter.peekVoxel1nx1py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx1py1nz = volIter.peekVoxel1nx1py1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx1py0pz = volIter.peekVoxel1nx1py0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx1py0pz = volIter.peekVoxel1nx1py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1nx1py1pz = volIter.peekVoxel1nx1py1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1nx1py1pz = volIter.peekVoxel1nx1py1pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
const VoxelType pVoxel0px1ny1nz = volIter.peekVoxel0px1ny1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1ny1nz = volIter.peekVoxel0px1ny1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px1ny0pz = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1ny0pz = volIter.peekVoxel0px1ny0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1ny1pz = volIter.peekVoxel0px1ny1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px0py1nz = volIter.peekVoxel0px0py1nz() > 0 ? 1: 0;
|
||||||
//const VoxelType pVoxel0px0py0pz = volIter.peekVoxel0px0py0pz() > 0 ? 1: 0;
|
//const VoxelType pVoxel0px0py0pz = volIter.peekVoxel0px0py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px0py1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px0py1pz = volIter.peekVoxel0px0py1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px1py1nz = volIter.peekVoxel0px1py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1py1nz = volIter.peekVoxel0px1py1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px1py0pz = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1py0pz = volIter.peekVoxel0px1py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel0px1py1pz = volIter.peekVoxel0px1py1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel0px1py1pz = volIter.peekVoxel0px1py1pz() > 0 ? 1: 0;
|
||||||
|
|
||||||
const VoxelType pVoxel1px1ny1nz = volIter.peekVoxel1px1ny1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px1ny1nz = volIter.peekVoxel1px1ny1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px1ny0pz = volIter.peekVoxel1px1ny0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px1ny0pz = volIter.peekVoxel1px1ny0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px1ny1pz = volIter.peekVoxel1px1ny1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px1ny1pz = volIter.peekVoxel1px1ny1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px0py1nz = volIter.peekVoxel1px0py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px0py1nz = volIter.peekVoxel1px0py1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px0py0pz = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px0py0pz = volIter.peekVoxel1px0py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px0py1pz = volIter.peekVoxel1px0py1pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px0py1pz = volIter.peekVoxel1px0py1pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px1py1nz = volIter.peekVoxel1px1py1nz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px1py1nz = volIter.peekVoxel1px1py1nz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
const VoxelType pVoxel1px1py0pz = volIter.peekVoxel1px1py0pz() > 0 ? 1: 0;
|
||||||
const VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;*/
|
const VoxelType pVoxel1px1py1pz = volIter.peekVoxel1px1py1pz() > 0 ? 1: 0;*/
|
||||||
|
|
||||||
const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
const float xGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||||
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
pVoxel1nx1ny1pz - weights[0][1][0] * pVoxel1nx0py1nz -
|
||||||
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
weights[1][1][0] * pVoxel1nx0py0pz - weights[2][1][0] *
|
||||||
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
pVoxel1nx0py1pz - weights[0][2][0] * pVoxel1nx1py1nz -
|
||||||
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
weights[1][2][0] * pVoxel1nx1py0pz - weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
pVoxel1nx1py1pz + weights[0][0][2] * pVoxel1px1ny1nz +
|
||||||
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
weights[1][0][2] * pVoxel1px1ny0pz + weights[2][0][2] *
|
||||||
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
pVoxel1px1ny1pz + weights[0][1][2] * pVoxel1px0py1nz +
|
||||||
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
weights[1][1][2] * pVoxel1px0py0pz + weights[2][1][2] *
|
||||||
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
pVoxel1px0py1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
const float yGrad(- weights[0][0][0] * pVoxel1nx1ny1nz -
|
||||||
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
weights[1][0][0] * pVoxel1nx1ny0pz - weights[2][0][0] *
|
||||||
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
pVoxel1nx1ny1pz + weights[0][2][0] * pVoxel1nx1py1nz +
|
||||||
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
weights[1][2][0] * pVoxel1nx1py0pz + weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz -
|
||||||
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
weights[1][0][1] * pVoxel0px1ny0pz - weights[2][0][1] *
|
||||||
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
pVoxel0px1ny1pz + weights[0][2][1] * pVoxel0px1py1nz +
|
||||||
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
weights[1][2][1] * pVoxel0px1py0pz + weights[2][2][1] *
|
||||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz -
|
||||||
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
weights[1][0][2] * pVoxel1px1ny0pz - weights[2][0][2] *
|
||||||
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
pVoxel1px1ny1pz + weights[0][2][2] * pVoxel1px1py1nz +
|
||||||
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
weights[1][2][2] * pVoxel1px1py0pz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
const float zGrad(- weights[0][0][0] * pVoxel1nx1ny1nz +
|
||||||
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
weights[2][0][0] * pVoxel1nx1ny1pz - weights[0][1][0] *
|
||||||
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
pVoxel1nx0py1nz + weights[2][1][0] * pVoxel1nx0py1pz -
|
||||||
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
weights[0][2][0] * pVoxel1nx1py1nz + weights[2][2][0] *
|
||||||
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
pVoxel1nx1py1pz - weights[0][0][1] * pVoxel0px1ny1nz +
|
||||||
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
weights[2][0][1] * pVoxel0px1ny1pz - weights[0][1][1] *
|
||||||
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
pVoxel0px0py1nz + weights[2][1][1] * pVoxel0px0py1pz -
|
||||||
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
weights[0][2][1] * pVoxel0px1py1nz + weights[2][2][1] *
|
||||||
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
pVoxel0px1py1pz - weights[0][0][2] * pVoxel1px1ny1nz +
|
||||||
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
weights[2][0][2] * pVoxel1px1ny1pz - weights[0][1][2] *
|
||||||
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
pVoxel1px0py1nz + weights[2][1][2] * pVoxel1px0py1pz -
|
||||||
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
weights[0][2][2] * pVoxel1px1py1nz + weights[2][2][2] *
|
||||||
pVoxel1px1py1pz);
|
pVoxel1px1py1pz);
|
||||||
|
|
||||||
//Note: The above actually give gradients going from low density to high density.
|
//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.
|
//For our normals we want the the other way around, so we switch the components as we return them.
|
||||||
return Vector3DFloat(-xGrad,-yGrad,-zGrad);
|
return Vector3DFloat(-xGrad,-yGrad,-zGrad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Utility_H__
|
#ifndef __PolyVox_Utility_H__
|
||||||
#define __PolyVox_Utility_H__
|
#define __PolyVox_Utility_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
POLYVOX_API uint8_t logBase2(uint32_t uInput);
|
POLYVOX_API uint8_t logBase2(uint32_t uInput);
|
||||||
POLYVOX_API bool isPowerOf2(uint32_t uInput);
|
POLYVOX_API bool isPowerOf2(uint32_t uInput);
|
||||||
|
|
||||||
int32_t roundTowardsNegInf(float r);
|
int32_t roundTowardsNegInf(float r);
|
||||||
int32_t roundToInteger(float r);
|
int32_t roundToInteger(float r);
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Type clamp(const Type& value, const Type& low, const Type& high);
|
Type clamp(const Type& value, const Type& low, const Type& high);
|
||||||
uint32_t upperPowerOfTwo(uint32_t v);
|
uint32_t upperPowerOfTwo(uint32_t v);
|
||||||
|
|
||||||
inline int32_t roundTowardsNegInf(float r)
|
inline int32_t roundTowardsNegInf(float r)
|
||||||
{
|
{
|
||||||
return (r >= 0.0) ? static_cast<int32_t>(r) : static_cast<int32_t>(r - 1.0f);
|
return (r >= 0.0) ? static_cast<int32_t>(r) : static_cast<int32_t>(r - 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t roundToNearestInteger(float r)
|
inline int32_t roundToNearestInteger(float r)
|
||||||
{
|
{
|
||||||
return (r >= 0.0) ? static_cast<int32_t>(r + 0.5f) : static_cast<int32_t>(r - 0.5f);
|
return (r >= 0.0) ? static_cast<int32_t>(r + 0.5f) : static_cast<int32_t>(r - 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
inline Type clamp(const Type& value, const Type& low, const Type& high)
|
inline Type clamp(const Type& value, const Type& low, const Type& high)
|
||||||
{
|
{
|
||||||
return (std::min)(high, (std::max)(low, value));
|
return (std::min)(high, (std::max)(low, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,46 +1,46 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_IteratorController_H__
|
#ifndef __PolyVox_IteratorController_H__
|
||||||
#define __PolyVox_IteratorController_H__
|
#define __PolyVox_IteratorController_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template <typename IteratorType>
|
template <typename IteratorType>
|
||||||
class IteratorController
|
class IteratorController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void reset(void);
|
void reset(void);
|
||||||
bool moveForward(void);
|
bool moveForward(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Region m_regValid;
|
Region m_regValid;
|
||||||
IteratorType* m_Iter;
|
IteratorType* m_Iter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/IteratorController.inl"
|
#include "PolyVoxCore/IteratorController.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_IteratorController_H__
|
#endif //__PolyVox_IteratorController_H__
|
||||||
|
@ -1,63 +1,63 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template <typename IteratorType>
|
template <typename IteratorType>
|
||||||
void IteratorController<IteratorType>::reset(void)
|
void IteratorController<IteratorType>::reset(void)
|
||||||
{
|
{
|
||||||
m_Iter->setPosition(m_regValid.getLowerCorner());
|
m_Iter->setPosition(m_regValid.getLowerCorner());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename IteratorType>
|
template <typename IteratorType>
|
||||||
bool IteratorController<IteratorType>::moveForward(void)
|
bool IteratorController<IteratorType>::moveForward(void)
|
||||||
{
|
{
|
||||||
Vector3DInt32 v3dInitialPosition(m_Iter->getPosition().getX(), m_Iter->getPosition().getY(), m_Iter->getPosition().getZ());
|
Vector3DInt32 v3dInitialPosition(m_Iter->getPosition().getX(), m_Iter->getPosition().getY(), m_Iter->getPosition().getZ());
|
||||||
|
|
||||||
if(v3dInitialPosition.getX() < m_regValid.getUpperX())
|
if(v3dInitialPosition.getX() < m_regValid.getUpperX())
|
||||||
{
|
{
|
||||||
m_Iter->movePositiveX();
|
m_Iter->movePositiveX();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3dInitialPosition.setX(m_regValid.getLowerX());
|
v3dInitialPosition.setX(m_regValid.getLowerX());
|
||||||
|
|
||||||
if(v3dInitialPosition.getY() < m_regValid.getUpperY())
|
if(v3dInitialPosition.getY() < m_regValid.getUpperY())
|
||||||
{
|
{
|
||||||
v3dInitialPosition.setY(v3dInitialPosition.getY() + 1);
|
v3dInitialPosition.setY(v3dInitialPosition.getY() + 1);
|
||||||
m_Iter->setPosition(v3dInitialPosition);
|
m_Iter->setPosition(v3dInitialPosition);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3dInitialPosition.setY(m_regValid.getLowerY());
|
v3dInitialPosition.setY(m_regValid.getLowerY());
|
||||||
|
|
||||||
if(v3dInitialPosition.getZ() < m_regValid.getUpperZ())
|
if(v3dInitialPosition.getZ() < m_regValid.getUpperZ())
|
||||||
{
|
{
|
||||||
v3dInitialPosition.setZ(v3dInitialPosition.getZ() + 1);
|
v3dInitialPosition.setZ(v3dInitialPosition.getZ() + 1);
|
||||||
m_Iter->setPosition(v3dInitialPosition);
|
m_Iter->setPosition(v3dInitialPosition);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef __PolyVox_LargeVolume_H__
|
#ifndef __PolyVox_LargeVolume_H__
|
||||||
#define __PolyVox_LargeVolume_H__
|
#define __PolyVox_LargeVolume_H__
|
||||||
|
|
||||||
#pragma message("WARNING - The LargeVolume class has been replaced by PagedVolume. Please use that instead.")
|
#pragma message("WARNING - The LargeVolume class has been replaced by PagedVolume. Please use that instead.")
|
||||||
|
|
||||||
#include "PagedVolume.h"
|
#include "PagedVolume.h"
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
#endif //__PolyVox_LargeVolume_H__
|
#endif //__PolyVox_LargeVolume_H__
|
@ -1,60 +1,60 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_LowPassFilter_H__
|
#ifndef __PolyVox_LowPassFilter_H__
|
||||||
#define __PolyVox_LowPassFilter_H__
|
#define __PolyVox_LowPassFilter_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/IteratorController.h"
|
#include "PolyVoxCore/IteratorController.h"
|
||||||
#include "PolyVoxCore/RawVolume.h" //Is this desirable?
|
#include "PolyVoxCore/RawVolume.h" //Is this desirable?
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||||
class LowPassFilter
|
class LowPassFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize);
|
LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize);
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
void executeSAT();
|
void executeSAT();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Source data
|
//Source data
|
||||||
SrcVolumeType* m_pVolSrc;
|
SrcVolumeType* m_pVolSrc;
|
||||||
Region m_regSrc;
|
Region m_regSrc;
|
||||||
|
|
||||||
//Destination data
|
//Destination data
|
||||||
DstVolumeType* m_pVolDst;
|
DstVolumeType* m_pVolDst;
|
||||||
Region m_regDst;
|
Region m_regDst;
|
||||||
|
|
||||||
//Kernel size
|
//Kernel size
|
||||||
uint32_t m_uKernelSize;
|
uint32_t m_uKernelSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace PolyVox
|
}//namespace PolyVox
|
||||||
|
|
||||||
#include "PolyVoxCore/LowPassFilter.inl"
|
#include "PolyVoxCore/LowPassFilter.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_LowPassFilter_H__
|
#endif //__PolyVox_LowPassFilter_H__
|
||||||
|
|
||||||
|
@ -1,255 +1,255 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* \param pVolSrc
|
* \param pVolSrc
|
||||||
* \param regSrc
|
* \param regSrc
|
||||||
* \param[out] pVolDst
|
* \param[out] pVolDst
|
||||||
* \param regDst
|
* \param regDst
|
||||||
* \param uKernelSize
|
* \param uKernelSize
|
||||||
*/
|
*/
|
||||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||||
LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize)
|
LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::LowPassFilter(SrcVolumeType* pVolSrc, Region regSrc, DstVolumeType* pVolDst, Region regDst, uint32_t uKernelSize)
|
||||||
:m_pVolSrc(pVolSrc)
|
:m_pVolSrc(pVolSrc)
|
||||||
,m_regSrc(regSrc)
|
,m_regSrc(regSrc)
|
||||||
,m_pVolDst(pVolDst)
|
,m_pVolDst(pVolDst)
|
||||||
,m_regDst(regDst)
|
,m_regDst(regDst)
|
||||||
,m_uKernelSize(uKernelSize)
|
,m_uKernelSize(uKernelSize)
|
||||||
{
|
{
|
||||||
//Kernel size must be at least three
|
//Kernel size must be at least three
|
||||||
if(m_uKernelSize < 3)
|
if(m_uKernelSize < 3)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Kernel size must be at least three");
|
POLYVOX_THROW(std::invalid_argument, "Kernel size must be at least three");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Kernel size must be odd
|
//Kernel size must be odd
|
||||||
if(m_uKernelSize % 2 == 0)
|
if(m_uKernelSize % 2 == 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Kernel size must be odd");
|
POLYVOX_THROW(std::invalid_argument, "Kernel size must be odd");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||||
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::execute()
|
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::execute()
|
||||||
{
|
{
|
||||||
int32_t iSrcMinX = m_regSrc.getLowerX();
|
int32_t iSrcMinX = m_regSrc.getLowerX();
|
||||||
int32_t iSrcMinY = m_regSrc.getLowerY();
|
int32_t iSrcMinY = m_regSrc.getLowerY();
|
||||||
int32_t iSrcMinZ = m_regSrc.getLowerZ();
|
int32_t iSrcMinZ = m_regSrc.getLowerZ();
|
||||||
|
|
||||||
int32_t iSrcMaxX = m_regSrc.getUpperX();
|
int32_t iSrcMaxX = m_regSrc.getUpperX();
|
||||||
int32_t iSrcMaxY = m_regSrc.getUpperY();
|
int32_t iSrcMaxY = m_regSrc.getUpperY();
|
||||||
int32_t iSrcMaxZ = m_regSrc.getUpperZ();
|
int32_t iSrcMaxZ = m_regSrc.getUpperZ();
|
||||||
|
|
||||||
int32_t iDstMinX = m_regDst.getLowerX();
|
int32_t iDstMinX = m_regDst.getLowerX();
|
||||||
int32_t iDstMinY = m_regDst.getLowerY();
|
int32_t iDstMinY = m_regDst.getLowerY();
|
||||||
int32_t iDstMinZ = m_regDst.getLowerZ();
|
int32_t iDstMinZ = m_regDst.getLowerZ();
|
||||||
|
|
||||||
//int32_t iDstMaxX = m_regDst.getUpperX();
|
//int32_t iDstMaxX = m_regDst.getUpperX();
|
||||||
//int32_t iDstMaxY = m_regDst.getUpperY();
|
//int32_t iDstMaxY = m_regDst.getUpperY();
|
||||||
//int32_t iDstMaxZ = m_regDst.getUpperZ();
|
//int32_t iDstMaxZ = m_regDst.getUpperZ();
|
||||||
|
|
||||||
typename SrcVolumeType::Sampler srcSampler(m_pVolSrc);
|
typename SrcVolumeType::Sampler srcSampler(m_pVolSrc);
|
||||||
|
|
||||||
for(int32_t iSrcZ = iSrcMinZ, iDstZ = iDstMinZ; iSrcZ <= iSrcMaxZ; iSrcZ++, iDstZ++)
|
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 iSrcY = iSrcMinY, iDstY = iDstMinY; iSrcY <= iSrcMaxY; iSrcY++, iDstY++)
|
||||||
{
|
{
|
||||||
for(int32_t iSrcX = iSrcMinX, iDstX = iDstMinX; iSrcX <= iSrcMaxX; iSrcX++, iDstX++)
|
for(int32_t iSrcX = iSrcMinX, iDstX = iDstMinX; iSrcX <= iSrcMaxX; iSrcX++, iDstX++)
|
||||||
{
|
{
|
||||||
AccumulationType tSrcVoxel(0);
|
AccumulationType tSrcVoxel(0);
|
||||||
srcSampler.setPosition(iSrcX, iSrcY, iSrcZ);
|
srcSampler.setPosition(iSrcX, iSrcY, iSrcZ);
|
||||||
|
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1ny1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx0py1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1nx1py1pz());
|
||||||
|
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1ny1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px0py1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel0px1py1pz());
|
||||||
|
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1ny1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px0py1pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1nz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1nz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py0pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py0pz());
|
||||||
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1pz());
|
tSrcVoxel += static_cast<AccumulationType>(srcSampler.peekVoxel1px1py1pz());
|
||||||
|
|
||||||
tSrcVoxel /= 27;
|
tSrcVoxel /= 27;
|
||||||
|
|
||||||
//tSrcVoxel.setDensity(uDensity);
|
//tSrcVoxel.setDensity(uDensity);
|
||||||
m_pVolDst->setVoxelAt(iSrcX, iSrcY, iSrcZ, static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel));
|
m_pVolDst->setVoxelAt(iSrcX, iSrcY, iSrcZ, static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
template< typename SrcVolumeType, typename DstVolumeType, typename AccumulationType>
|
||||||
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::executeSAT()
|
void LowPassFilter<SrcVolumeType, DstVolumeType, AccumulationType>::executeSAT()
|
||||||
{
|
{
|
||||||
const uint32_t border = (m_uKernelSize - 1) / 2;
|
const uint32_t border = (m_uKernelSize - 1) / 2;
|
||||||
|
|
||||||
Vector3DInt32 satLowerCorner = m_regSrc.getLowerCorner() - Vector3DInt32(border, border, border);
|
Vector3DInt32 satLowerCorner = m_regSrc.getLowerCorner() - Vector3DInt32(border, border, border);
|
||||||
Vector3DInt32 satUpperCorner = m_regSrc.getUpperCorner() + 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
|
//Use floats for the SAT volume to ensure it works with negative
|
||||||
//densities and with both integral and floating point input volumes.
|
//densities and with both integral and floating point input volumes.
|
||||||
RawVolume<AccumulationType> satVolume(Region(satLowerCorner, satUpperCorner));
|
RawVolume<AccumulationType> satVolume(Region(satLowerCorner, satUpperCorner));
|
||||||
|
|
||||||
//Clear to zeros (necessary?)
|
//Clear to zeros (necessary?)
|
||||||
//FIXME - use Volume::fill() method. Implemented in base class as below
|
//FIXME - use Volume::fill() method. Implemented in base class as below
|
||||||
//but with optimised implementations in subclasses?
|
//but with optimised implementations in subclasses?
|
||||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
satVolume.setVoxelAt(x,y,z,0);
|
satVolume.setVoxelAt(x,y,z,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typename RawVolume<AccumulationType>::Sampler satVolumeIter(&satVolume);
|
typename RawVolume<AccumulationType>::Sampler satVolumeIter(&satVolume);
|
||||||
|
|
||||||
IteratorController<typename RawVolume<AccumulationType>::Sampler> satIterCont;
|
IteratorController<typename RawVolume<AccumulationType>::Sampler> satIterCont;
|
||||||
satIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
satIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
||||||
satIterCont.m_Iter = &satVolumeIter;
|
satIterCont.m_Iter = &satVolumeIter;
|
||||||
satIterCont.reset();
|
satIterCont.reset();
|
||||||
|
|
||||||
typename SrcVolumeType::Sampler srcVolumeIter(m_pVolSrc);
|
typename SrcVolumeType::Sampler srcVolumeIter(m_pVolSrc);
|
||||||
|
|
||||||
IteratorController<typename SrcVolumeType::Sampler> srcIterCont;
|
IteratorController<typename SrcVolumeType::Sampler> srcIterCont;
|
||||||
srcIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
srcIterCont.m_regValid = Region(satLowerCorner, satUpperCorner);
|
||||||
srcIterCont.m_Iter = &srcVolumeIter;
|
srcIterCont.m_Iter = &srcVolumeIter;
|
||||||
srcIterCont.reset();
|
srcIterCont.reset();
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolumeIter.peekVoxel1nx0py0pz());
|
AccumulationType previousSum = static_cast<AccumulationType>(satVolumeIter.peekVoxel1nx0py0pz());
|
||||||
AccumulationType currentVal = static_cast<AccumulationType>(srcVolumeIter.getVoxel());
|
AccumulationType currentVal = static_cast<AccumulationType>(srcVolumeIter.getVoxel());
|
||||||
|
|
||||||
satVolumeIter.setVoxel(previousSum + currentVal);
|
satVolumeIter.setVoxel(previousSum + currentVal);
|
||||||
|
|
||||||
srcIterCont.moveForward();
|
srcIterCont.moveForward();
|
||||||
|
|
||||||
}while(satIterCont.moveForward());
|
}while(satIterCont.moveForward());
|
||||||
|
|
||||||
//Build SAT in three passes
|
//Build SAT in three passes
|
||||||
/*for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
/*for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x-1,y,z));
|
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxelAt(x-1,y,z));
|
||||||
AccumulationType currentVal = static_cast<AccumulationType>(m_pVolSrc->getVoxelAt(x,y,z));
|
AccumulationType currentVal = static_cast<AccumulationType>(m_pVolSrc->getVoxelAt(x,y,z));
|
||||||
|
|
||||||
satVolume.setVoxelAt(x,y,z,previousSum + currentVal);
|
satVolume.setVoxelAt(x,y,z,previousSum + currentVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y-1,z, WrapModes::Border));
|
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y-1,z, WrapModes::Border));
|
||||||
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
|
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
|
||||||
|
|
||||||
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
for(int32_t z = satLowerCorner.getZ(); z <= satUpperCorner.getZ(); z++)
|
||||||
{
|
{
|
||||||
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
for(int32_t y = satLowerCorner.getY(); y <= satUpperCorner.getY(); y++)
|
||||||
{
|
{
|
||||||
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
|
||||||
{
|
{
|
||||||
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z-1, WrapModes::Border));
|
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z-1, WrapModes::Border));
|
||||||
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
|
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
|
||||||
|
|
||||||
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now compute the average
|
//Now compute the average
|
||||||
const Vector3DInt32& v3dDstLowerCorner = m_regDst.getLowerCorner();
|
const Vector3DInt32& v3dDstLowerCorner = m_regDst.getLowerCorner();
|
||||||
const Vector3DInt32& v3dDstUpperCorner = m_regDst.getUpperCorner();
|
const Vector3DInt32& v3dDstUpperCorner = m_regDst.getUpperCorner();
|
||||||
|
|
||||||
const Vector3DInt32& v3dSrcLowerCorner = m_regSrc.getLowerCorner();
|
const Vector3DInt32& v3dSrcLowerCorner = m_regSrc.getLowerCorner();
|
||||||
|
|
||||||
for(int32_t iDstZ = v3dDstLowerCorner.getZ(), iSrcZ = v3dSrcLowerCorner.getZ(); iDstZ <= v3dDstUpperCorner.getZ(); iDstZ++, iSrcZ++)
|
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 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++)
|
for(int32_t iDstX = v3dDstLowerCorner.getX(), iSrcX = v3dSrcLowerCorner.getX(); iDstX <= v3dDstUpperCorner.getX(); iDstX++, iSrcX++)
|
||||||
{
|
{
|
||||||
int32_t satLowerX = iSrcX - border - 1;
|
int32_t satLowerX = iSrcX - border - 1;
|
||||||
int32_t satLowerY = iSrcY - border - 1;
|
int32_t satLowerY = iSrcY - border - 1;
|
||||||
int32_t satLowerZ = iSrcZ - border - 1;
|
int32_t satLowerZ = iSrcZ - border - 1;
|
||||||
|
|
||||||
int32_t satUpperX = iSrcX + border;
|
int32_t satUpperX = iSrcX + border;
|
||||||
int32_t satUpperY = iSrcY + border;
|
int32_t satUpperY = iSrcY + border;
|
||||||
int32_t satUpperZ = iSrcZ + border;
|
int32_t satUpperZ = iSrcZ + border;
|
||||||
|
|
||||||
AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, WrapModes::Border);
|
AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, WrapModes::Border);
|
||||||
AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, WrapModes::Border);
|
AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, WrapModes::Border);
|
||||||
AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, WrapModes::Border);
|
AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, WrapModes::Border);
|
||||||
AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, WrapModes::Border);
|
AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, WrapModes::Border);
|
||||||
AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, WrapModes::Border);
|
AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, WrapModes::Border);
|
||||||
AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, WrapModes::Border);
|
AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, WrapModes::Border);
|
||||||
AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, WrapModes::Border);
|
AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, WrapModes::Border);
|
||||||
AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, WrapModes::Border);
|
AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, WrapModes::Border);
|
||||||
|
|
||||||
AccumulationType sum = h+c-d-g-f-a+b+e;
|
AccumulationType sum = h+c-d-g-f-a+b+e;
|
||||||
uint32_t sideLength = border * 2 + 1;
|
uint32_t sideLength = border * 2 + 1;
|
||||||
AccumulationType average = sum / (sideLength*sideLength*sideLength);
|
AccumulationType average = sum / (sideLength*sideLength*sideLength);
|
||||||
|
|
||||||
m_pVolDst->setVoxelAt(iDstX, iDstY, iDstZ, static_cast<typename DstVolumeType::VoxelType>(average));
|
m_pVolDst->setVoxelAt(iDstX, iDstY, iDstZ, static_cast<typename DstVolumeType::VoxelType>(average));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,121 +35,121 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
#ifdef SWIG
|
#ifdef SWIG
|
||||||
struct MarchingCubesVertex
|
struct MarchingCubesVertex
|
||||||
#else
|
#else
|
||||||
template<typename _DataType>
|
template<typename _DataType>
|
||||||
struct POLYVOX_API MarchingCubesVertex
|
struct POLYVOX_API MarchingCubesVertex
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
typedef _DataType DataType;
|
typedef _DataType DataType;
|
||||||
|
|
||||||
// Each component of the position is stored using 8.8 fixed-point encoding.
|
// Each component of the position is stored using 8.8 fixed-point encoding.
|
||||||
Vector3DUint16 encodedPosition;
|
Vector3DUint16 encodedPosition;
|
||||||
|
|
||||||
// The normal is encoded as a 16-bit unsigned integer using the 'oct16'
|
// The normal is encoded as a 16-bit unsigned integer using the 'oct16'
|
||||||
// encoding described here: http://jcgt.org/published/0003/02/01/
|
// encoding described here: http://jcgt.org/published/0003/02/01/
|
||||||
uint16_t encodedNormal;
|
uint16_t encodedNormal;
|
||||||
|
|
||||||
// User data
|
// User data
|
||||||
DataType data;
|
DataType data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convienient shorthand for declaring a mesh of marching cubes vertices
|
// Convienient shorthand for declaring a mesh of marching cubes vertices
|
||||||
// Currently disabled because it requires GCC 4.7
|
// Currently disabled because it requires GCC 4.7
|
||||||
//template <typename VertexDataType, typename IndexType = DefaultIndexType>
|
//template <typename VertexDataType, typename IndexType = DefaultIndexType>
|
||||||
//using MarchingCubesMesh = Mesh< MarchingCubesVertex<VertexDataType>, IndexType >;
|
//using MarchingCubesMesh = Mesh< MarchingCubesVertex<VertexDataType>, IndexType >;
|
||||||
|
|
||||||
/// Decodes a position from a MarchingCubesVertex
|
/// Decodes a position from a MarchingCubesVertex
|
||||||
inline Vector3DFloat decodePosition(const Vector3DUint16& encodedPosition)
|
inline Vector3DFloat decodePosition(const Vector3DUint16& encodedPosition)
|
||||||
{
|
{
|
||||||
Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ());
|
Vector3DFloat result(encodedPosition.getX(), encodedPosition.getY(), encodedPosition.getZ());
|
||||||
result *= (1.0f / 256.0f); // Division is compile-time constant
|
result *= (1.0f / 256.0f); // Division is compile-time constant
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t encodeNormal(const Vector3DFloat& normal)
|
inline uint16_t encodeNormal(const Vector3DFloat& normal)
|
||||||
{
|
{
|
||||||
// The first part of this function is based off the code in Listing 1 of http://jcgt.org/published/0003/02/01/
|
// The first part of this function is based off the code in Listing 1 of http://jcgt.org/published/0003/02/01/
|
||||||
// It was rewritten in C++ and is restructued for the CPU rather than the GPU.
|
// It was rewritten in C++ and is restructued for the CPU rather than the GPU.
|
||||||
|
|
||||||
// Get the input components
|
// Get the input components
|
||||||
float vx = normal.getX();
|
float vx = normal.getX();
|
||||||
float vy = normal.getY();
|
float vy = normal.getY();
|
||||||
float vz = normal.getZ();
|
float vz = normal.getZ();
|
||||||
|
|
||||||
// Project the sphere onto the octahedron, and then onto the xy plane
|
// Project the sphere onto the octahedron, and then onto the xy plane
|
||||||
float px = vx * (1.0f / (std::abs(vx) + std::abs(vy) + std::abs(vz)));
|
float px = vx * (1.0f / (std::abs(vx) + std::abs(vy) + std::abs(vz)));
|
||||||
float py = vy * (1.0f / (std::abs(vx) + std::abs(vy) + std::abs(vz)));
|
float py = vy * (1.0f / (std::abs(vx) + std::abs(vy) + std::abs(vz)));
|
||||||
|
|
||||||
// Reflect the folds of the lower hemisphere over the diagonals.
|
// Reflect the folds of the lower hemisphere over the diagonals.
|
||||||
if (vz <= 0.0f)
|
if (vz <= 0.0f)
|
||||||
{
|
{
|
||||||
float refx = ((1.0f - std::abs(py)) * (px >= 0.0f ? +1.0f : -1.0f));
|
float refx = ((1.0f - std::abs(py)) * (px >= 0.0f ? +1.0f : -1.0f));
|
||||||
float refy = ((1.0f - std::abs(px)) * (py >= 0.0f ? +1.0f : -1.0f));
|
float refy = ((1.0f - std::abs(px)) * (py >= 0.0f ? +1.0f : -1.0f));
|
||||||
px = refx;
|
px = refx;
|
||||||
py = refy;
|
py = refy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The next part was not given in the paper. We map our two
|
// The next part was not given in the paper. We map our two
|
||||||
// floats into two bytes and store them in a single uint16_t
|
// floats into two bytes and store them in a single uint16_t
|
||||||
|
|
||||||
// Move from range [-1.0f, 1.0f] to [0.0f, 255.0f]
|
// Move from range [-1.0f, 1.0f] to [0.0f, 255.0f]
|
||||||
px = (px + 1.0f) * 127.5f;
|
px = (px + 1.0f) * 127.5f;
|
||||||
py = (py + 1.0f) * 127.5f;
|
py = (py + 1.0f) * 127.5f;
|
||||||
|
|
||||||
// Convert to uints
|
// Convert to uints
|
||||||
uint16_t resultX = static_cast<uint16_t>(px + 0.5f);
|
uint16_t resultX = static_cast<uint16_t>(px + 0.5f);
|
||||||
uint16_t resultY = static_cast<uint16_t>(py + 0.5f);
|
uint16_t resultY = static_cast<uint16_t>(py + 0.5f);
|
||||||
|
|
||||||
// Make sure only the lower bits are set. Probably
|
// Make sure only the lower bits are set. Probably
|
||||||
// not necessary but we're just being careful really.
|
// not necessary but we're just being careful really.
|
||||||
resultX &= 0xFF;
|
resultX &= 0xFF;
|
||||||
resultY &= 0xFF;
|
resultY &= 0xFF;
|
||||||
|
|
||||||
// Contatenate the bytes and return the result.
|
// Contatenate the bytes and return the result.
|
||||||
return (resultX << 8) | resultY;
|
return (resultX << 8) | resultY;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vector3DFloat decodeNormal(const uint16_t& encodedNormal)
|
inline Vector3DFloat decodeNormal(const uint16_t& encodedNormal)
|
||||||
{
|
{
|
||||||
// Extract the two bytes from the uint16_t.
|
// Extract the two bytes from the uint16_t.
|
||||||
uint16_t ux = (encodedNormal >> 8) & 0xFF;
|
uint16_t ux = (encodedNormal >> 8) & 0xFF;
|
||||||
uint16_t uy = (encodedNormal ) & 0xFF;
|
uint16_t uy = (encodedNormal ) & 0xFF;
|
||||||
|
|
||||||
// Convert to floats in the range [-1.0f, +1.0f].
|
// Convert to floats in the range [-1.0f, +1.0f].
|
||||||
float ex = ux / 127.5f - 1.0f;
|
float ex = ux / 127.5f - 1.0f;
|
||||||
float ey = uy / 127.5f - 1.0f;
|
float ey = uy / 127.5f - 1.0f;
|
||||||
|
|
||||||
// Reconstruct the origninal vector. This is a C++ implementation
|
// Reconstruct the origninal vector. This is a C++ implementation
|
||||||
// of Listing 2 of http://jcgt.org/published/0003/02/01/
|
// of Listing 2 of http://jcgt.org/published/0003/02/01/
|
||||||
float vx = ex;
|
float vx = ex;
|
||||||
float vy = ey;
|
float vy = ey;
|
||||||
float vz = 1.0f - std::abs(ex) - std::abs(ey);
|
float vz = 1.0f - std::abs(ex) - std::abs(ey);
|
||||||
|
|
||||||
if (vz < 0.0f)
|
if (vz < 0.0f)
|
||||||
{
|
{
|
||||||
float refX = ((1.0f - std::abs(vy)) * (vx >= 0.0f ? +1.0f : -1.0f));
|
float refX = ((1.0f - std::abs(vy)) * (vx >= 0.0f ? +1.0f : -1.0f));
|
||||||
float refY = ((1.0f - std::abs(vx)) * (vy >= 0.0f ? +1.0f : -1.0f));
|
float refY = ((1.0f - std::abs(vx)) * (vy >= 0.0f ? +1.0f : -1.0f));
|
||||||
vx = refX;
|
vx = refX;
|
||||||
vy = refY;
|
vy = refY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalise and return the result.
|
// Normalise and return the result.
|
||||||
Vector3DFloat v(vx, vy, vz);
|
Vector3DFloat v(vx, vy, vz);
|
||||||
v.normalise();
|
v.normalise();
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering.
|
/// Decodes a MarchingCubesVertex by converting it into a regular Vertex which can then be directly used for rendering.
|
||||||
template<typename DataType>
|
template<typename DataType>
|
||||||
Vertex<DataType> decodeVertex(const MarchingCubesVertex<DataType>& marchingCubesVertex)
|
Vertex<DataType> decodeVertex(const MarchingCubesVertex<DataType>& marchingCubesVertex)
|
||||||
{
|
{
|
||||||
Vertex<DataType> result;
|
Vertex<DataType> result;
|
||||||
result.position = decodePosition(marchingCubesVertex.encodedPosition);
|
result.position = decodePosition(marchingCubesVertex.encodedPosition);
|
||||||
result.normal = decodeNormal(marchingCubesVertex.encodedNormal);
|
result.normal = decodeNormal(marchingCubesVertex.encodedNormal);
|
||||||
result.data = marchingCubesVertex.data; // Data is not encoded
|
result.data = marchingCubesVertex.data; // Data is not encoded
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not use this class directly. Use the 'extractMarchingCubesSurface' function instead (see examples).
|
/// Do not use this class directly. Use the 'extractMarchingCubesSurface' function instead (see examples).
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,91 +1,91 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Material_H__
|
#ifndef __PolyVox_Material_H__
|
||||||
#define __PolyVox_Material_H__
|
#define __PolyVox_Material_H__
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
|
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
///This class represents a voxel storing only a material.
|
///This class represents a voxel storing only a material.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Detailed description...
|
/// Detailed description...
|
||||||
///
|
///
|
||||||
/// \sa Density, MaterialDensityPair
|
/// \sa Density, MaterialDensityPair
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class Material
|
class Material
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Material() : m_uMaterial(0) {}
|
Material() : m_uMaterial(0) {}
|
||||||
Material(Type uMaterial) : m_uMaterial(uMaterial) {}
|
Material(Type uMaterial) : m_uMaterial(uMaterial) {}
|
||||||
|
|
||||||
bool operator==(const Material& rhs) const
|
bool operator==(const Material& rhs) const
|
||||||
{
|
{
|
||||||
return (m_uMaterial == rhs.m_uMaterial);
|
return (m_uMaterial == rhs.m_uMaterial);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator!=(const Material& rhs) const
|
bool operator!=(const Material& rhs) const
|
||||||
{
|
{
|
||||||
return !(*this == rhs);
|
return !(*this == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \return The current material value of the voxel
|
/// \return The current material value of the voxel
|
||||||
Type getMaterial() const { return m_uMaterial; }
|
Type getMaterial() const { return m_uMaterial; }
|
||||||
/**
|
/**
|
||||||
* Set the material value of the voxel
|
* Set the material value of the voxel
|
||||||
*
|
*
|
||||||
* \param uMaterial The material to set to
|
* \param uMaterial The material to set to
|
||||||
*/
|
*/
|
||||||
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_uMaterial;
|
Type m_uMaterial;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Material<uint8_t> Material8;
|
typedef Material<uint8_t> Material8;
|
||||||
typedef Material<uint16_t> Material16;
|
typedef Material<uint16_t> Material16;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
class DefaultIsQuadNeeded< Material<Type> >
|
class DefaultIsQuadNeeded< Material<Type> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator()(Material<Type> back, Material<Type> front, Material<Type>& materialToUse)
|
bool operator()(Material<Type> back, Material<Type> front, Material<Type>& materialToUse)
|
||||||
{
|
{
|
||||||
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
||||||
{
|
{
|
||||||
materialToUse = back;
|
materialToUse = back;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__PolyVox_Material_H__
|
#endif //__PolyVox_Material_H__
|
||||||
|
@ -1,165 +1,165 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_MaterialDensityPair_H__
|
#ifndef __PolyVox_MaterialDensityPair_H__
|
||||||
#define __PolyVox_MaterialDensityPair_H__
|
#define __PolyVox_MaterialDensityPair_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
|
#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 "PolyVoxCore/DefaultMarchingCubesController.h" //We'll specialise the controller contained in here
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/// This class represents a voxel storing only a density.
|
/// This class represents a voxel storing only a density.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Detailed description...
|
/// Detailed description...
|
||||||
///
|
///
|
||||||
/// \sa Density, Material
|
/// \sa Density, Material
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||||
class MaterialDensityPair
|
class MaterialDensityPair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MaterialDensityPair() : m_uMaterial(0), m_uDensity(0) {}
|
MaterialDensityPair() : m_uMaterial(0), m_uDensity(0) {}
|
||||||
MaterialDensityPair(Type uMaterial, Type uDensity) : m_uMaterial(uMaterial), m_uDensity(uDensity) {}
|
MaterialDensityPair(Type uMaterial, Type uDensity) : m_uMaterial(uMaterial), m_uDensity(uDensity) {}
|
||||||
|
|
||||||
bool operator==(const MaterialDensityPair& rhs) const
|
bool operator==(const MaterialDensityPair& rhs) const
|
||||||
{
|
{
|
||||||
return (m_uMaterial == rhs.m_uMaterial) && (m_uDensity == rhs.m_uDensity);
|
return (m_uMaterial == rhs.m_uMaterial) && (m_uDensity == rhs.m_uDensity);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator!=(const MaterialDensityPair& rhs) const
|
bool operator!=(const MaterialDensityPair& rhs) const
|
||||||
{
|
{
|
||||||
return !(*this == rhs);
|
return !(*this == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& operator+=(const MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& rhs)
|
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& operator+=(const MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& rhs)
|
||||||
{
|
{
|
||||||
m_uDensity += rhs.m_uDensity;
|
m_uDensity += rhs.m_uDensity;
|
||||||
|
|
||||||
// What should we do with the material? Conceptually the idea of adding materials makes no sense, but for our
|
// 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.
|
// 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);
|
m_uMaterial = (std::max)(m_uMaterial, rhs.m_uMaterial);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& operator/=(uint32_t rhs)
|
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.
|
// There's nothing sensible we can do with the material, so this function only affects the density.
|
||||||
m_uDensity /= rhs;
|
m_uDensity /= rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getDensity() const { return m_uDensity; }
|
Type getDensity() const { return m_uDensity; }
|
||||||
Type getMaterial() const { return m_uMaterial; }
|
Type getMaterial() const { return m_uMaterial; }
|
||||||
|
|
||||||
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
void setDensity(Type uDensity) { m_uDensity = uDensity; }
|
||||||
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
void setMaterial(Type uMaterial) { m_uMaterial = uMaterial; }
|
||||||
|
|
||||||
static Type getMaxDensity() { return (0x01 << NoOfDensityBits) - 1; }
|
static Type getMaxDensity() { return (0x01 << NoOfDensityBits) - 1; }
|
||||||
static Type getMinDensity() { return 0; }
|
static Type getMinDensity() { return 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_uMaterial : NoOfMaterialBits;
|
Type m_uMaterial : NoOfMaterialBits;
|
||||||
Type m_uDensity : NoOfDensityBits;
|
Type m_uDensity : NoOfDensityBits;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
template<typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||||
class DefaultIsQuadNeeded< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
class DefaultIsQuadNeeded< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator()(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> back, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> front, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& materialToUse)
|
bool operator()(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> back, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> front, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>& materialToUse)
|
||||||
{
|
{
|
||||||
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
if((back.getMaterial() > 0) && (front.getMaterial() == 0))
|
||||||
{
|
{
|
||||||
materialToUse = back;
|
materialToUse = back;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
|
||||||
class DefaultMarchingCubesController< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
class DefaultMarchingCubesController< MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Type DensityType;
|
typedef Type DensityType;
|
||||||
typedef Type MaterialType;
|
typedef Type MaterialType;
|
||||||
|
|
||||||
DefaultMarchingCubesController(void)
|
DefaultMarchingCubesController(void)
|
||||||
{
|
{
|
||||||
// Default to a threshold value halfway between the min and max possible values.
|
// 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;
|
m_tThreshold = (MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>::getMinDensity() + MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits>::getMaxDensity()) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultMarchingCubesController(DensityType tThreshold)
|
DefaultMarchingCubesController(DensityType tThreshold)
|
||||||
{
|
{
|
||||||
m_tThreshold = tThreshold;
|
m_tThreshold = tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
DensityType convertToDensity(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
DensityType convertToDensity(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
||||||
{
|
{
|
||||||
return voxel.getDensity();
|
return voxel.getDensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialType convertToMaterial(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
MaterialType convertToMaterial(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> voxel)
|
||||||
{
|
{
|
||||||
return voxel.getMaterial();
|
return voxel.getMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> blendMaterials(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> a, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> b, float /*weight*/)
|
MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> blendMaterials(MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> a, MaterialDensityPair<Type, NoOfMaterialBits, NoOfDensityBits> b, float /*weight*/)
|
||||||
{
|
{
|
||||||
if(convertToDensity(a) > convertToDensity(b))
|
if(convertToDensity(a) > convertToDensity(b))
|
||||||
{
|
{
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DensityType getThreshold(void)
|
DensityType getThreshold(void)
|
||||||
{
|
{
|
||||||
return m_tThreshold;
|
return m_tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setThreshold(DensityType tThreshold)
|
void setThreshold(DensityType tThreshold)
|
||||||
{
|
{
|
||||||
m_tThreshold = tThreshold;
|
m_tThreshold = tThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DensityType m_tThreshold;
|
DensityType m_tThreshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||||
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,195 +1,195 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_ForwardDeclarations_H__
|
#ifndef __PolyVox_ForwardDeclarations_H__
|
||||||
#define __PolyVox_ForwardDeclarations_H__
|
#define __PolyVox_ForwardDeclarations_H__
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Array
|
// Array
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/*template<uint32_t dimensions, typename ElementType> class Array;
|
/*template<uint32_t dimensions, typename ElementType> class Array;
|
||||||
|
|
||||||
typedef Array<1,float> Array1DFloat;
|
typedef Array<1,float> Array1DFloat;
|
||||||
typedef Array<1,double> Array1DDouble;
|
typedef Array<1,double> Array1DDouble;
|
||||||
typedef Array<1,int8_t> Array1DInt8;
|
typedef Array<1,int8_t> Array1DInt8;
|
||||||
typedef Array<1,uint8_t> Array1DUint8;
|
typedef Array<1,uint8_t> Array1DUint8;
|
||||||
typedef Array<1,int16_t> Array1DInt16;
|
typedef Array<1,int16_t> Array1DInt16;
|
||||||
typedef Array<1,uint16_t> Array1DUint16;
|
typedef Array<1,uint16_t> Array1DUint16;
|
||||||
typedef Array<1,int32_t> Array1DInt32;
|
typedef Array<1,int32_t> Array1DInt32;
|
||||||
typedef Array<1,uint32_t> Array1DUint32;*/
|
typedef Array<1,uint32_t> Array1DUint32;*/
|
||||||
|
|
||||||
/*typedef Array<2,float> Array2DFloat;
|
/*typedef Array<2,float> Array2DFloat;
|
||||||
typedef Array<2,double> Array2DDouble;
|
typedef Array<2,double> Array2DDouble;
|
||||||
typedef Array<2,int8_t> Array2DInt8;
|
typedef Array<2,int8_t> Array2DInt8;
|
||||||
typedef Array<2,uint8_t> Array2DUint8;
|
typedef Array<2,uint8_t> Array2DUint8;
|
||||||
typedef Array<2,int16_t> Array2DInt16;
|
typedef Array<2,int16_t> Array2DInt16;
|
||||||
typedef Array<2,uint16_t> Array2DUint16;
|
typedef Array<2,uint16_t> Array2DUint16;
|
||||||
typedef Array<2,int32_t> Array2DInt32;
|
typedef Array<2,int32_t> Array2DInt32;
|
||||||
typedef Array<2,uint32_t> Array2DUint32;*/
|
typedef Array<2,uint32_t> Array2DUint32;*/
|
||||||
|
|
||||||
/*typedef Array<3,float> Array3DFloat;
|
/*typedef Array<3,float> Array3DFloat;
|
||||||
typedef Array<3,double> Array3DDouble;
|
typedef Array<3,double> Array3DDouble;
|
||||||
typedef Array<3,int8_t> Array3DInt8;
|
typedef Array<3,int8_t> Array3DInt8;
|
||||||
typedef Array<3,uint8_t> Array3DUint8;
|
typedef Array<3,uint8_t> Array3DUint8;
|
||||||
typedef Array<3,int16_t> Array3DInt16;
|
typedef Array<3,int16_t> Array3DInt16;
|
||||||
typedef Array<3,uint16_t> Array3DUint16;
|
typedef Array<3,uint16_t> Array3DUint16;
|
||||||
typedef Array<3,int32_t> Array3DInt32;
|
typedef Array<3,int32_t> Array3DInt32;
|
||||||
typedef Array<3,uint32_t> Array3DUint32;*/
|
typedef Array<3,uint32_t> Array3DUint32;*/
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Compressor
|
// Compressor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
class Compressor;
|
class Compressor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// CubicSurfaceExtractor
|
// CubicSurfaceExtractor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> class DefaultIsQuadNeeded;
|
template<typename VoxelType> class DefaultIsQuadNeeded;
|
||||||
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > class CubicSurfaceExtractor;
|
template<typename VolumeType, typename MeshType, typename IsQuadNeeded = DefaultIsQuadNeeded<typename VolumeType::VoxelType> > class CubicSurfaceExtractor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// CubicVertex
|
// CubicVertex
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> struct CubicVertex;
|
template<typename VoxelType> struct CubicVertex;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Density
|
// Density
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type> class Density;
|
template <typename Type> class Density;
|
||||||
|
|
||||||
typedef Density<int8_t> DensityI8;
|
typedef Density<int8_t> DensityI8;
|
||||||
typedef Density<uint8_t> DensityU8;
|
typedef Density<uint8_t> DensityU8;
|
||||||
typedef Density<int16_t> DensityI16;
|
typedef Density<int16_t> DensityI16;
|
||||||
typedef Density<uint16_t> DensityU16;
|
typedef Density<uint16_t> DensityU16;
|
||||||
typedef Density<float> DensityFloat;
|
typedef Density<float> DensityFloat;
|
||||||
typedef Density<double> DensityDouble;
|
typedef Density<double> DensityDouble;
|
||||||
|
|
||||||
typedef DensityU8 Density8; //Backwards compatibility
|
typedef DensityU8 Density8; //Backwards compatibility
|
||||||
typedef DensityU16 Density16; //Backwards compatibility
|
typedef DensityU16 Density16; //Backwards compatibility
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// FilePager
|
// FilePager
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class FilePager;
|
template <typename VoxelType> class FilePager;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// MarchingCubesSurfaceExtractor
|
// MarchingCubesSurfaceExtractor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VolumeType, typename MeshType, typename ControllerType> class MarchingCubesSurfaceExtractor;
|
template<typename VolumeType, typename MeshType, typename ControllerType> class MarchingCubesSurfaceExtractor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// MarchingCubesVertex
|
// MarchingCubesVertex
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename VoxelType> struct MarchingCubesVertex;
|
template<typename VoxelType> struct MarchingCubesVertex;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Material
|
// Material
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type> class Material;
|
template <typename Type> class Material;
|
||||||
|
|
||||||
typedef Material<uint8_t> MaterialU8;
|
typedef Material<uint8_t> MaterialU8;
|
||||||
typedef Material<uint16_t> MaterialU16;
|
typedef Material<uint16_t> MaterialU16;
|
||||||
typedef Material<uint32_t> MaterialU32;
|
typedef Material<uint32_t> MaterialU32;
|
||||||
|
|
||||||
typedef MaterialU8 Material8;
|
typedef MaterialU8 Material8;
|
||||||
typedef MaterialU16 Material16;
|
typedef MaterialU16 Material16;
|
||||||
typedef MaterialU32 Material32;
|
typedef MaterialU32 Material32;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// MaterialDensityPair
|
// MaterialDensityPair
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits> class MaterialDensityPair;
|
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits> class MaterialDensityPair;
|
||||||
|
|
||||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||||
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Mesh
|
// Mesh
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
typedef uint32_t DefaultIndexType;
|
typedef uint32_t DefaultIndexType;
|
||||||
template <typename VertexType, typename IndexType = DefaultIndexType> class Mesh;
|
template <typename VertexType, typename IndexType = DefaultIndexType> class Mesh;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// PagedVolume
|
// PagedVolume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class PagedVolume;
|
template <typename VoxelType> class PagedVolume;
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
using LargeVolume = PagedVolume<VoxelType>;
|
using LargeVolume = PagedVolume<VoxelType>;
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
using SimpleVolume = PagedVolume<VoxelType>;
|
using SimpleVolume = PagedVolume<VoxelType>;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Pager
|
// Pager
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class Pager;
|
template <typename VoxelType> class Pager;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// RawVolume
|
// RawVolume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType> class RawVolume;
|
template <typename VoxelType> class RawVolume;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Region
|
// Region
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
class Region;
|
class Region;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Vector
|
// Vector
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <uint32_t Size, typename StorageType, typename OperationType = StorageType> class Vector;
|
template <uint32_t Size, typename StorageType, typename OperationType = StorageType> class Vector;
|
||||||
|
|
||||||
typedef Vector<2,float,float> Vector2DFloat;
|
typedef Vector<2,float,float> Vector2DFloat;
|
||||||
typedef Vector<2,double,double> Vector2DDouble;
|
typedef Vector<2,double,double> Vector2DDouble;
|
||||||
typedef Vector<2,int8_t,int32_t> Vector2DInt8;
|
typedef Vector<2,int8_t,int32_t> Vector2DInt8;
|
||||||
typedef Vector<2,uint8_t,int32_t> Vector2DUint8;
|
typedef Vector<2,uint8_t,int32_t> Vector2DUint8;
|
||||||
typedef Vector<2,int16_t,int32_t> Vector2DInt16;
|
typedef Vector<2,int16_t,int32_t> Vector2DInt16;
|
||||||
typedef Vector<2,uint16_t,int32_t> Vector2DUint16;
|
typedef Vector<2,uint16_t,int32_t> Vector2DUint16;
|
||||||
typedef Vector<2,int32_t,int32_t> Vector2DInt32;
|
typedef Vector<2,int32_t,int32_t> Vector2DInt32;
|
||||||
typedef Vector<2,uint32_t,int32_t> Vector2DUint32;
|
typedef Vector<2,uint32_t,int32_t> Vector2DUint32;
|
||||||
|
|
||||||
typedef Vector<3,float,float> Vector3DFloat;
|
typedef Vector<3,float,float> Vector3DFloat;
|
||||||
typedef Vector<3,double,double> Vector3DDouble;
|
typedef Vector<3,double,double> Vector3DDouble;
|
||||||
typedef Vector<3,int8_t,int32_t> Vector3DInt8;
|
typedef Vector<3,int8_t,int32_t> Vector3DInt8;
|
||||||
typedef Vector<3,uint8_t,int32_t> Vector3DUint8;
|
typedef Vector<3,uint8_t,int32_t> Vector3DUint8;
|
||||||
typedef Vector<3,int16_t,int32_t> Vector3DInt16;
|
typedef Vector<3,int16_t,int32_t> Vector3DInt16;
|
||||||
typedef Vector<3,uint16_t,int32_t> Vector3DUint16;
|
typedef Vector<3,uint16_t,int32_t> Vector3DUint16;
|
||||||
typedef Vector<3,int32_t,int32_t> Vector3DInt32;
|
typedef Vector<3,int32_t,int32_t> Vector3DInt32;
|
||||||
typedef Vector<3,uint32_t,int32_t> Vector3DUint32;
|
typedef Vector<3,uint32_t,int32_t> Vector3DUint32;
|
||||||
|
|
||||||
typedef Vector<4,float,float> Vector4DFloat;
|
typedef Vector<4,float,float> Vector4DFloat;
|
||||||
typedef Vector<4,double,double> Vector4DDouble;
|
typedef Vector<4,double,double> Vector4DDouble;
|
||||||
typedef Vector<4,int8_t,int32_t> Vector4DInt8;
|
typedef Vector<4,int8_t,int32_t> Vector4DInt8;
|
||||||
typedef Vector<4,uint8_t,int32_t> Vector4DUint8;
|
typedef Vector<4,uint8_t,int32_t> Vector4DUint8;
|
||||||
typedef Vector<4,int16_t,int32_t> Vector4DInt16;
|
typedef Vector<4,int16_t,int32_t> Vector4DInt16;
|
||||||
typedef Vector<4,uint16_t,int32_t> Vector4DUint16;
|
typedef Vector<4,uint16_t,int32_t> Vector4DUint16;
|
||||||
typedef Vector<4,int32_t,int32_t> Vector4DInt32;
|
typedef Vector<4,int32_t,int32_t> Vector4DInt32;
|
||||||
typedef Vector<4,uint32_t,int32_t> Vector4DUint32;
|
typedef Vector<4,uint32_t,int32_t> Vector4DUint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,173 +1,173 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_RawVolume_H__
|
#ifndef __PolyVox_RawVolume_H__
|
||||||
#define __PolyVox_RawVolume_H__
|
#define __PolyVox_RawVolume_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/BaseVolume.h"
|
#include "PolyVoxCore/BaseVolume.h"
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
|
|
||||||
#include <cstdlib> //For abort()
|
#include <cstdlib> //For abort()
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept> //For invalid_argument
|
#include <stdexcept> //For invalid_argument
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
class RawVolume : public BaseVolume<VoxelType>
|
class RawVolume : public BaseVolume<VoxelType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
//There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
|
//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
|
//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
|
//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
|
//option. For now it seems best to 'fix' it with the preprocessor insstead, but maybe the workaround can be reinstated
|
||||||
//in the future
|
//in the future
|
||||||
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
//typedef Volume<VoxelType> VolumeOfVoxelType; //Workaround for GCC/VS2010 differences.
|
||||||
//class Sampler : public VolumeOfVoxelType::template Sampler< RawVolume<VoxelType> >
|
//class Sampler : public VolumeOfVoxelType::template Sampler< RawVolume<VoxelType> >
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
class Sampler : public BaseVolume<VoxelType>::Sampler< RawVolume<VoxelType> > //This line works on VS2010
|
class Sampler : public BaseVolume<VoxelType>::Sampler< RawVolume<VoxelType> > //This line works on VS2010
|
||||||
#else
|
#else
|
||||||
class Sampler : public BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> > //This line works on GCC
|
class Sampler : public BaseVolume<VoxelType>::template Sampler< RawVolume<VoxelType> > //This line works on GCC
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sampler(RawVolume<VoxelType>* volume);
|
Sampler(RawVolume<VoxelType>* volume);
|
||||||
~Sampler();
|
~Sampler();
|
||||||
|
|
||||||
inline VoxelType getVoxel(void) const;
|
inline VoxelType getVoxel(void) const;
|
||||||
|
|
||||||
void setPosition(const Vector3DInt32& v3dNewPos);
|
void setPosition(const Vector3DInt32& v3dNewPos);
|
||||||
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
|
||||||
inline bool setVoxel(VoxelType tValue);
|
inline bool setVoxel(VoxelType tValue);
|
||||||
|
|
||||||
void movePositiveX(void);
|
void movePositiveX(void);
|
||||||
void movePositiveY(void);
|
void movePositiveY(void);
|
||||||
void movePositiveZ(void);
|
void movePositiveZ(void);
|
||||||
|
|
||||||
void moveNegativeX(void);
|
void moveNegativeX(void);
|
||||||
void moveNegativeY(void);
|
void moveNegativeY(void);
|
||||||
void moveNegativeZ(void);
|
void moveNegativeZ(void);
|
||||||
|
|
||||||
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
inline VoxelType peekVoxel1nx1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
inline VoxelType peekVoxel1nx1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
inline VoxelType peekVoxel1nx1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
inline VoxelType peekVoxel1nx0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
inline VoxelType peekVoxel1nx0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
inline VoxelType peekVoxel1nx0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
inline VoxelType peekVoxel1nx1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
inline VoxelType peekVoxel1nx1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
inline VoxelType peekVoxel1nx1py1pz(void) const;
|
||||||
|
|
||||||
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
inline VoxelType peekVoxel0px1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
inline VoxelType peekVoxel0px1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
inline VoxelType peekVoxel0px1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py1nz(void) const;
|
inline VoxelType peekVoxel0px0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py0pz(void) const;
|
inline VoxelType peekVoxel0px0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px0py1pz(void) const;
|
inline VoxelType peekVoxel0px0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py1nz(void) const;
|
inline VoxelType peekVoxel0px1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py0pz(void) const;
|
inline VoxelType peekVoxel0px1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel0px1py1pz(void) const;
|
inline VoxelType peekVoxel0px1py1pz(void) const;
|
||||||
|
|
||||||
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
inline VoxelType peekVoxel1px1ny1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
inline VoxelType peekVoxel1px1ny0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
inline VoxelType peekVoxel1px1ny1pz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py1nz(void) const;
|
inline VoxelType peekVoxel1px0py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py0pz(void) const;
|
inline VoxelType peekVoxel1px0py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px0py1pz(void) const;
|
inline VoxelType peekVoxel1px0py1pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py1nz(void) const;
|
inline VoxelType peekVoxel1px1py1nz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py0pz(void) const;
|
inline VoxelType peekVoxel1px1py0pz(void) const;
|
||||||
inline VoxelType peekVoxel1px1py1pz(void) const;
|
inline VoxelType peekVoxel1px1py1pz(void) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//Other current position information
|
//Other current position information
|
||||||
VoxelType* mCurrentVoxel;
|
VoxelType* mCurrentVoxel;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor for creating a fixed size volume.
|
/// Constructor for creating a fixed size volume.
|
||||||
RawVolume(const Region& regValid);
|
RawVolume(const Region& regValid);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~RawVolume();
|
~RawVolume();
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const;
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const;
|
||||||
|
|
||||||
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
|
||||||
/// Gets a voxel at the position given by a 3D vector
|
/// Gets a voxel at the position given by a 3D vector
|
||||||
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
|
||||||
|
|
||||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
||||||
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||||
/// Sets the voxel at the position given by a 3D vector
|
/// Sets the voxel at the position given by a 3D vector
|
||||||
void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate);
|
||||||
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
|
/// 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);
|
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||||
/// Sets the voxel at the position given by a 3D vector
|
/// Sets the voxel at the position given by a 3D vector
|
||||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||||
|
|
||||||
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
/// Calculates approximatly how many bytes of memory the volume is currently using.
|
||||||
uint32_t calculateSizeInBytes(void);
|
uint32_t calculateSizeInBytes(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
RawVolume(const RawVolume& rhs);
|
RawVolume(const RawVolume& rhs);
|
||||||
|
|
||||||
/// Assignment operator
|
/// Assignment operator
|
||||||
RawVolume& operator=(const RawVolume& rhs);
|
RawVolume& operator=(const RawVolume& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initialise(const Region& regValidRegion);
|
void initialise(const Region& regValidRegion);
|
||||||
|
|
||||||
// A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057
|
// A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const;
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const;
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const;
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const;
|
||||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const;
|
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const;
|
||||||
|
|
||||||
//The voxel data
|
//The voxel data
|
||||||
VoxelType* m_pData;
|
VoxelType* m_pData;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/RawVolume.inl"
|
#include "PolyVoxCore/RawVolume.inl"
|
||||||
#include "PolyVoxCore/RawVolumeSampler.inl"
|
#include "PolyVoxCore/RawVolumeSampler.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_RawVolume_H__
|
#endif //__PolyVox_RawVolume_H__
|
||||||
|
@ -1,390 +1,390 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This constructor creates a volume with a fixed size which is specified as a parameter.
|
/// 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 regValid Specifies the minimum and maximum valid voxel positions.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
RawVolume<VoxelType>::RawVolume(const Region& regValid)
|
RawVolume<VoxelType>::RawVolume(const Region& regValid)
|
||||||
:BaseVolume<VoxelType>(regValid)
|
:BaseVolume<VoxelType>(regValid)
|
||||||
{
|
{
|
||||||
this->setBorderValue(VoxelType());
|
this->setBorderValue(VoxelType());
|
||||||
|
|
||||||
//Create a volume of the right size.
|
//Create a volume of the right size.
|
||||||
initialise(regValid);
|
initialise(regValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
/// 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
|
/// 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.
|
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||||
///
|
///
|
||||||
/// \sa VolumeResampler
|
/// \sa VolumeResampler
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/)
|
RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
|
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Destroys the volume
|
/// Destroys the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
RawVolume<VoxelType>::~RawVolume()
|
RawVolume<VoxelType>::~RawVolume()
|
||||||
{
|
{
|
||||||
delete[] m_pData;
|
delete[] m_pData;
|
||||||
m_pData = 0;
|
m_pData = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
|
/// 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
|
/// 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.
|
/// make a copy of a volume and in this case you should look at the Volumeresampler.
|
||||||
///
|
///
|
||||||
/// \sa VolumeResampler
|
/// \sa VolumeResampler
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/)
|
RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
|
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function requires the wrap mode to be specified as a
|
/// This version of the function requires the wrap mode to be specified as a
|
||||||
/// template parameter, which can provide better performance.
|
/// template parameter, which can provide better performance.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
// Simply call through to the real implementation
|
// Simply call through to the real implementation
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<eWrapMode>(), tBorder);
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<eWrapMode>(), tBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function requires the wrap mode to be specified as a
|
/// This version of the function requires the wrap mode to be specified as a
|
||||||
/// template parameter, which can provide better performance.
|
/// template parameter, which can provide better performance.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
// Simply call through to the real implementation
|
// Simply call through to the real implementation
|
||||||
return getVoxel<eWrapMode>(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder);
|
return getVoxel<eWrapMode>(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function is provided so that the wrap mode does not need
|
/// This version of the function is provided so that the wrap mode does not need
|
||||||
/// to be specified as a template parameter, as it may be confusing to some users.
|
/// to be specified as a template parameter, as it may be confusing to some users.
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
switch(eWrapMode)
|
switch(eWrapMode)
|
||||||
{
|
{
|
||||||
case WrapModes::Validate:
|
case WrapModes::Validate:
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Validate>(), tBorder);
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Validate>(), tBorder);
|
||||||
case WrapModes::Clamp:
|
case WrapModes::Clamp:
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Clamp>(), tBorder);
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Clamp>(), tBorder);
|
||||||
case WrapModes::Border:
|
case WrapModes::Border:
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Border>(), tBorder);
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::Border>(), tBorder);
|
||||||
case WrapModes::AssumeValid:
|
case WrapModes::AssumeValid:
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder);
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder);
|
||||||
default:
|
default:
|
||||||
// Should never happen
|
// Should never happen
|
||||||
POLYVOX_ASSERT(false, "Invalid wrap mode");
|
POLYVOX_ASSERT(false, "Invalid wrap mode");
|
||||||
return VoxelType();
|
return VoxelType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This version of the function is provided so that the wrap mode does not need
|
/// This version of the function is provided so that the wrap mode does not need
|
||||||
/// to be specified as a template parameter, as it may be confusing to some users.
|
/// to be specified as a template parameter, as it may be confusing to some users.
|
||||||
/// \param v3dPos The 3D position of the voxel
|
/// \param v3dPos The 3D position of the voxel
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
/// \param tBorder The border value to use if the wrap mode is set to 'Border'.
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
|
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos The \c x position of the voxel
|
/// \param uXPos The \c x position of the voxel
|
||||||
/// \param uYPos The \c y position of the voxel
|
/// \param uYPos The \c y position of the voxel
|
||||||
/// \param uZPos The \c z position of the voxel
|
/// \param uZPos The \c z position of the voxel
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
VoxelType RawVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||||
{
|
{
|
||||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||||
{
|
{
|
||||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||||
|
|
||||||
return m_pData
|
return m_pData
|
||||||
[
|
[
|
||||||
iLocalXPos +
|
iLocalXPos +
|
||||||
iLocalYPos * this->getWidth() +
|
iLocalYPos * this->getWidth() +
|
||||||
iLocalZPos * this->getWidth() * this->getHeight()
|
iLocalZPos * this->getWidth() * this->getHeight()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this->getBorderValue();
|
return this->getBorderValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos The 3D position of the voxel
|
/// \param v3dPos The 3D position of the voxel
|
||||||
/// \return The voxel value
|
/// \return The voxel value
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
|
VoxelType RawVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
|
||||||
{
|
{
|
||||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos the \c x position of the voxel
|
/// \param uXPos the \c x position of the voxel
|
||||||
/// \param uYPos the \c y position of the voxel
|
/// \param uYPos the \c y position of the voxel
|
||||||
/// \param uZPos the \c z position of the voxel
|
/// \param uZPos the \c z position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data.
|
/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void RawVolume<VoxelType>::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode)
|
void RawVolume<VoxelType>::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode)
|
||||||
{
|
{
|
||||||
if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid))
|
if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid))
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'.");
|
POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This validation is skipped if the wrap mode is 'DontCheck'
|
// This validation is skipped if the wrap mode is 'DontCheck'
|
||||||
if(eWrapMode == WrapModes::Validate)
|
if(eWrapMode == WrapModes::Validate)
|
||||||
{
|
{
|
||||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false)
|
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::out_of_range, "Position is outside valid region");
|
POLYVOX_THROW(std::out_of_range, "Position is outside valid region");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||||
|
|
||||||
m_pData
|
m_pData
|
||||||
[
|
[
|
||||||
iLocalXPos +
|
iLocalXPos +
|
||||||
iLocalYPos * this->getWidth() +
|
iLocalYPos * this->getWidth() +
|
||||||
iLocalZPos * this->getWidth() * this->getHeight()
|
iLocalZPos * this->getWidth() * this->getHeight()
|
||||||
] = tValue;
|
] = tValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
/// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume.
|
||||||
/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data.
|
/// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void RawVolume<VoxelType>::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode)
|
void RawVolume<VoxelType>::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode)
|
||||||
{
|
{
|
||||||
setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode);
|
setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param uXPos the \c x position of the voxel
|
/// \param uXPos the \c x position of the voxel
|
||||||
/// \param uYPos the \c y position of the voxel
|
/// \param uYPos the \c y position of the voxel
|
||||||
/// \param uZPos the \c z position of the voxel
|
/// \param uZPos the \c z position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \return whether the requested position is inside the volume
|
/// \return whether the requested position is inside the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool RawVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
bool RawVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
||||||
{
|
{
|
||||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
|
||||||
{
|
{
|
||||||
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
|
||||||
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
|
||||||
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
int32_t iLocalYPos = uYPos - v3dLowerCorner.getY();
|
||||||
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ();
|
||||||
|
|
||||||
m_pData
|
m_pData
|
||||||
[
|
[
|
||||||
iLocalXPos +
|
iLocalXPos +
|
||||||
iLocalYPos * this->getWidth() +
|
iLocalYPos * this->getWidth() +
|
||||||
iLocalZPos * this->getWidth() * this->getHeight()
|
iLocalZPos * this->getWidth() * this->getHeight()
|
||||||
] = tValue;
|
] = tValue;
|
||||||
|
|
||||||
//Return true to indicate that we modified a voxel.
|
//Return true to indicate that we modified a voxel.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
/// \param tValue the value to which the voxel will be set
|
/// \param tValue the value to which the voxel will be set
|
||||||
/// \return whether the requested position is inside the volume
|
/// \return whether the requested position is inside the volume
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool RawVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
|
bool RawVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
|
||||||
{
|
{
|
||||||
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// This function should probably be made internal...
|
/// This function should probably be made internal...
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void RawVolume<VoxelType>::initialise(const Region& regValidRegion)
|
void RawVolume<VoxelType>::initialise(const Region& regValidRegion)
|
||||||
{
|
{
|
||||||
this->m_regValidRegion = regValidRegion;
|
this->m_regValidRegion = regValidRegion;
|
||||||
|
|
||||||
if(this->getWidth() <= 0)
|
if(this->getWidth() <= 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume width must be greater than zero.");
|
POLYVOX_THROW(std::invalid_argument, "Volume width must be greater than zero.");
|
||||||
}
|
}
|
||||||
if(this->getHeight() <= 0)
|
if(this->getHeight() <= 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume height must be greater than zero.");
|
POLYVOX_THROW(std::invalid_argument, "Volume height must be greater than zero.");
|
||||||
}
|
}
|
||||||
if(this->getDepth() <= 0)
|
if(this->getDepth() <= 0)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::invalid_argument, "Volume depth must be greater than zero.");
|
POLYVOX_THROW(std::invalid_argument, "Volume depth must be greater than zero.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create the data
|
//Create the data
|
||||||
m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()];
|
m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()];
|
||||||
|
|
||||||
//Other properties we might find useful later
|
//Other properties we might find useful later
|
||||||
this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
|
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_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()));
|
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...
|
/// Note: This function needs reviewing for accuracy...
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
uint32_t RawVolume<VoxelType>::calculateSizeInBytes(void)
|
uint32_t RawVolume<VoxelType>::calculateSizeInBytes(void)
|
||||||
{
|
{
|
||||||
return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType);
|
return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
template <WrapMode eWrapMode>
|
template <WrapMode eWrapMode>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<eWrapMode>, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
// This function should never be called because one of the specialisations should always match.
|
// This function should never be called because one of the specialisations should always match.
|
||||||
POLYVOX_ASSERT(false, "This function is not implemented and should never be called!");
|
POLYVOX_ASSERT(false, "This function is not implemented and should never be called!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Validate>, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false)
|
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false)
|
||||||
{
|
{
|
||||||
POLYVOX_THROW(std::out_of_range, "Position is outside valid region");
|
POLYVOX_THROW(std::out_of_range, "Position is outside valid region");
|
||||||
}
|
}
|
||||||
|
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Clamp>, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
//Perform clamping
|
//Perform clamping
|
||||||
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
|
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
|
||||||
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
|
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
|
||||||
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
|
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
|
||||||
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
|
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
|
||||||
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
|
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
|
||||||
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
|
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
|
||||||
|
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const
|
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const
|
||||||
{
|
{
|
||||||
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
|
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
|
||||||
{
|
{
|
||||||
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType<WrapModes::AssumeValid>(), tBorder); // No wrapping as we've just validated the position.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return tBorder;
|
return tBorder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType /*tBorder*/) const
|
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType /*tBorder*/) const
|
||||||
{
|
{
|
||||||
const Region& regValidRegion = this->m_regValidRegion;
|
const Region& regValidRegion = this->m_regValidRegion;
|
||||||
int32_t iLocalXPos = uXPos - regValidRegion.getLowerX();
|
int32_t iLocalXPos = uXPos - regValidRegion.getLowerX();
|
||||||
int32_t iLocalYPos = uYPos - regValidRegion.getLowerY();
|
int32_t iLocalYPos = uYPos - regValidRegion.getLowerY();
|
||||||
int32_t iLocalZPos = uZPos - regValidRegion.getLowerZ();
|
int32_t iLocalZPos = uZPos - regValidRegion.getLowerZ();
|
||||||
|
|
||||||
return m_pData
|
return m_pData
|
||||||
[
|
[
|
||||||
iLocalXPos +
|
iLocalXPos +
|
||||||
iLocalYPos * this->getWidth() +
|
iLocalYPos * this->getWidth() +
|
||||||
iLocalZPos * this->getWidth() * this->getHeight()
|
iLocalZPos * this->getWidth() * this->getHeight()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,103 +1,103 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Raycast_H__
|
#ifndef __PolyVox_Raycast_H__
|
||||||
#define __PolyVox_Raycast_H__
|
#define __PolyVox_Raycast_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
namespace RaycastResults
|
namespace RaycastResults
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The results of a raycast
|
* The results of a raycast
|
||||||
*/
|
*/
|
||||||
enum RaycastResult
|
enum RaycastResult
|
||||||
{
|
{
|
||||||
Completed, ///< If the ray passed through the volume without being interupted
|
Completed, ///< If the ray passed through the volume without being interupted
|
||||||
Interupted ///< If the ray was interupted while travelling
|
Interupted ///< If the ray was interupted while travelling
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
typedef RaycastResults::RaycastResult RaycastResult;
|
typedef RaycastResults::RaycastResult RaycastResult;
|
||||||
|
|
||||||
/// OUT OF DATE SINCE UNCLASSING
|
/// OUT OF DATE SINCE UNCLASSING
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \file Raycast.h
|
/// \file Raycast.h
|
||||||
///
|
///
|
||||||
/// The principle behind raycasting is to fire a 'ray' through the volume and determine
|
/// 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
|
/// 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.
|
/// 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.
|
/// 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
|
/// 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,
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// of the RaycastResult structure and the intersectionFound flag is set to true, otherwise
|
||||||
/// the intersectionFound flag is set to false.
|
/// the intersectionFound flag is set to false.
|
||||||
///
|
///
|
||||||
/// **Important Note:** These has been confusion in the past with people not realising
|
/// **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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// you must scale the direction vector so that it's length represents the maximum distance
|
||||||
/// over which you want the ray to be cast.
|
/// over which you want the ray to be cast.
|
||||||
///
|
///
|
||||||
/// The following code snippet shows how the class is used:
|
/// The following code snippet shows how the class is used:
|
||||||
/// \code
|
/// \code
|
||||||
/// Vector3DFloat start(rayOrigin.x(), rayOrigin.y(), rayOrigin.z());
|
/// Vector3DFloat start(rayOrigin.x(), rayOrigin.y(), rayOrigin.z());
|
||||||
/// Vector3DFloat direction(rayDir.x(), rayDir.y(), rayDir.z());
|
/// Vector3DFloat direction(rayDir.x(), rayDir.y(), rayDir.z());
|
||||||
/// direction.normalise();
|
/// direction.normalise();
|
||||||
/// direction *= 1000.0f; //Casts ray of length 1000
|
/// direction *= 1000.0f; //Casts ray of length 1000
|
||||||
///
|
///
|
||||||
/// RaycastResult raycastResult;
|
/// RaycastResult raycastResult;
|
||||||
/// Raycast<Material8> raycast(m_pPolyVoxVolume, start, direction, raycastResult);
|
/// Raycast<Material8> raycast(m_pPolyVoxVolume, start, direction, raycastResult);
|
||||||
/// raycast.execute();
|
/// raycast.execute();
|
||||||
///
|
///
|
||||||
/// if(raycastResult.foundIntersection)
|
/// if(raycastResult.foundIntersection)
|
||||||
/// {
|
/// {
|
||||||
/// //...
|
/// //...
|
||||||
/// }
|
/// }
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// Some further notes, the Raycast uses full 26-connectivity, which basically means it
|
/// 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.
|
/// 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
|
/// 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'
|
/// 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
|
/// surace extractors. It's behaviour with the Marching Cubes surface extractor has not
|
||||||
/// been tested yet.
|
/// been tested yet.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<typename VolumeType, typename Callback>
|
template<typename VolumeType, typename Callback>
|
||||||
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback);
|
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback);
|
||||||
|
|
||||||
template<typename VolumeType, typename Callback>
|
template<typename VolumeType, typename Callback>
|
||||||
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback);
|
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/Raycast.inl"
|
#include "PolyVoxCore/Raycast.inl"
|
||||||
|
|
||||||
#endif //__PolyVox_Raycast_H__
|
#endif //__PolyVox_Raycast_H__
|
||||||
|
@ -1,178 +1,178 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
// This function is based on Christer Ericson's code and description of the 'Uniform Grid Intersection Test' in
|
// 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:
|
// '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.
|
// 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:
|
// 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 tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) / Abs(x2 - x1);
|
||||||
// float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) / Abs(y2 - y1);
|
// float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) / Abs(y2 - y1);
|
||||||
//
|
//
|
||||||
// Thanks to Jetro Lauha of Fathammer in Helsinki, Finland for reporting this error.
|
// 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
|
// 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
|
// 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.
|
// 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
|
// Where it is important to handle negative line coordinates the computation of these variables should be
|
||||||
// changed to something like this:
|
// changed to something like this:
|
||||||
//
|
//
|
||||||
// // Determine start grid cell coordinates (i, j)
|
// // Determine start grid cell coordinates (i, j)
|
||||||
// int i = (int)floorf(x1 / CELL_SIDE);
|
// int i = (int)floorf(x1 / CELL_SIDE);
|
||||||
// int j = (int)floorf(y1 / CELL_SIDE);
|
// int j = (int)floorf(y1 / CELL_SIDE);
|
||||||
//
|
//
|
||||||
// // Determine end grid cell coordinates (iend, jend)
|
// // Determine end grid cell coordinates (iend, jend)
|
||||||
// int iend = (int)floorf(x2 / CELL_SIDE);
|
// int iend = (int)floorf(x2 / CELL_SIDE);
|
||||||
// int jend = (int)floorf(y2 / 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.
|
// page 328. The if-statement that reads "if (ty <= tx && ty <= tz)" has a superfluous condition.
|
||||||
// It should simply read "if (ty <= tz)".
|
// It should simply read "if (ty <= tz)".
|
||||||
//
|
//
|
||||||
// This error was reported by Joey Hammer (PixelActive).
|
// This error was reported by Joey Hammer (PixelActive).
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast a ray through a volume by specifying the start and end positions
|
* 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
|
* 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
|
* 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
|
* returns a RaycastResults::Interupted. If it passes from start to end
|
||||||
* without \a callback returning \a false, it returns RaycastResults::Completed.
|
* without \a callback returning \a false, it returns RaycastResults::Completed.
|
||||||
*
|
*
|
||||||
* \param volData The volume to pass the ray though
|
* \param volData The volume to pass the ray though
|
||||||
* \param v3dStart The start position in the volume
|
* \param v3dStart The start position in the volume
|
||||||
* \param v3dEnd The end position in the volume
|
* \param v3dEnd The end position in the volume
|
||||||
* \param callback The callback to call for each voxel
|
* \param callback The callback to call for each voxel
|
||||||
*
|
*
|
||||||
* \return A RaycastResults designating whether the ray hit anything or not
|
* \return A RaycastResults designating whether the ray hit anything or not
|
||||||
*/
|
*/
|
||||||
template<typename VolumeType, typename Callback>
|
template<typename VolumeType, typename Callback>
|
||||||
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback)
|
RaycastResult raycastWithEndpoints(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dEnd, Callback& callback)
|
||||||
{
|
{
|
||||||
typename VolumeType::Sampler sampler(volData);
|
typename VolumeType::Sampler sampler(volData);
|
||||||
|
|
||||||
//The doRaycast function is assuming that it is iterating over the areas defined between
|
//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
|
//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.
|
//what the CubicSurfaceExtractor generates). We add 0.5 here to adjust for this.
|
||||||
const float x1 = v3dStart.getX() + 0.5f;
|
const float x1 = v3dStart.getX() + 0.5f;
|
||||||
const float y1 = v3dStart.getY() + 0.5f;
|
const float y1 = v3dStart.getY() + 0.5f;
|
||||||
const float z1 = v3dStart.getZ() + 0.5f;
|
const float z1 = v3dStart.getZ() + 0.5f;
|
||||||
const float x2 = v3dEnd.getX() + 0.5f;
|
const float x2 = v3dEnd.getX() + 0.5f;
|
||||||
const float y2 = v3dEnd.getY() + 0.5f;
|
const float y2 = v3dEnd.getY() + 0.5f;
|
||||||
const float z2 = v3dEnd.getZ() + 0.5f;
|
const float z2 = v3dEnd.getZ() + 0.5f;
|
||||||
|
|
||||||
int i = (int)floorf(x1);
|
int i = (int)floorf(x1);
|
||||||
int j = (int)floorf(y1);
|
int j = (int)floorf(y1);
|
||||||
int k = (int)floorf(z1);
|
int k = (int)floorf(z1);
|
||||||
|
|
||||||
const int iend = (int)floorf(x2);
|
const int iend = (int)floorf(x2);
|
||||||
const int jend = (int)floorf(y2);
|
const int jend = (int)floorf(y2);
|
||||||
const int kend = (int)floorf(z2);
|
const int kend = (int)floorf(z2);
|
||||||
|
|
||||||
const int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
|
const int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
|
||||||
const int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
|
const int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
|
||||||
const int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
|
const int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
|
||||||
|
|
||||||
const float deltatx = 1.0f / std::abs(x2 - x1);
|
const float deltatx = 1.0f / std::abs(x2 - x1);
|
||||||
const float deltaty = 1.0f / std::abs(y2 - y1);
|
const float deltaty = 1.0f / std::abs(y2 - y1);
|
||||||
const float deltatz = 1.0f / std::abs(z2 - z1);
|
const float deltatz = 1.0f / std::abs(z2 - z1);
|
||||||
|
|
||||||
const float minx = floorf(x1), maxx = minx + 1.0f;
|
const float minx = floorf(x1), maxx = minx + 1.0f;
|
||||||
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
|
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
|
||||||
const float miny = floorf(y1), maxy = miny + 1.0f;
|
const float miny = floorf(y1), maxy = miny + 1.0f;
|
||||||
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
|
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
|
||||||
const float minz = floorf(z1), maxz = minz + 1.0f;
|
const float minz = floorf(z1), maxz = minz + 1.0f;
|
||||||
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
|
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
|
||||||
|
|
||||||
sampler.setPosition(i,j,k);
|
sampler.setPosition(i,j,k);
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if(!callback(sampler))
|
if(!callback(sampler))
|
||||||
{
|
{
|
||||||
return RaycastResults::Interupted;
|
return RaycastResults::Interupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tx <= ty && tx <= tz)
|
if(tx <= ty && tx <= tz)
|
||||||
{
|
{
|
||||||
if(i == iend) break;
|
if(i == iend) break;
|
||||||
tx += deltatx;
|
tx += deltatx;
|
||||||
i += di;
|
i += di;
|
||||||
|
|
||||||
if(di == 1) sampler.movePositiveX();
|
if(di == 1) sampler.movePositiveX();
|
||||||
if(di == -1) sampler.moveNegativeX();
|
if(di == -1) sampler.moveNegativeX();
|
||||||
} else if (ty <= tz)
|
} else if (ty <= tz)
|
||||||
{
|
{
|
||||||
if(j == jend) break;
|
if(j == jend) break;
|
||||||
ty += deltaty;
|
ty += deltaty;
|
||||||
j += dj;
|
j += dj;
|
||||||
|
|
||||||
if(dj == 1) sampler.movePositiveY();
|
if(dj == 1) sampler.movePositiveY();
|
||||||
if(dj == -1) sampler.moveNegativeY();
|
if(dj == -1) sampler.moveNegativeY();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
if(k == kend) break;
|
if(k == kend) break;
|
||||||
tz += deltatz;
|
tz += deltatz;
|
||||||
k += dk;
|
k += dk;
|
||||||
|
|
||||||
if(dk == 1) sampler.movePositiveZ();
|
if(dk == 1) sampler.movePositiveZ();
|
||||||
if(dk == -1) sampler.moveNegativeZ();
|
if(dk == -1) sampler.moveNegativeZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return RaycastResults::Completed;
|
return RaycastResults::Completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast a ray through a volume by specifying the start and a direction
|
* Cast a ray through a volume by specifying the start and a direction
|
||||||
*
|
*
|
||||||
* The ray will move from \a v3dStart along \a v3dDirectionAndLength, calling
|
* The ray will move from \a v3dStart along \a v3dDirectionAndLength, calling
|
||||||
* \a callback for each voxel it passes through until \a callback returns
|
* \a callback for each voxel it passes through until \a callback returns
|
||||||
* \a false. In this case it returns a RaycastResults::Interupted. If it
|
* \a false. In this case it returns a RaycastResults::Interupted. If it
|
||||||
* passes from start to end without \a callback returning \a false, it
|
* passes from start to end without \a callback returning \a false, it
|
||||||
* returns RaycastResults::Completed.
|
* returns RaycastResults::Completed.
|
||||||
*
|
*
|
||||||
* \note These has been confusion in the past with people not realising
|
* \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
|
* 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
|
* 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
|
* 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
|
* 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
|
* you must scale the direction vector so that it's length represents the maximum distance
|
||||||
* over which you want the ray to be cast.
|
* over which you want the ray to be cast.
|
||||||
*
|
*
|
||||||
* \param volData The volume to pass the ray though
|
* \param volData The volume to pass the ray though
|
||||||
* \param v3dStart The start position in the volume
|
* \param v3dStart The start position in the volume
|
||||||
* \param v3dDirectionAndLength The direction and length of the ray
|
* \param v3dDirectionAndLength The direction and length of the ray
|
||||||
* \param callback The callback to call for each voxel
|
* \param callback The callback to call for each voxel
|
||||||
*
|
*
|
||||||
* \return A RaycastResults designating whether the ray hit anything or not
|
* \return A RaycastResults designating whether the ray hit anything or not
|
||||||
*/
|
*/
|
||||||
template<typename VolumeType, typename Callback>
|
template<typename VolumeType, typename Callback>
|
||||||
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
|
RaycastResult raycastWithDirection(VolumeType* volData, const Vector3DFloat& v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
|
||||||
{
|
{
|
||||||
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
|
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
|
||||||
return raycastWithEndpoints<VolumeType, Callback>(volData, v3dStart, v3dEnd, callback);
|
return raycastWithEndpoints<VolumeType, Callback>(volData, v3dStart, v3dEnd, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,461 +1,461 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Region_H__
|
#ifndef __PolyVox_Region_H__
|
||||||
#define __PolyVox_Region_H__
|
#define __PolyVox_Region_H__
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.h"
|
#include "PolyVoxCore/Vector.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/** Represents a part of a Volume.
|
/** 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
|
* 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
|
* 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
|
* 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.
|
* 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
|
* 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
|
* bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are
|
||||||
* <em>inclusive</em>.
|
* <em>inclusive</em>.
|
||||||
*
|
*
|
||||||
* As well as the expected set of getters and setters, this class also provide utility functions for increasing and decresing
|
* As well as the expected set of getters and setters, this class also provide utility functions for increasing and decresing
|
||||||
* the size of the Region, shifting the Region in 3D space, testing whether it contains a given position, enlarging it so that
|
* the size of the Region, shifting the Region in 3D space, testing whether it contains a given position, enlarging it so that
|
||||||
* it does contain a given position, croppng it to another Region, and various other utility functions.
|
* it does contain a given position, croppng it to another Region, and various other utility functions.
|
||||||
*
|
*
|
||||||
* \Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information
|
* \Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information
|
||||||
* about these definitions.
|
* about these definitions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifdef SWIG
|
#ifdef SWIG
|
||||||
class Region
|
class Region
|
||||||
#else
|
#else
|
||||||
class POLYVOX_API Region
|
class POLYVOX_API Region
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// A Region with the lower corner set as low as possible and the upper corner set as high as possible.
|
/// A Region with the lower corner set as low as possible and the upper corner set as high as possible.
|
||||||
static const Region MaxRegion;
|
static const Region MaxRegion;
|
||||||
/// A Region with the lower corner set as high as possible and the upper corner set as low as possible.
|
/// A Region with the lower corner set as high as possible and the upper corner set as low as possible.
|
||||||
static const Region InvertedRegion;
|
static const Region InvertedRegion;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Region();
|
Region();
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner);
|
Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner);
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ);
|
Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ);
|
||||||
|
|
||||||
/// Equality Operator.
|
/// Equality Operator.
|
||||||
bool operator==(const Region& rhs) const;
|
bool operator==(const Region& rhs) const;
|
||||||
/// Inequality Operator.
|
/// Inequality Operator.
|
||||||
bool operator!=(const Region& rhs) const;
|
bool operator!=(const Region& rhs) const;
|
||||||
|
|
||||||
/// Gets the 'x' position of the centre.
|
/// Gets the 'x' position of the centre.
|
||||||
int32_t getCentreX(void) const;
|
int32_t getCentreX(void) const;
|
||||||
/// Gets the 'y' position of the centre.
|
/// Gets the 'y' position of the centre.
|
||||||
int32_t getCentreY(void) const;
|
int32_t getCentreY(void) const;
|
||||||
/// Gets the 'z' position of the centrer.
|
/// Gets the 'z' position of the centrer.
|
||||||
int32_t getCentreZ(void) const;
|
int32_t getCentreZ(void) const;
|
||||||
/// Gets the 'x' position of the lower corner.
|
/// Gets the 'x' position of the lower corner.
|
||||||
int32_t getLowerX(void) const;
|
int32_t getLowerX(void) const;
|
||||||
/// Gets the 'y' position of the lower corner.
|
/// Gets the 'y' position of the lower corner.
|
||||||
int32_t getLowerY(void) const;
|
int32_t getLowerY(void) const;
|
||||||
/// Gets the 'z' position of the lower corner.
|
/// Gets the 'z' position of the lower corner.
|
||||||
int32_t getLowerZ(void) const;
|
int32_t getLowerZ(void) const;
|
||||||
/// Gets the 'x' position of the upper corner.
|
/// Gets the 'x' position of the upper corner.
|
||||||
int32_t getUpperX(void) const;
|
int32_t getUpperX(void) const;
|
||||||
/// Gets the 'y' position of the upper corner.
|
/// Gets the 'y' position of the upper corner.
|
||||||
int32_t getUpperY(void) const;
|
int32_t getUpperY(void) const;
|
||||||
/// Gets the 'z' position of the upper corner.
|
/// Gets the 'z' position of the upper corner.
|
||||||
int32_t getUpperZ(void) const;
|
int32_t getUpperZ(void) const;
|
||||||
|
|
||||||
/// Gets the centre of the region
|
/// Gets the centre of the region
|
||||||
Vector3DInt32 getCentre(void) const;
|
Vector3DInt32 getCentre(void) const;
|
||||||
/// Gets the position of the lower corner.
|
/// Gets the position of the lower corner.
|
||||||
Vector3DInt32 getLowerCorner(void) const;
|
Vector3DInt32 getLowerCorner(void) const;
|
||||||
/// Gets the position of the upper corner.
|
/// Gets the position of the upper corner.
|
||||||
Vector3DInt32 getUpperCorner(void) const;
|
Vector3DInt32 getUpperCorner(void) const;
|
||||||
|
|
||||||
/// Gets the width of the region measured in voxels.
|
/// Gets the width of the region measured in voxels.
|
||||||
int32_t getWidthInVoxels(void) const;
|
int32_t getWidthInVoxels(void) const;
|
||||||
/// Gets the height of the region measured in voxels.
|
/// Gets the height of the region measured in voxels.
|
||||||
int32_t getHeightInVoxels(void) const;
|
int32_t getHeightInVoxels(void) const;
|
||||||
/// Gets the depth of the region measured in voxels.
|
/// Gets the depth of the region measured in voxels.
|
||||||
int32_t getDepthInVoxels(void) const;
|
int32_t getDepthInVoxels(void) const;
|
||||||
/// Gets the dimensions of the region measured in voxels.
|
/// Gets the dimensions of the region measured in voxels.
|
||||||
Vector3DInt32 getDimensionsInVoxels(void) const;
|
Vector3DInt32 getDimensionsInVoxels(void) const;
|
||||||
|
|
||||||
/// Gets the width of the region measured in cells.
|
/// Gets the width of the region measured in cells.
|
||||||
int32_t getWidthInCells(void) const;
|
int32_t getWidthInCells(void) const;
|
||||||
/// Gets the height of the region measured in cells.
|
/// Gets the height of the region measured in cells.
|
||||||
int32_t getHeightInCells(void) const;
|
int32_t getHeightInCells(void) const;
|
||||||
/// Gets the depth of the region measured in cells.
|
/// Gets the depth of the region measured in cells.
|
||||||
int32_t getDepthInCells(void) const;
|
int32_t getDepthInCells(void) const;
|
||||||
/// Gets the dimensions of the region measured in cells.
|
/// Gets the dimensions of the region measured in cells.
|
||||||
Vector3DInt32 getDimensionsInCells(void) const;
|
Vector3DInt32 getDimensionsInCells(void) const;
|
||||||
|
|
||||||
/// Sets the 'x' position of the lower corner.
|
/// Sets the 'x' position of the lower corner.
|
||||||
void setLowerX(int32_t iX);
|
void setLowerX(int32_t iX);
|
||||||
/// Sets the 'y' position of the lower corner.
|
/// Sets the 'y' position of the lower corner.
|
||||||
void setLowerY(int32_t iY);
|
void setLowerY(int32_t iY);
|
||||||
/// Sets the 'z' position of the lower corner.
|
/// Sets the 'z' position of the lower corner.
|
||||||
void setLowerZ(int32_t iZ);
|
void setLowerZ(int32_t iZ);
|
||||||
/// Sets the 'x' position of the upper corner.
|
/// Sets the 'x' position of the upper corner.
|
||||||
void setUpperX(int32_t iX);
|
void setUpperX(int32_t iX);
|
||||||
/// Sets the 'y' position of the upper corner.
|
/// Sets the 'y' position of the upper corner.
|
||||||
void setUpperY(int32_t iY);
|
void setUpperY(int32_t iY);
|
||||||
/// Sets the 'z' position of the upper corner.
|
/// Sets the 'z' position of the upper corner.
|
||||||
void setUpperZ(int32_t iZ);
|
void setUpperZ(int32_t iZ);
|
||||||
|
|
||||||
/// Sets the position of the lower corner.
|
/// Sets the position of the lower corner.
|
||||||
void setLowerCorner(const Vector3DInt32& v3dLowerCorner);
|
void setLowerCorner(const Vector3DInt32& v3dLowerCorner);
|
||||||
/// Sets the position of the upper corner.
|
/// Sets the position of the upper corner.
|
||||||
void setUpperCorner(const Vector3DInt32& v3dUpperCorner);
|
void setUpperCorner(const Vector3DInt32& v3dUpperCorner);
|
||||||
|
|
||||||
/// Tests whether the given point is contained in this Region.
|
/// Tests whether the given point is contained in this Region.
|
||||||
bool containsPoint(float fX, float fY, float fZ, float boundary = 0.0f) const;
|
bool containsPoint(float fX, float fY, float fZ, float boundary = 0.0f) const;
|
||||||
/// Tests whether the given point is contained in this Region.
|
/// Tests whether the given point is contained in this Region.
|
||||||
bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const;
|
bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const;
|
||||||
/// Tests whether the given point is contained in this Region.
|
/// Tests whether the given point is contained in this Region.
|
||||||
bool containsPoint(int32_t iX, int32_t iY, int32_t iZ, uint8_t boundary = 0) const;
|
bool containsPoint(int32_t iX, int32_t iY, int32_t iZ, uint8_t boundary = 0) const;
|
||||||
/// Tests whether the given point is contained in this Region.
|
/// Tests whether the given point is contained in this Region.
|
||||||
bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const;
|
bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const;
|
||||||
/// Tests whether the given position is contained in the 'x' range of this Region.
|
/// Tests whether the given position is contained in the 'x' range of this Region.
|
||||||
bool containsPointInX(float pos, float boundary = 0.0f) const;
|
bool containsPointInX(float pos, float boundary = 0.0f) const;
|
||||||
/// Tests whether the given position is contained in the 'x' range of this Region.
|
/// Tests whether the given position is contained in the 'x' range of this Region.
|
||||||
bool containsPointInX(int32_t pos, uint8_t boundary = 0) const;
|
bool containsPointInX(int32_t pos, uint8_t boundary = 0) const;
|
||||||
/// Tests whether the given position is contained in the 'y' range of this Region.
|
/// Tests whether the given position is contained in the 'y' range of this Region.
|
||||||
bool containsPointInY(float pos, float boundary = 0.0f) const;
|
bool containsPointInY(float pos, float boundary = 0.0f) const;
|
||||||
/// Tests whether the given position is contained in the 'y' range of this Region.
|
/// Tests whether the given position is contained in the 'y' range of this Region.
|
||||||
bool containsPointInY(int32_t pos, uint8_t boundary = 0) const;
|
bool containsPointInY(int32_t pos, uint8_t boundary = 0) const;
|
||||||
/// Tests whether the given position is contained in the 'z' range of this Region.
|
/// Tests whether the given position is contained in the 'z' range of this Region.
|
||||||
bool containsPointInZ(float pos, float boundary = 0.0f) const;
|
bool containsPointInZ(float pos, float boundary = 0.0f) const;
|
||||||
/// Tests whether the given position is contained in the 'z' range of this Region.
|
/// Tests whether the given position is contained in the 'z' range of this Region.
|
||||||
bool containsPointInZ(int32_t pos, uint8_t boundary = 0) const;
|
bool containsPointInZ(int32_t pos, uint8_t boundary = 0) const;
|
||||||
|
|
||||||
/// Tests whether the given Region is contained in this Region.
|
/// Tests whether the given Region is contained in this Region.
|
||||||
bool containsRegion(const Region& reg, uint8_t boundary = 0) const;
|
bool containsRegion(const Region& reg, uint8_t boundary = 0) const;
|
||||||
|
|
||||||
/// Enlarges the Region so that it contains the specified position.
|
/// Enlarges the Region so that it contains the specified position.
|
||||||
void accumulate(int32_t iX, int32_t iY, int32_t iZ);
|
void accumulate(int32_t iX, int32_t iY, int32_t iZ);
|
||||||
/// Enlarges the Region so that it contains the specified position.
|
/// Enlarges the Region so that it contains the specified position.
|
||||||
void accumulate(const Vector3DInt32& v3dPos);
|
void accumulate(const Vector3DInt32& v3dPos);
|
||||||
/// Enlarges the Region so that it contains the specified Region.
|
/// Enlarges the Region so that it contains the specified Region.
|
||||||
void accumulate(const Region& reg);
|
void accumulate(const Region& reg);
|
||||||
|
|
||||||
/// Crops the extents of this Region accoring to another Region.
|
/// Crops the extents of this Region accoring to another Region.
|
||||||
void cropTo(const Region& other);
|
void cropTo(const Region& other);
|
||||||
|
|
||||||
/// Grows this region by the amount specified.
|
/// Grows this region by the amount specified.
|
||||||
void grow(int32_t iAmount);
|
void grow(int32_t iAmount);
|
||||||
/// Grows this region by the amounts specified.
|
/// Grows this region by the amounts specified.
|
||||||
void grow(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
void grow(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||||
/// Grows this region by the amounts specified.
|
/// Grows this region by the amounts specified.
|
||||||
void grow(const Vector3DInt32& v3dAmount);
|
void grow(const Vector3DInt32& v3dAmount);
|
||||||
|
|
||||||
/// Tests whether all components of the upper corner are at least
|
/// Tests whether all components of the upper corner are at least
|
||||||
/// as great as the corresponding components of the lower corner.
|
/// as great as the corresponding components of the lower corner.
|
||||||
bool isValid(void) const;
|
bool isValid(void) const;
|
||||||
|
|
||||||
/// Moves the Region by the amount specified.
|
/// Moves the Region by the amount specified.
|
||||||
void shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
void shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||||
/// Moves the Region by the amount specified.
|
/// Moves the Region by the amount specified.
|
||||||
void shift(const Vector3DInt32& v3dAmount);
|
void shift(const Vector3DInt32& v3dAmount);
|
||||||
/// Moves the lower corner of the Region by the amount specified.
|
/// Moves the lower corner of the Region by the amount specified.
|
||||||
void shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
void shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||||
/// Moves the lower corner of the Region by the amount specified.
|
/// Moves the lower corner of the Region by the amount specified.
|
||||||
void shiftLowerCorner(const Vector3DInt32& v3dAmount);
|
void shiftLowerCorner(const Vector3DInt32& v3dAmount);
|
||||||
/// Moves the upper corner of the Region by the amount specified.
|
/// Moves the upper corner of the Region by the amount specified.
|
||||||
void shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
void shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||||
/// Moves the upper corner of the Region by the amount specified.
|
/// Moves the upper corner of the Region by the amount specified.
|
||||||
void shiftUpperCorner(const Vector3DInt32& v3dAmount);
|
void shiftUpperCorner(const Vector3DInt32& v3dAmount);
|
||||||
|
|
||||||
/// Shrinks this region by the amount specified.
|
/// Shrinks this region by the amount specified.
|
||||||
void shrink(int32_t iAmount);
|
void shrink(int32_t iAmount);
|
||||||
/// Shrinks this region by the amounts specified.
|
/// Shrinks this region by the amounts specified.
|
||||||
void shrink(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
void shrink(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ);
|
||||||
/// Shrinks this region by the amounts specified.
|
/// Shrinks this region by the amounts specified.
|
||||||
void shrink(const Vector3DInt32& v3dAmount);
|
void shrink(const Vector3DInt32& v3dAmount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_iLowerX;
|
int32_t m_iLowerX;
|
||||||
int32_t m_iLowerY;
|
int32_t m_iLowerY;
|
||||||
int32_t m_iLowerZ;
|
int32_t m_iLowerZ;
|
||||||
int32_t m_iUpperX;
|
int32_t m_iUpperX;
|
||||||
int32_t m_iUpperY;
|
int32_t m_iUpperY;
|
||||||
int32_t m_iUpperZ;
|
int32_t m_iUpperZ;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Non-member functions
|
// Non-member functions
|
||||||
bool intersects(const Region& a, const Region& b);
|
bool intersects(const Region& a, const Region& b);
|
||||||
|
|
||||||
// Non-member overloaded operators.
|
// Non-member overloaded operators.
|
||||||
/// Stream insertion operator.
|
/// Stream insertion operator.
|
||||||
std::ostream& operator<<(std::ostream& os, const Region& region);
|
std::ostream& operator<<(std::ostream& os, const Region& region);
|
||||||
|
|
||||||
// Functions to be inlined to to be in the header rather than the .cpp.
|
// Functions to be inlined to to be in the header rather than the .cpp.
|
||||||
// 'inline' keyword is used for the definition rather than the declaration.
|
// 'inline' keyword is used for the definition rather than the declaration.
|
||||||
// See also http://www.parashift.com/c++-faq-lite/inline-functions.html
|
// See also http://www.parashift.com/c++-faq-lite/inline-functions.html
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'x' position of the centre.
|
* \return The 'x' position of the centre.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getCentreX(void) const
|
inline int32_t Region::getCentreX(void) const
|
||||||
{
|
{
|
||||||
return (m_iLowerX + m_iUpperX) / 2;
|
return (m_iLowerX + m_iUpperX) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'y' position of the centre.
|
* \return The 'y' position of the centre.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getCentreY(void) const
|
inline int32_t Region::getCentreY(void) const
|
||||||
{
|
{
|
||||||
return (m_iLowerY + m_iUpperY) / 2;
|
return (m_iLowerY + m_iUpperY) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'z' position of the centre.
|
* \return The 'z' position of the centre.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getCentreZ(void) const
|
inline int32_t Region::getCentreZ(void) const
|
||||||
{
|
{
|
||||||
return (m_iLowerZ + m_iUpperZ) / 2;
|
return (m_iLowerZ + m_iUpperZ) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'x' position of the lower corner.
|
* \return The 'x' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getLowerX(void) const
|
inline int32_t Region::getLowerX(void) const
|
||||||
{
|
{
|
||||||
return m_iLowerX;
|
return m_iLowerX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'y' position of the lower corner.
|
* \return The 'y' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getLowerY(void) const
|
inline int32_t Region::getLowerY(void) const
|
||||||
{
|
{
|
||||||
return m_iLowerY;
|
return m_iLowerY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'z' position of the lower corner.
|
* \return The 'z' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getLowerZ(void) const
|
inline int32_t Region::getLowerZ(void) const
|
||||||
{
|
{
|
||||||
return m_iLowerZ;
|
return m_iLowerZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'x' position of the upper corner.
|
* \return The 'x' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getUpperX(void) const
|
inline int32_t Region::getUpperX(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperX;
|
return m_iUpperX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'y' position of the upper corner.
|
* \return The 'y' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getUpperY(void) const
|
inline int32_t Region::getUpperY(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperY;
|
return m_iUpperY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The 'z' position of the upper corner.
|
* \return The 'z' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getUpperZ(void) const
|
inline int32_t Region::getUpperZ(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperZ;
|
return m_iUpperZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The position of the lower corner.
|
* \return The position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline Vector3DInt32 Region::getCentre(void) const
|
inline Vector3DInt32 Region::getCentre(void) const
|
||||||
{
|
{
|
||||||
return Vector3DInt32(getCentreX(), getCentreY(), getCentreZ());
|
return Vector3DInt32(getCentreX(), getCentreY(), getCentreZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The position of the lower corner.
|
* \return The position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline Vector3DInt32 Region::getLowerCorner(void) const
|
inline Vector3DInt32 Region::getLowerCorner(void) const
|
||||||
{
|
{
|
||||||
return Vector3DInt32(m_iLowerX, m_iLowerY, m_iLowerZ);
|
return Vector3DInt32(m_iLowerX, m_iLowerY, m_iLowerZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The position of the upper corner.
|
* \return The position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline Vector3DInt32 Region::getUpperCorner(void) const
|
inline Vector3DInt32 Region::getUpperCorner(void) const
|
||||||
{
|
{
|
||||||
return Vector3DInt32(m_iUpperX, m_iUpperY, m_iUpperZ);
|
return Vector3DInt32(m_iUpperX, m_iUpperY, m_iUpperZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The width of the region measured in voxels.
|
* \return The width of the region measured in voxels.
|
||||||
* \sa getWidthInCells()
|
* \sa getWidthInCells()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getWidthInVoxels(void) const
|
inline int32_t Region::getWidthInVoxels(void) const
|
||||||
{
|
{
|
||||||
return getWidthInCells() + 1;
|
return getWidthInCells() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The height of the region measured in voxels.
|
* \return The height of the region measured in voxels.
|
||||||
* \sa getHeightInCells()
|
* \sa getHeightInCells()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getHeightInVoxels(void) const
|
inline int32_t Region::getHeightInVoxels(void) const
|
||||||
{
|
{
|
||||||
return getHeightInCells() + 1;
|
return getHeightInCells() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The depth of the region measured in voxels.
|
* \return The depth of the region measured in voxels.
|
||||||
* \sa getDepthInCells()
|
* \sa getDepthInCells()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getDepthInVoxels(void) const
|
inline int32_t Region::getDepthInVoxels(void) const
|
||||||
{
|
{
|
||||||
return getDepthInCells() + 1;
|
return getDepthInCells() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The dimensions of the region measured in voxels.
|
* \return The dimensions of the region measured in voxels.
|
||||||
* \sa getDimensionsInCells()
|
* \sa getDimensionsInCells()
|
||||||
*/
|
*/
|
||||||
inline Vector3DInt32 Region::getDimensionsInVoxels(void) const
|
inline Vector3DInt32 Region::getDimensionsInVoxels(void) const
|
||||||
{
|
{
|
||||||
return getDimensionsInCells() + Vector3DInt32(1, 1, 1);
|
return getDimensionsInCells() + Vector3DInt32(1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The width of the region measured in cells.
|
* \return The width of the region measured in cells.
|
||||||
* \sa getWidthInVoxels()
|
* \sa getWidthInVoxels()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getWidthInCells(void) const
|
inline int32_t Region::getWidthInCells(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperX - m_iLowerX;
|
return m_iUpperX - m_iLowerX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The height of the region measured in cells.
|
* \return The height of the region measured in cells.
|
||||||
* \sa getHeightInVoxels()
|
* \sa getHeightInVoxels()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getHeightInCells(void) const
|
inline int32_t Region::getHeightInCells(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperY - m_iLowerY;
|
return m_iUpperY - m_iLowerY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The depth of the region measured in cells.
|
* \return The depth of the region measured in cells.
|
||||||
* \sa getDepthInVoxels()
|
* \sa getDepthInVoxels()
|
||||||
*/
|
*/
|
||||||
inline int32_t Region::getDepthInCells(void) const
|
inline int32_t Region::getDepthInCells(void) const
|
||||||
{
|
{
|
||||||
return m_iUpperZ - m_iLowerZ;
|
return m_iUpperZ - m_iLowerZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return The dimensions of the region measured in cells.
|
* \return The dimensions of the region measured in cells.
|
||||||
* \sa getDimensionsInVoxels()
|
* \sa getDimensionsInVoxels()
|
||||||
*/
|
*/
|
||||||
inline Vector3DInt32 Region::getDimensionsInCells(void) const
|
inline Vector3DInt32 Region::getDimensionsInCells(void) const
|
||||||
{
|
{
|
||||||
return Vector3DInt32(getWidthInCells(), getHeightInCells(), getDepthInCells());
|
return Vector3DInt32(getWidthInCells(), getHeightInCells(), getDepthInCells());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iX The new 'x' position of the lower corner.
|
* \param iX The new 'x' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setLowerX(int32_t iX)
|
inline void Region::setLowerX(int32_t iX)
|
||||||
{
|
{
|
||||||
m_iLowerX = iX;
|
m_iLowerX = iX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iY The new 'y' position of the lower corner.
|
* \param iY The new 'y' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setLowerY(int32_t iY)
|
inline void Region::setLowerY(int32_t iY)
|
||||||
{
|
{
|
||||||
m_iLowerY = iY;
|
m_iLowerY = iY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iZ The new 'z' position of the lower corner.
|
* \param iZ The new 'z' position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setLowerZ(int32_t iZ)
|
inline void Region::setLowerZ(int32_t iZ)
|
||||||
{
|
{
|
||||||
m_iLowerZ = iZ;
|
m_iLowerZ = iZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iX The new 'x' position of the upper corner.
|
* \param iX The new 'x' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setUpperX(int32_t iX)
|
inline void Region::setUpperX(int32_t iX)
|
||||||
{
|
{
|
||||||
m_iUpperX = iX;
|
m_iUpperX = iX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iY The new 'y' position of the upper corner.
|
* \param iY The new 'y' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setUpperY(int32_t iY)
|
inline void Region::setUpperY(int32_t iY)
|
||||||
{
|
{
|
||||||
m_iUpperY = iY;
|
m_iUpperY = iY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param iZ The new 'z' position of the upper corner.
|
* \param iZ The new 'z' position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setUpperZ(int32_t iZ)
|
inline void Region::setUpperZ(int32_t iZ)
|
||||||
{
|
{
|
||||||
m_iUpperZ = iZ;
|
m_iUpperZ = iZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param v3dLowerCorner The new position of the lower corner.
|
* \param v3dLowerCorner The new position of the lower corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner)
|
inline void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner)
|
||||||
{
|
{
|
||||||
m_iLowerX = v3dLowerCorner.getX();
|
m_iLowerX = v3dLowerCorner.getX();
|
||||||
m_iLowerY = v3dLowerCorner.getY();
|
m_iLowerY = v3dLowerCorner.getY();
|
||||||
m_iLowerZ = v3dLowerCorner.getZ();
|
m_iLowerZ = v3dLowerCorner.getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param v3dUpperCorner The new position of the upper corner.
|
* \param v3dUpperCorner The new position of the upper corner.
|
||||||
*/
|
*/
|
||||||
inline void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner)
|
inline void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner)
|
||||||
{
|
{
|
||||||
m_iUpperX = v3dUpperCorner.getX();
|
m_iUpperX = v3dUpperCorner.getX();
|
||||||
m_iUpperY = v3dUpperCorner.getY();
|
m_iUpperY = v3dUpperCorner.getY();
|
||||||
m_iUpperZ = v3dUpperCorner.getZ();
|
m_iUpperZ = v3dUpperCorner.getZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef __PolyVox_SimpleVolume_H__
|
#ifndef __PolyVox_SimpleVolume_H__
|
||||||
#define __PolyVox_SimpleVolume_H__
|
#define __PolyVox_SimpleVolume_H__
|
||||||
|
|
||||||
#pragma message("WARNING - The SimpleVolume class has been replaced by PagedVolume. Please use that instead.")
|
#pragma message("WARNING - The SimpleVolume class has been replaced by PagedVolume. Please use that instead.")
|
||||||
|
|
||||||
#include "PagedVolume.h"
|
#include "PagedVolume.h"
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
#endif //__PolyVox_SimpleVolume_H__
|
#endif //__PolyVox_SimpleVolume_H__
|
@ -1,248 +1,248 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_Vector_H__
|
#ifndef __PolyVox_Vector_H__
|
||||||
#define __PolyVox_Vector_H__
|
#define __PolyVox_Vector_H__
|
||||||
|
|
||||||
#include "Impl/ErrorHandling.h"
|
#include "Impl/ErrorHandling.h"
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Represents a vector in space.
|
* Represents a vector in space.
|
||||||
*
|
*
|
||||||
* This is a generl purpose vector class designed to represent both positions and directions. It is templatised
|
* This is a generl purpose vector class designed to represent both positions and directions. It is templatised
|
||||||
* on both size and data type but note that some of the operations do not make sense with integer types. For
|
* on both size and data type but 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.
|
* example it does not make conceptual sense to try and normalise an integer Vector.
|
||||||
*
|
*
|
||||||
* Every Vector must have at at least two elements, and the first four elements of any vector are known as the
|
* Every Vector must have at at least two elements, and the first four elements of any vector are known as the
|
||||||
* X, Y, Z and W elements. Note that W is last even though it comes before X in the alphabet. These elements can
|
* X, Y, Z and W elements. Note that W is last even though it comes before X in the alphabet. These elements can
|
||||||
* be accessed through getX(), setX(), getY(), setY(), getZ(), setZ(), getW() and setW(), while other elements
|
* be accessed through getX(), setX(), getY(), setY(), getZ(), setZ(), getW() and setW(), while other elements
|
||||||
* can be accessed through getElemen() and setElement().
|
* can be accessed through getElemen() and setElement().
|
||||||
*
|
*
|
||||||
* This class includes a number of common mathematical operations (addition, subtraction, etc) as well as vector
|
* This class includes a number of common mathematical operations (addition, subtraction, etc) as well as vector
|
||||||
* specific operations such as the dot and cross products. Note that this class is also templatised on an
|
* specific operations such as the dot and cross products. Note that this class is also templatised on an
|
||||||
* OperationType which is used for many internal calculations and some results. For example, the square of a
|
* OperationType which is used for many internal calculations and some results. For example, the square of a
|
||||||
* vector's length will always be an integer if all the elements are integers, but the value might be outside
|
* vector's length will always be an integer if all the elements are integers, but the value might be outside
|
||||||
* that which can be represented by the StorageType. You don't need to worry about this as long as you are using
|
* that which can be represented by the StorageType. You don't need to worry about this as long as you are using
|
||||||
* the built in typedefs for common configurations.
|
* the built in typedefs for common configurations.
|
||||||
*
|
*
|
||||||
* Typedefs are provided for 2, 3 and 4 dimensional vector with int8_t, uint8_t, int16_t, uint6_t, int32_t,
|
* Typedefs are provided for 2, 3 and 4 dimensional vector with int8_t, uint8_t, int16_t, uint6_t, int32_t,
|
||||||
* uint32_t, float and double types. These typedefs are used as follows:
|
* uint32_t, float and double types. These typedefs are used as follows:
|
||||||
*
|
*
|
||||||
* \code
|
* \code
|
||||||
* Vector2DInt32 test(1,2); //Declares a 2 dimensional Vector of type int32_t.
|
* Vector2DInt32 test(1,2); //Declares a 2 dimensional Vector of type int32_t.
|
||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
template <uint32_t Size, typename StorageType, typename OperationType>
|
template <uint32_t Size, typename StorageType, typename OperationType>
|
||||||
class Vector
|
class Vector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Vector(void);
|
Vector(void);
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
Vector(StorageType tFillValue);
|
Vector(StorageType tFillValue);
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
Vector(StorageType x, StorageType y);
|
Vector(StorageType x, StorageType y);
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
Vector(StorageType x, StorageType y, StorageType z);
|
Vector(StorageType x, StorageType y, StorageType z);
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
Vector(StorageType x, StorageType y, StorageType z, StorageType w);
|
Vector(StorageType x, StorageType y, StorageType z, StorageType w);
|
||||||
/// Copy Constructor.
|
/// Copy Constructor.
|
||||||
Vector(const Vector<Size,StorageType,OperationType>& vector);
|
Vector(const Vector<Size,StorageType,OperationType>& vector);
|
||||||
/// Copy Constructor which performs casting.
|
/// Copy Constructor which performs casting.
|
||||||
template <typename CastType> explicit Vector(const Vector<Size,CastType>& vector);
|
template <typename CastType> explicit Vector(const Vector<Size,CastType>& vector);
|
||||||
/// Destructor.
|
/// Destructor.
|
||||||
~Vector(void);
|
~Vector(void);
|
||||||
|
|
||||||
/// Assignment Operator.
|
/// Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator=(const Vector<Size,StorageType,OperationType>& rhs);
|
Vector<Size,StorageType,OperationType>& operator=(const Vector<Size,StorageType,OperationType>& rhs);
|
||||||
/// Equality Operator.
|
/// Equality Operator.
|
||||||
bool operator==(const Vector<Size,StorageType,OperationType>& rhs) const;
|
bool operator==(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||||
/// Inequality Operator.
|
/// Inequality Operator.
|
||||||
bool operator!=(const Vector<Size,StorageType,OperationType>& rhs) const;
|
bool operator!=(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||||
/// Comparison Operator.
|
/// Comparison Operator.
|
||||||
POLYVOX_DEPRECATED bool operator<(const Vector<Size,StorageType,OperationType>& rhs) const;
|
POLYVOX_DEPRECATED bool operator<(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||||
/// Addition and Assignment Operator.
|
/// Addition and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator+=(const Vector<Size,StorageType,OperationType> &rhs);
|
Vector<Size,StorageType,OperationType>& operator+=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||||
/// Subtraction and Assignment Operator.
|
/// Subtraction and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator-=(const Vector<Size,StorageType,OperationType> &rhs);
|
Vector<Size,StorageType,OperationType>& operator-=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||||
/// Multiplication and Assignment Operator.
|
/// Multiplication and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator*=(const Vector<Size,StorageType,OperationType> &rhs);
|
Vector<Size,StorageType,OperationType>& operator*=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||||
/// Division and Assignment Operator.
|
/// Division and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator/=(const Vector<Size,StorageType,OperationType> &rhs);
|
Vector<Size,StorageType,OperationType>& operator/=(const Vector<Size,StorageType,OperationType> &rhs);
|
||||||
/// Multiplication and Assignment Operator.
|
/// Multiplication and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator*=(const StorageType& rhs);
|
Vector<Size,StorageType,OperationType>& operator*=(const StorageType& rhs);
|
||||||
/// Division and Assignment Operator.
|
/// Division and Assignment Operator.
|
||||||
Vector<Size,StorageType,OperationType>& operator/=(const StorageType& rhs);
|
Vector<Size,StorageType,OperationType>& operator/=(const StorageType& rhs);
|
||||||
|
|
||||||
/// Element Access.
|
/// Element Access.
|
||||||
StorageType getElement(uint32_t index) const;
|
StorageType getElement(uint32_t index) const;
|
||||||
/// Get the x component of the vector.
|
/// Get the x component of the vector.
|
||||||
StorageType getX(void) const;
|
StorageType getX(void) const;
|
||||||
/// Get the y component of the vector.
|
/// Get the y component of the vector.
|
||||||
StorageType getY(void) const;
|
StorageType getY(void) const;
|
||||||
/// Get the z component of the vector.
|
/// Get the z component of the vector.
|
||||||
StorageType getZ(void) const;
|
StorageType getZ(void) const;
|
||||||
/// Get the w component of the vector.
|
/// Get the w component of the vector.
|
||||||
StorageType getW(void) const;
|
StorageType getW(void) const;
|
||||||
|
|
||||||
/// Element Access.
|
/// Element Access.
|
||||||
void setElement(uint32_t index, StorageType tValue);
|
void setElement(uint32_t index, StorageType tValue);
|
||||||
/// Element Access.
|
/// Element Access.
|
||||||
void setElements(StorageType x, StorageType y);
|
void setElements(StorageType x, StorageType y);
|
||||||
/// Element Access.
|
/// Element Access.
|
||||||
void setElements(StorageType x, StorageType y, StorageType z);
|
void setElements(StorageType x, StorageType y, StorageType z);
|
||||||
/// Element Access.
|
/// Element Access.
|
||||||
void setElements(StorageType x, StorageType y, StorageType z, StorageType w);
|
void setElements(StorageType x, StorageType y, StorageType z, StorageType w);
|
||||||
/// Set the x component of the vector.
|
/// Set the x component of the vector.
|
||||||
void setX(StorageType tX);
|
void setX(StorageType tX);
|
||||||
/// Set the y component of the vector.
|
/// Set the y component of the vector.
|
||||||
void setY(StorageType tY);
|
void setY(StorageType tY);
|
||||||
/// Set the z component of the vector.
|
/// Set the z component of the vector.
|
||||||
void setZ(StorageType tZ);
|
void setZ(StorageType tZ);
|
||||||
/// Set the w component of the vector.
|
/// Set the w component of the vector.
|
||||||
void setW(StorageType tW);
|
void setW(StorageType tW);
|
||||||
|
|
||||||
/// Get the length of the vector.
|
/// Get the length of the vector.
|
||||||
float length(void) const;
|
float length(void) const;
|
||||||
/// Get the squared length of the vector.
|
/// Get the squared length of the vector.
|
||||||
OperationType lengthSquared(void) const;
|
OperationType lengthSquared(void) const;
|
||||||
/// Find the angle between this vector and that which is passed as a parameter.
|
/// Find the angle between this vector and that which is passed as a parameter.
|
||||||
float angleTo(const Vector<Size,StorageType,OperationType>& vector) const;
|
float angleTo(const Vector<Size,StorageType,OperationType>& vector) const;
|
||||||
/// Find the cross product between this vector and the vector passed as a parameter.
|
/// Find the cross product between this vector and the vector passed as a parameter.
|
||||||
Vector<Size,StorageType,OperationType> cross(const Vector<Size,StorageType,OperationType>& vector) const;
|
Vector<Size,StorageType,OperationType> cross(const Vector<Size,StorageType,OperationType>& vector) const;
|
||||||
/// Find the dot product between this vector and the vector passed as a parameter.
|
/// Find the dot product between this vector and the vector passed as a parameter.
|
||||||
OperationType dot(const Vector<Size,StorageType,OperationType>& rhs) const;
|
OperationType dot(const Vector<Size,StorageType,OperationType>& rhs) const;
|
||||||
/// Normalise the vector.
|
/// Normalise the vector.
|
||||||
void normalise(void);
|
void normalise(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Values for the vector
|
// Values for the vector
|
||||||
StorageType m_tElements[Size];
|
StorageType m_tElements[Size];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Non-member overloaded operators.
|
// Non-member overloaded operators.
|
||||||
/// Addition operator.
|
/// Addition operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator+(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
Vector<Size,StorageType,OperationType> operator+(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||||
/// Subtraction operator.
|
/// Subtraction operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator-(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
Vector<Size,StorageType,OperationType> operator-(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||||
/// Multiplication operator.
|
/// Multiplication operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||||
/// Division operator.
|
/// Division operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const Vector<Size,StorageType,OperationType>& rhs);
|
||||||
/// Multiplication operator.
|
/// Multiplication operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
Vector<Size,StorageType,OperationType> operator*(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
||||||
/// Division operator.
|
/// Division operator.
|
||||||
template <uint32_t Size,typename StorageType,typename OperationType>
|
template <uint32_t Size,typename StorageType,typename OperationType>
|
||||||
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
Vector<Size,StorageType,OperationType> operator/(const Vector<Size,StorageType,OperationType>& lhs, const StorageType& rhs);
|
||||||
/// Stream insertion operator.
|
/// Stream insertion operator.
|
||||||
template <uint32_t Size, typename StorageType,typename OperationType>
|
template <uint32_t Size, typename StorageType,typename OperationType>
|
||||||
std::ostream& operator<<(std::ostream& os, const Vector<Size,StorageType,OperationType>& vector);
|
std::ostream& operator<<(std::ostream& os, const Vector<Size,StorageType,OperationType>& vector);
|
||||||
|
|
||||||
//Some handy typedefs
|
//Some handy typedefs
|
||||||
|
|
||||||
/// A 2D Vector of floats.
|
/// A 2D Vector of floats.
|
||||||
typedef Vector<2,float,float> Vector2DFloat;
|
typedef Vector<2,float,float> Vector2DFloat;
|
||||||
/// A 2D Vector of doubles.
|
/// A 2D Vector of doubles.
|
||||||
typedef Vector<2,double,double> Vector2DDouble;
|
typedef Vector<2,double,double> Vector2DDouble;
|
||||||
/// A 2D Vector of signed 8-bit values.
|
/// A 2D Vector of signed 8-bit values.
|
||||||
typedef Vector<2,int8_t,int32_t> Vector2DInt8;
|
typedef Vector<2,int8_t,int32_t> Vector2DInt8;
|
||||||
/// A 2D Vector of unsigned 8-bit values.
|
/// A 2D Vector of unsigned 8-bit values.
|
||||||
typedef Vector<2,uint8_t,int32_t> Vector2DUint8;
|
typedef Vector<2,uint8_t,int32_t> Vector2DUint8;
|
||||||
/// A 2D Vector of signed 16-bit values.
|
/// A 2D Vector of signed 16-bit values.
|
||||||
typedef Vector<2,int16_t,int32_t> Vector2DInt16;
|
typedef Vector<2,int16_t,int32_t> Vector2DInt16;
|
||||||
/// A 2D Vector of unsigned 16-bit values.
|
/// A 2D Vector of unsigned 16-bit values.
|
||||||
typedef Vector<2,uint16_t,int32_t> Vector2DUint16;
|
typedef Vector<2,uint16_t,int32_t> Vector2DUint16;
|
||||||
/// A 2D Vector of signed 32-bit values.
|
/// A 2D Vector of signed 32-bit values.
|
||||||
typedef Vector<2,int32_t,int32_t> Vector2DInt32;
|
typedef Vector<2,int32_t,int32_t> Vector2DInt32;
|
||||||
/// A 2D Vector of unsigned 32-bit values.
|
/// A 2D Vector of unsigned 32-bit values.
|
||||||
typedef Vector<2,uint32_t,int32_t> Vector2DUint32;
|
typedef Vector<2,uint32_t,int32_t> Vector2DUint32;
|
||||||
|
|
||||||
/// A 3D Vector of floats.
|
/// A 3D Vector of floats.
|
||||||
typedef Vector<3,float,float> Vector3DFloat;
|
typedef Vector<3,float,float> Vector3DFloat;
|
||||||
/// A 3D Vector of doubles.
|
/// A 3D Vector of doubles.
|
||||||
typedef Vector<3,double,double> Vector3DDouble;
|
typedef Vector<3,double,double> Vector3DDouble;
|
||||||
/// A 3D Vector of signed 8-bit values.
|
/// A 3D Vector of signed 8-bit values.
|
||||||
typedef Vector<3,int8_t,int32_t> Vector3DInt8;
|
typedef Vector<3,int8_t,int32_t> Vector3DInt8;
|
||||||
/// A 3D Vector of unsigned 8-bit values.
|
/// A 3D Vector of unsigned 8-bit values.
|
||||||
typedef Vector<3,uint8_t,int32_t> Vector3DUint8;
|
typedef Vector<3,uint8_t,int32_t> Vector3DUint8;
|
||||||
/// A 3D Vector of signed 16-bit values.
|
/// A 3D Vector of signed 16-bit values.
|
||||||
typedef Vector<3,int16_t,int32_t> Vector3DInt16;
|
typedef Vector<3,int16_t,int32_t> Vector3DInt16;
|
||||||
/// A 3D Vector of unsigned 16-bit values.
|
/// A 3D Vector of unsigned 16-bit values.
|
||||||
typedef Vector<3,uint16_t,int32_t> Vector3DUint16;
|
typedef Vector<3,uint16_t,int32_t> Vector3DUint16;
|
||||||
/// A 3D Vector of signed 32-bit values.
|
/// A 3D Vector of signed 32-bit values.
|
||||||
typedef Vector<3,int32_t,int32_t> Vector3DInt32;
|
typedef Vector<3,int32_t,int32_t> Vector3DInt32;
|
||||||
/// A 3D Vector of unsigned 32-bit values.
|
/// A 3D Vector of unsigned 32-bit values.
|
||||||
typedef Vector<3,uint32_t,int32_t> Vector3DUint32;
|
typedef Vector<3,uint32_t,int32_t> Vector3DUint32;
|
||||||
|
|
||||||
/// A 4D Vector of floats.
|
/// A 4D Vector of floats.
|
||||||
typedef Vector<4,float,float> Vector4DFloat;
|
typedef Vector<4,float,float> Vector4DFloat;
|
||||||
/// A 4D Vector of doubles.
|
/// A 4D Vector of doubles.
|
||||||
typedef Vector<4,double,double> Vector4DDouble;
|
typedef Vector<4,double,double> Vector4DDouble;
|
||||||
/// A 4D Vector of signed 8-bit values.
|
/// A 4D Vector of signed 8-bit values.
|
||||||
typedef Vector<4,int8_t,int32_t> Vector4DInt8;
|
typedef Vector<4,int8_t,int32_t> Vector4DInt8;
|
||||||
/// A 4D Vector of unsigned 8-bit values.
|
/// A 4D Vector of unsigned 8-bit values.
|
||||||
typedef Vector<4,uint8_t,int32_t> Vector4DUint8;
|
typedef Vector<4,uint8_t,int32_t> Vector4DUint8;
|
||||||
/// A 4D Vector of signed 16-bit values.
|
/// A 4D Vector of signed 16-bit values.
|
||||||
typedef Vector<4,int16_t,int32_t> Vector4DInt16;
|
typedef Vector<4,int16_t,int32_t> Vector4DInt16;
|
||||||
/// A 4D Vector of unsigned 16-bit values.
|
/// A 4D Vector of unsigned 16-bit values.
|
||||||
typedef Vector<4,uint16_t,int32_t> Vector4DUint16;
|
typedef Vector<4,uint16_t,int32_t> Vector4DUint16;
|
||||||
/// A 4D Vector of signed 32-bit values.
|
/// A 4D Vector of signed 32-bit values.
|
||||||
typedef Vector<4,int32_t,int32_t> Vector4DInt32;
|
typedef Vector<4,int32_t,int32_t> Vector4DInt32;
|
||||||
/// A 4D Vector of unsigned 32-bit values.
|
/// A 4D Vector of unsigned 32-bit values.
|
||||||
typedef Vector<4,uint32_t,int32_t> Vector4DUint32;
|
typedef Vector<4,uint32_t,int32_t> Vector4DUint32;
|
||||||
|
|
||||||
|
|
||||||
}//namespace PolyVox
|
}//namespace PolyVox
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
struct hash<PolyVox::Vector3DInt32>
|
struct hash<PolyVox::Vector3DInt32>
|
||||||
{
|
{
|
||||||
std::size_t operator()(const PolyVox::Vector3DInt32& vec) const
|
std::size_t operator()(const PolyVox::Vector3DInt32& vec) const
|
||||||
{
|
{
|
||||||
return ((vec.getX() & 0xFF)) | ((vec.getY() & 0xFF) << 8) | ((vec.getZ() & 0xFF) << 16);
|
return ((vec.getX() & 0xFF)) | ((vec.getY() & 0xFF) << 8) | ((vec.getZ() & 0xFF) << 16);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "PolyVoxCore/Vector.inl"
|
#include "PolyVoxCore/Vector.inl"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,57 +1,57 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_VolumeResampler_H__
|
#ifndef __PolyVox_VolumeResampler_H__
|
||||||
#define __PolyVox_VolumeResampler_H__
|
#define __PolyVox_VolumeResampler_H__
|
||||||
|
|
||||||
#include "PolyVoxCore/Region.h"
|
#include "PolyVoxCore/Region.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template< typename SrcVolumeType, typename DstVolumeType>
|
template< typename SrcVolumeType, typename DstVolumeType>
|
||||||
class VolumeResampler
|
class VolumeResampler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VolumeResampler(SrcVolumeType* pVolSrc, const Region& regSrc, DstVolumeType* pVolDst, const Region& regDst);
|
VolumeResampler(SrcVolumeType* pVolSrc, const Region& regSrc, DstVolumeType* pVolDst, const Region& regDst);
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resampleSameSize();
|
void resampleSameSize();
|
||||||
void resampleArbitrary();
|
void resampleArbitrary();
|
||||||
|
|
||||||
//Source data
|
//Source data
|
||||||
SrcVolumeType* m_pVolSrc;
|
SrcVolumeType* m_pVolSrc;
|
||||||
Region m_regSrc;
|
Region m_regSrc;
|
||||||
|
|
||||||
//Destination data
|
//Destination data
|
||||||
DstVolumeType* m_pVolDst;
|
DstVolumeType* m_pVolDst;
|
||||||
Region m_regDst;
|
Region m_regDst;
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace PolyVox
|
}//namespace PolyVox
|
||||||
|
|
||||||
#include "PolyVoxCore/VolumeResampler.inl"
|
#include "PolyVoxCore/VolumeResampler.inl"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,138 +1,138 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/Interpolation.h"
|
#include "PolyVoxCore/Interpolation.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* \param pVolSrc
|
* \param pVolSrc
|
||||||
* \param regSrc
|
* \param regSrc
|
||||||
* \param[out] pVolDst
|
* \param[out] pVolDst
|
||||||
* \param regDst
|
* \param regDst
|
||||||
*/
|
*/
|
||||||
template< typename SrcVolumeType, typename DstVolumeType>
|
template< typename SrcVolumeType, typename DstVolumeType>
|
||||||
VolumeResampler<SrcVolumeType, DstVolumeType>::VolumeResampler(SrcVolumeType* pVolSrc, const Region ®Src, DstVolumeType* pVolDst, const Region& regDst)
|
VolumeResampler<SrcVolumeType, DstVolumeType>::VolumeResampler(SrcVolumeType* pVolSrc, const Region ®Src, DstVolumeType* pVolDst, const Region& regDst)
|
||||||
:m_pVolSrc(pVolSrc)
|
:m_pVolSrc(pVolSrc)
|
||||||
,m_regSrc(regSrc)
|
,m_regSrc(regSrc)
|
||||||
,m_pVolDst(pVolDst)
|
,m_pVolDst(pVolDst)
|
||||||
,m_regDst(regDst)
|
,m_regDst(regDst)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SrcVolumeType, typename DstVolumeType>
|
template< typename SrcVolumeType, typename DstVolumeType>
|
||||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::execute()
|
void VolumeResampler<SrcVolumeType, DstVolumeType>::execute()
|
||||||
{
|
{
|
||||||
int32_t uSrcWidth = m_regSrc.getUpperX() - m_regSrc.getLowerX() + 1;
|
int32_t uSrcWidth = m_regSrc.getUpperX() - m_regSrc.getLowerX() + 1;
|
||||||
int32_t uSrcHeight = m_regSrc.getUpperY() - m_regSrc.getLowerY() + 1;
|
int32_t uSrcHeight = m_regSrc.getUpperY() - m_regSrc.getLowerY() + 1;
|
||||||
int32_t uSrcDepth = m_regSrc.getUpperZ() - m_regSrc.getLowerZ() + 1;
|
int32_t uSrcDepth = m_regSrc.getUpperZ() - m_regSrc.getLowerZ() + 1;
|
||||||
|
|
||||||
int32_t uDstWidth = m_regDst.getUpperX() - m_regDst.getLowerX() + 1;
|
int32_t uDstWidth = m_regDst.getUpperX() - m_regDst.getLowerX() + 1;
|
||||||
int32_t uDstHeight = m_regDst.getUpperY() - m_regDst.getLowerY() + 1;
|
int32_t uDstHeight = m_regDst.getUpperY() - m_regDst.getLowerY() + 1;
|
||||||
int32_t uDstDepth = m_regDst.getUpperZ() - m_regDst.getLowerZ() + 1;
|
int32_t uDstDepth = m_regDst.getUpperZ() - m_regDst.getLowerZ() + 1;
|
||||||
|
|
||||||
if((uSrcWidth == uDstWidth) && (uSrcHeight == uDstHeight) && (uSrcDepth == uDstDepth))
|
if((uSrcWidth == uDstWidth) && (uSrcHeight == uDstHeight) && (uSrcDepth == uDstDepth))
|
||||||
{
|
{
|
||||||
resampleSameSize();
|
resampleSameSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resampleArbitrary();
|
resampleArbitrary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SrcVolumeType, typename DstVolumeType>
|
template< typename SrcVolumeType, typename DstVolumeType>
|
||||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleSameSize()
|
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleSameSize()
|
||||||
{
|
{
|
||||||
for(int32_t sz = m_regSrc.getLowerZ(), dz = m_regDst.getLowerZ(); dz <= m_regDst.getUpperZ(); sz++, dz++)
|
for(int32_t sz = m_regSrc.getLowerZ(), dz = m_regDst.getLowerZ(); dz <= m_regDst.getUpperZ(); sz++, dz++)
|
||||||
{
|
{
|
||||||
for(int32_t sy = m_regSrc.getLowerY(), dy = m_regDst.getLowerY(); dy <= m_regDst.getUpperY(); sy++, dy++)
|
for(int32_t sy = m_regSrc.getLowerY(), dy = m_regDst.getLowerY(); dy <= m_regDst.getUpperY(); sy++, dy++)
|
||||||
{
|
{
|
||||||
for(int32_t sx = m_regSrc.getLowerX(), dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); sx++,dx++)
|
for(int32_t sx = m_regSrc.getLowerX(), dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); sx++,dx++)
|
||||||
{
|
{
|
||||||
const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxel(sx,sy,sz, WrapModes::AssumeValid); // FIXME use templatised version of getVoxel(), but watch out for Linux compile issues.
|
const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxel(sx,sy,sz, WrapModes::AssumeValid); // FIXME use templatised version of getVoxel(), but watch out for Linux compile issues.
|
||||||
const typename DstVolumeType::VoxelType& tDstVoxel = static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel);
|
const typename DstVolumeType::VoxelType& tDstVoxel = static_cast<typename DstVolumeType::VoxelType>(tSrcVoxel);
|
||||||
m_pVolDst->setVoxelAt(dx,dy,dz,tDstVoxel);
|
m_pVolDst->setVoxelAt(dx,dy,dz,tDstVoxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename SrcVolumeType, typename DstVolumeType>
|
template< typename SrcVolumeType, typename DstVolumeType>
|
||||||
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleArbitrary()
|
void VolumeResampler<SrcVolumeType, DstVolumeType>::resampleArbitrary()
|
||||||
{
|
{
|
||||||
float srcWidth = m_regSrc.getWidthInCells();
|
float srcWidth = m_regSrc.getWidthInCells();
|
||||||
float srcHeight = m_regSrc.getHeightInCells();
|
float srcHeight = m_regSrc.getHeightInCells();
|
||||||
float srcDepth = m_regSrc.getDepthInCells();
|
float srcDepth = m_regSrc.getDepthInCells();
|
||||||
|
|
||||||
float dstWidth = m_regDst.getWidthInCells();
|
float dstWidth = m_regDst.getWidthInCells();
|
||||||
float dstHeight = m_regDst.getHeightInCells();
|
float dstHeight = m_regDst.getHeightInCells();
|
||||||
float dstDepth = m_regDst.getDepthInCells();
|
float dstDepth = m_regDst.getDepthInCells();
|
||||||
|
|
||||||
float fScaleX = srcWidth / dstWidth;
|
float fScaleX = srcWidth / dstWidth;
|
||||||
float fScaleY = srcHeight / dstHeight;
|
float fScaleY = srcHeight / dstHeight;
|
||||||
float fScaleZ = srcDepth / dstDepth;
|
float fScaleZ = srcDepth / dstDepth;
|
||||||
|
|
||||||
typename SrcVolumeType::Sampler sampler(m_pVolSrc);
|
typename SrcVolumeType::Sampler sampler(m_pVolSrc);
|
||||||
|
|
||||||
for(int32_t dz = m_regDst.getLowerZ(); dz <= m_regDst.getUpperZ(); dz++)
|
for(int32_t dz = m_regDst.getLowerZ(); dz <= m_regDst.getUpperZ(); dz++)
|
||||||
{
|
{
|
||||||
for(int32_t dy = m_regDst.getLowerY(); dy <= m_regDst.getUpperY(); dy++)
|
for(int32_t dy = m_regDst.getLowerY(); dy <= m_regDst.getUpperY(); dy++)
|
||||||
{
|
{
|
||||||
for(int32_t dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); dx++)
|
for(int32_t dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); dx++)
|
||||||
{
|
{
|
||||||
float sx = (dx - m_regDst.getLowerX()) * fScaleX;
|
float sx = (dx - m_regDst.getLowerX()) * fScaleX;
|
||||||
float sy = (dy - m_regDst.getLowerY()) * fScaleY;
|
float sy = (dy - m_regDst.getLowerY()) * fScaleY;
|
||||||
float sz = (dz - m_regDst.getLowerZ()) * fScaleZ;
|
float sz = (dz - m_regDst.getLowerZ()) * fScaleZ;
|
||||||
|
|
||||||
sx += m_regSrc.getLowerX();
|
sx += m_regSrc.getLowerX();
|
||||||
sy += m_regSrc.getLowerY();
|
sy += m_regSrc.getLowerY();
|
||||||
sz += m_regSrc.getLowerZ();
|
sz += m_regSrc.getLowerZ();
|
||||||
|
|
||||||
sampler.setPosition(sx,sy,sz);
|
sampler.setPosition(sx,sy,sz);
|
||||||
const typename SrcVolumeType::VoxelType& voxel000 = sampler.peekVoxel0px0py0pz();
|
const typename SrcVolumeType::VoxelType& voxel000 = sampler.peekVoxel0px0py0pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel001 = sampler.peekVoxel0px0py1pz();
|
const typename SrcVolumeType::VoxelType& voxel001 = sampler.peekVoxel0px0py1pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel010 = sampler.peekVoxel0px1py0pz();
|
const typename SrcVolumeType::VoxelType& voxel010 = sampler.peekVoxel0px1py0pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel011 = sampler.peekVoxel0px1py1pz();
|
const typename SrcVolumeType::VoxelType& voxel011 = sampler.peekVoxel0px1py1pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel100 = sampler.peekVoxel1px0py0pz();
|
const typename SrcVolumeType::VoxelType& voxel100 = sampler.peekVoxel1px0py0pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel101 = sampler.peekVoxel1px0py1pz();
|
const typename SrcVolumeType::VoxelType& voxel101 = sampler.peekVoxel1px0py1pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel110 = sampler.peekVoxel1px1py0pz();
|
const typename SrcVolumeType::VoxelType& voxel110 = sampler.peekVoxel1px1py0pz();
|
||||||
const typename SrcVolumeType::VoxelType& voxel111 = sampler.peekVoxel1px1py1pz();
|
const typename SrcVolumeType::VoxelType& voxel111 = sampler.peekVoxel1px1py1pz();
|
||||||
|
|
||||||
//FIXME - should accept all float parameters, but GCC complains?
|
//FIXME - should accept all float parameters, but GCC complains?
|
||||||
double dummy;
|
double dummy;
|
||||||
sx = modf(sx, &dummy);
|
sx = modf(sx, &dummy);
|
||||||
sy = modf(sy, &dummy);
|
sy = modf(sy, &dummy);
|
||||||
sz = modf(sz, &dummy);
|
sz = modf(sz, &dummy);
|
||||||
|
|
||||||
typename SrcVolumeType::VoxelType tInterpolatedValue = trilerp<float>(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,sx,sy,sz);
|
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);
|
typename DstVolumeType::VoxelType result = static_cast<typename DstVolumeType::VoxelType>(tInterpolatedValue);
|
||||||
m_pVolDst->setVoxelAt(dx,dy,dz,result);
|
m_pVolDst->setVoxelAt(dx,dy,dz,result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef __PolyVox_VoxelFilters_H__
|
#ifndef __PolyVox_VoxelFilters_H__
|
||||||
#define __PolyVox_VoxelFilters_H__
|
#define __PolyVox_VoxelFilters_H__
|
||||||
|
|
||||||
#include "Impl/TypeDef.h"
|
#include "Impl/TypeDef.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
template< typename VolumeType >
|
template< typename VolumeType >
|
||||||
float computeSmoothedVoxel(typename VolumeType::Sampler& volIter);
|
float computeSmoothedVoxel(typename VolumeType::Sampler& volIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "PolyVoxCore/VoxelFilters.inl"
|
#include "PolyVoxCore/VoxelFilters.inl"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,67 +1,67 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
Copyright (c) 2005-2009 David Williams
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
including commercial applications, and to alter it and redistribute it
|
including commercial applications, and to alter it and redistribute it
|
||||||
freely, subject to the following restrictions:
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
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
|
claim that you wrote the original software. If you use this software
|
||||||
in a product, an acknowledgment in the product documentation would be
|
in a product, an acknowledgment in the product documentation would be
|
||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
3. This notice may not be removed or altered from any source
|
||||||
distribution.
|
distribution.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "PolyVoxCore/AStarPathfinder.h"
|
#include "PolyVoxCore/AStarPathfinder.h"
|
||||||
|
|
||||||
using namespace PolyVox;
|
using namespace PolyVox;
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
const Vector3DInt32 arrayPathfinderFaces[6] =
|
const Vector3DInt32 arrayPathfinderFaces[6] =
|
||||||
{
|
{
|
||||||
Vector3DInt32(0, 0, -1),
|
Vector3DInt32(0, 0, -1),
|
||||||
Vector3DInt32(0, 0, +1),
|
Vector3DInt32(0, 0, +1),
|
||||||
Vector3DInt32(0, -1, 0),
|
Vector3DInt32(0, -1, 0),
|
||||||
Vector3DInt32(0, +1, 0),
|
Vector3DInt32(0, +1, 0),
|
||||||
Vector3DInt32(-1, 0, 0),
|
Vector3DInt32(-1, 0, 0),
|
||||||
Vector3DInt32(+1, 0, 0)
|
Vector3DInt32(+1, 0, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector3DInt32 arrayPathfinderEdges[12] =
|
const Vector3DInt32 arrayPathfinderEdges[12] =
|
||||||
{
|
{
|
||||||
Vector3DInt32(0, -1, -1),
|
Vector3DInt32(0, -1, -1),
|
||||||
Vector3DInt32(0, -1, +1),
|
Vector3DInt32(0, -1, +1),
|
||||||
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, 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),
|
||||||
Vector3DInt32(+1, -1, 0),
|
Vector3DInt32(+1, -1, 0),
|
||||||
Vector3DInt32(+1, +1, 0)
|
Vector3DInt32(+1, +1, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector3DInt32 arrayPathfinderCorners[8] =
|
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),
|
||||||
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)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,92 +1,92 @@
|
|||||||
# Copyright (c) 2008-2012 Matt Williams
|
# Copyright (c) 2008-2012 Matt Williams
|
||||||
# Copyright (c) 2008-2012 David Williams
|
# Copyright (c) 2008-2012 David Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
PROJECT(PolyVoxUtil)
|
PROJECT(PolyVoxUtil)
|
||||||
|
|
||||||
#Projects source files
|
#Projects source files
|
||||||
SET(UTIL_SRC_FILES
|
SET(UTIL_SRC_FILES
|
||||||
source/Dummy.cpp
|
source/Dummy.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
#Projects headers files
|
#Projects headers files
|
||||||
SET(UTIL_INC_FILES
|
SET(UTIL_INC_FILES
|
||||||
#Nothing here at the moment...
|
#Nothing here at the moment...
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll
|
ADD_DEFINITIONS(-DPOLYVOX_SHARED_EXPORTS) #Export symbols in the .dll
|
||||||
|
|
||||||
#"Sources" and "Headers" are the group names in Visual Studio.
|
#"Sources" and "Headers" are the group names in Visual Studio.
|
||||||
#They may have other uses too...
|
#They may have other uses too...
|
||||||
SOURCE_GROUP("Source Files" FILES ${UTIL_SRC_FILES})
|
SOURCE_GROUP("Source Files" FILES ${UTIL_SRC_FILES})
|
||||||
SOURCE_GROUP("Header Files" FILES ${UTIL_INC_FILES})
|
SOURCE_GROUP("Header Files" FILES ${UTIL_INC_FILES})
|
||||||
|
|
||||||
#Tell CMake the paths
|
#Tell CMake the paths
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include ${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include)
|
||||||
#There has to be a better way!
|
#There has to be a better way!
|
||||||
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}/debug ${PolyVoxCore_BINARY_DIR}/release ${PolyVoxCore_BINARY_DIR})
|
LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR}/debug ${PolyVoxCore_BINARY_DIR}/release ${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#Util
|
#Util
|
||||||
#Build
|
#Build
|
||||||
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
IF(LIBRARY_TYPE STREQUAL "STATIC")
|
||||||
ADD_LIBRARY(PolyVoxUtil STATIC ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
ADD_LIBRARY(PolyVoxUtil STATIC ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
SET_TARGET_PROPERTIES(PolyVoxCore PROPERTIES COMPILE_FLAGS -fPIC)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
IF(LIBRARY_TYPE STREQUAL "DYNAMIC")
|
||||||
ADD_LIBRARY(PolyVoxUtil SHARED ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
ADD_LIBRARY(PolyVoxUtil SHARED ${UTIL_SRC_FILES} ${UTIL_INC_FILES})
|
||||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "-DPOLYVOX_SHARED_EXPORTS")
|
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "-DPOLYVOX_SHARED_EXPORTS")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
SET_PROPERTY(TARGET PolyVoxUtil PROPERTY FOLDER "Library")
|
SET_PROPERTY(TARGET PolyVoxUtil PROPERTY FOLDER "Library")
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(PolyVoxUtil PolyVoxCore)
|
TARGET_LINK_LIBRARIES(PolyVoxUtil PolyVoxCore)
|
||||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES VERSION ${POLYVOX_VERSION} SOVERSION ${POLYVOX_VERSION_MAJOR})
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "/W4 /wd4251 /wd4127") #Disable warning on STL exports
|
SET_TARGET_PROPERTIES(PolyVoxUtil PROPERTIES COMPILE_FLAGS "/W4 /wd4251 /wd4127") #Disable warning on STL exports
|
||||||
ENDIF(MSVC)
|
ENDIF(MSVC)
|
||||||
|
|
||||||
#Install
|
#Install
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
INSTALL(TARGETS PolyVoxUtil
|
INSTALL(TARGETS PolyVoxUtil
|
||||||
RUNTIME DESTINATION PolyVoxUtil/bin COMPONENT library
|
RUNTIME DESTINATION PolyVoxUtil/bin COMPONENT library
|
||||||
LIBRARY DESTINATION PolyVoxUtil/lib COMPONENT library
|
LIBRARY DESTINATION PolyVoxUtil/lib COMPONENT library
|
||||||
ARCHIVE DESTINATION PolyVoxUtil/lib COMPONENT library
|
ARCHIVE DESTINATION PolyVoxUtil/lib COMPONENT library
|
||||||
)
|
)
|
||||||
|
|
||||||
#Install the util header files.
|
#Install the util header files.
|
||||||
INSTALL(DIRECTORY include DESTINATION PolyVoxUtil COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
INSTALL(DIRECTORY include DESTINATION PolyVoxUtil COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
||||||
|
|
||||||
#On windows, we also install the debug information. It's unfortunate that we have to hard-code
|
#On windows, we also install the debug information. It's unfortunate that we have to hard-code
|
||||||
#the 'Debug' part of the path, but CMake doesn't seem to provide a way around this. The best I
|
#the 'Debug' part of the path, but CMake doesn't seem to provide a way around this. The best I
|
||||||
#found was: http://www.cmake.org/pipermail/cmake/2007-October/016924.html (and it is a bit ugly).
|
#found was: http://www.cmake.org/pipermail/cmake/2007-October/016924.html (and it is a bit ugly).
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/PolyVoxUtil.pdb DESTINATION PolyVoxUtil/lib CONFIGURATIONS Debug)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/PolyVoxUtil.pdb DESTINATION PolyVoxUtil/lib CONFIGURATIONS Debug)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/PolyVoxUtil.pdb DESTINATION PolyVoxUtil/lib CONFIGURATIONS RelWithDebInfo)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/PolyVoxUtil.pdb DESTINATION PolyVoxUtil/lib CONFIGURATIONS RelWithDebInfo)
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
INSTALL(TARGETS PolyVoxUtil
|
INSTALL(TARGETS PolyVoxUtil
|
||||||
RUNTIME DESTINATION bin COMPONENT library
|
RUNTIME DESTINATION bin COMPONENT library
|
||||||
LIBRARY DESTINATION lib COMPONENT library
|
LIBRARY DESTINATION lib COMPONENT library
|
||||||
ARCHIVE DESTINATION lib COMPONENT library
|
ARCHIVE DESTINATION lib COMPONENT library
|
||||||
)
|
)
|
||||||
|
|
||||||
#Install the util header files.
|
#Install the util header files.
|
||||||
INSTALL(DIRECTORY include/ DESTINATION include/PolyVoxUtil COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
INSTALL(DIRECTORY include/ DESTINATION include/PolyVoxUtil COMPONENT development PATTERN "*.svn*" EXCLUDE)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
class POLYVOX_API DummyClass
|
class POLYVOX_API DummyClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int getx(void);
|
int getx(void);
|
||||||
int x;
|
int x;
|
||||||
};
|
};
|
||||||
|
|
||||||
int DummyClass::getx(void)
|
int DummyClass::getx(void)
|
||||||
{
|
{
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
%module Array
|
%module Array
|
||||||
%{
|
%{
|
||||||
#include "PolyVoxImpl\SubArray.h"
|
#include "PolyVoxImpl\SubArray.h"
|
||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "PolyVoxImpl\SubArray.h"
|
%include "PolyVoxImpl\SubArray.h"
|
||||||
%include "Array.h"
|
%include "Array.h"
|
||||||
|
|
||||||
%template(Array3IndexAndMaterial) PolyVox::Array<3, PolyVox::IndexAndMaterial>;
|
%template(Array3IndexAndMaterial) PolyVox::Array<3, PolyVox::IndexAndMaterial>;
|
||||||
|
@ -1,65 +1,65 @@
|
|||||||
# Copyright (c) 2009-2013 Matt Williams
|
# Copyright (c) 2009-2013 Matt Williams
|
||||||
#
|
#
|
||||||
# This software is provided 'as-is', without any express or implied
|
# This software is provided 'as-is', without any express or implied
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
# warranty. In no event will the authors be held liable for any damages
|
||||||
# arising from the use of this software.
|
# arising from the use of this software.
|
||||||
#
|
#
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
# Permission is granted to anyone to use this software for any purpose,
|
||||||
# including commercial applications, and to alter it and redistribute it
|
# including commercial applications, and to alter it and redistribute it
|
||||||
# freely, subject to the following restrictions:
|
# freely, subject to the following restrictions:
|
||||||
#
|
#
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
# 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
|
# claim that you wrote the original software. If you use this software
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
# in a product, an acknowledgment in the product documentation would be
|
||||||
# appreciated but is not required.
|
# appreciated but is not required.
|
||||||
#
|
#
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
#
|
#
|
||||||
# 3. This notice may not be removed or altered from any source
|
# 3. This notice may not be removed or altered from any source
|
||||||
# distribution.
|
# distribution.
|
||||||
|
|
||||||
option(ENABLE_BINDINGS "Build bindings" ON)
|
option(ENABLE_BINDINGS "Build bindings" ON)
|
||||||
if(ENABLE_BINDINGS)
|
if(ENABLE_BINDINGS)
|
||||||
find_package(SWIG)
|
find_package(SWIG)
|
||||||
mark_as_advanced(SWIG_DIR SWIG_VERSION)
|
mark_as_advanced(SWIG_DIR SWIG_VERSION)
|
||||||
find_package(PythonLibs 3)
|
find_package(PythonLibs 3)
|
||||||
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
if(CMAKE_VERSION VERSION_LESS "2.8.6")
|
||||||
set_package_info(SWIG "Bindings generator" http://www.swig.org)
|
set_package_info(SWIG "Bindings generator" http://www.swig.org)
|
||||||
set_package_info(PythonLibs "Programming language" http://www.python.org)
|
set_package_info(PythonLibs "Programming language" http://www.python.org)
|
||||||
else()
|
else()
|
||||||
set_package_properties(SWIG PROPERTIES DESCRIPTION "Bindings generator" URL http://www.swig.org)
|
set_package_properties(SWIG PROPERTIES DESCRIPTION "Bindings generator" URL http://www.swig.org)
|
||||||
set_package_properties(PythonLibs PROPERTIES DESCRIPTION "Programming language" URL http://www.python.org)
|
set_package_properties(PythonLibs PROPERTIES DESCRIPTION "Programming language" URL http://www.python.org)
|
||||||
endif()
|
endif()
|
||||||
if(SWIG_FOUND)
|
if(SWIG_FOUND)
|
||||||
set(BUILD_BINDINGS ON CACHE BOOL "Will the bindings be built" FORCE)
|
set(BUILD_BINDINGS ON CACHE BOOL "Will the bindings be built" FORCE)
|
||||||
include(${SWIG_USE_FILE})
|
include(${SWIG_USE_FILE})
|
||||||
|
|
||||||
set(CMAKE_SWIG_FLAGS "")
|
set(CMAKE_SWIG_FLAGS "")
|
||||||
set_source_files_properties(PolyVoxCore.i PROPERTIES CPLUSPLUS ON)
|
set_source_files_properties(PolyVoxCore.i PROPERTIES CPLUSPLUS ON)
|
||||||
|
|
||||||
include_directories(${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include/PolyVoxCore)
|
include_directories(${PolyVoxCore_BINARY_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include ${PolyVoxCore_SOURCE_DIR}/include/PolyVoxCore)
|
||||||
if(PYTHONLIBS_FOUND)
|
if(PYTHONLIBS_FOUND)
|
||||||
include_directories(${PYTHON_INCLUDE_PATH})
|
include_directories(${PYTHON_INCLUDE_PATH})
|
||||||
link_directories(${PolyVoxCore_BINARY_DIR})
|
link_directories(${PolyVoxCore_BINARY_DIR})
|
||||||
|
|
||||||
#set_source_files_properties(PolyVoxCore.i PROPERTIES SWIG_FLAGS "-builtin")
|
#set_source_files_properties(PolyVoxCore.i PROPERTIES SWIG_FLAGS "-builtin")
|
||||||
set(SWIG_MODULE_PolyVoxCorePython_EXTRA_FLAGS "-py3")
|
set(SWIG_MODULE_PolyVoxCorePython_EXTRA_FLAGS "-py3")
|
||||||
swig_add_module(PolyVoxCorePython python PolyVoxCore.i)
|
swig_add_module(PolyVoxCorePython python PolyVoxCore.i)
|
||||||
swig_link_libraries(PolyVoxCorePython ${PYTHON_LIBRARIES} PolyVoxCore)
|
swig_link_libraries(PolyVoxCorePython ${PYTHON_LIBRARIES} PolyVoxCore)
|
||||||
set_target_properties(${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTIES OUTPUT_NAME _PolyVoxCore)
|
set_target_properties(${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTIES OUTPUT_NAME _PolyVoxCore)
|
||||||
#set_target_properties(${SWIG_MODULE_PolyVoxCore_REAL_NAME} PROPERTIES SUFFIX ".pyd")
|
#set_target_properties(${SWIG_MODULE_PolyVoxCore_REAL_NAME} PROPERTIES SUFFIX ".pyd")
|
||||||
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTY FOLDER "Bindings")
|
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCorePython_REAL_NAME} PROPERTY FOLDER "Bindings")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SWIG_MODULE_PolyVoxCoreCSharp_EXTRA_FLAGS "-dllimport;PolyVoxCoreCSharp") #This _should_ be inside UseSWIG.cmake - http://www.cmake.org/Bug/view.php?id=13814
|
set(SWIG_MODULE_PolyVoxCoreCSharp_EXTRA_FLAGS "-dllimport;PolyVoxCoreCSharp") #This _should_ be inside UseSWIG.cmake - http://www.cmake.org/Bug/view.php?id=13814
|
||||||
swig_add_module(PolyVoxCoreCSharp csharp PolyVoxCore.i)
|
swig_add_module(PolyVoxCoreCSharp csharp PolyVoxCore.i)
|
||||||
swig_link_libraries(PolyVoxCoreCSharp PolyVoxCore)
|
swig_link_libraries(PolyVoxCoreCSharp PolyVoxCore)
|
||||||
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCoreCSharp_REAL_NAME} PROPERTY FOLDER "Bindings")
|
SET_PROPERTY(TARGET ${SWIG_MODULE_PolyVoxCoreCSharp_REAL_NAME} PROPERTY FOLDER "Bindings")
|
||||||
else()
|
else()
|
||||||
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
set(BUILD_BINDINGS OFF CACHE BOOL "Will the bindings be built" FORCE)
|
||||||
endif()
|
endif()
|
||||||
mark_as_advanced(FORCE BUILD_BINDINGS)
|
mark_as_advanced(FORCE BUILD_BINDINGS)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
%module CubicSurfaceExtractor
|
%module CubicSurfaceExtractor
|
||||||
%{
|
%{
|
||||||
#include "CubicSurfaceExtractor.h"
|
#include "CubicSurfaceExtractor.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "CubicSurfaceExtractor.h"
|
%include "CubicSurfaceExtractor.h"
|
||||||
|
|
||||||
%template(CubicSurfaceExtractorSimpleVolumeuint8) PolyVox::CubicSurfaceExtractor<PolyVox::SimpleVolume<uint8_t>, PolyVox::DefaultIsQuadNeeded<uint8_t> >;
|
%template(CubicSurfaceExtractorSimpleVolumeuint8) PolyVox::CubicSurfaceExtractor<PolyVox::SimpleVolume<uint8_t>, PolyVox::DefaultIsQuadNeeded<uint8_t> >;
|
||||||
//EXTRACTORS(CubicSurfaceExtractor)
|
//EXTRACTORS(CubicSurfaceExtractor)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
%module CubicSurfaceExtractorWithNormals
|
%module CubicSurfaceExtractorWithNormals
|
||||||
%{
|
%{
|
||||||
#include "CubicSurfaceExtractorWithNormals.h"
|
#include "CubicSurfaceExtractorWithNormals.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "CubicSurfaceExtractorWithNormals.h"
|
%include "CubicSurfaceExtractorWithNormals.h"
|
||||||
|
|
||||||
%template(CubicSurfaceExtractorWithNormalsSimpleVolumeuint8) PolyVox::CubicSurfaceExtractorWithNormals<PolyVox::SimpleVolume<uint8_t>, PolyVox::DefaultIsQuadNeeded<uint8_t> >;
|
%template(CubicSurfaceExtractorWithNormalsSimpleVolumeuint8) PolyVox::CubicSurfaceExtractorWithNormals<PolyVox::SimpleVolume<uint8_t>, PolyVox::DefaultIsQuadNeeded<uint8_t> >;
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
|
|
||||||
%include "MeshDecimator.h"
|
%include "MeshDecimator.h"
|
||||||
|
|
||||||
%template(MeshDecimatorMaterial8) PolyVox::MeshDecimator<PolyVox::Material8>;
|
%template(MeshDecimatorMaterial8) PolyVox::MeshDecimator<PolyVox::Material8>;
|
||||||
%template(MeshDecimatorDensity8) PolyVox::MeshDecimator<PolyVox::Density8>;
|
%template(MeshDecimatorDensity8) PolyVox::MeshDecimator<PolyVox::Density8>;
|
@ -1,98 +1,98 @@
|
|||||||
%module PolyVoxCore
|
%module PolyVoxCore
|
||||||
|
|
||||||
#define POLYVOX_API
|
#define POLYVOX_API
|
||||||
%include "Impl/TypeDef.h"
|
%include "Impl/TypeDef.h"
|
||||||
#define __attribute__(x) //Silence DEPRECATED errors
|
#define __attribute__(x) //Silence DEPRECATED errors
|
||||||
|
|
||||||
//This macro allows us to use Python properties on our classes
|
//This macro allows us to use Python properties on our classes
|
||||||
%define PROPERTY(type,name,getter,setter)
|
%define PROPERTY(type,name,getter,setter)
|
||||||
%extend type {
|
%extend type {
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
__swig_getmethods__["name"] = getter
|
__swig_getmethods__["name"] = getter
|
||||||
__swig_setmethods__["name"] = setter
|
__swig_setmethods__["name"] = setter
|
||||||
if _newclass: name = property(getter, setter)
|
if _newclass: name = property(getter, setter)
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Put this in an %extend section to wrap operator<< as __str__
|
//Put this in an %extend section to wrap operator<< as __str__
|
||||||
%define STR()
|
%define STR()
|
||||||
const char* __str__() {
|
const char* __str__() {
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << *$self;
|
out << *$self;
|
||||||
return out.str().c_str();
|
return out.str().c_str();
|
||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Centralise this to avoid repeating ourselves
|
//Centralise this to avoid repeating ourselves
|
||||||
//This macro will be called in the volume interface files to define the various volume types.
|
//This macro will be called in the volume interface files to define the various volume types.
|
||||||
%define VOLUMETYPES(class)
|
%define VOLUMETYPES(class)
|
||||||
%template(class ## int8) PolyVox::class<int8_t>;
|
%template(class ## int8) PolyVox::class<int8_t>;
|
||||||
%template(class ## int16) PolyVox::class<int16_t>;
|
%template(class ## int16) PolyVox::class<int16_t>;
|
||||||
%template(class ## int32) PolyVox::class<int32_t>;
|
%template(class ## int32) PolyVox::class<int32_t>;
|
||||||
%template(class ## uint8) PolyVox::class<uint8_t>;
|
%template(class ## uint8) PolyVox::class<uint8_t>;
|
||||||
%template(class ## uint16) PolyVox::class<uint16_t>;
|
%template(class ## uint16) PolyVox::class<uint16_t>;
|
||||||
%template(class ## uint32) PolyVox::class<uint32_t>;
|
%template(class ## uint32) PolyVox::class<uint32_t>;
|
||||||
%template(class ## float) PolyVox::class<float>;
|
%template(class ## float) PolyVox::class<float>;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Template based on voxel type
|
//Template based on voxel type
|
||||||
%define EXTRACTOR(class, volumetype)
|
%define EXTRACTOR(class, volumetype)
|
||||||
%template(class ## volumetype ## int8) PolyVox::class<PolyVox::volumetype<int8_t> >;
|
%template(class ## volumetype ## int8) PolyVox::class<PolyVox::volumetype<int8_t> >;
|
||||||
%template(class ## volumetype ## int16) PolyVox::class<PolyVox::volumetype<int16_t> >;
|
%template(class ## volumetype ## int16) PolyVox::class<PolyVox::volumetype<int16_t> >;
|
||||||
%template(class ## volumetype ## int32) PolyVox::class<PolyVox::volumetype<int32_t> >;
|
%template(class ## volumetype ## int32) PolyVox::class<PolyVox::volumetype<int32_t> >;
|
||||||
%template(class ## volumetype ## uint8) PolyVox::class<PolyVox::volumetype<uint8_t> >;
|
%template(class ## volumetype ## uint8) PolyVox::class<PolyVox::volumetype<uint8_t> >;
|
||||||
%template(class ## volumetype ## uint16) PolyVox::class<PolyVox::volumetype<uint16_t> >;
|
%template(class ## volumetype ## uint16) PolyVox::class<PolyVox::volumetype<uint16_t> >;
|
||||||
%template(class ## volumetype ## uint32) PolyVox::class<PolyVox::volumetype<uint32_t> >;
|
%template(class ## volumetype ## uint32) PolyVox::class<PolyVox::volumetype<uint32_t> >;
|
||||||
%template(class ## volumetype ## float) PolyVox::class<PolyVox::volumetype<float> >;
|
%template(class ## volumetype ## float) PolyVox::class<PolyVox::volumetype<float> >;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
//Template based on volume type
|
//Template based on volume type
|
||||||
%define EXTRACTORS(shortname)
|
%define EXTRACTORS(shortname)
|
||||||
EXTRACTOR(shortname, SimpleVolume)
|
EXTRACTOR(shortname, SimpleVolume)
|
||||||
EXTRACTOR(shortname, RawVolume)
|
EXTRACTOR(shortname, RawVolume)
|
||||||
EXTRACTOR(shortname, LargeVolume)
|
EXTRACTOR(shortname, LargeVolume)
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%feature("autodoc", "1");
|
%feature("autodoc", "1");
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
#ifdef SWIGPYTHON
|
||||||
//This will rename "operator=" to "assign" since Python doesn't have assignment
|
//This will rename "operator=" to "assign" since Python doesn't have assignment
|
||||||
%rename(assign) *::operator=;
|
%rename(assign) *::operator=;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SWIGCSHARP
|
#ifdef SWIGCSHARP
|
||||||
//These operators are not wrappable in C# and their function is provided by other means
|
//These operators are not wrappable in C# and their function is provided by other means
|
||||||
%ignore *::operator=;
|
%ignore *::operator=;
|
||||||
%ignore *::operator+=;
|
%ignore *::operator+=;
|
||||||
%ignore *::operator-=;
|
%ignore *::operator-=;
|
||||||
%ignore *::operator*=;
|
%ignore *::operator*=;
|
||||||
%ignore *::operator/=;
|
%ignore *::operator/=;
|
||||||
%ignore *::operator<<; //This is covered by STR()
|
%ignore *::operator<<; //This is covered by STR()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%include "stdint.i"
|
%include "stdint.i"
|
||||||
%include "std_vector.i"
|
%include "std_vector.i"
|
||||||
%include "Vector.i"
|
%include "Vector.i"
|
||||||
%include "DefaultMarchingCubesController.i"
|
%include "DefaultMarchingCubesController.i"
|
||||||
%include "Region.i"
|
%include "Region.i"
|
||||||
%include "Block.i"
|
%include "Block.i"
|
||||||
%include "CompressedBlock.i"
|
%include "CompressedBlock.i"
|
||||||
%include "UncompressedBlock.i"
|
%include "UncompressedBlock.i"
|
||||||
%include "BlockCompressor.i"
|
%include "BlockCompressor.i"
|
||||||
%include "Pager.i"
|
%include "Pager.i"
|
||||||
%include "FilePager.i"
|
%include "FilePager.i"
|
||||||
%include "MinizBlockCompressor.i"
|
%include "MinizBlockCompressor.i"
|
||||||
%include "RLEBlockCompressor.i"
|
%include "RLEBlockCompressor.i"
|
||||||
%include "BaseVolume.i"
|
%include "BaseVolume.i"
|
||||||
%include "SimpleVolume.i"
|
%include "SimpleVolume.i"
|
||||||
%include "RawVolume.i"
|
%include "RawVolume.i"
|
||||||
%include "LargeVolume.i"
|
%include "LargeVolume.i"
|
||||||
//%include "SubArray.i"
|
//%include "SubArray.i"
|
||||||
//%include "Array.i"
|
//%include "Array.i"
|
||||||
%include "VertexTypes.i"
|
%include "VertexTypes.i"
|
||||||
%include "SurfaceMesh.i"
|
%include "SurfaceMesh.i"
|
||||||
%include "MarchingCubesSurfaceExtractor.i"
|
%include "MarchingCubesSurfaceExtractor.i"
|
||||||
%include "CubicSurfaceExtractor.i"
|
%include "CubicSurfaceExtractor.i"
|
||||||
%include "CubicSurfaceExtractorWithNormals.i"
|
%include "CubicSurfaceExtractorWithNormals.i"
|
||||||
%include "Raycast.i"
|
%include "Raycast.i"
|
||||||
%include "Picking.i"
|
%include "Picking.i"
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
%module SimpleVolumeSampler
|
%module SimpleVolumeSampler
|
||||||
%{
|
%{
|
||||||
#include "SimpleVolume.h"
|
#include "SimpleVolume.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "SimpleVolume.h"
|
%include "SimpleVolume.h"
|
||||||
|
|
||||||
%template(SimpleVolumeSamplerMaterial8) PolyVox::SimpleVolume::Sampler<PolyVox::Material8>;
|
%template(SimpleVolumeSamplerMaterial8) PolyVox::SimpleVolume::Sampler<PolyVox::Material8>;
|
||||||
%template(SimpleVolumeSamplerDensity8) PolyVox::SimpleVolume::Sampler<PolyVox::Density8>;
|
%template(SimpleVolumeSamplerDensity8) PolyVox::SimpleVolume::Sampler<PolyVox::Density8>;
|
@ -1,9 +1,9 @@
|
|||||||
%module SubArray
|
%module SubArray
|
||||||
%{
|
%{
|
||||||
#include "PolyVoxImpl\SubArray.h"
|
#include "PolyVoxImpl\SubArray.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "PolyVoxImpl\SubArray.h"
|
%include "PolyVoxImpl\SubArray.h"
|
||||||
|
|
||||||
//%template(SubArray) PolyVox::SubArray<uint32_t, PolyVox::IndexAndMaterial>;
|
//%template(SubArray) PolyVox::SubArray<uint32_t, PolyVox::IndexAndMaterial>;
|
||||||
//%template(SubArray) PolyVox::SubArray<uint32_t, PolyVox::IndexAndMaterial>;
|
//%template(SubArray) PolyVox::SubArray<uint32_t, PolyVox::IndexAndMaterial>;
|
@ -1,20 +1,20 @@
|
|||||||
%module SurfaceMesh
|
%module SurfaceMesh
|
||||||
%{
|
%{
|
||||||
#include "Region.h"
|
#include "Region.h"
|
||||||
#include "VertexTypes.h"
|
#include "VertexTypes.h"
|
||||||
#include "SurfaceMesh.h"
|
#include "SurfaceMesh.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "Region.h"
|
%include "Region.h"
|
||||||
%include "VertexTypes.h"
|
%include "VertexTypes.h"
|
||||||
%include "SurfaceMesh.h"
|
%include "SurfaceMesh.h"
|
||||||
|
|
||||||
//%template(VertexTypeVector) std::vector<PolyVox::VertexType>;
|
//%template(VertexTypeVector) std::vector<PolyVox::VertexType>;
|
||||||
%template(PositionMaterialVector) std::vector<PolyVox::PositionMaterial>;
|
%template(PositionMaterialVector) std::vector<PolyVox::PositionMaterial>;
|
||||||
%template(PositionMaterialNormalVector) std::vector<PolyVox::PositionMaterialNormal>;
|
%template(PositionMaterialNormalVector) std::vector<PolyVox::PositionMaterialNormal>;
|
||||||
%template(LodRecordVector) std::vector<PolyVox::LodRecord>;
|
%template(LodRecordVector) std::vector<PolyVox::LodRecord>;
|
||||||
%template(uint8Vector) std::vector<uint8_t>;
|
%template(uint8Vector) std::vector<uint8_t>;
|
||||||
%template(uint32Vector) std::vector<uint32_t>;
|
%template(uint32Vector) std::vector<uint32_t>;
|
||||||
|
|
||||||
%template(SurfaceMeshPositionMaterial) PolyVox::SurfaceMesh<PolyVox::PositionMaterial>;
|
%template(SurfaceMeshPositionMaterial) PolyVox::SurfaceMesh<PolyVox::PositionMaterial>;
|
||||||
%template(SurfaceMeshPositionMaterialNormal) PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>;
|
%template(SurfaceMeshPositionMaterialNormal) PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>;
|
@ -1,6 +1,6 @@
|
|||||||
%module TypeDef
|
%module TypeDef
|
||||||
%{
|
%{
|
||||||
#include "PolyVoxImpl/TypeDef.h"
|
#include "PolyVoxImpl/TypeDef.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "PolyVoxImpl/TypeDef.h"
|
%include "PolyVoxImpl/TypeDef.h"
|
@ -1,121 +1,121 @@
|
|||||||
%module Vector
|
%module Vector
|
||||||
%{
|
%{
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "Vector.h"
|
%include "Vector.h"
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
#ifdef SWIGPYTHON
|
||||||
PROPERTY(PolyVox::Vector, x, getX, setX)
|
PROPERTY(PolyVox::Vector, x, getX, setX)
|
||||||
PROPERTY(PolyVox::Vector, y, getY, setY)
|
PROPERTY(PolyVox::Vector, y, getY, setY)
|
||||||
PROPERTY(PolyVox::Vector, z, getZ, setZ)
|
PROPERTY(PolyVox::Vector, z, getZ, setZ)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%rename(Plus) operator +;
|
%rename(Plus) operator +;
|
||||||
%rename(Minus) operator -;
|
%rename(Minus) operator -;
|
||||||
%rename(Multiply) operator *;
|
%rename(Multiply) operator *;
|
||||||
%rename(Divide) operator /;
|
%rename(Divide) operator /;
|
||||||
%rename(Equal) operator ==;
|
%rename(Equal) operator ==;
|
||||||
%rename(NotEqual) operator !=;
|
%rename(NotEqual) operator !=;
|
||||||
|
|
||||||
%extend PolyVox::Vector {
|
%extend PolyVox::Vector {
|
||||||
#ifdef SWIGPYTHON
|
#ifdef SWIGPYTHON
|
||||||
PolyVox::Vector __add__(const PolyVox::Vector& rhs) {
|
PolyVox::Vector __add__(const PolyVox::Vector& rhs) {
|
||||||
return *$self + rhs;
|
return *$self + rhs;
|
||||||
}
|
}
|
||||||
PolyVox::Vector __sub__(const PolyVox::Vector& rhs) {
|
PolyVox::Vector __sub__(const PolyVox::Vector& rhs) {
|
||||||
return *$self - rhs;
|
return *$self - rhs;
|
||||||
}
|
}
|
||||||
PolyVox::Vector __div__(const PolyVox::Vector& rhs) {
|
PolyVox::Vector __div__(const PolyVox::Vector& rhs) {
|
||||||
return *$self / rhs;
|
return *$self / rhs;
|
||||||
}
|
}
|
||||||
PolyVox::Vector __div__(const StorageType& rhs) {
|
PolyVox::Vector __div__(const StorageType& rhs) {
|
||||||
return *$self / rhs;
|
return *$self / rhs;
|
||||||
}
|
}
|
||||||
PolyVox::Vector __mul__(const PolyVox::Vector& rhs) {
|
PolyVox::Vector __mul__(const PolyVox::Vector& rhs) {
|
||||||
return *$self * rhs;
|
return *$self * rhs;
|
||||||
}
|
}
|
||||||
PolyVox::Vector __mul__(const StorageType& rhs) {
|
PolyVox::Vector __mul__(const StorageType& rhs) {
|
||||||
return *$self * rhs;
|
return *$self * rhs;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
STR()
|
STR()
|
||||||
};
|
};
|
||||||
|
|
||||||
%feature("pythonprepend") PolyVox::Vector::operator< %{
|
%feature("pythonprepend") PolyVox::Vector::operator< %{
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("deprecated", DeprecationWarning)
|
warnings.warn("deprecated", DeprecationWarning)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//%csattributes PolyVox::Vector::operator< "[System.Obsolete(\"deprecated\")]"
|
//%csattributes PolyVox::Vector::operator< "[System.Obsolete(\"deprecated\")]"
|
||||||
|
|
||||||
%define VECTOR3(StorageType,OperationType,ReducedStorageType)
|
%define VECTOR3(StorageType,OperationType,ReducedStorageType)
|
||||||
#if SWIGCSHARP
|
#if SWIGCSHARP
|
||||||
%extend PolyVox::Vector<3,StorageType,OperationType> {
|
%extend PolyVox::Vector<3,StorageType,OperationType> {
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator+(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self + rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator+(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self + rhs;}
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator-(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self - rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator-(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self - rhs;}
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator*(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self * rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator*(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self * rhs;}
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator/(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self / rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator/(const PolyVox::Vector<3,StorageType,OperationType>& rhs) {return *$self / rhs;}
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator*(const StorageType& rhs) {return *$self * rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator*(const StorageType& rhs) {return *$self * rhs;}
|
||||||
PolyVox::Vector<3,StorageType,OperationType> operator/(const StorageType& rhs) {return *$self / rhs;}
|
PolyVox::Vector<3,StorageType,OperationType> operator/(const StorageType& rhs) {return *$self / rhs;}
|
||||||
};
|
};
|
||||||
%typemap(cscode) PolyVox::Vector<3,StorageType,OperationType> %{
|
%typemap(cscode) PolyVox::Vector<3,StorageType,OperationType> %{
|
||||||
public static Vector3D##StorageType operator+(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
public static Vector3D##StorageType operator+(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Plus(rhs);
|
newVec = lhs.Plus(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public static Vector3D##StorageType operator-(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
public static Vector3D##StorageType operator-(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Minus(rhs);
|
newVec = lhs.Minus(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Multiply(rhs);
|
newVec = lhs.Multiply(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, Vector3D##StorageType rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Divide(rhs);
|
newVec = lhs.Divide(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
public static Vector3D##StorageType operator*(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Multiply(rhs);
|
newVec = lhs.Multiply(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
public static Vector3D##StorageType operator/(Vector3D##StorageType lhs, $typemap(cstype, StorageType) rhs) {
|
||||||
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
Vector3D##StorageType newVec = new Vector3D##StorageType();
|
||||||
newVec = lhs.Divide(rhs);
|
newVec = lhs.Divide(rhs);
|
||||||
return newVec;
|
return newVec;
|
||||||
}
|
}
|
||||||
public bool Equals(Vector3D##StorageType rhs) {
|
public bool Equals(Vector3D##StorageType rhs) {
|
||||||
if ((object)rhs == null)
|
if ((object)rhs == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Equal(rhs);
|
return Equal(rhs);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::operator<; //This is deprecated
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::operator<; //This is deprecated
|
||||||
#endif
|
#endif
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType);
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::Vector(ReducedStorageType,ReducedStorageType);
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::getW() const;
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::getW() const;
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::setW(ReducedStorageType);
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::setW(ReducedStorageType);
|
||||||
%ignore PolyVox::Vector<3,StorageType,OperationType>::setElements(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
%ignore PolyVox::Vector<3,StorageType,OperationType>::setElements(ReducedStorageType,ReducedStorageType,ReducedStorageType,ReducedStorageType);
|
||||||
%template(Vector3D ## StorageType) PolyVox::Vector<3,StorageType,OperationType>;
|
%template(Vector3D ## StorageType) PolyVox::Vector<3,StorageType,OperationType>;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
VECTOR3(float,float,float)
|
VECTOR3(float,float,float)
|
||||||
VECTOR3(double,double,double)
|
VECTOR3(double,double,double)
|
||||||
VECTOR3(int8_t,int32_t,signed char)
|
VECTOR3(int8_t,int32_t,signed char)
|
||||||
VECTOR3(uint8_t,int32_t,unsigned char)
|
VECTOR3(uint8_t,int32_t,unsigned char)
|
||||||
VECTOR3(int16_t,int32_t,signed short)
|
VECTOR3(int16_t,int32_t,signed short)
|
||||||
VECTOR3(uint16_t,int32_t,unsigned short)
|
VECTOR3(uint16_t,int32_t,unsigned short)
|
||||||
VECTOR3(int32_t,int32_t,signed int)
|
VECTOR3(int32_t,int32_t,signed int)
|
||||||
VECTOR3(uint32_t,int32_t,unsigned int)
|
VECTOR3(uint32_t,int32_t,unsigned int)
|
||||||
|
|
||||||
//%rename(assign) Vector3DFloat::operator=;
|
//%rename(assign) Vector3DFloat::operator=;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user