Reverted some of ker's changes to bring back the concepts of width, height, and depth.
This commit is contained in:
		| @@ -58,9 +58,9 @@ void OpenGLWidget::setVolume(PolyVox::Volume<MaterialDensityPair44>* volData) | |||||||
| 	//If we have any volume data then generate the new surface patches. | 	//If we have any volume data then generate the new surface patches. | ||||||
| 	if(m_volData != 0) | 	if(m_volData != 0) | ||||||
| 	{ | 	{ | ||||||
| 		m_uVolumeWidthInRegions = g_uVolumeSideLength / m_uRegionSideLength; | 		m_uVolumeWidthInRegions = volData->getWidth() / m_uRegionSideLength; | ||||||
| 		m_uVolumeHeightInRegions = g_uVolumeSideLength / m_uRegionSideLength; | 		m_uVolumeHeightInRegions = volData->getHeight() / m_uRegionSideLength; | ||||||
| 		m_uVolumeDepthInRegions = g_uVolumeSideLength / m_uRegionSideLength; | 		m_uVolumeDepthInRegions = volData->getDepth() / m_uRegionSideLength; | ||||||
|  |  | ||||||
| 		//Our volume is broken down into cuboid regions, and we create one mesh for each region. | 		//Our volume is broken down into cuboid regions, and we create one mesh for each region. | ||||||
| 		//This three-level for loop iterates over each region. | 		//This three-level for loop iterates over each region. | ||||||
| @@ -180,9 +180,8 @@ void OpenGLWidget::paintGL() | |||||||
| 		glMatrixMode(GL_MODELVIEW);  // Select The Model View Matrix | 		glMatrixMode(GL_MODELVIEW);  // Select The Model View Matrix | ||||||
| 		glLoadIdentity();									// Reset The Current Modelview Matrix | 		glLoadIdentity();									// Reset The Current Modelview Matrix | ||||||
|  |  | ||||||
| 		float diag_len = sqrtf(static_cast<float>(255 * 255 * 3)); |  | ||||||
| 		//Moves the camera back so we can see the volume | 		//Moves the camera back so we can see the volume | ||||||
| 		glTranslatef(0.0f, 0.0f, -diag_len); | 		glTranslatef(0.0f, 0.0f, -m_volData->getDiagonalLength());	 | ||||||
|  |  | ||||||
| 		glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); | 		glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); | ||||||
| 		glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); | 		glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); | ||||||
| @@ -249,8 +248,7 @@ void OpenGLWidget::setupProjectionMatrix(void) | |||||||
| 	glMatrixMode(GL_PROJECTION); | 	glMatrixMode(GL_PROJECTION); | ||||||
| 	glLoadIdentity(); | 	glLoadIdentity(); | ||||||
|  |  | ||||||
| 	float diag_len = sqrtf(static_cast<float>(255 * 255 * 3)); | 	float frustumSize = m_volData->getDiagonalLength() / 2.0f; | ||||||
| 	float frustumSize = diag_len / 2.0f; |  | ||||||
| 	float aspect = static_cast<float>(width()) / static_cast<float>(height()); | 	float aspect = static_cast<float>(width()) / static_cast<float>(height()); | ||||||
|  |  | ||||||
| 	glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 5000); | 	glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 5000); | ||||||
|   | |||||||
| @@ -27,19 +27,17 @@ freely, subject to the following restrictions: | |||||||
|  |  | ||||||
| using namespace PolyVox; | using namespace PolyVox; | ||||||
|  |  | ||||||
| const uint16_t g_uVolumeSideLength = 128; |  | ||||||
|  |  | ||||||
| void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius, uint8_t uValue) | void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius, uint8_t uValue) | ||||||
| { | { | ||||||
| 	//This vector hold the position of the center of the volume | 	//This vector hold the position of the center of the volume | ||||||
| 	Vector3DFloat v3dVolCenter( g_uVolumeSideLength / 2, g_uVolumeSideLength / 2, g_uVolumeSideLength / 2); | 	Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); | ||||||
|  |  | ||||||
| 	//This three-level for loop iterates over every voxel in the volume | 	//This three-level for loop iterates over every voxel in the volume | ||||||
| 	for (int z = 0; z < g_uVolumeSideLength ; z++) | 	for (int z = 0; z < volData.getWidth(); z++) | ||||||
| 	{ | 	{ | ||||||
| 		for (int y = 0; y < g_uVolumeSideLength; y++) | 		for (int y = 0; y < volData.getHeight(); y++) | ||||||
| 		{ | 		{ | ||||||
| 			for (int x = 0; x < g_uVolumeSideLength; x++) | 			for (int x = 0; x < volData.getDepth(); x++) | ||||||
| 			{ | 			{ | ||||||
| 				//Store our current position as a vector... | 				//Store our current position as a vector... | ||||||
| 				Vector3DFloat v3dCurrentPos(x,y,z);	 | 				Vector3DFloat v3dCurrentPos(x,y,z);	 | ||||||
|   | |||||||
| @@ -72,7 +72,7 @@ void exampleLog(string message, int severity) | |||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	logHandler = &exampleLog; | 	logHandler = &exampleLog; | ||||||
| 	Volume<MaterialDensityPair44> volData; | 	Volume<MaterialDensityPair44> volData(g_uVolumeSideLength, g_uVolumeSideLength, g_uVolumeSideLength); | ||||||
|  |  | ||||||
| 	//Make our volume contain a sphere in the center. | 	//Make our volume contain a sphere in the center. | ||||||
| 	int32_t minPos = 0; | 	int32_t minPos = 0; | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ namespace PolyVox | |||||||
|  |  | ||||||
| 		void setLowerCorner(const Vector3DInt32& v3dLowerCorner); | 		void setLowerCorner(const Vector3DInt32& v3dLowerCorner); | ||||||
| 		void setUpperCorner(const Vector3DInt32& v3dUpperCorner); | 		void setUpperCorner(const Vector3DInt32& v3dUpperCorner); | ||||||
|  | 		void setToMaxSize(void); | ||||||
|  |  | ||||||
| 		bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const; | 		bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const; | ||||||
| 		bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const; | 		bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const; | ||||||
|   | |||||||
| @@ -32,7 +32,6 @@ freely, subject to the following restrictions: | |||||||
| #include <set> | #include <set> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <functional> |  | ||||||
|  |  | ||||||
| namespace PolyVox | namespace PolyVox | ||||||
| { | { | ||||||
| @@ -124,9 +123,27 @@ namespace PolyVox | |||||||
| 	public:		 | 	public:		 | ||||||
| 		/// Constructor | 		/// Constructor | ||||||
| 		Volume(uint16_t uBlockSideLength = 32); | 		Volume(uint16_t uBlockSideLength = 32); | ||||||
|  | 		/// Constructor | ||||||
|  | 		Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength = 32); | ||||||
| 		/// Destructor | 		/// Destructor | ||||||
| 		~Volume(); | 		~Volume(); | ||||||
|  |  | ||||||
|  | 		/// Gets the value used for voxels which are outside the volume | ||||||
|  | 		VoxelType getBorderValue(void) const; | ||||||
|  | 		/// Gets a Region representing the extents of the Volume. | ||||||
|  | 		Region getEnclosingRegion(void) const; | ||||||
|  | 		/// Gets the width of the volume in voxels. | ||||||
|  | 		int32_t getWidth(void) const; | ||||||
|  | 		/// Gets the height of the volume in voxels. | ||||||
|  | 		int32_t getHeight(void) const; | ||||||
|  | 		/// Gets the depth of the volume in voxels. | ||||||
|  | 		int32_t getDepth(void) const; | ||||||
|  | 		/// Gets the length of the longest side in voxels | ||||||
|  | 		int32_t getLongestSideLength(void) const; | ||||||
|  | 		/// Gets the length of the shortest side in voxels | ||||||
|  | 		int32_t getShortestSideLength(void) const; | ||||||
|  | 		/// Gets the length of the diagonal in voxels | ||||||
|  | 		float getDiagonalLength(void) const; | ||||||
| 		/// Gets a voxel by <tt>x,y,z</tt> position | 		/// Gets a voxel by <tt>x,y,z</tt> position | ||||||
| 		VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | 		VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; | ||||||
| 		/// Gets a voxel by 3D vector position | 		/// Gets a voxel by 3D vector position | ||||||
| @@ -148,6 +165,7 @@ namespace PolyVox | |||||||
| 		uint32_t calculateSizeInBytes(void); | 		uint32_t calculateSizeInBytes(void); | ||||||
| 		/// Resizes the volume to the specified dimensions | 		/// Resizes the volume to the specified dimensions | ||||||
| 		void resize(uint16_t uBlockSideLength = 32); | 		void resize(uint16_t uBlockSideLength = 32); | ||||||
|  | 		void resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength); | ||||||
| 		/// gets called when a new region is allocated and needs to be filled | 		/// gets called when a new region is allocated and needs to be filled | ||||||
| 		/// NOTE: accessing ANY voxels outside this region during the process of this function | 		/// NOTE: accessing ANY voxels outside this region during the process of this function | ||||||
| 		/// is absolutely unsafe | 		/// is absolutely unsafe | ||||||
| @@ -184,8 +202,40 @@ namespace PolyVox | |||||||
| 		//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume. | 		//the VolumeIterator can do it's usual pointer arithmetic without needing to know it's gone outside the volume. | ||||||
| 		VoxelType* m_pUncompressedBorderData; | 		VoxelType* m_pUncompressedBorderData; | ||||||
|  |  | ||||||
|  | 		/*int32_t m_uMinX; | ||||||
|  | 		int32_t m_uMinY; | ||||||
|  | 		int32_t m_uMinZ; | ||||||
|  |  | ||||||
|  | 		int32_t m_uMaxX; | ||||||
|  | 		int32_t m_uMaxY; | ||||||
|  | 		int32_t m_uMaxZ;*/ | ||||||
|  |  | ||||||
|  | 		Region m_regValidRegion; | ||||||
|  |  | ||||||
|  | 		/*int32_t m_uBlockMinX; | ||||||
|  | 		int32_t m_uBlockMinY; | ||||||
|  | 		int32_t m_uBlockMinZ; | ||||||
|  |  | ||||||
|  | 		int32_t m_uBlockMaxX; | ||||||
|  | 		int32_t m_uBlockMaxY; | ||||||
|  | 		int32_t m_uBlockMaxZ;*/ | ||||||
|  |  | ||||||
|  | 		Region m_regValidRegionInBlocks; | ||||||
|  |  | ||||||
|  | 		int32_t m_uWidthInBlocks; | ||||||
|  | 		int32_t m_uHeightInBlocks; | ||||||
|  | 		int32_t m_uDepthInBlocks; | ||||||
|  |  | ||||||
|  | 		int32_t m_uWidth; | ||||||
|  | 		int32_t m_uHeight;	 | ||||||
|  | 		int32_t m_uDepth; | ||||||
|  |  | ||||||
| 		uint8_t m_uBlockSideLengthPower; | 		uint8_t m_uBlockSideLengthPower; | ||||||
| 		uint16_t m_uBlockSideLength; | 		uint16_t m_uBlockSideLength; | ||||||
|  |  | ||||||
|  | 		int32_t m_uLongestSideLength; | ||||||
|  | 		int32_t m_uShortestSideLength; | ||||||
|  | 		float m_fDiagonalLength; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	//Some handy typedefs | 	//Some handy typedefs | ||||||
|   | |||||||
| @@ -59,10 +59,48 @@ namespace PolyVox | |||||||
| 	{ | 	{ | ||||||
| 		setBlockCacheSize(m_uMaxUncompressedBlockCacheSize); | 		setBlockCacheSize(m_uMaxUncompressedBlockCacheSize); | ||||||
|  |  | ||||||
|  | 		m_regValidRegion.setToMaxSize(); | ||||||
|  |  | ||||||
|  | 		m_regValidRegionInBlocks.setLowerCorner(m_regValidRegion.getLowerCorner()  / static_cast<int32_t>(uBlockSideLength)); | ||||||
|  | 		m_regValidRegionInBlocks.setUpperCorner(m_regValidRegion.getUpperCorner()  / static_cast<int32_t>(uBlockSideLength)); | ||||||
|  |  | ||||||
| 		//Create a volume of the right size. | 		//Create a volume of the right size. | ||||||
| 		resize(uBlockSideLength); | 		resize(uBlockSideLength); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// Builds a volume of the desired dimensions | ||||||
|  | 	/// \param uWidth The desired width in voxels. This must be a power of two. | ||||||
|  | 	/// \param uHeight The desired height in voxels. This must be a power of two. | ||||||
|  | 	/// \param uDepth The desired depth in voxels. This must be a power of two. | ||||||
|  | 	/// \param uBlockSideLength The size of the blocks which make up the volume. Small | ||||||
|  | 	/// blocks are more likely to be homogeneous (so more easily shared) and have better | ||||||
|  | 	/// cache behaviour. However, there is a memory overhead per block so if they are | ||||||
|  | 	/// not shared it could actually be less efficient (this will depend on the data). | ||||||
|  | 	/// The size of the volume may also be a factor when choosing block size. Accept  | ||||||
|  | 	/// the default if you are not sure what to choose here. | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	Volume<VoxelType>::Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength) | ||||||
|  | 		:m_uTimestamper(0) | ||||||
|  | 		,m_uMaxUncompressedBlockCacheSize(256) | ||||||
|  | 		,m_uBlockSideLength(uBlockSideLength) | ||||||
|  | 		,m_pUncompressedBorderData(0) | ||||||
|  | 		,m_uMaxBlocksLoaded(4096) | ||||||
|  | 		,m_v3dLastAccessedBlockPos((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)()) //An invalid index | ||||||
|  | 	{ | ||||||
|  | 		setBlockCacheSize(m_uMaxUncompressedBlockCacheSize); | ||||||
|  |  | ||||||
|  | 		m_regValidRegion.setLowerCorner(Vector3DInt32(0,0,0)); | ||||||
|  | 		m_regValidRegion.setUpperCorner(Vector3DInt32(uWidth - 1,uHeight - 1,uDepth - 1)); | ||||||
|  |  | ||||||
|  | 		m_regValidRegionInBlocks.setLowerCorner(m_regValidRegion.getLowerCorner()  / static_cast<int32_t>(uBlockSideLength)); | ||||||
|  | 		m_regValidRegionInBlocks.setUpperCorner(m_regValidRegion.getUpperCorner()  / static_cast<int32_t>(uBlockSideLength)); | ||||||
|  |  | ||||||
|  | 		//Create a volume of the right size. | ||||||
|  | 		resize(uWidth, uHeight, uDepth, uBlockSideLength); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	//////////////////////////////////////////////////////////////////////////////// | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
| 	/// Destroys the volume and frees any blocks which are not in use by other volumes. | 	/// Destroys the volume and frees any blocks which are not in use by other volumes. | ||||||
| 	//////////////////////////////////////////////////////////////////////////////// | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -75,6 +113,95 @@ namespace PolyVox | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// The border value is returned whenever an atempt is made to read a voxel which | ||||||
|  | 	/// is outside the extents of the volume. | ||||||
|  | 	/// \return The value used for voxels outside of the volume | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	VoxelType Volume<VoxelType>::getBorderValue(void) const | ||||||
|  | 	{ | ||||||
|  | 		/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(const_cast<Block<VoxelType>*>(&m_pBorderBlock)); | ||||||
|  | 		return pUncompressedBorderBlock->getVoxelAt(0,0,0);*/ | ||||||
|  | 		return *m_pUncompressedBorderData; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// The result will always have a lower corner at (0,0,0) and an upper corner at one | ||||||
|  | 	/// less than the side length. For example, if a volume has dimensions 256x512x1024 | ||||||
|  | 	/// then the upper corner of the enclosing region will be at (255,511,1023). | ||||||
|  | 	/// \return A Region representing the extent of the volume. | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	Region Volume<VoxelType>::getEnclosingRegion(void) const | ||||||
|  | 	{ | ||||||
|  | 		return Region(Vector3DInt32(0,0,0), Vector3DInt32(m_uWidth-1,m_uHeight-1,m_uDepth-1)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The width of the volume in voxels | ||||||
|  | 	/// \sa getHeight(), getDepth() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	int32_t Volume<VoxelType>::getWidth(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_uWidth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The height of the volume in voxels | ||||||
|  | 	/// \sa getWidth(), getDepth() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	int32_t Volume<VoxelType>::getHeight(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_uHeight; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The depth of the volume in voxels | ||||||
|  | 	/// \sa getWidth(), getHeight() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	int32_t Volume<VoxelType>::getDepth(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_uDepth; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The length of the shortest side in voxels. For example, if a volume has | ||||||
|  | 	/// dimensions 256x512x1024 this function will return 256. | ||||||
|  | 	/// \sa getLongestSideLength(), getDiagonalLength() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	int32_t Volume<VoxelType>::getShortestSideLength(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_uShortestSideLength; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The length of the longest side in voxels. For example, if a volume has | ||||||
|  | 	/// dimensions 256x512x1024 this function will return 1024. | ||||||
|  | 	/// \sa getShortestSideLength(), getDiagonalLength() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	int32_t Volume<VoxelType>::getLongestSideLength(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_uLongestSideLength; | ||||||
|  | 	}	 | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \return The length of the diagonal in voxels. For example, if a volume has | ||||||
|  | 	/// dimensions 256x512x1024 this function will return sqrt(256*256+512*512+1024*1024) | ||||||
|  | 	/// = 1173.139. This value is computed on volume creation so retrieving it is fast. | ||||||
|  | 	/// \sa getShortestSideLength(), getLongestSideLength() | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	float Volume<VoxelType>::getDiagonalLength(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_fDiagonalLength; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	//////////////////////////////////////////////////////////////////////////////// | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
| 	/// \param uXPos the \c x position of the voxel | 	/// \param uXPos the \c x position of the voxel | ||||||
| 	/// \param uYPos the \c y position of the voxel | 	/// \param uYPos the \c y position of the voxel | ||||||
| @@ -145,6 +272,17 @@ namespace PolyVox | |||||||
| 		m_uMaxBlocksLoaded  = uMaxBlocks; | 		m_uMaxBlocksLoaded  = uMaxBlocks; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// \param tBorder The value to use for voxels outside the volume. | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	void Volume<VoxelType>::setBorderValue(const VoxelType& tBorder)  | ||||||
|  | 	{ | ||||||
|  | 		/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock); | ||||||
|  | 		return pUncompressedBorderBlock->fill(tBorder);*/ | ||||||
|  | 		std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	//////////////////////////////////////////////////////////////////////////////// | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
| 	/// \param uXPos the \c x position of the voxel | 	/// \param uXPos the \c x position of the voxel | ||||||
| 	/// \param uYPos the \c y position of the voxel | 	/// \param uYPos the \c y position of the voxel | ||||||
| @@ -230,6 +368,99 @@ namespace PolyVox | |||||||
| 		m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); | 		m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	/// Note: Calling this function will destroy all existing data in the volume. | ||||||
|  | 	/// \param uWidth The desired width in voxels. This must be a power of two. | ||||||
|  | 	/// \param uHeight The desired height in voxels. This must be a power of two. | ||||||
|  | 	/// \param uDepth The desired depth in voxels. This must be a power of two. | ||||||
|  | 	/// \param uBlockSideLength The size of the blocks which make up the volume. Small | ||||||
|  | 	/// blocks are more likely to be homogeneous (so more easily shared) and have better | ||||||
|  | 	/// cache behaviour. However, there is a memory overhead per block so if they are | ||||||
|  | 	/// not shared it could actually be less efficient (this will depend on the data). | ||||||
|  | 	/// The size of the volume may also be a factor when choosing block size. Accept  | ||||||
|  | 	/// the default if you are not sure what to choose here. | ||||||
|  | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 	template <typename VoxelType> | ||||||
|  | 	void Volume<VoxelType>::resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength) | ||||||
|  | 	{ | ||||||
|  | 		//Debug mode validation | ||||||
|  | 		assert(uBlockSideLength > 0); | ||||||
|  | 		assert(isPowerOf2(uBlockSideLength)); | ||||||
|  | 		assert(uBlockSideLength <= uWidth); | ||||||
|  | 		assert(uBlockSideLength <= uHeight); | ||||||
|  | 		assert(uBlockSideLength <= uDepth); | ||||||
|  | 		assert(0 < uWidth); | ||||||
|  | 		assert(0 < uHeight); | ||||||
|  | 		assert(0 < uDepth); | ||||||
|  |  | ||||||
|  | 		//Release mode validation | ||||||
|  | 		if(uBlockSideLength == 0) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Block side length cannot be zero."); | ||||||
|  | 		} | ||||||
|  | 		if(!isPowerOf2(uBlockSideLength)) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Block side length must be a power of two."); | ||||||
|  | 		} | ||||||
|  | 		if(uBlockSideLength > uWidth) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Block side length cannot be greater than volume width."); | ||||||
|  | 		} | ||||||
|  | 		if(uBlockSideLength > uHeight) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Block side length cannot be greater than volume height."); | ||||||
|  | 		} | ||||||
|  | 		if(uBlockSideLength > uDepth) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Block side length cannot be greater than volume depth."); | ||||||
|  | 		} | ||||||
|  | 		if(0 >= uWidth) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Volume width cannot be smaller than 1."); | ||||||
|  | 		} | ||||||
|  | 		if(0 >= uHeight) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Volume height cannot be smaller than 1."); | ||||||
|  | 		} | ||||||
|  | 		if(0 >= uDepth) | ||||||
|  | 		{ | ||||||
|  | 			throw std::invalid_argument("Volume depth cannot be smaller than 1."); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		//Clear the previous data | ||||||
|  | 		m_pBlocks.clear(); | ||||||
|  | 		m_pUncompressedTimestamps.clear(); | ||||||
|  |  | ||||||
|  | 		//Compute the volume side lengths | ||||||
|  | 		m_uWidth = uWidth; | ||||||
|  | 		m_uHeight = uHeight; | ||||||
|  | 		m_uDepth = uDepth; | ||||||
|  |  | ||||||
|  | 		//Compute the block side length | ||||||
|  | 		m_uBlockSideLength = uBlockSideLength; | ||||||
|  | 		m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); | ||||||
|  |  | ||||||
|  | 		//Compute the side lengths in blocks | ||||||
|  | 		m_uWidthInBlocks = m_uWidth / m_uBlockSideLength; | ||||||
|  | 		m_uHeightInBlocks = m_uHeight / m_uBlockSideLength; | ||||||
|  | 		m_uDepthInBlocks = m_uDepth / m_uBlockSideLength; | ||||||
|  |  | ||||||
|  | 		//Clear the previous data | ||||||
|  | 		m_pBlocks.clear(); | ||||||
|  | 		m_pUncompressedTimestamps.clear(); | ||||||
|  |  | ||||||
|  | 		m_pUncompressedTimestamps.resize(m_uMaxUncompressedBlockCacheSize, 0); | ||||||
|  |  | ||||||
|  | 		//Create the border block | ||||||
|  | 		m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength]; | ||||||
|  | 		std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType()); | ||||||
|  |  | ||||||
|  | 		//Other properties we might find useful later | ||||||
|  | 		m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth); | ||||||
|  | 		m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth); | ||||||
|  | 		m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	template <typename VoxelType> | 	template <typename VoxelType> | ||||||
| 	void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const | 	void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -153,10 +153,24 @@ namespace PolyVox | |||||||
| 				uYPosInBlock * mVolume->m_uBlockSideLength +  | 				uYPosInBlock * mVolume->m_uBlockSideLength +  | ||||||
| 				uZPosInBlock * mVolume->m_uBlockSideLength * mVolume->m_uBlockSideLength; | 				uZPosInBlock * mVolume->m_uBlockSideLength * mVolume->m_uBlockSideLength; | ||||||
|  |  | ||||||
|  | 		//if((uXBlock < mVolume->m_uWidthInBlocks) && (uYBlock < mVolume->m_uHeightInBlocks) && (uZBlock < mVolume->m_uDepthInBlocks) && (uXBlock >= 0) && (uYBlock >= 0) && (uZBlock >=0)) | ||||||
|  | 		//if((uXBlock <= mVolume->m_uBlockMaxX) && (uYBlock <= mVolume->m_uBlockMaxY) && (uZBlock <= mVolume->m_uBlockMaxZ) && (uXBlock >= mVolume->m_uBlockMinX) && (uYBlock >= mVolume->m_uBlockMinY) && (uZBlock >= mVolume->m_uBlockMinZ)) | ||||||
|  | 		if(mVolume->m_regValidRegionInBlocks.containsPoint(Vector3DInt32(uXBlock, uYBlock, uZBlock))) | ||||||
|  | 		{ | ||||||
|  | 			/*const uint32_t uBlockIndexInVolume = uXBlock +  | ||||||
|  | 				uYBlock * mVolume->m_uWidthInBlocks +  | ||||||
|  | 				uZBlock * mVolume->m_uWidthInBlocks * mVolume->m_uHeightInBlocks; | ||||||
|  | 			const Block<VoxelType>& currentBlock = mVolume->m_pBlocks[uBlockIndexInVolume];*/ | ||||||
|  |  | ||||||
| 			Block<VoxelType>* pUncompressedCurrentBlock = mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock); | 			Block<VoxelType>* pUncompressedCurrentBlock = mVolume->getUncompressedBlock(uXBlock, uYBlock, uZBlock); | ||||||
|  |  | ||||||
| 			mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock; | 			mCurrentVoxel = pUncompressedCurrentBlock->m_tUncompressedData + uVoxelIndexInBlock; | ||||||
| 		} | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			mCurrentVoxel = mVolume->m_pUncompressedBorderData + uVoxelIndexInBlock; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	template <typename VoxelType> | 	template <typename VoxelType> | ||||||
| 	void VolumeSampler<VoxelType>::movePositiveX(void) | 	void VolumeSampler<VoxelType>::movePositiveX(void) | ||||||
|   | |||||||
| @@ -41,6 +41,12 @@ namespace PolyVox | |||||||
|  |  | ||||||
| 			VolumeSampler<uint8_t> volIter(volumeData); | 			VolumeSampler<uint8_t> volIter(volumeData); | ||||||
|  |  | ||||||
|  | 			//Check all corners are within the volume, allowing a boundary for gradient estimation | ||||||
|  | 			bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,2); | ||||||
|  | 			bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),2); | ||||||
|  |  | ||||||
|  | 			if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was | ||||||
|  | 			{ | ||||||
| 				Vector3DFloat v3dGradient = computeNormal(volumeData, v3dPos, normalGenerationMethod); | 				Vector3DFloat v3dGradient = computeNormal(volumeData, v3dPos, normalGenerationMethod); | ||||||
| 				 | 				 | ||||||
| 				if(v3dGradient.lengthSquared() > 0.0001) | 				if(v3dGradient.lengthSquared() > 0.0001) | ||||||
| @@ -50,6 +56,7 @@ namespace PolyVox | |||||||
| 					v3dGradient.normalise(); | 					v3dGradient.normalise(); | ||||||
| 					iterSurfaceVertex->setNormal(v3dGradient); | 					iterSurfaceVertex->setNormal(v3dGradient); | ||||||
| 				} | 				} | ||||||
|  | 			} //(lowerCornerInside && upperCornerInside) | ||||||
| 			++iterSurfaceVertex; | 			++iterSurfaceVertex; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -57,6 +57,14 @@ namespace PolyVox | |||||||
| 		m_v3dUpperCorner = v3dUpperCorner; | 		m_v3dUpperCorner = v3dUpperCorner; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	void Region::setToMaxSize(void) | ||||||
|  | 	{ | ||||||
|  | 		int32_t iMin = (std::numeric_limits<int32_t>::min)(); | ||||||
|  | 		int32_t iMax = (std::numeric_limits<int32_t>::max)(); | ||||||
|  | 		m_v3dLowerCorner = Vector3DInt32(iMin, iMin,iMin); | ||||||
|  | 		m_v3dUpperCorner = Vector3DInt32(iMax, iMax,iMax); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const | 	bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const | ||||||
| 	{ | 	{ | ||||||
| 		return (pos.getX() <= m_v3dUpperCorner.getX() - boundary) | 		return (pos.getX() <= m_v3dUpperCorner.getX() - boundary) | ||||||
|   | |||||||
| @@ -29,6 +29,13 @@ namespace PolyVox | |||||||
| { | { | ||||||
| 	float computeSmoothedVoxel(VolumeSampler<uint8_t>& volIter) | 	float computeSmoothedVoxel(VolumeSampler<uint8_t>& volIter) | ||||||
| 	{ | 	{ | ||||||
|  | 		assert(volIter.getPosX() >= 1); | ||||||
|  | 		assert(volIter.getPosY() >= 1); | ||||||
|  | 		assert(volIter.getPosZ() >= 1); | ||||||
|  | 		assert(volIter.getPosX() <= volIter.getVolume()->getWidth() - 2); | ||||||
|  | 		assert(volIter.getPosY() <= volIter.getVolume()->getHeight() - 2); | ||||||
|  | 		assert(volIter.getPosZ() <= volIter.getVolume()->getDepth() - 2); | ||||||
|  |  | ||||||
| 		float sum = 0.0; | 		float sum = 0.0; | ||||||
|  |  | ||||||
| 		if(volIter.peekVoxel1nx1ny1nz() != 0) sum += 1.0f; | 		if(volIter.peekVoxel1nx1ny1nz() != 0) sum += 1.0f; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user