From 28dda03cb3fc4bca6c2c3e1ed3169b71da516c8f Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 16 May 2008 20:53:41 +0000 Subject: [PATCH] Got mesh smoothing working. Cleaning up code. Various changes made without internet access. --- include/Block.h | 17 +- include/Block.inl | 81 +++-- include/Constants.h | 31 +- include/GradientEstimators.h | 24 ++ include/GradientEstimators.inl | 52 +++ include/IndexedSurfacePatch.h | 21 ++ include/LinearVolume.h | 2 +- include/LinearVolume.inl | 4 +- include/MarchingCubesTables.h | 21 ++ include/PolyVoxForwardDeclarations.h | 29 +- include/PolyVoxSceneManager.h | 15 +- include/RegionGeometry.h | 4 +- include/SurfaceVertex.h | 4 +- include/TypeDef.h | 4 +- include/Utility.h | 21 ++ include/Vector.h | 29 +- include/Vector.inl | 21 ++ include/Volume.h | 36 +- include/Volume.inl | 166 +++++---- include/VolumeIterator.h | 9 +- include/VolumeIterator.inl | 289 ++++++++------- source/IndexedSurfacePatch.cpp | 21 ++ source/MarchingCubesTables.cpp | 21 ++ source/PolyVoxSceneManager.cpp | 523 ++++++++++++++++++++++++--- source/RegionGeometry.cpp | 21 ++ source/SurfaceVertex.cpp | 21 ++ source/Utility.cpp | 21 ++ 27 files changed, 1155 insertions(+), 353 deletions(-) diff --git a/include/Block.h b/include/Block.h index cd97bce5..52ad4b48 100644 --- a/include/Block.h +++ b/include/Block.h @@ -1,6 +1,6 @@ #pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -23,9 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define __PolyVox_Block_H__ #pragma region Headers -#include "Constants.h" #include "PolyVoxForwardDeclarations.h" -#include "TypeDef.h" #include "boost/cstdint.hpp" #pragma endregion @@ -37,8 +35,6 @@ namespace PolyVox { //Make VolumeIterator a friend friend class VolumeIterator; - - //Block interface public: Block(boost::uint8_t uSideLengthPower); Block(const Block& rhs); @@ -46,17 +42,12 @@ namespace PolyVox Block& operator=(const Block& rhs); - //bool isHomogeneous(void); + boost::uint16_t getSideLength(void) const; + VoxelType getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const; - boost::uint16_t getSideLength(void); - - VoxelType getVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition) const; - void setVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition, const VoxelType value); - - //void fillWithValue(const VoxelType value); + void setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue); private: - boost::uint32_t getNoOfVoxels(void); boost::uint8_t m_uSideLengthPower; boost::uint16_t m_uSideLength; VoxelType* m_tData; diff --git a/include/Block.inl b/include/Block.inl index f1befb98..ccb5400c 100644 --- a/include/Block.inl +++ b/include/Block.inl @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,18 +17,25 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion -#include +#pragma region Headers +#include +#include //For memcpy +#pragma endregion namespace PolyVox { - + #pragma region Constructors/Destructors template Block::Block(boost::uint8_t uSideLengthPower) :m_tData(0) { //Check the block size is sensible. This corresponds to a side length of 256 voxels - assert(uSideLengthPower <= 8); + if(uSideLengthPower > 8) + { + throw std::invalid_argument("Block side length must be less than or equal to eight"); + } //Compute the side length m_uSideLengthPower = uSideLengthPower; @@ -35,7 +43,7 @@ namespace PolyVox //If this fails an exception will be thrown. Memory is not //allocated and there is nothing else in this class to clean up - m_tData = new VoxelType[getNoOfVoxels()]; + m_tData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength]; } template @@ -50,7 +58,9 @@ namespace PolyVox delete[] m_tData; m_tData = 0; } + #pragma endregion + #pragma region Operators template Block& Block::operator=(const Block& rhs) { @@ -58,43 +68,48 @@ namespace PolyVox { return *this; } - - memcpy(m_tData,rhs.m_tData,getNoOfVoxels()); - + memcpy(m_tData, rhs.m_tData, m_uSideLength * m_uSideLength * m_uSideLength); return *this; } + #pragma endregion + #pragma region Getters template - VoxelType Block::getVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition) const - { - return m_tData - [ - xPosition + - yPosition * m_uSideLength + - zPosition * m_uSideLength * m_uSideLength - ]; - } - - template - void Block::setVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition, const VoxelType value) - { - m_tData - [ - xPosition + - yPosition * m_uSideLength + - zPosition * m_uSideLength * m_uSideLength - ] = value; - } - - template - boost::uint16_t Block::getSideLength(void) + boost::uint16_t Block::getSideLength(void) const { return m_uSideLength; } template - boost::uint32_t Block::getNoOfVoxels(void) + VoxelType Block::getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const { - return m_uSideLength * m_uSideLength * m_uSideLength; + assert(uXPos < m_uSideLength); + assert(uYPos < m_uSideLength); + assert(uZPos < m_uSideLength); + + return m_tData + [ + uXPos + + uYPos * m_uSideLength + + uZPos * m_uSideLength * m_uSideLength + ]; } + #pragma endregion + + #pragma region Setters + template + void Block::setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue) + { + assert(uXPos < m_uSideLength); + assert(uYPos < m_uSideLength); + assert(uZPos < m_uSideLength); + + m_tData + [ + uXPos + + uYPos * m_uSideLength + + uZPos * m_uSideLength * m_uSideLength + ] = tValue; + } + #pragma endregion } diff --git a/include/Constants.h b/include/Constants.h index 925412bd..a9ae13f5 100644 --- a/include/Constants.h +++ b/include/Constants.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_Constants_H__ #define __PolyVox_Constants_H__ @@ -10,15 +31,15 @@ namespace PolyVox //const boost::uint32_t POLYVOX_BLOCK_SIDE_LENGTH = (0x0001 << POLYVOX_BLOCK_SIDE_LENGTH_POWER); //const boost::uint32_t POLYVOX_NO_OF_VOXELS_IN_BLOCK = (POLYVOX_BLOCK_SIDE_LENGTH * POLYVOX_BLOCK_SIDE_LENGTH * POLYVOX_BLOCK_SIDE_LENGTH); - const boost::uint32_t POLYVOX_VOLUME_SIDE_LENGTH_POWER = 8; - const boost::uint32_t POLYVOX_VOLUME_SIDE_LENGTH = (0x0001 << POLYVOX_VOLUME_SIDE_LENGTH_POWER); + const boost::uint16_t POLYVOX_VOLUME_SIDE_LENGTH_POWER = 8; + const boost::uint16_t POLYVOX_VOLUME_SIDE_LENGTH = (0x0001 << POLYVOX_VOLUME_SIDE_LENGTH_POWER); //const boost::uint32_t POLYVOX_VOLUME_SIDE_LENGTH_IN_BLOCKS = (POLYVOX_VOLUME_SIDE_LENGTH >> POLYVOX_BLOCK_SIDE_LENGTH_POWER); //const boost::uint32_t POLYVOX_NO_OF_BLOCKS_IN_VOLUME = (POLYVOX_VOLUME_SIDE_LENGTH_IN_BLOCKS * POLYVOX_VOLUME_SIDE_LENGTH_IN_BLOCKS * POLYVOX_VOLUME_SIDE_LENGTH_IN_BLOCKS); //const boost::uint32_t POLYVOX_NO_OF_VOXELS_IN_VOLUME = (POLYVOX_VOLUME_SIDE_LENGTH * POLYVOX_VOLUME_SIDE_LENGTH * POLYVOX_VOLUME_SIDE_LENGTH); - const boost::uint32_t POLYVOX_REGION_SIDE_LENGTH_POWER = 4; - const boost::uint32_t POLYVOX_REGION_SIDE_LENGTH = (0x0001 << POLYVOX_REGION_SIDE_LENGTH_POWER); - const boost::uint32_t POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS = (POLYVOX_VOLUME_SIDE_LENGTH >> POLYVOX_REGION_SIDE_LENGTH_POWER); + const boost::uint16_t POLYVOX_REGION_SIDE_LENGTH_POWER = 4; + const boost::uint16_t POLYVOX_REGION_SIDE_LENGTH = (0x0001 << POLYVOX_REGION_SIDE_LENGTH_POWER); + const boost::uint16_t POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS = (POLYVOX_VOLUME_SIDE_LENGTH >> POLYVOX_REGION_SIDE_LENGTH_POWER); } #endif diff --git a/include/GradientEstimators.h b/include/GradientEstimators.h index 05203b15..de0e294b 100644 --- a/include/GradientEstimators.h +++ b/include/GradientEstimators.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_GradientEstimators_H__ #define __PolyVox_GradientEstimators_H__ @@ -9,6 +30,9 @@ namespace PolyVox template Vector3DFloat computeCentralDifferenceGradient(const VolumeIterator& volIter); + template + Vector3DFloat computeSmoothCentralDifferenceGradient(VolumeIterator& volIter); + template Vector3DFloat computeSobelGradient(const VolumeIterator& volIter); } diff --git a/include/GradientEstimators.inl b/include/GradientEstimators.inl index 439be9db..91cf44e9 100644 --- a/include/GradientEstimators.inl +++ b/include/GradientEstimators.inl @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + namespace PolyVox { template @@ -21,6 +42,37 @@ namespace PolyVox ); } + template + Vector3DFloat computeSmoothCentralDifferenceGradient(VolumeIterator& volIter) + { + boost::uint16_t initialX = volIter.getPosX(); + boost::uint16_t initialY = volIter.getPosY(); + boost::uint16_t initialZ = volIter.getPosZ(); + + //FIXME - bitwise way of doing this? + volIter.setPosition(initialX-1, initialY, initialZ); + float voxel1nx = volIter.getAveragedVoxel(1); + volIter.setPosition(initialX+1, initialY, initialZ); + float voxel1px = volIter.getAveragedVoxel(1); + + volIter.setPosition(initialX, initialY-1, initialZ); + float voxel1ny = volIter.getAveragedVoxel(1); + volIter.setPosition(initialX, initialY+1, initialZ); + float voxel1py = volIter.getAveragedVoxel(1); + + volIter.setPosition(initialX, initialY, initialZ-1); + float voxel1nz = volIter.getAveragedVoxel(1); + volIter.setPosition(initialX, initialY, initialZ+1); + float voxel1pz = volIter.getAveragedVoxel(1); + + return Vector3DFloat + ( + voxel1px - voxel1nx, + voxel1py - voxel1ny, + voxel1pz - voxel1nz + ); + } + template Vector3DFloat computeSobelGradient(const VolumeIterator& volIter) { diff --git a/include/IndexedSurfacePatch.h b/include/IndexedSurfacePatch.h index 5153dcab..4a1c0c30 100644 --- a/include/IndexedSurfacePatch.h +++ b/include/IndexedSurfacePatch.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_IndexedSurfacePatch_H__ #define __PolyVox_IndexedSurfacePatch_H__ diff --git a/include/LinearVolume.h b/include/LinearVolume.h index a8d84a50..2509ac69 100644 --- a/include/LinearVolume.h +++ b/include/LinearVolume.h @@ -1,6 +1,6 @@ #pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or diff --git a/include/LinearVolume.inl b/include/LinearVolume.inl index eb2a6837..80537c09 100644 --- a/include/LinearVolume.inl +++ b/include/LinearVolume.inl @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion #include diff --git a/include/MarchingCubesTables.h b/include/MarchingCubesTables.h index bf7af207..ca93972e 100644 --- a/include/MarchingCubesTables.h +++ b/include/MarchingCubesTables.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_MarchingCubeTables_H__ #define __PolyVox_MarchingCubeTables_H__ diff --git a/include/PolyVoxForwardDeclarations.h b/include/PolyVoxForwardDeclarations.h index 184ccf13..c97aafe8 100644 --- a/include/PolyVoxForwardDeclarations.h +++ b/include/PolyVoxForwardDeclarations.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_ForwardDeclarations_H__ #define __PolyVox_ForwardDeclarations_H__ @@ -13,12 +34,12 @@ namespace PolyVox class RegionGeometry; class SurfaceVertex; template class Vector; - typedef Vector<2,float> Vector2DFloat; - typedef Vector<2,double> Vector2DDouble; - typedef Vector<2,boost::int32_t> Vector2DInt32; - typedef Vector<2,boost::uint32_t> Vector2DUint32; typedef Vector<3,float> Vector3DFloat; typedef Vector<3,double> Vector3DDouble; + typedef Vector<3,boost::int8_t> Vector3DInt8; + typedef Vector<3,boost::uint8_t> Vector3DUint8; + typedef Vector<3,boost::int16_t> Vector3DInt16; + typedef Vector<3,boost::uint16_t> Vector3DUint16; typedef Vector<3,boost::int32_t> Vector3DInt32; typedef Vector<3,boost::uint32_t> Vector3DUint32; template class Volume; diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index 4c602933..e39c13fb 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_PolyVoxSceneManager_H__ #define __PolyVox_PolyVoxSceneManager_H__ @@ -49,6 +52,8 @@ namespace PolyVox const std::string& getTypeName(void) const; boost::uint16_t getSideLength(void); + const Volume* getVolumeData(void) const; + //Setters void setVolumeData(Volume* volumeDataToSet); @@ -62,15 +67,17 @@ namespace PolyVox //void generateLevelVolume(void); - void generateMeshDataForRegion(boost::uint16_t regionX, boost::uint16_t regionY, boost::uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const; + void generateRoughMeshDataForRegion(boost::uint16_t regionX, boost::uint16_t regionY, boost::uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const; + void generateSmoothMeshDataForRegion(boost::uint16_t regionX, boost::uint16_t regionY, boost::uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const; - bool containsPoint(Vector3DFloat pos, float boundary); - bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary); + //bool containsPoint(Vector3DFloat pos, float boundary); + //bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary); LinearVolume* volSurfaceUpToDate; Vector3DFloat computeNormal(const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) const; + Vector3DFloat computeSmoothNormal(const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) const; public: void markVoxelChanged(boost::uint16_t x, boost::uint16_t y, boost::uint16_t z); diff --git a/include/RegionGeometry.h b/include/RegionGeometry.h index 87f61e35..ea868feb 100644 --- a/include/RegionGeometry.h +++ b/include/RegionGeometry.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion #ifndef __PolyVox_RegionGeometry_H__ #define __PolyVox_RegionGeometry_H__ diff --git a/include/SurfaceVertex.h b/include/SurfaceVertex.h index 955d8702..5be6b722 100644 --- a/include/SurfaceVertex.h +++ b/include/SurfaceVertex.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion #ifndef __PolyVox_SurfaceVertex_H__ #define __PolyVox_SurfaceVertex_H__ diff --git a/include/TypeDef.h b/include/TypeDef.h index 4bbeb079..38a863d1 100644 --- a/include/TypeDef.h +++ b/include/TypeDef.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion //Dave, maybe make use of OgrePlatform.h instead? // I think use _OgreExport instead of POLYVOX_API and define OGRE_NONCLIENT_BUILD instead of POLYVOX_EXPORT? diff --git a/include/Utility.h b/include/Utility.h index 750d577d..41f26ed6 100644 --- a/include/Utility.h +++ b/include/Utility.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_Utility_H__ #define __PolyVox_Utility_H__ diff --git a/include/Vector.h b/include/Vector.h index 2cef95a5..18c46b8e 100644 --- a/include/Vector.h +++ b/include/Vector.h @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_Vector_H__ #define __PolyVox_Vector_H__ @@ -103,12 +124,12 @@ namespace PolyVox std::ostream& operator<<(std::ostream& os, const Vector& vector) throw(); //Some handy typedefs - typedef Vector<2,float> Vector2DFloat; - typedef Vector<2,double> Vector2DDouble; - typedef Vector<2,boost::int32_t> Vector2DInt32; - typedef Vector<2,boost::uint32_t> Vector2DUint32; typedef Vector<3,float> Vector3DFloat; typedef Vector<3,double> Vector3DDouble; + typedef Vector<3,boost::int8_t> Vector3DInt8; + typedef Vector<3,boost::uint8_t> Vector3DUint8; + typedef Vector<3,boost::int16_t> Vector3DInt16; + typedef Vector<3,boost::uint16_t> Vector3DUint16; typedef Vector<3,boost::int32_t> Vector3DInt32; typedef Vector<3,boost::uint32_t> Vector3DUint32; diff --git a/include/Vector.inl b/include/Vector.inl index 91d6605e..2560fd16 100644 --- a/include/Vector.inl +++ b/include/Vector.inl @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #include #include #include diff --git a/include/Volume.h b/include/Volume.h index 13061427..d6507ce7 100644 --- a/include/Volume.h +++ b/include/Volume.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,15 +17,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion + #ifndef __PolyVox_Volume_H__ #define __PolyVox_Volume_H__ -#include "boost/cstdint.hpp" - -#include "Constants.h" +#pragma region Headers #include "PolyVoxForwardDeclarations.h" -#include "TypeDef.h" -#include "Vector.h" + +#include "boost/cstdint.hpp" +#pragma endregion namespace PolyVox { @@ -34,30 +36,24 @@ namespace PolyVox //Make VolumeIterator a friend friend class VolumeIterator; - //Volume interface public: Volume(boost::uint8_t uSideLengthPower, boost::uint8_t uBlockSideLengthPower = 5); - ~Volume(); - - private: Volume(const Volume& rhs); + ~Volume(); + Volume& operator=(const Volume& rhs); - public: - bool containsPoint(Vector3DFloat pos, float boundary); - bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary); - boost::uint16_t getSideLength(void); - boost::uint8_t getSideLengthPower(void); - boost::uint16_t getSideLengthInBlocks(void); + VoxelType getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const; + VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const; - boost::uint16_t getBlockSideLength(void); - boost::uint16_t getBlockSideLengthPower(void); + void setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue); + void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); - void tidy(void); + bool containsPoint(Vector3DFloat pos, float boundary) const; + bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) const; private: - Block* getBlock(boost::uint16_t index); Block** mBlocks; boost::uint32_t m_uNoOfBlocksInVolume; boost::uint16_t m_uSideLengthInBlocks; diff --git a/include/Volume.inl b/include/Volume.inl index aa11538d..3df00af3 100644 --- a/include/Volume.inl +++ b/include/Volume.inl @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,23 +17,27 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion -#include -#include //FIXME - remove this... -#include - +#pragma region Headers #include "Block.h" -#include "VolumeIterator.h" //Maybe this shouldn't be here? + +#include +#include //For memcpy +#pragma endregion namespace PolyVox { - + #pragma region Constructors/Destructors template Volume::Volume(boost::uint8_t uSideLengthPower, boost::uint8_t uBlockSideLengthPower) :mBlocks(0) { //Check the volume size is sensible. This corresponds to a side length of 65536 voxels - assert(uSideLengthPower <= 16); + if(uSideLengthPower > 16) + { + throw std::invalid_argument("Block side length must be less than or equal to 65536"); + } //Compute the volume side length m_uSideLengthPower = uSideLengthPower; @@ -63,7 +68,6 @@ namespace PolyVox template Volume::Volume(const Volume& rhs) { - std::cout << "Warning - Copying Volume" << std::endl; *this = rhs; } @@ -75,11 +79,12 @@ namespace PolyVox delete mBlocks[i]; } } + #pragma endregion + #pragma region Operators template Volume& Volume::operator=(const Volume& rhs) { - std::cout << "Warning - Assigning Volume" << std::endl; if (this == &rhs) { return *this; @@ -108,57 +113,9 @@ namespace PolyVox return *this; } + #pragma endregion - template - Block* Volume::getBlock(boost::uint16_t index) - { - return mBlocks[index]; - } - - template - bool Volume::containsPoint(Vector3DFloat pos, float boundary) - { - return (pos.x() < m_uSideLength - 1 - boundary) - && (pos.y() < m_uSideLength - 1 - boundary) - && (pos.z() < m_uSideLength - 1 - boundary) - && (pos.x() > boundary) - && (pos.y() > boundary) - && (pos.z() > boundary); - } - - template - bool Volume::containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) - { - return (pos.x() < m_uSideLength - 1 - boundary) - && (pos.y() < m_uSideLength - 1 - boundary) - && (pos.z() < m_uSideLength - 1 - boundary) - && (pos.x() > boundary) - && (pos.y() > boundary) - && (pos.z() > boundary); - } - - template - void Volume::tidy(void) - { - //Check for homogeneous blocks - /*for(uint32_t ct = 0; ct < POLYVOX_NO_OF_BLOCKS_IN_VOLUME; ++ct) - { - if(mBlocks[ct]->isHomogeneous()) - { - //LogManager::getSingleton().logMessage("Got homogeneous block with value " + stringConverter::tostring(mBlocks[ct]->getVoxelAt(0,0,0))); - - const VoxelType homogeneousValue = mBlocks[ct]->getVoxelAt(0,0,0); - SharedPtr& homogeneousBlock = mHomogeneousBlocks[homogeneousValue]; - if(homogeneousBlock.isNull()) - { - homogeneousBlock = SharedPtr(new Block); - homogeneousBlock->fillWithValue(homogeneousValue); - } - mBlocks[ct] = homogeneousBlock; - } - }*/ - } - + #pragma region Getters template boost::uint16_t Volume::getSideLength(void) { @@ -166,26 +123,99 @@ namespace PolyVox } template - boost::uint8_t Volume::getSideLengthPower(void) + VoxelType Volume::getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const { - return m_uSideLengthPower; + assert(uXPos < mVolume.getSideLength()); + assert(uYPos < mVolume.getSideLength()); + assert(uZPos < mVolume.getSideLength()); + + const uint16_t blockX = uXPos >> m_uBlockSideLengthPower; + const uint16_t blockY = uYPos >> m_uBlockSideLengthPower; + const uint16_t blockZ = uZPos >> m_uBlockSideLengthPower; + + const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); + const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); + const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); + + const Block* block = mBlocks + [ + blockX + + blockY * m_uSideLengthInBlocks + + blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks + ]; + + return block->getVoxelAt(xOffset,yOffset,zOffset); } template - boost::uint16_t Volume::getSideLengthInBlocks(void) + VoxelType Volume::getVoxelAt(const Vector3DUint16& v3dPos) const { - return m_uSideLengthInBlocks; + assert(v3dPos.x() < m_uSideLength); + assert(v3dPos.y() < m_uSideLength); + assert(v3dPos.z() < m_uSideLength); + + return getVoxelAt(v3dPos.x(), v3dPos.y(), v3dPos.z()); + } + #pragma endregion + + #pragma region Setters + template + void Volume::setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue) + { + assert(uXPos < mVolume.getSideLength()); + assert(uYPos < mVolume.getSideLength()); + assert(uZPos < mVolume.getSideLength()); + + const uint16_t blockX = uXPos >> m_uBlockSideLengthPower; + const uint16_t blockY = uYPos >> m_uBlockSideLengthPower; + const uint16_t blockZ = uZPos >> m_uBlockSideLengthPower; + + const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); + const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); + const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); + + const Block* block = mBlocks + [ + blockX + + blockY * m_uSideLengthInBlocks + + blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks + ]; + + return block->setVoxelAt(xOffset,yOffset,zOffset, tValue); } template - boost::uint16_t Volume::getBlockSideLength(void) + void Volume::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue) { - return m_uBlockSideLength; + assert(v3dPos.x() < m_uSideLength); + assert(v3dPos.y() < m_uSideLength); + assert(v3dPos.z() < m_uSideLength); + + setVoxelAt(v3dPos.x(), v3dPos.y(), v3dPos.z(), tValue); + } + #pragma endregion + + #pragma region Other + template + bool Volume::containsPoint(Vector3DFloat pos, float boundary) const + { + return (pos.x() <= m_uSideLength - 1 - boundary) + && (pos.y() <= m_uSideLength - 1 - boundary) + && (pos.z() <= m_uSideLength - 1 - boundary) + && (pos.x() >= boundary) + && (pos.y() >= boundary) + && (pos.z() >= boundary); } template - boost::uint16_t Volume::getBlockSideLengthPower(void) + bool Volume::containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) const { - return m_uBlockSideLengthPower; + return (pos.x() <= m_uSideLength - 1 - boundary) + && (pos.y() <= m_uSideLength - 1 - boundary) + && (pos.z() <= m_uSideLength - 1 - boundary) + && (pos.x() >= boundary) + && (pos.y() >= boundary) + && (pos.z() >= boundary); } + #pragma endregion } diff --git a/include/VolumeIterator.h b/include/VolumeIterator.h index 3f492632..55c68ba0 100644 --- a/include/VolumeIterator.h +++ b/include/VolumeIterator.h @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion + #ifndef __VolumeIterator_H__ #define __VolumeIterator_H__ @@ -37,7 +40,7 @@ namespace PolyVox void setVoxel(VoxelType value); VoxelType getVoxel(void); - float getAveragedVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition, boost::uint16_t size) const; + float getAveragedVoxel(boost::uint16_t size) const; @@ -83,7 +86,7 @@ namespace PolyVox private: - VoxelType getVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition) const; + //VoxelType getVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition) const; //The current volume Volume& mVolume; diff --git a/include/VolumeIterator.inl b/include/VolumeIterator.inl index d0623766..45994265 100644 --- a/include/VolumeIterator.inl +++ b/include/VolumeIterator.inl @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion #include "block.h" #include "Volume.h" @@ -36,9 +38,9 @@ namespace PolyVox ,mXRegionFirstBlock(0) ,mYRegionFirstBlock(0) ,mZRegionFirstBlock(0) - ,mXRegionLastBlock(volume.getSideLengthInBlocks()-1) - ,mYRegionLastBlock(volume.getSideLengthInBlocks()-1) - ,mZRegionLastBlock(volume.getSideLengthInBlocks()-1) + ,mXRegionLastBlock(volume.m_uSideLengthInBlocks-1) + ,mYRegionLastBlock(volume.m_uSideLengthInBlocks-1) + ,mZRegionLastBlock(volume.m_uSideLengthInBlocks-1) ,mXPosInVolume(0) ,mYPosInVolume(0) ,mZPosInVolume(0) @@ -84,38 +86,49 @@ namespace PolyVox return *mCurrentVoxel; } - template + /*template VoxelType VolumeIterator::getVoxelAt(const uint16_t xPosition, const uint16_t yPosition, const uint16_t zPosition) const { - const uint16_t blockX = xPosition >> mVolume.getBlockSideLengthPower(); - const uint16_t blockY = yPosition >> mVolume.getBlockSideLengthPower(); - const uint16_t blockZ = zPosition >> mVolume.getBlockSideLengthPower(); + assert(xPosition < mVolume.getSideLength()); + assert(yPosition < mVolume.getSideLength()); + assert(zPosition < mVolume.getSideLength()); - const uint16_t xOffset = xPosition - (blockX << mVolume.getBlockSideLengthPower()); - const uint16_t yOffset = yPosition - (blockY << mVolume.getBlockSideLengthPower()); - const uint16_t zOffset = zPosition - (blockZ << mVolume.getBlockSideLengthPower()); + const uint16_t blockX = xPosition >> mVolume.m_uBlockSideLengthPower; + const uint16_t blockY = yPosition >> mVolume.m_uBlockSideLengthPower; + const uint16_t blockZ = zPosition >> mVolume.m_uBlockSideLengthPower; + + const uint16_t xOffset = xPosition - (blockX << mVolume.m_uBlockSideLengthPower); + const uint16_t yOffset = yPosition - (blockY << mVolume.m_uBlockSideLengthPower); + const uint16_t zOffset = zPosition - (blockZ << mVolume.m_uBlockSideLengthPower); const Block* block = mVolume.mBlocks [ blockX + - blockY * mVolume.getSideLengthInBlocks() + - blockZ * mVolume.getSideLengthInBlocks() * mVolume.getSideLengthInBlocks() + blockY * mVolume.m_uSideLengthInBlocks + + blockZ * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks ]; return block->getVoxelAt(xOffset,yOffset,zOffset); - } + }*/ template - float VolumeIterator::getAveragedVoxelAt(const uint16_t xPosition, const uint16_t yPosition, const uint16_t zPosition, uint16_t size) const + float VolumeIterator::getAveragedVoxel(uint16_t size) const { + assert(mXPosInVolume >= size); + assert(mYPosInVolume >= size); + assert(mZPosInVolume >= size); + assert(mXPosInVolume < mVolume.getSideLength() - (size + 1)); + assert(mYPosInVolume < mVolume.getSideLength() - (size + 1)); + assert(mZPosInVolume < mVolume.getSideLength() - (size + 1)); + float sum = 0.0; - for(uint16_t z = zPosition-size; z <= zPosition+size; ++z) + for(uint16_t z = mZPosInVolume-size; z <= mZPosInVolume+size; ++z) { - for(uint16_t y = yPosition-size; y <= yPosition+size; ++y) + for(uint16_t y = mYPosInVolume-size; y <= mYPosInVolume+size; ++y) { - for(uint16_t x = xPosition-size; x <= xPosition+size; ++x) + for(uint16_t x = mXPosInVolume-size; x <= mXPosInVolume+size; ++x) { - if(getVoxelAt(x,y,z) != 0) + if(mVolume.getVoxelAt(x,y,z) != 0) { sum += 1.0; } @@ -155,22 +168,22 @@ namespace PolyVox mYPosInVolume = yPos; mZPosInVolume = zPos; - mXBlock = mXPosInVolume >> mVolume.getBlockSideLengthPower(); - mYBlock = mYPosInVolume >> mVolume.getBlockSideLengthPower(); - mZBlock = mZPosInVolume >> mVolume.getBlockSideLengthPower(); + mXBlock = mXPosInVolume >> mVolume.m_uBlockSideLengthPower; + mYBlock = mYPosInVolume >> mVolume.m_uBlockSideLengthPower; + mZBlock = mZPosInVolume >> mVolume.m_uBlockSideLengthPower; - mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.getBlockSideLengthPower()); - mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.getBlockSideLengthPower()); - mZPosInBlock = mZPosInVolume - (mZBlock << mVolume.getBlockSideLengthPower()); + mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.m_uBlockSideLengthPower); + mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.m_uBlockSideLengthPower); + mZPosInBlock = mZPosInVolume - (mZBlock << mVolume.m_uBlockSideLengthPower); mBlockIndexInVolume = mXBlock + - mYBlock * mVolume.getSideLengthInBlocks() + - mZBlock * mVolume.getSideLengthInBlocks() * mVolume.getSideLengthInBlocks(); + mYBlock * mVolume.m_uSideLengthInBlocks + + mZBlock * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; mVoxelIndexInBlock = mXPosInBlock + - mYPosInBlock * mVolume.getBlockSideLength() + - mZPosInBlock * mVolume.getBlockSideLength() * mVolume.getBlockSideLength(); + mYPosInBlock * mVolume.m_uBlockSideLength + + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; } @@ -186,13 +199,13 @@ namespace PolyVox mYRegionLast = yLast; mZRegionLast = zLast; - mXRegionFirstBlock = mXRegionFirst >> mVolume.getBlockSideLengthPower(); - mYRegionFirstBlock = mYRegionFirst >> mVolume.getBlockSideLengthPower(); - mZRegionFirstBlock = mZRegionFirst >> mVolume.getBlockSideLengthPower(); + mXRegionFirstBlock = mXRegionFirst >> mVolume.m_uBlockSideLengthPower; + mYRegionFirstBlock = mYRegionFirst >> mVolume.m_uBlockSideLengthPower; + mZRegionFirstBlock = mZRegionFirst >> mVolume.m_uBlockSideLengthPower; - mXRegionLastBlock = mXRegionLast >> mVolume.getBlockSideLengthPower(); - mYRegionLastBlock = mYRegionLast >> mVolume.getBlockSideLengthPower(); - mZRegionLastBlock = mZRegionLast >> mVolume.getBlockSideLengthPower(); + mXRegionLastBlock = mXRegionLast >> mVolume.m_uBlockSideLengthPower; + mYRegionLastBlock = mYRegionLast >> mVolume.m_uBlockSideLengthPower; + mZRegionLastBlock = mZRegionLast >> mVolume.m_uBlockSideLengthPower; } template @@ -201,34 +214,34 @@ namespace PolyVox mXPosInBlock++; mCurrentVoxel++; mXPosInVolume++; - if((mXPosInBlock == mVolume.getBlockSideLength()) || (mXPosInVolume > mXRegionLast)) + if((mXPosInBlock == mVolume.m_uBlockSideLength) || (mXPosInVolume > mXRegionLast)) { - mXPosInVolume = (std::max)(mXRegionFirst,uint16_t(mXBlock * mVolume.getBlockSideLength())); - mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.getBlockSideLengthPower()); + mXPosInVolume = (std::max)(mXRegionFirst,uint16_t(mXBlock * mVolume.m_uBlockSideLength)); + mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.m_uBlockSideLengthPower); mVoxelIndexInBlock = mXPosInBlock + - mYPosInBlock * mVolume.getBlockSideLength() + - mZPosInBlock * mVolume.getBlockSideLength() * mVolume.getBlockSideLength(); + mYPosInBlock * mVolume.m_uBlockSideLength + + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; mYPosInBlock++; mYPosInVolume++; - mCurrentVoxel += mVolume.getBlockSideLength(); - if((mYPosInBlock == mVolume.getBlockSideLength()) || (mYPosInVolume > mYRegionLast)) + mCurrentVoxel += mVolume.m_uBlockSideLength; + if((mYPosInBlock == mVolume.m_uBlockSideLength) || (mYPosInVolume > mYRegionLast)) { - mYPosInVolume = (std::max)(mYRegionFirst,uint16_t(mYBlock * mVolume.getBlockSideLength())); - mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.getBlockSideLengthPower()); + mYPosInVolume = (std::max)(mYRegionFirst,uint16_t(mYBlock * mVolume.m_uBlockSideLength)); + mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.m_uBlockSideLengthPower); mVoxelIndexInBlock = mXPosInBlock + - mYPosInBlock * mVolume.getBlockSideLength() + - mZPosInBlock * mVolume.getBlockSideLength() * mVolume.getBlockSideLength(); + mYPosInBlock * mVolume.m_uBlockSideLength + + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; mZPosInBlock++; mZPosInVolume++; - mCurrentVoxel += mVolume.getBlockSideLength() * mVolume.getBlockSideLength(); + mCurrentVoxel += mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; - if((mZPosInBlock == mVolume.getBlockSideLength()) || (mZPosInVolume > mZRegionLast)) + if((mZPosInBlock == mVolume.m_uBlockSideLength) || (mZPosInVolume > mZRegionLast)) { //At this point we've left the current block. Find a new one... @@ -238,20 +251,20 @@ namespace PolyVox { mXBlock = mXRegionFirstBlock; mBlockIndexInVolume = mXBlock + - mYBlock * mVolume.getSideLengthInBlocks() + - mZBlock * mVolume.getSideLengthInBlocks() * mVolume.getSideLengthInBlocks(); + mYBlock * mVolume.m_uSideLengthInBlocks + + mZBlock * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; ++mYBlock; - mBlockIndexInVolume += mVolume.getSideLengthInBlocks(); + mBlockIndexInVolume += mVolume.m_uSideLengthInBlocks; if(mYBlock > mYRegionLastBlock) { mYBlock = mYRegionFirstBlock; mBlockIndexInVolume = mXBlock + - mYBlock * mVolume.getSideLengthInBlocks() + - mZBlock * mVolume.getSideLengthInBlocks() * mVolume.getSideLengthInBlocks(); + mYBlock * mVolume.m_uSideLengthInBlocks + + mZBlock * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; ++mZBlock; - mBlockIndexInVolume += mVolume.getSideLengthInBlocks() * mVolume.getSideLengthInBlocks(); + mBlockIndexInVolume += mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; if(mZBlock > mZRegionLastBlock) { mIsValidForRegion = false; @@ -263,17 +276,17 @@ namespace PolyVox Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; //mCurrentBlock = mVolume->mBlocks[mBlockIndexInVolume]; - mXPosInVolume = (std::max)(mXRegionFirst,uint16_t(mXBlock * mVolume.getBlockSideLength())); - mYPosInVolume = (std::max)(mYRegionFirst,uint16_t(mYBlock * mVolume.getBlockSideLength())); - mZPosInVolume = (std::max)(mZRegionFirst,uint16_t(mZBlock * mVolume.getBlockSideLength())); + mXPosInVolume = (std::max)(mXRegionFirst,uint16_t(mXBlock * mVolume.m_uBlockSideLength)); + mYPosInVolume = (std::max)(mYRegionFirst,uint16_t(mYBlock * mVolume.m_uBlockSideLength)); + mZPosInVolume = (std::max)(mZRegionFirst,uint16_t(mZBlock * mVolume.m_uBlockSideLength)); - mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.getBlockSideLengthPower()); - mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.getBlockSideLengthPower()); - mZPosInBlock = mZPosInVolume - (mZBlock << mVolume.getBlockSideLengthPower()); + mXPosInBlock = mXPosInVolume - (mXBlock << mVolume.m_uBlockSideLengthPower); + mYPosInBlock = mYPosInVolume - (mYBlock << mVolume.m_uBlockSideLengthPower); + mZPosInBlock = mZPosInVolume - (mZBlock << mVolume.m_uBlockSideLengthPower); mVoxelIndexInBlock = mXPosInBlock + - mYPosInBlock * mVolume.getBlockSideLength() + - mZPosInBlock * mVolume.getBlockSideLength() * mVolume.getBlockSideLength(); + mYPosInBlock * mVolume.m_uBlockSideLength + + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; } @@ -290,91 +303,91 @@ namespace PolyVox template VoxelType VolumeIterator::peekVoxel1nx1ny1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - 1 - mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 - mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1nx1ny0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - 1 - mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 - mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1nx1ny1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel - 1 - mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 - mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume-1,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel1nx0py1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - 1 - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1nx0py0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0)) { return *(mCurrentVoxel - 1); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1nx0py1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel - 1 + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel1nx1py1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - 1 + mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 + mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1nx1py0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel - 1 + mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 + mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1nx1py1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != 0) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != 0) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel - 1 + mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - 1 + mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume-1,mYPosInVolume+1,mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -382,41 +395,41 @@ namespace PolyVox template VoxelType VolumeIterator::peekVoxel0px1ny1nz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel0px1ny0pz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - mVolume.getBlockSideLength()); + return *(mCurrentVoxel - mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel0px1ny1pz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel - mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume-1,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel0px0py1nz(void) const { - if((mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume,mZPosInVolume-1); } template @@ -428,41 +441,41 @@ namespace PolyVox template VoxelType VolumeIterator::peekVoxel0px0py1pz(void) const { - if((mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel0px1py1nz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel + mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel0px1py0pz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + mVolume.getBlockSideLength()); + return *(mCurrentVoxel + mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel0px1py1pz(void) const { - if((mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume,mYPosInVolume+1,mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -470,90 +483,90 @@ namespace PolyVox template VoxelType VolumeIterator::peekVoxel1px1ny1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel + 1 - mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 - mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1px1ny0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel + 1 - mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 - mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1px1ny1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != 0) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != 0) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + 1 - mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 - mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume-1,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel1px0py1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel + 1 - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1px0py0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { return *(mCurrentVoxel + 1); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1px0py1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + 1 + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume,mZPosInVolume+1); } template VoxelType VolumeIterator::peekVoxel1px1py1nz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != 0)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != 0)) { - return *(mCurrentVoxel + 1 + mVolume.getBlockSideLength() - mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 + mVolume.m_uBlockSideLength - mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume-1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume-1); } template VoxelType VolumeIterator::peekVoxel1px1py0pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + 1 + mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 + mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume); } template VoxelType VolumeIterator::peekVoxel1px1py1pz(void) const { - if((mXPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mYPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1) && (mZPosInVolume%mVolume.getBlockSideLength() != mVolume.getBlockSideLength()-1)) + if((mXPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mYPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1) && (mZPosInVolume%mVolume.m_uBlockSideLength != mVolume.m_uBlockSideLength-1)) { - return *(mCurrentVoxel + 1 + mVolume.getBlockSideLength() + mVolume.getBlockSideLength()*mVolume.getBlockSideLength()); + return *(mCurrentVoxel + 1 + mVolume.m_uBlockSideLength + mVolume.m_uBlockSideLength*mVolume.m_uBlockSideLength); } - return getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume+1); + return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume+1); } } diff --git a/source/IndexedSurfacePatch.cpp b/source/IndexedSurfacePatch.cpp index 58c3a363..03d40e19 100644 --- a/source/IndexedSurfacePatch.cpp +++ b/source/IndexedSurfacePatch.cpp @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #include "IndexedSurfacePatch.h" using namespace boost; diff --git a/source/MarchingCubesTables.cpp b/source/MarchingCubesTables.cpp index a70252b1..94456686 100644 --- a/source/MarchingCubesTables.cpp +++ b/source/MarchingCubesTables.cpp @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + //Based on code by Paul Bourke //From the article "Polygonising a scalar field" diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index 5e9db3eb..ae9a22e9 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -1,5 +1,6 @@ +#pragma region License /****************************************************************************** -This file is part of a voxel plugin for OGRE +This file is part of the PolyVox library Copyright (C) 2006 David Williams This program is free software; you can redistribute it and/or @@ -16,6 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ +#pragma endregion #include "GradientEstimators.h" #include "IndexedSurfacePatch.h" @@ -80,7 +82,7 @@ namespace PolyVox regionGeometry.m_patchMultiMaterial = new IndexedSurfacePatch(true); regionGeometry.m_v3dRegionPosition = Vector3DInt32(regionX, regionY, regionZ); - generateMeshDataForRegion(regionX,regionY,regionZ, regionGeometry.m_patchSingleMaterial, regionGeometry.m_patchMultiMaterial); + generateRoughMeshDataForRegion(regionX,regionY,regionZ, regionGeometry.m_patchSingleMaterial, regionGeometry.m_patchMultiMaterial); regionGeometry.m_bContainsSingleMaterialPatch = regionGeometry.m_patchSingleMaterial->getVertices().size() > 0; regionGeometry.m_bContainsMultiMaterialPatch = regionGeometry.m_patchMultiMaterial->getVertices().size() > 0; @@ -159,15 +161,15 @@ namespace PolyVox markRegionChanged(firstX,firstY,firstZ,lastX,lastY,lastZ); } - void PolyVoxSceneManager::generateMeshDataForRegion(const uint16_t regionX, const uint16_t regionY, const uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const + void PolyVoxSceneManager::generateRoughMeshDataForRegion(const uint16_t regionX, const uint16_t regionY, const uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const { //First and last voxels in the region const uint16_t firstX = regionX * POLYVOX_REGION_SIDE_LENGTH; const uint16_t firstY = regionY * POLYVOX_REGION_SIDE_LENGTH; const uint16_t firstZ = regionZ * POLYVOX_REGION_SIDE_LENGTH; - const uint16_t lastX = (std::min)(firstX + POLYVOX_REGION_SIDE_LENGTH-1,static_cast(volumeData->getSideLength()-2)); - const uint16_t lastY = (std::min)(firstY + POLYVOX_REGION_SIDE_LENGTH-1,static_cast(volumeData->getSideLength()-2)); - const uint16_t lastZ = (std::min)(firstZ + POLYVOX_REGION_SIDE_LENGTH-1,static_cast(volumeData->getSideLength()-2)); + const uint16_t lastX = (std::min)(firstX + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); + const uint16_t lastY = (std::min)(firstY + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); + const uint16_t lastZ = (std::min)(firstZ + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); //Offset from lower block corner const Vector3DFloat offset(firstX,firstY,firstZ); @@ -323,12 +325,359 @@ namespace PolyVox //If all the materials are the same, we just need one triangle for that material with all the alphas set high. if((material0 == material1) && (material1 == material2)) { - SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1,1.0); - SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1,1.0); - SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1,1.0); + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1f,1.0f); singleMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); } else if(material0 == material1) + { + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material0 + 0.1f,0.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material2 + 0.1f,0.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material2 + 0.1f,0.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1f,1.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + } + else if(material0 == material2) + { + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material0 + 0.1f,0.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material0 + 0.1f,1.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material1 + 0.1f,0.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material1 + 0.1f,0.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + } + else if(material1 == material2) + { + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material1 + 0.1f,0.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material1 + 0.1f,1.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material0 + 0.1f,0.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material0 + 0.1f,0.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + } + else + { + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material0 + 0.1f,0.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material0 + 0.1f,0.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material1 + 0.1f,0.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material1 + 0.1f,0.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + + { + SurfaceVertex surfaceVertex0Alpha1(vertex0,material2 + 0.1f,0.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material2 + 0.1f,0.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1f,1.0f); + multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + } + } + //If there not all the same, we need one triangle for each unique material. + //We'll also need some vertices with low alphas for blending. + /*else + { + SurfaceVertex surfaceVertex0Alpha0(vertex0,0.0); + SurfaceVertex surfaceVertex1Alpha0(vertex1,0.0); + SurfaceVertex surfaceVertex2Alpha0(vertex2,0.0); + + if(material0 == material1) + { + surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha0); + surfacePatchMapResult[material2]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha0, surfaceVertex2Alpha1); + } + else if(material1 == material2) + { + surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha0); + } + else if(material2 == material0) + { + surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha1); + surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha0); + } + else + { + surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha0); + surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha0); + surfacePatchMapResult[material2]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha0, surfaceVertex2Alpha1); + } + }*/ + }//For each triangle + }//For each cell + + //FIXME - can it happen that we have no vertices or triangles? Should exit early? + + + //for(std::map::iterator iterPatch = surfacePatchMapResult.begin(); iterPatch != surfacePatchMapResult.end(); ++iterPatch) + { + + std::vector::iterator iterSurfaceVertex = singleMaterialPatch->getVertices().begin(); + while(iterSurfaceVertex != singleMaterialPatch->getVertices().end()) + { + Vector3DFloat tempNormal = computeNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); + const_cast(*iterSurfaceVertex).setNormal(tempNormal); + ++iterSurfaceVertex; + } + + iterSurfaceVertex = multiMaterialPatch->getVertices().begin(); + while(iterSurfaceVertex != multiMaterialPatch->getVertices().end()) + { + Vector3DFloat tempNormal = computeNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); + const_cast(*iterSurfaceVertex).setNormal(tempNormal); + ++iterSurfaceVertex; + } + + uint16_t noOfRemovedVertices = 0; + //do + { + //noOfRemovedVertices = iterPatch->second.decimate(); + } + //while(noOfRemovedVertices > 10); //We don't worry about the last few vertices - it's not worth the overhead of calling the function. + } + + //return singleMaterialPatch; + } + + void PolyVoxSceneManager::generateSmoothMeshDataForRegion(const uint16_t regionX, const uint16_t regionY, const uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const + { + //First and last voxels in the region + const uint16_t firstX = regionX * POLYVOX_REGION_SIDE_LENGTH; + const uint16_t firstY = regionY * POLYVOX_REGION_SIDE_LENGTH; + const uint16_t firstZ = regionZ * POLYVOX_REGION_SIDE_LENGTH; + const uint16_t lastX = (std::min)(firstX + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); + const uint16_t lastY = (std::min)(firstY + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); + const uint16_t lastZ = (std::min)(firstZ + POLYVOX_REGION_SIDE_LENGTH-1,volumeData->getSideLength()-2); + + //Offset from lower block corner + const Vector3DFloat offset(firstX,firstY,firstZ); + + Vector3DFloat vertlist[12]; + uint8_t vertMaterials[12]; + VolumeIterator volIter(*volumeData); + volIter.setValidRegion(firstX,firstY,firstZ,lastX,lastY,lastZ); + + const float threshold = 0.5f; + + ////////////////////////////////////////////////////////////////////////// + //Get mesh data + ////////////////////////////////////////////////////////////////////////// + + //Iterate over each cell in the region + for(volIter.setPosition(firstX,firstY,firstZ);volIter.isValidForRegion();volIter.moveForwardInRegion()) + { + //Current position + const uint16_t x = volIter.getPosX(); + const uint16_t y = volIter.getPosY(); + const uint16_t z = volIter.getPosZ(); + + //Voxels values + VolumeIterator tempVolIter(*volumeData); + tempVolIter.setPosition(x,y,z); + const float v000 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x+1,y,z); + const float v100 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x,y+1,z); + const float v010 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x+1,y+1,z); + const float v110 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x,y,z+1); + const float v001 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x+1,y,z+1); + const float v101 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x,y+1,z+1); + const float v011 = tempVolIter.getAveragedVoxel(1); + tempVolIter.setPosition(x+1,y+1,z+1); + const float v111 = tempVolIter.getAveragedVoxel(1); + + //Determine the index into the edge table which tells us which vertices are inside of the surface + uint8_t iCubeIndex = 0; + + if (v000 < threshold) iCubeIndex |= 1; + if (v100 < threshold) iCubeIndex |= 2; + if (v110 < threshold) iCubeIndex |= 4; + if (v010 < threshold) iCubeIndex |= 8; + if (v001 < threshold) iCubeIndex |= 16; + if (v101 < threshold) iCubeIndex |= 32; + if (v111 < threshold) iCubeIndex |= 64; + if (v011 < threshold) iCubeIndex |= 128; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[iCubeIndex] == 0) + { + continue; + } + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[iCubeIndex] & 1) + { + float a = v000; + float b = v100; + float val = (threshold-a)/(b-a); + vertlist[0].setX(x + val); + vertlist[0].setY(y); + vertlist[0].setZ(z); + vertMaterials[0] = 1;//v000 | v100; //Because one of these is 0, the or operation takes the max. + } + if (edgeTable[iCubeIndex] & 2) + { + float a = v100; + float b = v110; + float val = (threshold-a)/(b-a); + vertlist[1].setX(x + 1.0f); + vertlist[1].setY(y + val); + vertlist[1].setZ(z); + vertMaterials[1] = 1;//v100 | v110; + } + if (edgeTable[iCubeIndex] & 4) + { + float a = v010; + float b = v110; + float val = (threshold-a)/(b-a); + vertlist[2].setX(x + val); + vertlist[2].setY(y + 1.0f); + vertlist[2].setZ(z); + vertMaterials[2] = 1;//v010 | v110; + } + if (edgeTable[iCubeIndex] & 8) + { + float a = v000; + float b = v010; + float val = (threshold-a)/(b-a); + vertlist[3].setX(x); + vertlist[3].setY(y + val); + vertlist[3].setZ(z); + vertMaterials[3] = 1;//v000 | v010; + } + if (edgeTable[iCubeIndex] & 16) + { + float a = v001; + float b = v101; + float val = (threshold-a)/(b-a); + vertlist[4].setX(x + val); + vertlist[4].setY(y); + vertlist[4].setZ(z + 1.0f); + vertMaterials[4] = 1;//v001 | v101; + } + if (edgeTable[iCubeIndex] & 32) + { + float a = v101; + float b = v111; + float val = (threshold-a)/(b-a); + vertlist[5].setX(x + 1.0f); + vertlist[5].setY(y + val); + vertlist[5].setZ(z + 1.0f); + vertMaterials[5] = 1;//v101 | v111; + } + if (edgeTable[iCubeIndex] & 64) + { + float a = v011; + float b = v111; + float val = (threshold-a)/(b-a); + vertlist[6].setX(x + val); + vertlist[6].setY(y + 1.0f); + vertlist[6].setZ(z + 1.0f); + vertMaterials[6] = 1;//v011 | v111; + } + if (edgeTable[iCubeIndex] & 128) + { + float a = v001; + float b = v011; + float val = (threshold-a)/(b-a); + vertlist[7].setX(x); + vertlist[7].setY(y + val); + vertlist[7].setZ(z + 1.0f); + vertMaterials[7] = 1;//v001 | v011; + } + if (edgeTable[iCubeIndex] & 256) + { + float a = v000; + float b = v001; + float val = (threshold-a)/(b-a); + vertlist[8].setX(x); + vertlist[8].setY(y); + vertlist[8].setZ(z + val); + vertMaterials[8] = 1;//v000 | v001; + } + if (edgeTable[iCubeIndex] & 512) + { + float a = v100; + float b = v101; + float val = (threshold-a)/(b-a); + vertlist[9].setX(x + 1.0f); + vertlist[9].setY(y); + vertlist[9].setZ(z + val); + vertMaterials[9] = 1;//v100 | v101; + } + if (edgeTable[iCubeIndex] & 1024) + { + float a = v110; + float b = v111; + float val = (threshold-a)/(b-a); + vertlist[10].setX(x + 1.0f); + vertlist[10].setY(y + 1.0f); + vertlist[10].setZ(z + val); + vertMaterials[10] = 1;//v110 | v111; + } + if (edgeTable[iCubeIndex] & 2048) + { + float a = v010; + float b = v011; + float val = (threshold-a)/(b-a); + vertlist[11].setX(x); + vertlist[11].setY(y + 1.0f); + vertlist[11].setZ(z + val); + vertMaterials[11] = 1;//v010 | v011; + } + + for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) + { + //The three vertices forming a triangle + const Vector3DFloat vertex0 = vertlist[triTable[iCubeIndex][i ]] - offset; + const Vector3DFloat vertex1 = vertlist[triTable[iCubeIndex][i+1]] - offset; + const Vector3DFloat vertex2 = vertlist[triTable[iCubeIndex][i+2]] - offset; + + const uint8_t material0 = vertMaterials[triTable[iCubeIndex][i ]]; + const uint8_t material1 = vertMaterials[triTable[iCubeIndex][i+1]]; + const uint8_t material2 = vertMaterials[triTable[iCubeIndex][i+2]]; + + //If all the materials are the same, we just need one triangle for that material with all the alphas set high. + /*if((material0 == material1) && (material1 == material2)) + {*/ + SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); + SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); + SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1f,1.0f); + singleMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); + /*} + else if(material0 == material1) { { SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1,1.0); @@ -398,37 +747,7 @@ namespace PolyVox SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1,1.0); multiMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); } - } - //If there not all the same, we need one triangle for each unique material. - //We'll also need some vertices with low alphas for blending. - /*else - { - SurfaceVertex surfaceVertex0Alpha0(vertex0,0.0); - SurfaceVertex surfaceVertex1Alpha0(vertex1,0.0); - SurfaceVertex surfaceVertex2Alpha0(vertex2,0.0); - - if(material0 == material1) - { - surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha0); - surfacePatchMapResult[material2]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha0, surfaceVertex2Alpha1); - } - else if(material1 == material2) - { - surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha1); - surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha0); - } - else if(material2 == material0) - { - surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha1); - surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha0); - } - else - { - surfacePatchMapResult[material0]->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha0, surfaceVertex2Alpha0); - surfacePatchMapResult[material1]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha1, surfaceVertex2Alpha0); - surfacePatchMapResult[material2]->addTriangle(surfaceVertex0Alpha0, surfaceVertex1Alpha0, surfaceVertex2Alpha1); - } - }*/ + }*/ }//For each triangle }//For each cell @@ -441,7 +760,7 @@ namespace PolyVox std::vector::iterator iterSurfaceVertex = singleMaterialPatch->getVertices().begin(); while(iterSurfaceVertex != singleMaterialPatch->getVertices().end()) { - Vector3DFloat tempNormal = computeNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); + Vector3DFloat tempNormal = computeSmoothNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); const_cast(*iterSurfaceVertex).setNormal(tempNormal); ++iterSurfaceVertex; } @@ -449,20 +768,11 @@ namespace PolyVox iterSurfaceVertex = multiMaterialPatch->getVertices().begin(); while(iterSurfaceVertex != multiMaterialPatch->getVertices().end()) { - Vector3DFloat tempNormal = computeNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); + Vector3DFloat tempNormal = computeSmoothNormal(static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); const_cast(*iterSurfaceVertex).setNormal(tempNormal); ++iterSurfaceVertex; } - - uint16_t noOfRemovedVertices = 0; - //do - { - //noOfRemovedVertices = iterPatch->second.decimate(); - } - //while(noOfRemovedVertices > 10); //We don't worry about the last few vertices - it's not worth the overhead of calling the function. } - - //return singleMaterialPatch; } Vector3DFloat PolyVoxSceneManager::computeNormal(const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) const @@ -545,17 +855,113 @@ namespace PolyVox if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 { uint8_t uCeil = volIter.peekVoxel1px0py0pz() > 0 ? 1 : 0; - result = Vector3DFloat(uFloor - uCeil,0.0,0.0); + result = Vector3DFloat(static_cast(uFloor - uCeil),0.0,0.0); } else if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 { uint8_t uCeil = volIter.peekVoxel0px1py0pz() > 0 ? 1 : 0; - result = Vector3DFloat(0.0,uFloor - uCeil,0.0); + result = Vector3DFloat(0.0,static_cast(uFloor - uCeil),0.0); } else if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 { uint8_t uCeil = volIter.peekVoxel0px0py1pz() > 0 ? 1 : 0; - result = Vector3DFloat(0.0, 0.0,uFloor - uCeil); + result = Vector3DFloat(0.0, 0.0,static_cast(uFloor - uCeil)); + } + } + return result; + } + + Vector3DFloat PolyVoxSceneManager::computeSmoothNormal(const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) const + { + + + const float posX = position.x(); + const float posY = position.y(); + const float posZ = position.z(); + + const uint16_t floorX = static_cast(posX); + const uint16_t floorY = static_cast(posY); + const uint16_t floorZ = static_cast(posZ); + + //Check all corners are within the volume, allowing a boundary for gradient estimation + bool lowerCornerInside = volumeData->containsPoint(Vector3DInt32(floorX, floorY, floorZ),1); + bool upperCornerInside = volumeData->containsPoint(Vector3DInt32(floorX+1, floorY+1, floorZ+1),1); + if((!lowerCornerInside) || (!upperCornerInside)) + { + normalGenerationMethod = SIMPLE; + } + + Vector3DFloat result; + + VolumeIterator volIter(*volumeData); //FIXME - save this somewhere - could be expensive to create? + + + if(normalGenerationMethod == SOBEL) + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const Vector3DFloat gradFloor = computeSobelGradient(volIter); + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); + } + if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); + } + if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); + } + const Vector3DFloat gradCeil = computeSobelGradient(volIter); + result = ((gradFloor + gradCeil) * -1.0); + if(result.lengthSquared() < 0.0001) + { + //Operation failed - fall back on simple gradient estimation + normalGenerationMethod = SIMPLE; + } + } + if(normalGenerationMethod == CENTRAL_DIFFERENCE) + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const Vector3DFloat gradFloor = computeSmoothCentralDifferenceGradient(volIter); + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); + } + if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); + } + if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); + } + const Vector3DFloat gradCeil = computeSmoothCentralDifferenceGradient(volIter); + result = ((gradFloor + gradCeil) * -1.0); + if(result.lengthSquared() < 0.0001) + { + //Operation failed - fall back on simple gradient estimation + normalGenerationMethod = SIMPLE; + } + } + if(normalGenerationMethod == SIMPLE) + { + volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); + const uint8_t uFloor = volIter.getVoxel() > 0 ? 1 : 0; + if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 + { + uint8_t uCeil = volIter.peekVoxel1px0py0pz() > 0 ? 1 : 0; + result = Vector3DFloat(static_cast(uFloor - uCeil),0.0,0.0); + } + else if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 + { + uint8_t uCeil = volIter.peekVoxel0px1py0pz() > 0 ? 1 : 0; + result = Vector3DFloat(0.0,static_cast(uFloor - uCeil),0.0); + } + else if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 + { + uint8_t uCeil = volIter.peekVoxel0px0py1pz() > 0 ? 1 : 0; + result = Vector3DFloat(0.0, 0.0,static_cast(uFloor - uCeil)); } } return result; @@ -649,7 +1055,7 @@ namespace PolyVox m_normalGenerationMethod = method; } - bool PolyVoxSceneManager::containsPoint(Vector3DFloat pos, float boundary) + /*bool PolyVoxSceneManager::containsPoint(Vector3DFloat pos, float boundary) { return volumeData->containsPoint(pos, boundary); } @@ -657,7 +1063,7 @@ namespace PolyVox bool PolyVoxSceneManager::containsPoint(Vector3DInt32 pos, uint16_t boundary) { return volumeData->containsPoint(pos, boundary); - } + }*/ /* @@ -666,4 +1072,9 @@ namespace PolyVox if(m_axisNode) m_axisNode->setVisible(visible); }*/ + + const Volume* PolyVoxSceneManager::getVolumeData(void) const + { + return volumeData; + } } diff --git a/source/RegionGeometry.cpp b/source/RegionGeometry.cpp index b4659027..1c486372 100644 --- a/source/RegionGeometry.cpp +++ b/source/RegionGeometry.cpp @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #include "IndexedSurfacePatch.h" #include "RegionGeometry.h" diff --git a/source/SurfaceVertex.cpp b/source/SurfaceVertex.cpp index 83eee643..00084c24 100644 --- a/source/SurfaceVertex.cpp +++ b/source/SurfaceVertex.cpp @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #include #include "Constants.h" diff --git a/source/Utility.cpp b/source/Utility.cpp index a17f1a3b..ab53bd71 100644 --- a/source/Utility.cpp +++ b/source/Utility.cpp @@ -1,3 +1,24 @@ +#pragma region License +/****************************************************************************** +This file is part of the PolyVox library +Copyright (C) 2006 David Williams + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +******************************************************************************/ +#pragma endregion + #include "Utility.h" #include