Hey everyone, this is addressed mostly to the Williams but if someone else has run into this before feel free to jump in.
First I'll describe my setup and then I'll go into the problem.
I have built Polyvox on windows and used it successfully in an Ogre project for the last week. I initially just had a volume class being setup that was capable of filling a set of dynamic buffers of a SimpleRenderable. This volume class contained the surface extractor, Polyvox volume and wrapper methods to interact with it. Four of these wrapper methods let you add or delete single voxels, or add or delete a sphere of a variable size. At first I set up the class to use CubicSurfaceExtractorWithNormals and everything was great. Materials were rendered by attaching a vertex color to the buffer, looked up from a color palette indexed by the material.
I wanted to try to take advantage of the improvements made to the CubicSurfaceExtractor as well as lower the vertex bandwidth by removing the normals. So, I switched the class to use a CubicSurfaceExtractor instead and just calculated the normals in the pixel shader. This was also done because I was switching to a per-pixel lighting and I thought it would just make sense to offload a bit of work to the GPU. However, here is where my problems start.
Adding voxels seems to work just fine, the volume is updated and the extractor runs over it correctly. Removing single voxels also works, but removing them in a sphere causes a runtime assert when processing a voxelof the last z loop( z == m_regSizeInVoxels.getUpperCorner().getZ() )
Its not the first voxel in either the x or y direction... so I'm not sure why its failing. The comment specifically says
//If we exit the loop here then apparently all the slots were full but none of
//them matched. I don't think this can happen so let's put an assert to make sure.
The code I am using to remove voxels is pretty simple, but I'll post it just in case I'm doing something odd.
Code:
void VoxelVolume::RemoveVoxel( Ogre::Vector3 voxelPosition )
{
if( PositionIsValid( voxelPosition ) == false )
{
return;
}
//Our new density value
uint8_t uDensity = 0;
//Get the old voxel
MaterialDensityPair44 voxel = mVolData->getVoxelAt(voxelPosition.x,voxelPosition.y,voxelPosition.z);
//Modify the density
voxel.setDensity(uDensity);
uint8_t uMaterial = 0;
//Wrte the voxel value into the volume
mVolData->setVoxelAt(voxelPosition.x, voxelPosition.y, voxelPosition.z, voxel);
mDirty = true;
}
void VoxelVolume::RemoveSphereFromVolume( Ogre::Vector3 position, int radius )
{
//This vector hold the position of the center of the sphere to remove
Vector3DFloat v3dVolCenter( position.x, position.y, position.z );
float fRadius = (float)radius;
//This three-level for loop iterates over every voxel in the region to be removed
for (int z = position.z - radius; z < position.z + radius; z++)
{
for (int y = position.y - radius; y < position.y + radius; y++)
{
for (int x = position.x - radius; x < position.x + radius; x++)
{
//Store our current position as a vector...
Vector3DFloat v3dCurrentPos(x,y,z);
//And compute how far the current position is from the center of the intended sphere
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
//If the current voxel is less than 'radius' units from the center then we make it solid.
if(fDistToCenter <= fRadius)
{
RemoveVoxel( Vector3(x, y, z) );
}
}
}
}
}
To be clear the assert is in the CubicSurfaceExtractor::addVertex() method, line 265( using latest Git source. ) Also, with a danger of stating the obvious, the assert does not happen until the surface extractor is run after modifying the volume.
EDIT -
After running in release mode to skip past the asserts I produced the following screenshots. I hope those help to illustrate the problem a bit better.