Thank you again David it's really helping me understand how PolyVox works internally.
So, from what I gather on that topic, the smoothing is calculated from the Density of the voxel?
How exactly does this influence the smoothing?
I tried to create a function that iterates back through the volData once the origional data is set via heightmap, then take the surrounding 6 voxels density and average them together to get our current voxel's density.
Code:
void SmoothTerrainData(SimpleVolume<MaterialDensityPair44>& volData)
{
for (int z = 1; z < volData.getDepth()-1; z++)
{
for (int x = 1; x < volData.getWidth()-1; x++)
{
for (int y = 0; y < volData.getHeight()-1; y++)
{
//Get Our Voxel
MaterialDensityPair44 Voxel = volData.getVoxelAt(x,y,z);
//Get The Voxels Around Us
//Left
MaterialDensityPair44 LTVoxel = volData.getVoxelAt(x+1,y,z);
uint8_t LTDen = LTVoxel.getDensity();
//Right
MaterialDensityPair44 RTVoxel = volData.getVoxelAt(x-1,y,z);
uint8_t RTDen = RTVoxel.getDensity();
//Up
MaterialDensityPair44 UPVoxel = volData.getVoxelAt(x,y+1,z);
uint8_t UPDen = UPVoxel.getDensity();
//Down
MaterialDensityPair44 DNVoxel = volData.getVoxelAt(x,y-1,z);
uint8_t DNDen = DNVoxel.getDensity();
//Front
MaterialDensityPair44 FTVoxel = volData.getVoxelAt(x,y,z+1);
uint8_t FTDen = FTVoxel.getDensity();
//Back
MaterialDensityPair44 BKVoxel = volData.getVoxelAt(x,y,z-1);
uint8_t BKDen = BKVoxel.getDensity();
//Compute Our Average Density
uint8_t AvgDen = (LTDen + RTDen + UPDen + DNDen + FTDen + BKDen)/6;
//Set Our Voxel To This New Density
Voxel.setDensity(AvgDen);
}
}
}
}
It appears to have had no effect on the resulting mesh what so ever.
Also for people who might stumble upon this in the future to get PolyVox and Irrlicht integrated here is what we're doing so far:
Create voldata:
Code:
//Create Our PolyVox Volume
SimpleVolume<MaterialDensityPair44> volData(Region(Vector3DInt32(0,0,0), Vector3DInt32( 256, 64, 256 )));
Create our Image to be used as a heightmap
Code:
//Get our heightmap
IImage* Heightmap = driver->createImageFromFile("content/heightmaps/terrain-heightmap.bmp");
Run both of those through our CreateTerrainFromHieightmap function
Code:
void GenerateTerrainFromHeightmap(SimpleVolume<MaterialDensityPair44>& volData, IImage* Heightmap)
{
//This three-level for loop iterates over every voxel in the volume
for (int z = 0; z <= volData.getDepth(); z++)
{
for (int x = 0; x <= volData.getWidth(); x++)
{
//Get Our Position On The Heightmap
SColor HeightCol = Heightmap->getPixel(x, z);
//Compute Voxel's Height From The Pixel Color
uint32_t Height = (HeightCol.getRed() + HeightCol.getGreen() + HeightCol.getBlue())/volData.getHeight();
for (int y = 0; y < Height; y++)
{
//Get Our Voxel
MaterialDensityPair44 Voxel = volData.getVoxelAt(x,y,z);
//Modify Density
Voxel.setDensity(255);
//Modify Material
Voxel.setMaterial(1);
//Write New Voxel Into Volume
volData.setVoxelAt(x,y,z,Voxel);
}
}
}
SmoothTerrainData(volData);
}
Run that through our SmoothTerrainData function
Finally convert the volData to a Mesh Buffer
Code:
IMeshBuffer* ConvertMesh(const SurfaceMesh<PositionMaterialNormal>& mesh)
{
const vector<uint32_t>& indices = mesh.getIndices();
const vector<PositionMaterialNormal>& vertices = mesh.getVertices();
IDynamicMeshBuffer *mb = new CDynamicMeshBuffer(EVT_STANDARD, EIT_32BIT);
mb->getVertexBuffer().set_used(vertices.size());
for (size_t i = 0; i < vertices.size(); ++i)
{
const Vector3DFloat& position = vertices[i].getPosition();
const Vector3DFloat& normal = vertices[i].getNormal();
mb->getVertexBuffer()[i].Pos.X = position.getX();
mb->getVertexBuffer()[i].Pos.Y = position.getY();
mb->getVertexBuffer()[i].Pos.Z = position.getZ();
mb->getVertexBuffer()[i].Normal.X = normal.getX();
mb->getVertexBuffer()[i].Normal.Y = normal.getY();
mb->getVertexBuffer()[i].Normal.Z = normal.getZ();
mb->getVertexBuffer()[i].TCoords = vector2df(position.getX(), position.getZ());
mb->getVertexBuffer()[i].Color = SColor(255, 255, 255, 255);
}
mb->getIndexBuffer().set_used(indices.size());
for (size_t i = 0; i < indices.size(); ++i)
{
mb->getIndexBuffer().setValue(i, indices[i]);
}
mb->recalculateBoundingBox();
return mb;
}
And create a SceneNode from the Mesh Buffer applying a nice pretty texture
Code:
//Create An Irrlicht Mesh
SurfaceMesh<PositionMaterialNormal> mesh;
// Extract the mesh From PolyVox
MarchingCubesSurfaceExtractor<SimpleVolume<MaterialDensityPair44>> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
//CubicSurfaceExtractorWithNormals<SimpleVolume<MaterialDensityPair44>> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
surfaceExtractor.execute();
// Convert the mesh and hand it to Irrlicht
SMesh* testMesh = new SMesh;
IMeshBuffer * testBuffer = ConvertMesh(mesh);
testMesh->addMeshBuffer(testBuffer);
testMesh->recalculateBoundingBox();
//Create a scene node from our mesh
ISceneNode* testNode= smgr->addMeshSceneNode(testMesh, 0, 0, vector3df(0, 0, 0), vector3df(0, 0, 0),vector3df(1.0F, 1.0F, 1.0F));
//Scale Our Node
testNode->setScale(vector3df(1.F,1.F,1.F));
//Create A New Texture
ITexture* NewTex = driver->getTexture("content/materials/terrain-texture.jpg");
//Enable Full Bright
testNode->setMaterialFlag(EMF_LIGHTING, false);
//Set Our Nodes Material Texture To Our Newly Created Texture
testNode->setMaterialTexture(0,NewTex);
//Scale The Texture
matrix4 mat;
mat.setTextureScale(.003F,.003F);
//mat.setScale(.01F);
testNode->getMaterial(0).setTexture(0,NewTex);
testNode->getMaterial(0).setTextureMatrix(0,mat);
testNode->getMaterial(0).setFlag(EMF_LIGHTING, false);