Applying ker's patch unmodified.
This commit is contained in:
parent
d7cea1b72e
commit
8e6b1a3b7e
@ -1,2 +1,3 @@
|
|||||||
David Williams - Lead programmer.
|
David Williams - Lead programmer.
|
||||||
Matthew Williams - Linux port, build system, support and maintainence.
|
Matthew Williams - Linux port, build system, support and maintainence.
|
||||||
|
Oliver Schneider - Very large Volumes
|
@ -348,14 +348,14 @@ void createPerlinVolumeSlow(Volume<MaterialDensityPair44>& volData)
|
|||||||
{
|
{
|
||||||
Perlin perlin(2,8,1,234);
|
Perlin perlin(2,8,1,234);
|
||||||
|
|
||||||
for(int z = 1; z < volData.getDepth()-1; z++)
|
for(int z = 1; z < 256-1; z++)
|
||||||
{
|
{
|
||||||
std::cout << z << std::endl;
|
std::cout << z << std::endl;
|
||||||
for(int y = 1; y < volData.getHeight()-1; y++)
|
for(int y = 1; y < 256-1; y++)
|
||||||
{
|
{
|
||||||
for(int x = 1; x < volData.getWidth()-1; x++)
|
for(int x = 1; x < 256-1; x++)
|
||||||
{
|
{
|
||||||
float perlinVal = perlin.Get3D(x /static_cast<float>(volData.getWidth()-1), (y) / static_cast<float>(volData.getHeight()-1), z / static_cast<float>(volData.getDepth()-1));
|
float perlinVal = perlin.Get3D(x /static_cast<float>(256-1), (y) / static_cast<float>(256-1), z / static_cast<float>(256-1));
|
||||||
|
|
||||||
perlinVal += 1.0f;
|
perlinVal += 1.0f;
|
||||||
perlinVal *= 0.5f;
|
perlinVal *= 0.5f;
|
||||||
@ -435,18 +435,18 @@ void createPerlinTerrain(Volume<MaterialDensityPair44>& volData)
|
|||||||
{
|
{
|
||||||
Perlin perlin(2,2,1,234);
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
for(int x = 1; x < volData.getWidth()-1; x++)
|
for(int x = 1; x < 255-1; x++)
|
||||||
{
|
{
|
||||||
if(x%(volData.getWidth()/100) == 0) {
|
if(x%(255/100) == 0) {
|
||||||
std::cout << "." << std::flush;
|
std::cout << "." << std::flush;
|
||||||
}
|
}
|
||||||
for(int y = 1; y < volData.getHeight()-1; y++)
|
for(int y = 1; y < 255-1; y++)
|
||||||
{
|
{
|
||||||
float perlinVal = perlin.Get(x / static_cast<float>(volData.getHeight()-1), y / static_cast<float>(volData.getDepth()-1));
|
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
||||||
perlinVal += 1.0f;
|
perlinVal += 1.0f;
|
||||||
perlinVal *= 0.5f;
|
perlinVal *= 0.5f;
|
||||||
perlinVal *= volData.getShortestSideLength();
|
perlinVal *= 255;
|
||||||
for(int z = 1; z < volData.getDepth()-1; z++)
|
for(int z = 1; z < 255-1; z++)
|
||||||
{
|
{
|
||||||
MaterialDensityPair44 voxel;
|
MaterialDensityPair44 voxel;
|
||||||
if(z < perlinVal)
|
if(z < perlinVal)
|
||||||
@ -506,6 +506,53 @@ void createSphereInVolume(Volume<MaterialDensityPair44>& volData, Vector3DFloat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load(const Volume<MaterialDensityPair44>& volume, PolyVox::Region reg)
|
||||||
|
{
|
||||||
|
Perlin perlin(2,2,1,234);
|
||||||
|
|
||||||
|
for(int x = reg.getLowerCorner().getX(); x <= reg.getUpperCorner().getX(); x++)
|
||||||
|
{
|
||||||
|
for(int y = reg.getLowerCorner().getY(); y <= reg.getUpperCorner().getY(); y++)
|
||||||
|
{
|
||||||
|
float perlinVal = perlin.Get(x / static_cast<float>(255-1), y / static_cast<float>(255-1));
|
||||||
|
perlinVal += 1.0f;
|
||||||
|
perlinVal *= 0.5f;
|
||||||
|
perlinVal *= 255;
|
||||||
|
for(int z = reg.getLowerCorner().getZ(); z <= reg.getUpperCorner().getZ(); z++)
|
||||||
|
{
|
||||||
|
MaterialDensityPair44 voxel;
|
||||||
|
if(z < perlinVal)
|
||||||
|
{
|
||||||
|
const int xpos = 50;
|
||||||
|
const int zpos = 100;
|
||||||
|
if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) {
|
||||||
|
// tunnel
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
} else {
|
||||||
|
// solid
|
||||||
|
voxel.setMaterial(245);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voxel.setMaterial(0);
|
||||||
|
voxel.setDensity(MaterialDensityPair44::getMinDensity());
|
||||||
|
}
|
||||||
|
|
||||||
|
volume.load_setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void unload(const Volume<MaterialDensityPair44>& vol, PolyVox::Region reg)
|
||||||
|
{
|
||||||
|
std::cout << "warning unloading region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
@ -514,13 +561,15 @@ int main(int argc, char *argv[])
|
|||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//Create an empty volume and then place a sphere in it
|
||||||
Volume<MaterialDensityPair44> volData(1024*128,16,16,16);
|
Volume<MaterialDensityPair44> volData(128);
|
||||||
volData.useCompatibilityMode();
|
volData.m_LoadCallback = std::bind(&load, std::placeholders::_1, std::placeholders::_2);
|
||||||
|
volData.m_UnloadCallback = boost::bind(&unload, _1, _2);
|
||||||
|
volData.setBlockCacheSize(4096);
|
||||||
//createSphereInVolume(volData, 30);
|
//createSphereInVolume(volData, 30);
|
||||||
createPerlinTerrain(volData);
|
//createPerlinTerrain(volData);
|
||||||
//createPerlinVolumeSlow(volData);
|
//createPerlinVolumeSlow(volData);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
volData.setBlockCacheSize(64);
|
//volData.setBlockCacheSize(64);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
@ -540,8 +589,11 @@ int main(int argc, char *argv[])
|
|||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> mesh;
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
//CubicSurfaceExtractorWithNormals<MaterialDensityPair44> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
//CubicSurfaceExtractorWithNormals<MaterialDensityPair44> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
SurfaceExtractor<MaterialDensityPair44> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,1024,255));
|
||||||
|
SurfaceExtractor<MaterialDensityPair44> surfaceExtractor(&volData, reg, &mesh);
|
||||||
|
//CubicSurfaceExtractorWithNormals<MaterialDensityPair44> surfaceExtractor(&volData, reg, &mesh);
|
||||||
surfaceExtractor.execute();
|
surfaceExtractor.execute();
|
||||||
|
std::cout << "#vertices: " << mesh.getNoOfVertices() << std::endl;
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.setSurfaceMeshToRender(mesh);
|
openGLWidget.setSurfaceMeshToRender(mesh);
|
||||||
|
@ -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 = volData->getWidth() / m_uRegionSideLength;
|
m_uVolumeWidthInRegions = g_uVolumeSideLength / m_uRegionSideLength;
|
||||||
m_uVolumeHeightInRegions = volData->getHeight() / m_uRegionSideLength;
|
m_uVolumeHeightInRegions = g_uVolumeSideLength / m_uRegionSideLength;
|
||||||
m_uVolumeDepthInRegions = volData->getDepth() / m_uRegionSideLength;
|
m_uVolumeDepthInRegions = g_uVolumeSideLength / 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,8 +180,9 @@ 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, -m_volData->getDiagonalLength());
|
glTranslatef(0.0f, 0.0f, -diag_len);
|
||||||
|
|
||||||
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);
|
||||||
@ -248,7 +249,8 @@ void OpenGLWidget::setupProjectionMatrix(void)
|
|||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
float frustumSize = m_volData->getDiagonalLength() / 2.0f;
|
float diag_len = sqrtf(static_cast<float>(255 * 255 * 3));
|
||||||
|
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,17 +27,19 @@ 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(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
Vector3DFloat v3dVolCenter( g_uVolumeSideLength / 2, g_uVolumeSideLength / 2, g_uVolumeSideLength / 2);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getWidth(); z++)
|
for (int z = 0; z < g_uVolumeSideLength ; z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < volData.getHeight(); y++)
|
for (int y = 0; y < g_uVolumeSideLength; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < volData.getDepth(); x++)
|
for (int x = 0; x < g_uVolumeSideLength; 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(g_uVolumeSideLength, g_uVolumeSideLength, g_uVolumeSideLength);
|
Volume<MaterialDensityPair44> volData;
|
||||||
|
|
||||||
//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;
|
||||||
|
@ -6,7 +6,6 @@ namespace PolyVox
|
|||||||
void smoothRegion(Volume<VoxelType>& volData, const Region& regionToSmooth)
|
void smoothRegion(Volume<VoxelType>& volData, const Region& regionToSmooth)
|
||||||
{
|
{
|
||||||
Region croppedRegion = regionToSmooth;
|
Region croppedRegion = regionToSmooth;
|
||||||
croppedRegion.cropTo(volData.getEnclosingRegion());
|
|
||||||
|
|
||||||
Array<3, uint16_t> temp(ArraySizes(croppedRegion.width())(croppedRegion.height())(croppedRegion.depth()));
|
Array<3, uint16_t> temp(ArraySizes(croppedRegion.width())(croppedRegion.height())(croppedRegion.depth()));
|
||||||
|
|
||||||
|
@ -70,6 +70,8 @@ namespace PolyVox
|
|||||||
uint8_t m_uSideLengthPower;
|
uint8_t m_uSideLengthPower;
|
||||||
bool m_bIsCompressed;
|
bool m_bIsCompressed;
|
||||||
bool m_bIsUncompressedDataModified;
|
bool m_bIsUncompressedDataModified;
|
||||||
|
uint32_t m_uTimestamp;
|
||||||
|
uint32_t m_uUncompressedIndex;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,11 @@ namespace PolyVox
|
|||||||
Block<VoxelType>::Block(uint16_t uSideLength)
|
Block<VoxelType>::Block(uint16_t uSideLength)
|
||||||
:m_uSideLength(0)
|
:m_uSideLength(0)
|
||||||
,m_uSideLengthPower(0)
|
,m_uSideLengthPower(0)
|
||||||
,m_tUncompressedData(0)
|
,m_tUncompressedData(NULL)
|
||||||
,m_bIsCompressed(true)
|
,m_bIsCompressed(true)
|
||||||
,m_bIsUncompressedDataModified(true)
|
,m_bIsUncompressedDataModified(true)
|
||||||
|
,m_uTimestamp(0)
|
||||||
|
,m_uUncompressedIndex((std::numeric_limits<uint32_t>::max)())
|
||||||
{
|
{
|
||||||
if(uSideLength != 0)
|
if(uSideLength != 0)
|
||||||
{
|
{
|
||||||
@ -103,14 +105,20 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void Block<VoxelType>::fill(VoxelType tValue)
|
void Block<VoxelType>::fill(VoxelType tValue)
|
||||||
{
|
{
|
||||||
assert(m_tUncompressedData);
|
if(!m_bIsCompressed) {
|
||||||
|
|
||||||
//The memset *may* be faster than the std::fill(), but it doesn't compile nicely
|
//The memset *may* be faster than the std::fill(), but it doesn't compile nicely
|
||||||
//in 64-bit mode as casting the pointer to an int causes a loss of precision.
|
//in 64-bit mode as casting the pointer to an int causes a loss of precision.
|
||||||
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
|
||||||
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue);
|
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue);
|
||||||
|
|
||||||
m_bIsUncompressedDataModified = true;
|
m_bIsUncompressedDataModified = true;
|
||||||
|
} else {
|
||||||
|
RunlengthEntry<uint16_t> rle;
|
||||||
|
rle.length = m_uSideLength*m_uSideLength*m_uSideLength;
|
||||||
|
rle.value = tValue;
|
||||||
|
m_vecCompressedData.clear();
|
||||||
|
m_vecCompressedData.push_back(rle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
@ -128,6 +136,8 @@ namespace PolyVox
|
|||||||
//Compute the side length
|
//Compute the side length
|
||||||
m_uSideLength = uSideLength;
|
m_uSideLength = uSideLength;
|
||||||
m_uSideLengthPower = logBase2(uSideLength);
|
m_uSideLengthPower = logBase2(uSideLength);
|
||||||
|
|
||||||
|
Block<VoxelType>::fill(VoxelType());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
|
@ -32,6 +32,7 @@ freely, subject to the following restrictions:
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
@ -115,33 +116,17 @@ namespace PolyVox
|
|||||||
|
|
||||||
struct UncompressedBlock
|
struct UncompressedBlock
|
||||||
{
|
{
|
||||||
uint32_t uBlockIndex;
|
Vector3DInt32 v3dBlockIndex;
|
||||||
VoxelType* data;
|
VoxelType* data;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength = 32);
|
Volume(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
|
||||||
@ -149,6 +134,8 @@ namespace PolyVox
|
|||||||
|
|
||||||
/// Sets the number of blocks for which uncompressed data is stored.
|
/// Sets the number of blocks for which uncompressed data is stored.
|
||||||
void setBlockCacheSize(uint16_t uBlockCacheSize);
|
void setBlockCacheSize(uint16_t uBlockCacheSize);
|
||||||
|
/// Sets the number of blocks which can be in memory before unload is called
|
||||||
|
void setMaxBlocksLoaded(uint16_t uBlockCacheSize);
|
||||||
/// Sets the value used for voxels which are outside the volume
|
/// Sets the value used for voxels which are outside the volume
|
||||||
void setBorderValue(const VoxelType& tBorder);
|
void setBorderValue(const VoxelType& tBorder);
|
||||||
/// Sets the voxel at an <tt>x,y,z</tt> position
|
/// Sets the voxel at an <tt>x,y,z</tt> position
|
||||||
@ -159,15 +146,25 @@ namespace PolyVox
|
|||||||
void clearBlockCache(void);
|
void clearBlockCache(void);
|
||||||
float calculateCompressionRatio(void);
|
float calculateCompressionRatio(void);
|
||||||
uint32_t calculateSizeInBytes(void);
|
uint32_t calculateSizeInBytes(void);
|
||||||
void useCompatibilityMode(void);
|
|
||||||
/// Resizes the volume to the specified dimensions
|
/// Resizes the volume to the specified dimensions
|
||||||
void resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength = 32);
|
void resize(uint16_t uBlockSideLength = 32);
|
||||||
|
/// gets called when a new region is allocated and needs to be filled
|
||||||
|
/// NOTE: accessing ANY voxels outside this region during the process of this function
|
||||||
|
/// is absolutely unsafe
|
||||||
|
std::function<void(const Volume<VoxelType>&, Region)> m_LoadCallback;
|
||||||
|
/// this function can be called by m_LoadCallback without causing any weird effects
|
||||||
|
bool load_setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
|
||||||
|
/// gets called when a Region needs to be stored by the user, because Volume will erase it right after
|
||||||
|
/// this function returns
|
||||||
|
/// NOTE: accessing ANY voxels outside this region during the process of this function
|
||||||
|
/// is absolutely unsafe
|
||||||
|
std::function<void(const Volume<VoxelType>&, Region)> m_UnloadCallback;
|
||||||
private:
|
private:
|
||||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||||
|
void eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const;
|
||||||
|
|
||||||
//The block data
|
//The block data
|
||||||
mutable std::vector< Block<VoxelType> > m_pBlocks;
|
mutable std::map<Vector3DInt32, Block<VoxelType> > m_pBlocks;
|
||||||
|
|
||||||
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
||||||
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
||||||
@ -176,8 +173,10 @@ namespace PolyVox
|
|||||||
mutable std::vector< UncompressedBlock > m_vecUncompressedBlockCache;
|
mutable std::vector< UncompressedBlock > m_vecUncompressedBlockCache;
|
||||||
mutable std::vector<uint32_t> m_pUncompressedTimestamps;
|
mutable std::vector<uint32_t> m_pUncompressedTimestamps;
|
||||||
mutable uint32_t m_uTimestamper;
|
mutable uint32_t m_uTimestamper;
|
||||||
uint32_t m_ulastAccessedBlockIndex;
|
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||||
|
mutable Vector3DInt32 m_v3dLoadBlockPos;
|
||||||
uint32_t m_uMaxUncompressedBlockCacheSize;
|
uint32_t m_uMaxUncompressedBlockCacheSize;
|
||||||
|
uint32_t m_uMaxBlocksLoaded;
|
||||||
|
|
||||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||||
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
//block does not have a position (so can't be passed to getUncompressedBlock()) and partly because there's a
|
||||||
@ -185,22 +184,8 @@ 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;
|
||||||
|
|
||||||
uint32_t m_uNoOfBlocksInVolume;
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -48,17 +48,19 @@ namespace PolyVox
|
|||||||
/// the default if you are not sure what to choose here.
|
/// the default if you are not sure what to choose here.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Volume<VoxelType>::Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength)
|
Volume<VoxelType>::Volume(uint16_t uBlockSideLength)
|
||||||
:m_uTimestamper(0)
|
:
|
||||||
|
m_uTimestamper(0)
|
||||||
,m_uMaxUncompressedBlockCacheSize(256)
|
,m_uMaxUncompressedBlockCacheSize(256)
|
||||||
|
,m_uMaxBlocksLoaded(4096)
|
||||||
,m_uBlockSideLength(uBlockSideLength)
|
,m_uBlockSideLength(uBlockSideLength)
|
||||||
,m_pUncompressedBorderData(0)
|
,m_pUncompressedBorderData(0)
|
||||||
,m_ulastAccessedBlockIndex((std::numeric_limits<uint32_t>::max)()) //An invalid index
|
,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);
|
setBlockCacheSize(m_uMaxUncompressedBlockCacheSize);
|
||||||
|
|
||||||
//Create a volume of the right size.
|
//Create a volume of the right size.
|
||||||
resize(uWidth, uHeight, uDepth, uBlockSideLength);
|
resize(uBlockSideLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -67,95 +69,10 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Volume<VoxelType>::~Volume()
|
Volume<VoxelType>::~Volume()
|
||||||
{
|
{
|
||||||
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
||||||
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) {
|
||||||
|
eraseBlock(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -166,10 +83,6 @@ namespace PolyVox
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType Volume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
VoxelType Volume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
|
||||||
{
|
|
||||||
//We don't use getEnclosingRegion here because we care
|
|
||||||
//about speed
|
|
||||||
if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
|
|
||||||
{
|
{
|
||||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||||
@ -183,11 +96,6 @@ namespace PolyVox
|
|||||||
|
|
||||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return getBorderValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
@ -214,14 +122,27 @@ namespace PolyVox
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param tBorder The value to use for voxels outside the volume.
|
/// Increasing the number of blocks in memory causes fewer calls to load/unload
|
||||||
|
/// \param uMaxBlocks The number of blocks
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void Volume<VoxelType>::setBorderValue(const VoxelType& tBorder)
|
void Volume<VoxelType>::setMaxBlocksLoaded(uint16_t uMaxBlocks)
|
||||||
{
|
{
|
||||||
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
|
if(uMaxBlocks < m_pBlocks.size()) {
|
||||||
return pUncompressedBorderBlock->fill(tBorder);*/
|
std::cout << uMaxBlocks << ", " << m_pBlocks.size() << ", " << m_pBlocks.size() - uMaxBlocks << std::endl;
|
||||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
|
// we need to unload some blocks
|
||||||
|
for(int j = 0; j < m_pBlocks.size() - uMaxBlocks; j++) {
|
||||||
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
||||||
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||||
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
|
||||||
|
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) {
|
||||||
|
itUnloadBlock = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eraseBlock(itUnloadBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_uMaxBlocksLoaded = uMaxBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -233,10 +154,6 @@ namespace PolyVox
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool Volume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
bool Volume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
|
||||||
{
|
|
||||||
//We don't use getEnclosingRegion here because we care
|
|
||||||
//about speed
|
|
||||||
if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
|
|
||||||
{
|
{
|
||||||
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||||
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||||
@ -253,12 +170,6 @@ namespace PolyVox
|
|||||||
//Return true to indicate that we modified a voxel.
|
//Return true to indicate that we modified a voxel.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
//Return false to indicate that no voxel was modified.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// \param v3dPos the 3D position of the voxel
|
/// \param v3dPos the 3D position of the voxel
|
||||||
@ -276,7 +187,7 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||||
{
|
{
|
||||||
m_pBlocks[m_vecUncompressedBlockCache[ct].uBlockIndex].compress();
|
m_pBlocks[m_vecUncompressedBlockCache[ct].v3dBlockIndex].compress();
|
||||||
delete[] m_vecUncompressedBlockCache[ct].data;
|
delete[] m_vecUncompressedBlockCache[ct].data;
|
||||||
}
|
}
|
||||||
m_vecUncompressedBlockCache.clear();
|
m_vecUncompressedBlockCache.clear();
|
||||||
@ -284,9 +195,6 @@ namespace PolyVox
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Note: Calling this function will destroy all existing data in the volume.
|
/// 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
|
/// \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
|
/// 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
|
/// cache behaviour. However, there is a memory overhead per block so if they are
|
||||||
@ -295,17 +203,11 @@ namespace PolyVox
|
|||||||
/// the default if you are not sure what to choose here.
|
/// the default if you are not sure what to choose here.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void Volume<VoxelType>::resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength)
|
void Volume<VoxelType>::resize(uint16_t uBlockSideLength)
|
||||||
{
|
{
|
||||||
//Debug mode validation
|
//Debug mode validation
|
||||||
assert(uBlockSideLength > 0);
|
assert(uBlockSideLength > 0);
|
||||||
assert(isPowerOf2(uBlockSideLength));
|
assert(isPowerOf2(uBlockSideLength));
|
||||||
assert(uBlockSideLength <= uWidth);
|
|
||||||
assert(uBlockSideLength <= uHeight);
|
|
||||||
assert(uBlockSideLength <= uDepth);
|
|
||||||
assert(0 < uWidth);
|
|
||||||
assert(0 < uHeight);
|
|
||||||
assert(0 < uDepth);
|
|
||||||
|
|
||||||
//Release mode validation
|
//Release mode validation
|
||||||
if(uBlockSideLength == 0)
|
if(uBlockSideLength == 0)
|
||||||
@ -316,103 +218,112 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
throw std::invalid_argument("Block side length must be a power of two.");
|
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
|
//Clear the previous data
|
||||||
m_pBlocks.clear();
|
m_pBlocks.clear();
|
||||||
m_pUncompressedTimestamps.clear();
|
m_pUncompressedTimestamps.clear();
|
||||||
|
|
||||||
//Compute the volume side lengths
|
m_pUncompressedTimestamps.resize(m_uMaxUncompressedBlockCacheSize, 0);
|
||||||
m_uWidth = uWidth;
|
|
||||||
m_uHeight = uHeight;
|
|
||||||
m_uDepth = uDepth;
|
|
||||||
|
|
||||||
//Compute the block side length
|
//Compute the block side length
|
||||||
m_uBlockSideLength = uBlockSideLength;
|
m_uBlockSideLength = uBlockSideLength;
|
||||||
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
|
||||||
|
}
|
||||||
|
|
||||||
//Compute the side lengths in blocks
|
template <typename VoxelType>
|
||||||
m_uWidthInBlocks = m_uWidth / m_uBlockSideLength;
|
void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const
|
||||||
m_uHeightInBlocks = m_uHeight / m_uBlockSideLength;
|
|
||||||
m_uDepthInBlocks = m_uDepth / m_uBlockSideLength;
|
|
||||||
|
|
||||||
//Compute number of blocks in the volume
|
|
||||||
m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
|
|
||||||
|
|
||||||
//Create the blocks
|
|
||||||
m_pBlocks.resize(m_uNoOfBlocksInVolume);
|
|
||||||
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
|
|
||||||
{
|
{
|
||||||
m_pBlocks[i].initialise(m_uBlockSideLength);
|
Vector3DInt32 v3dPos = itBlock->first;
|
||||||
|
Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
|
||||||
|
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
||||||
|
Region reg(v3dLower, v3dUpper);
|
||||||
|
if(m_UnloadCallback) {
|
||||||
|
m_UnloadCallback(std::ref(*this), reg);
|
||||||
|
}
|
||||||
|
m_pBlocks.erase(itBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pUncompressedTimestamps.resize(m_uNoOfBlocksInVolume);
|
template <typename VoxelType>
|
||||||
std::fill(m_pUncompressedTimestamps.begin(), m_pUncompressedTimestamps.end(), 0);
|
bool Volume<VoxelType>::load_setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
|
||||||
|
{
|
||||||
//Create the border block
|
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||||
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||||
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
|
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||||
|
assert(blockX == m_v3dLoadBlockPos.getX());
|
||||||
//Other properties we might find useful later
|
assert(blockY == m_v3dLoadBlockPos.getY());
|
||||||
m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth);
|
assert(blockZ == m_v3dLoadBlockPos.getZ());
|
||||||
m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth);
|
if(blockX != m_v3dLoadBlockPos.getX() && blockY != m_v3dLoadBlockPos.getY() && blockZ != m_v3dLoadBlockPos.getZ()) {
|
||||||
m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth));
|
throw(std::invalid_argument("you are not allowed to write to any voxels outside the designated region"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
|
||||||
|
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||||
|
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||||
|
|
||||||
|
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||||
|
|
||||||
|
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||||
|
|
||||||
|
//Return true to indicate that we modified a voxel.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Block<VoxelType>* Volume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
Block<VoxelType>* Volume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||||
{
|
{
|
||||||
assert(uBlockX >= 0);
|
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
||||||
assert(uBlockY >= 0);
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||||
assert(uBlockZ >= 0);
|
// check whether the block is already loaded
|
||||||
assert(uBlockX < m_uWidthInBlocks);
|
if(itBlock == m_pBlocks.end()) {
|
||||||
assert(uBlockY < m_uHeightInBlocks);
|
// it is not loaded
|
||||||
assert(uBlockZ < m_uDepthInBlocks);
|
// check wether another block needs to be unloaded before this one can be loaded
|
||||||
//Compute the block's index from it's position.
|
if(m_pBlocks.size() == m_uMaxBlocksLoaded) {
|
||||||
const int32_t uBlockIndex =
|
// find the least recently used block
|
||||||
uBlockX +
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
||||||
uBlockY * m_uWidthInBlocks +
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||||
uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
|
||||||
assert(uBlockIndex < m_uNoOfBlocksInVolume);
|
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) {
|
||||||
assert(uBlockIndex >= 0);
|
itUnloadBlock = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eraseBlock(itUnloadBlock);
|
||||||
|
}
|
||||||
|
Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
|
||||||
|
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
||||||
|
Region reg(v3dLower, v3dUpper);
|
||||||
|
// create the new block
|
||||||
|
m_pBlocks[v3dBlockPos] = Block<VoxelType>(m_uBlockSideLength);
|
||||||
|
itBlock = m_pBlocks.find(v3dBlockPos);
|
||||||
|
// fill it with data (well currently fill it with nothingness)
|
||||||
|
// "load" will actually call setVoxel, which will in turn call this function again but the block will be found
|
||||||
|
// so this if(itBlock == m_pBlocks.end()) never is entered
|
||||||
|
|
||||||
|
m_v3dLoadBlockPos = v3dBlockPos;
|
||||||
|
if(m_LoadCallback) {
|
||||||
|
m_LoadCallback(std::ref(*this), reg);
|
||||||
|
}
|
||||||
|
m_v3dLoadBlockPos = Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)());
|
||||||
|
}
|
||||||
|
|
||||||
//Get the block
|
//Get the block
|
||||||
Block<VoxelType>* block = &(m_pBlocks[uBlockIndex]);
|
Block<VoxelType>* block = &(itBlock->second);
|
||||||
|
|
||||||
//Check if we have the same block as last time, if so there's no need to even update
|
//Check if we have the same block as last time, if so there's no need to even update
|
||||||
//the time stamp. If we updated it everytime then that would be every time we touched
|
//the time stamp. If we updated it everytime then that would be every time we touched
|
||||||
//a voxel, which would overflow a uint32_t and require us to use a uint64_t instead.
|
//a voxel, which would overflow a uint32_t and require us to use a uint64_t instead.
|
||||||
if(uBlockIndex == m_ulastAccessedBlockIndex)
|
if(v3dBlockPos == m_v3dLastAccessedBlockPos)
|
||||||
{
|
{
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||||
|
|
||||||
m_pUncompressedTimestamps[uBlockIndex] = ++m_uTimestamper;
|
m_uTimestamper++;
|
||||||
|
block->m_uTimestamp = m_uTimestamper;
|
||||||
|
|
||||||
if(block->m_bIsCompressed == false)
|
if(block->m_bIsCompressed == false)
|
||||||
{
|
{
|
||||||
|
m_pUncompressedTimestamps[block->m_uUncompressedIndex] = m_uTimestamper;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,28 +338,27 @@ namespace PolyVox
|
|||||||
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;)
|
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;)
|
||||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||||
{
|
{
|
||||||
if(m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex] < uLeastRecentTimestamp)
|
if(m_pUncompressedTimestamps[ct] < uLeastRecentTimestamp)
|
||||||
{
|
{
|
||||||
uLeastRecentTimestamp = m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex];
|
uLeastRecentTimestamp = m_pUncompressedTimestamps[ct];
|
||||||
leastRecentlyUsedBlockIndex = ct;
|
leastRecentlyUsedBlockIndex = ct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uUncompressedBlockIndex = leastRecentlyUsedBlockIndex;
|
uUncompressedBlockIndex = leastRecentlyUsedBlockIndex;
|
||||||
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].compress();
|
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex].compress();
|
||||||
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].m_tUncompressedData = 0;
|
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex = v3dBlockPos;
|
||||||
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex = uBlockIndex;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UncompressedBlock uncompressedBlock;
|
UncompressedBlock uncompressedBlock;
|
||||||
//uncompressedBlock.block = block;
|
//uncompressedBlock.block = block;
|
||||||
uncompressedBlock.uBlockIndex = uBlockIndex;
|
uncompressedBlock.v3dBlockIndex = v3dBlockPos;
|
||||||
uncompressedBlock.data = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
uncompressedBlock.data = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
||||||
m_vecUncompressedBlockCache.push_back(uncompressedBlock);
|
m_vecUncompressedBlockCache.push_back(uncompressedBlock);
|
||||||
uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1;
|
uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1;
|
||||||
}
|
}
|
||||||
|
block->m_uUncompressedIndex = uUncompressedBlockIndex;
|
||||||
block->uncompress(m_vecUncompressedBlockCache[uUncompressedBlockIndex].data);
|
block->uncompress(m_vecUncompressedBlockCache[uUncompressedBlockIndex].data);
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
@ -457,7 +367,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
float Volume<VoxelType>::calculateCompressionRatio(void)
|
float Volume<VoxelType>::calculateCompressionRatio(void)
|
||||||
{
|
{
|
||||||
float fRawSize = m_uWidth * m_uHeight * m_uDepth * sizeof(VoxelType);
|
float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType);
|
||||||
float fCompressedSize = calculateSizeInBytes();
|
float fCompressedSize = calculateSizeInBytes();
|
||||||
return fCompressedSize/fRawSize;
|
return fCompressedSize/fRawSize;
|
||||||
}
|
}
|
||||||
@ -468,9 +378,9 @@ namespace PolyVox
|
|||||||
uint32_t uSizeInBytes = sizeof(Volume);
|
uint32_t uSizeInBytes = sizeof(Volume);
|
||||||
|
|
||||||
//Memory used by the blocks
|
//Memory used by the blocks
|
||||||
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
|
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
||||||
{
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
|
||||||
uSizeInBytes += m_pBlocks[i].calculateSizeInBytes();
|
i->second.calculateSizeInBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Memory used by the block cache.
|
//Memory used by the block cache.
|
||||||
@ -487,20 +397,4 @@ namespace PolyVox
|
|||||||
return uSizeInBytes;
|
return uSizeInBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
|
||||||
void Volume<VoxelType>::useCompatibilityMode(void)
|
|
||||||
{
|
|
||||||
setBlockCacheSize(m_uNoOfBlocksInVolume * 2); //Times two gives space to spare
|
|
||||||
|
|
||||||
for(int32_t z = 0; z < m_uDepthInBlocks; z++)
|
|
||||||
{
|
|
||||||
for(int32_t y = 0; y < m_uHeightInBlocks; y++)
|
|
||||||
{
|
|
||||||
for(int32_t x = 0; x < m_uWidthInBlocks; x++)
|
|
||||||
{
|
|
||||||
getUncompressedBlock(x,y,z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,11 @@ freely, subject to the following restrictions:
|
|||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "Region.h"
|
#include "Region.h"
|
||||||
|
|
||||||
|
#define BORDER_LOW(x) ((( x >> mVolume->m_uBlockSideLengthPower) << mVolume->m_uBlockSideLengthPower) != x)
|
||||||
|
#define BORDER_HIGH(x) ((( (x+1) >> mVolume->m_uBlockSideLengthPower) << mVolume->m_uBlockSideLengthPower) != (x+1))
|
||||||
|
//#define BORDER_LOW(x) (( x % mVolume->m_uBlockSideLength) != 0)
|
||||||
|
//#define BORDER_HIGH(x) (( x % mVolume->m_uBlockSideLength) != mVolume->m_uBlockSideLength - 1)
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
namespace PolyVox
|
namespace PolyVox
|
||||||
{
|
{
|
||||||
@ -148,22 +153,10 @@ 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))
|
|
||||||
{
|
|
||||||
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)
|
||||||
@ -264,7 +257,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -274,7 +267,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -284,7 +277,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1ny1pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -294,7 +287,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -304,7 +297,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mXPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1);
|
return *(mCurrentVoxel - 1);
|
||||||
}
|
}
|
||||||
@ -314,7 +307,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx0py1pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -324,7 +317,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -334,7 +327,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -344,7 +337,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1nx1py1pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != 0) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_LOW(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -356,7 +349,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1nz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -366,7 +359,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny0pz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -376,7 +369,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1ny1pz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -386,7 +379,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -402,7 +395,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px0py1pz(void) const
|
||||||
{
|
{
|
||||||
if((mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -412,7 +405,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -422,7 +415,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py0pz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -432,7 +425,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel0px1py1pz(void) const
|
||||||
{
|
{
|
||||||
if((mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -444,7 +437,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -454,7 +447,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -464,7 +457,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1ny1pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != 0) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -474,7 +467,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -484,7 +477,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mXPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1);
|
return *(mCurrentVoxel + 1);
|
||||||
}
|
}
|
||||||
@ -494,7 +487,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px0py1pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -504,7 +497,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1nz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1nz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mZPosInVolume%mVolume->m_uBlockSideLength != 0))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_LOW(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength - mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -514,7 +507,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py0pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py0pz(void) const
|
||||||
{
|
{
|
||||||
if((mXPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1) && (mYPosInVolume%mVolume->m_uBlockSideLength != mVolume->m_uBlockSideLength-1))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
@ -524,7 +517,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1pz(void) const
|
VoxelType VolumeSampler<VoxelType>::peekVoxel1px1py1pz(void) const
|
||||||
{
|
{
|
||||||
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))
|
if( BORDER_HIGH(mXPosInVolume) && BORDER_HIGH(mYPosInVolume) && BORDER_HIGH(mZPosInVolume) )
|
||||||
{
|
{
|
||||||
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
return *(mCurrentVoxel + 1 + mVolume->m_uBlockSideLength + mVolume->m_uBlockSideLength*mVolume->m_uBlockSideLength);
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,6 @@ 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)
|
||||||
@ -56,7 +50,6 @@ namespace PolyVox
|
|||||||
v3dGradient.normalise();
|
v3dGradient.normalise();
|
||||||
iterSurfaceVertex->setNormal(v3dGradient);
|
iterSurfaceVertex->setNormal(v3dGradient);
|
||||||
}
|
}
|
||||||
} //(lowerCornerInside && upperCornerInside)
|
|
||||||
++iterSurfaceVertex;
|
++iterSurfaceVertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,6 @@ 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;
|
||||||
|
@ -32,7 +32,7 @@ using namespace PolyVox;
|
|||||||
void TestVolume::testSize()
|
void TestVolume::testSize()
|
||||||
{
|
{
|
||||||
const int32_t g_uVolumeSideLength = 128;
|
const int32_t g_uVolumeSideLength = 128;
|
||||||
Volume<uint8_t> volData(g_uVolumeSideLength, g_uVolumeSideLength, g_uVolumeSideLength);
|
Volume<uint8_t> volData;
|
||||||
|
|
||||||
//Note: Deliberatly go past each edge by one to test if the bounds checking works.
|
//Note: Deliberatly go past each edge by one to test if the bounds checking works.
|
||||||
for (int32_t z = 0; z < g_uVolumeSideLength + 1; z++)
|
for (int32_t z = 0; z < g_uVolumeSideLength + 1; z++)
|
||||||
@ -45,10 +45,6 @@ void TestVolume::testSize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QCOMPARE(volData.getWidth(), g_uVolumeSideLength);
|
|
||||||
QCOMPARE(volData.getHeight(), g_uVolumeSideLength);
|
|
||||||
QCOMPARE(volData.getDepth(), g_uVolumeSideLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestVolume)
|
QTEST_MAIN(TestVolume)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user