diff --git a/CMakeLists.txt b/CMakeLists.txt index 52bb107d..aa16d384 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ SET(SRC_FILES source/PolyVoxSceneManager.cpp source/RegionGeometry.cpp source/SurfaceVertex.cpp + source/Utility.cpp ) #Projects headers files @@ -16,6 +17,8 @@ SET(INC_FILES include/Constants.h include/GradientEstimators.h include/GradientEstimators.inl + include/LinearVolume.h + include/LinearVolume.inl include/IndexedSurfacePatch.h include/MarchingCubesTables.h include/PolyVoxForwardDeclarations.h @@ -23,6 +26,7 @@ SET(INC_FILES include/RegionGeometry.h include/SurfaceVertex.h include/TypeDef.h + include/Utility.h include/Vector.h include/Vector.inl include/Volume.h diff --git a/include/Constants.h b/include/Constants.h index 709bd674..925412bd 100644 --- a/include/Constants.h +++ b/include/Constants.h @@ -19,9 +19,6 @@ namespace PolyVox 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::uint32_t POLYVOX_NO_OF_REGIONS_IN_VOLUME = (POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS * POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS * POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS); - - const boost::uint32_t POLYVOX_MAX_VOXELS_TO_BURN_PER_FRAME = 1000; } #endif diff --git a/include/LinearVolume.h b/include/LinearVolume.h new file mode 100644 index 00000000..a8d84a50 --- /dev/null +++ b/include/LinearVolume.h @@ -0,0 +1,64 @@ +#pragma region License +/****************************************************************************** +This file is part of a voxel plugin for OGRE +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_LinearVolume_H__ +#define __PolyVox_LinearVolume_H__ + +#pragma region Headers +#include "Constants.h" +#include "PolyVoxForwardDeclarations.h" +#include "TypeDef.h" + +#include "boost/cstdint.hpp" +#pragma endregion + +namespace PolyVox +{ + template + class LinearVolume + { + public: + LinearVolume(boost::uint8_t uSideLengthPower); + LinearVolume(const LinearVolume& rhs); + ~LinearVolume(); + + LinearVolume& operator=(const LinearVolume& rhs); + + //bool isHomogeneous(void); + + 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); + + private: + boost::uint32_t getNoOfVoxels(void); + boost::uint8_t m_uSideLengthPower; + boost::uint16_t m_uSideLength; + VoxelType* m_tData; + }; +} + +#include "LinearVolume.inl" + +#endif diff --git a/include/LinearVolume.inl b/include/LinearVolume.inl new file mode 100644 index 00000000..eb2a6837 --- /dev/null +++ b/include/LinearVolume.inl @@ -0,0 +1,100 @@ +/****************************************************************************** +This file is part of a voxel plugin for OGRE +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. +******************************************************************************/ + +#include + +namespace PolyVox +{ + + template + LinearVolume::LinearVolume(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); + + //Compute the side length + m_uSideLengthPower = uSideLengthPower; + m_uSideLength = 0x01 << uSideLengthPower; + + //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()]; + } + + template + LinearVolume::LinearVolume(const LinearVolume& rhs) + { + *this = rhs; + } + + template + LinearVolume::~LinearVolume() + { + delete[] m_tData; + m_tData = 0; + } + + template + LinearVolume& LinearVolume::operator=(const LinearVolume& rhs) + { + if (this == &rhs) + { + return *this; + } + + memcpy(m_tData,rhs.m_tData,getNoOfVoxels()); + + return *this; + } + + template + VoxelType LinearVolume::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 LinearVolume::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 LinearVolume::getSideLength(void) + { + return m_uSideLength; + } + + template + boost::uint32_t LinearVolume::getNoOfVoxels(void) + { + return m_uSideLength * m_uSideLength * m_uSideLength; + } +} diff --git a/include/PolyVoxForwardDeclarations.h b/include/PolyVoxForwardDeclarations.h index b4958628..184ccf13 100644 --- a/include/PolyVoxForwardDeclarations.h +++ b/include/PolyVoxForwardDeclarations.h @@ -8,6 +8,7 @@ namespace PolyVox template class Block; class IndexedSurfacePatch; class IntegrealVector3; + template class LinearVolume; class PolyVoxSceneManager; class RegionGeometry; class SurfaceVertex; diff --git a/include/PolyVoxSceneManager.h b/include/PolyVoxSceneManager.h index 0a7d912d..4c602933 100644 --- a/include/PolyVoxSceneManager.h +++ b/include/PolyVoxSceneManager.h @@ -51,6 +51,7 @@ namespace PolyVox //Setters + void setVolumeData(Volume* volumeDataToSet); void setNormalGenerationMethod(NormalGenerationMethod method); //void _findVisibleObjects(Camera* cam, VisibleObjectsBoundsInfo * visibleBounds, bool onlyShadowCasters); @@ -61,15 +62,13 @@ 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 generateMeshDataForRegion(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 surfaceUpToDate[POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS][POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS][POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS]; - bool regionIsHomogenous[POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS][POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS][POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS]; + LinearVolume* volSurfaceUpToDate; Vector3DFloat computeNormal(const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) const; @@ -85,7 +84,7 @@ namespace PolyVox NormalGenerationMethod m_normalGenerationMethod; - + private: Volume* volumeData; bool m_bHaveGeneratedMeshes; diff --git a/include/Utility.h b/include/Utility.h new file mode 100644 index 00000000..750d577d --- /dev/null +++ b/include/Utility.h @@ -0,0 +1,14 @@ +#ifndef __PolyVox_Utility_H__ +#define __PolyVox_Utility_H__ + +#include "Typedef.h" + +#include "boost/cstdint.hpp" + +namespace PolyVox +{ + POLYVOX_API boost::uint8_t logBase2(boost::uint32_t uInput); + POLYVOX_API bool isPowerOf2(boost::uint32_t uInput); +} + +#endif \ No newline at end of file diff --git a/include/VolumeIterator.inl b/include/VolumeIterator.inl index b4c27273..d0623766 100644 --- a/include/VolumeIterator.inl +++ b/include/VolumeIterator.inl @@ -186,14 +186,6 @@ namespace PolyVox mYRegionLast = yLast; mZRegionLast = zLast; - /*mXRegionFirst = (std::max)(0,xFirst); - mYRegionFirst = (std::max)(0,yFirst); - mZRegionFirst = (std::max)(0,zFirst); - - mXRegionLast = (std::min)(POLYVOX_VOLUME_SIDE_LENGTH-1, xLast); - mYRegionLast = (std::min)(POLYVOX_VOLUME_SIDE_LENGTH-1, yLast); - mZRegionLast = (std::min)(POLYVOX_VOLUME_SIDE_LENGTH-1, zLast);*/ - mXRegionFirstBlock = mXRegionFirst >> mVolume.getBlockSideLengthPower(); mYRegionFirstBlock = mYRegionFirst >> mVolume.getBlockSideLengthPower(); mZRegionFirstBlock = mZRegionFirst >> mVolume.getBlockSideLengthPower(); diff --git a/source/PolyVoxSceneManager.cpp b/source/PolyVoxSceneManager.cpp index 8b779e87..5e9db3eb 100644 --- a/source/PolyVoxSceneManager.cpp +++ b/source/PolyVoxSceneManager.cpp @@ -19,10 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "GradientEstimators.h" #include "IndexedSurfacePatch.h" +#include "LinearVolume.h" #include "MarchingCubesTables.h" #include "PolyVoxSceneManager.h" #include "RegionGeometry.h" #include "SurfaceVertex.h" +#include "Utility.h" #include "Vector.h" #include "Volume.h" #include "VolumeIterator.h" @@ -42,13 +44,19 @@ namespace PolyVox ,m_normalGenerationMethod(SOBEL) ,m_bHaveGeneratedMeshes(false) { - //sceneNodes.clear(); + //sceneNodes.clear();` } PolyVoxSceneManager::~PolyVoxSceneManager() { } + void PolyVoxSceneManager::setVolumeData(Volume* volumeDataToSet) + { + volumeData = volumeDataToSet; + volSurfaceUpToDate = new LinearVolume(PolyVox::logBase2(POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS)); + } + std::list PolyVoxSceneManager::getChangedRegionGeometry(void) { std::list listChangedRegionGeometry; @@ -63,7 +71,8 @@ namespace PolyVox for(uint16_t regionX = 0; regionX < POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS; ++regionX) //for(uint16_t regionX = 3; regionX < 4; ++regionX) { - if(surfaceUpToDate[regionX][regionY][regionZ] == false) + //if(surfaceUpToDate[regionX][regionY][regionZ] == false) + if(volSurfaceUpToDate->getVoxelAt(regionX, regionY, regionZ) == false) { //Generate the surface RegionGeometry regionGeometry; @@ -94,7 +103,8 @@ namespace PolyVox { for(uint16_t blockX = 0; blockX < POLYVOX_VOLUME_SIDE_LENGTH_IN_REGIONS; ++blockX) { - surfaceUpToDate[blockX][blockY][blockZ] = newUpToDateValue; + //surfaceUpToDate[blockX][blockY][blockZ] = newUpToDateValue; + volSurfaceUpToDate->setVoxelAt(blockX, blockY, blockZ, newUpToDateValue); } } } @@ -149,93 +159,6 @@ namespace PolyVox markRegionChanged(firstX,firstY,firstZ,lastX,lastY,lastZ); } - /*void PolyVoxSceneManager::generateLevelVolume(void) - { - //volumeData = VolumePtr(new Volume); - volumeData = new Volume(POLYVOX_VOLUME_SIDE_LENGTH_POWER); - VolumeIterator volIter(*volumeData); - for(uint16_t z = 0; z < POLYVOX_VOLUME_SIDE_LENGTH; ++z) - { - for(uint16_t y = 0; y < POLYVOX_VOLUME_SIDE_LENGTH; ++y) - { - for(uint16_t x = 0; x < POLYVOX_VOLUME_SIDE_LENGTH; ++x) - { - volIter.setPosition(x,y,z); - if((x/16+y/16+z/16)%2 == 0) - volIter.setVoxel(4); - else - volIter.setVoxel(8); - } - } - } - - for(uint16_t z = 0; z < POLYVOX_VOLUME_SIDE_LENGTH; ++z) - { - for(uint16_t y = 0; y < POLYVOX_VOLUME_SIDE_LENGTH; ++y) - { - for(uint16_t x = 0; x < POLYVOX_VOLUME_SIDE_LENGTH; ++x) - { - if( - (z<62)|| - (z>193)|| - (y<78)|| - (y>177)|| - (x<30)|| - (x>225) - ) - { - volIter.setPosition(x,y,z); - volIter.setVoxel(2); - } - } - } - } - - //Rooms - Vector3DFloat centre(128,128,128); - Vector3DFloat v3dSize(192,96,128); - - uint16_t uHalfX = static_cast(v3dSize.x() / 2); - uint16_t uHalfY = static_cast(v3dSize.y() / 2); - uint16_t uHalfZ = static_cast(v3dSize.z() / 2); - - for(uint16_t z = static_cast(centre.z()) - uHalfZ; z < static_cast(centre.z()) + uHalfZ; z++) - { - for(uint16_t y = static_cast(centre.y()) - uHalfY; y < static_cast(centre.y()) + uHalfY; y++) - { - for(uint16_t x = static_cast(centre.x()) - uHalfX; x < static_cast(centre.x()) + uHalfX; x++) - { - volIter.setPosition(x,y,z); - volIter.setVoxel(0); - } - } - } - - for(uint16_t z = 0; z < POLYVOX_VOLUME_SIDE_LENGTH; ++z) - { - for(uint16_t y = 0; y < POLYVOX_VOLUME_SIDE_LENGTH; ++y) - { - for(uint16_t x = 0; x < POLYVOX_VOLUME_SIDE_LENGTH; ++x) - { - if( - (x%64 < 8) && - (y < 128) && - (z>=62)&& - (z<=193)&& - (y>=78)&& - (y<=177)&& - (x>=30)&& - (x<=225) - ) - { - volIter.setPosition(x,y,z); - volIter.setVoxel(1); - } - } - } - } - }*/ - void PolyVoxSceneManager::generateMeshDataForRegion(const uint16_t regionX, const uint16_t regionY, const uint16_t regionZ, IndexedSurfacePatch* singleMaterialPatch, IndexedSurfacePatch* multiMaterialPatch) const { //First and last voxels in the region @@ -648,7 +571,8 @@ namespace PolyVox (z % POLYVOX_REGION_SIDE_LENGTH != 0) && (z % POLYVOX_REGION_SIDE_LENGTH != POLYVOX_REGION_SIDE_LENGTH-1)) { - surfaceUpToDate[x >> POLYVOX_REGION_SIDE_LENGTH_POWER][y >> POLYVOX_REGION_SIDE_LENGTH_POWER][z >> POLYVOX_REGION_SIDE_LENGTH_POWER] = false; + //surfaceUpToDate[x >> POLYVOX_REGION_SIDE_LENGTH_POWER][y >> POLYVOX_REGION_SIDE_LENGTH_POWER][z >> POLYVOX_REGION_SIDE_LENGTH_POWER] = false; + volSurfaceUpToDate->setVoxelAt(x >> POLYVOX_REGION_SIDE_LENGTH_POWER, y >> POLYVOX_REGION_SIDE_LENGTH_POWER, z >> POLYVOX_REGION_SIDE_LENGTH_POWER, false); } else //Mark surrounding block as well { @@ -670,7 +594,8 @@ namespace PolyVox { for(uint16_t xCt = minRegionX; xCt <= maxRegionX; xCt++) { - surfaceUpToDate[xCt][yCt][zCt] = false; + //surfaceUpToDate[xCt][yCt][zCt] = false; + volSurfaceUpToDate->setVoxelAt(xCt,yCt,zCt,false); } } } @@ -693,7 +618,8 @@ namespace PolyVox { for(uint16_t xCt = firstRegionX; xCt <= lastRegionX; xCt++) { - surfaceUpToDate[xCt][yCt][zCt] = false; + //surfaceUpToDate[xCt][yCt][zCt] = false; + volSurfaceUpToDate->setVoxelAt(xCt,yCt,zCt,false); } } } diff --git a/source/Utility.cpp b/source/Utility.cpp new file mode 100644 index 00000000..a17f1a3b --- /dev/null +++ b/source/Utility.cpp @@ -0,0 +1,38 @@ +#include "Utility.h" + +#include + +namespace PolyVox +{ + //Note: this function only works for inputs which are a power of two and not zero + //If this is not the case then the output is undefined. + boost::uint8_t logBase2(boost::uint32_t uInput) + { + assert(uInput != 0); + assert(isPowerOf2(uInput)); + + boost::uint8_t result = 0; + uInput = uInput >> 1; + while(uInput) + { + uInput = uInput >> 1; + ++result; + } + return result; + } + + bool isPowerOf2(boost::uint32_t uInput) + { + boost::uint8_t uNonZeroBits = 0; + boost::uint32_t uMask = 0x00000001; + for(boost::uint8_t ct = 0; ct < 32; ++ct) + { + if(uInput & uMask) + { + ++uNonZeroBits; + } + uMask = uMask << 1; + } + return uNonZeroBits == 1 ? true : false; + } +} \ No newline at end of file