Hello everyone! :]
I am using Accidental Noise Library to generate the base density values for my volume!
I was wondering if anyone else has had success with this?
This is currently what I'm getting:

It's only giving me like a slice for whatever reason.
Has anyone encountered this?
I'll try to post all of the code involved so you can follow my logic:
Generator.h all the ANL stuff (thanks GM_Riscvul)
Code:
#ifndef __Generator_h__
#define __Generator_h__
#include "anl.h"
class Generator
{
public:
Generator(unsigned int seed)
{
//This can be altered to change relative height and slant of landscape
groundGradient.setGradient(0.0,0.0,0.0,1.0,0.0,0.0);
//Set up lowlands generation
lowlandShapeFractal = new anl::CImplicitFractal(anl::BILLOW, anl::GRADIENT, anl::QUINTIC);
lowlandShapeFractal->setSeed(seed);
lowlandShapeFractal->setNumOctaves(2);
lowlandShapeFractal->setFrequency(0.25);
lowlandAutoCorrect.setSource(lowlandShapeFractal);
lowlandAutoCorrect.setRange(0.0,1.0);
lowlandScale = new anl::CImplicitScaleOffset(0.125,-0.45);
lowlandScale->setSource(&lowlandAutoCorrect);
lowlandYScale.setSource(lowlandScale);
lowlandYScale.setYScale(0.0);
lowlandTerrain.setSource(&groundGradient);
lowlandTerrain.setYAxisSource(&lowlandYScale);
//Add Oceans by scaling lowlands fractal
//oceanScale = new anl::CImplicitScaleOffset(0.125,-0.55);
//oceanScale->setSource(&lowlandAutoCorrect);
//oceanYScale.setSource(oceanScale);
//oceanYScale.setYScale(0.0);
//oceanTerrain.setSource(&groundGradient);
//oceanTerrain.setYAxisSource(&oceanYScale);
//Set up highlands generation
highlandShapeFractal = new anl::CImplicitFractal(anl::FBM, anl::GRADIENT, anl::QUINTIC);
highlandShapeFractal->setSeed(seed);
highlandShapeFractal->setNumOctaves(4);
highlandShapeFractal->setFrequency(3);
highlandAutoCorrect.setSource(highlandShapeFractal);
highlandAutoCorrect.setRange(-1.0,1.0);
highlandScale = new anl::CImplicitScaleOffset(0.25,0.0);
highlandScale->setSource(&highlandAutoCorrect);
highlandYScale.setSource(highlandScale);
highlandYScale.setYScale(0.65);
highlandTerrain.setSource(&groundGradient);
highlandTerrain.setYAxisSource(&highlandYScale);
//Set up mountains generation
mountainShapeFractal = new anl::CImplicitFractal(anl::RIDGEDMULTI, anl::GRADIENT, anl::QUINTIC);
mountainShapeFractal->setSeed(seed);
mountainShapeFractal->setNumOctaves(6);
mountainShapeFractal->setFrequency(1);
mountainAutoCorrect.setSource(mountainShapeFractal);
mountainAutoCorrect.setRange(-1.0,1.0);
mountainScale = new anl::CImplicitScaleOffset(0.65,0.15);
mountainScale->setSource(&mountainAutoCorrect);
mountainTerrain.setSource(&groundGradient);
mountainTerrain.setYAxisSource(mountainScale);
//Blend different terrain types together
terrainTypeFractal = new anl::CImplicitFractal(anl::FBM, anl::GRADIENT, anl::QUINTIC);
terrainTypeFractal->setSeed(seed);
terrainTypeFractal->setNumOctaves(3);
terrainTypeFractal->setFrequency(0.125);
terrainAutoCorrect.setSource(terrainTypeFractal);
terrainAutoCorrect.setRange(-1.0,1.0);
terrainTypeYScale.setSource(&terrainAutoCorrect);
terrainTypeYScale.setScale(1.0,0);
terrainTypeCache.setSource(&terrainTypeYScale);
highlandMountainSelect.setLowSource(&highlandTerrain);
highlandMountainSelect.setHighSource(&mountainTerrain);
highlandMountainSelect.setControlSource(&terrainTypeCache);
highlandMountainSelect.setThreshold(0.60);
highlandMountainSelect.setFalloff(0.2);
highlandLowlandSelect.setLowSource(&lowlandTerrain);
highlandLowlandSelect.setHighSource(&highlandMountainSelect);
highlandLowlandSelect.setControlSource(&terrainTypeCache);
highlandLowlandSelect.setThreshold(0.15);
highlandLowlandSelect.setFalloff(0.15);
//LowlandOceanSelect.setLowSource(&oceanTerrain);
//LowlandOceanSelect.setHighSource(&highlandLowlandSelect);
//LowlandOceanSelect.setControlSource(&terrainTypeCache);
//LowlandOceanSelect.setThreshold(0.15);
//LowlandOceanSelect.setFalloff(0.15);
//highlandLowlandSelectCache.setSource(&LowlandOceanSelect);
highlandLowlandSelectCache.setSource(&highlandLowlandSelect);
//Set Up cave generation
caveShape = new anl::CImplicitFractal(anl::RIDGEDMULTI, anl::GRADIENT,anl::QUINTIC);
caveShape->setSeed(seed);
caveShape->setNumOctaves(1);
caveShape->setFrequency(4);
caveAttenuateBias = new anl::CImplicitBias(0.45);
caveAttenuateBias->setSource(&highlandLowlandSelectCache);
caveShapeAttenuate = new anl::CImplicitCombiner(anl::MULT);
caveShapeAttenuate->setSource(0,caveShape);
caveShapeAttenuate->setSource(1,caveAttenuateBias);
cavePerturbFractal = new anl::CImplicitFractal(anl::FBM,anl::GRADIENT,anl::QUINTIC);
cavePerturbFractal->setSeed(seed);
cavePerturbFractal->setNumOctaves(6);
cavePerturbFractal->setFrequency(3);
cavePerturbScale = new anl::CImplicitScaleOffset(0.5,0.0);
cavePerturbScale->setSource(cavePerturbFractal);
cavePerturb.setSource(caveShapeAttenuate);
cavePerturb.setXAxisSource(cavePerturbScale);
caveSelect.setLowSource(1.0);
caveSelect.setHighSource(0.0);
caveSelect.setControlSource(&cavePerturb);
caveSelect.setThreshold(0.48);
caveSelect.setFalloff(0.0);
//Select module performs a step function on the gradient in order to get a clear boundary between earth and sky
//Change threshold to alter height of landscape based on gradient
groundSelect.setLowSource(0.0);
groundSelect.setHighSource(1.0);
groundSelect.setThreshold(0.5);
groundSelect.setControlSource(&highlandLowlandSelectCache);
groundCaveMultiply = new anl::CImplicitCombiner(anl::MULT);
groundCaveMultiply->setSource(0,&caveSelect);
groundCaveMultiply->setSource(1,&groundSelect);
}
inline double getMaterial(int x, int y, int z)
{
return groundCaveMultiply->get(x, y, z);
}
private:
//Defines landscape shape in lowland regions
anl::CImplicitFractal * lowlandShapeFractal;
anl::CImplicitAutoCorrect lowlandAutoCorrect;
anl::CImplicitScaleOffset * lowlandScale;
anl::CImplicitScaleDomain lowlandYScale;
anl::CImplicitTranslateDomain lowlandTerrain;
//Defines landscape in ocean regions
anl::CImplicitScaleOffset * oceanScale;
anl::CImplicitScaleDomain oceanYScale;
anl::CImplicitTranslateDomain oceanTerrain;
//Defines landscape shape in highland regions
anl::CImplicitFractal * highlandShapeFractal;
anl::CImplicitAutoCorrect highlandAutoCorrect;
anl::CImplicitScaleOffset * highlandScale;
anl::CImplicitScaleDomain highlandYScale;
anl::CImplicitTranslateDomain highlandTerrain;
//Defines landscape shape in mountain regions
anl::CImplicitFractal * mountainShapeFractal;
anl::CImplicitAutoCorrect mountainAutoCorrect;
anl::CImplicitScaleOffset * mountainScale;
anl::CImplicitScaleDomain mountainYScale;
anl::CImplicitTranslateDomain mountainTerrain;
//Defines cave shapes
anl::CImplicitFractal * caveShape;
anl::CImplicitSelect caveSelect;
anl::CImplicitFractal * cavePerturbFractal;
anl::CImplicitScaleOffset * cavePerturbScale;
anl::CImplicitTranslateDomain cavePerturb;
anl::CImplicitBias * caveAttenuateBias;
anl::CImplicitCombiner * caveShapeAttenuate;
anl::CImplicitCombiner * groundCaveMultiply;
//Blend between different landscape types
anl::CImplicitFractal * terrainTypeFractal;
anl::CImplicitAutoCorrect terrainAutoCorrect;
anl::CImplicitScaleDomain terrainTypeYScale;
anl::CImplicitCache terrainTypeCache;
anl::CImplicitSelect highlandMountainSelect;
anl::CImplicitSelect highlandLowlandSelect;
anl::CImplicitSelect LowlandOceanSelect;
anl::CImplicitCache highlandLowlandSelectCache;
//Select module performs a step function on the gradient in order to get a clear boundary between earth and sky
anl::CImplicitSelect groundSelect;
//Form gradient to base land shape off of. This can be altered to change relative height and slant of landscape
anl::CImplicitGradient groundGradient;
};
#endif
This function generates a new sector which creates chunks of specified block regions, iterates through those regions polling ANL for the density value and adds it into the LargeVolume
Code:
void GenerateSector( int secX, int secY, int secZ )
{
//Create A New Sector
DayX_Sector *NewSector = new DayX_Sector;
NewSector->SectorPos = PolyVox::Vector3DInt16( secX, secY, secZ );
std::cout << "NEW SECTOR: " << secX << " " << secY << " " << secZ << std::endl;
for (int chkX = secX*ChunksPerSectorX; chkX < (secX*ChunksPerSectorX)+ChunksPerSectorX; chkX++)
{
for (int chkZ = secZ*ChunksPerSectorZ; chkZ < (secZ*ChunksPerSectorZ)+ChunksPerSectorZ; chkZ++)
{
for (int chkY = secY*ChunksPerSectorY; chkY < (secY*ChunksPerSectorY)+ChunksPerSectorY; chkY++)
{
//Create A New Chunk
std::cout << "-NEW CHUNK: " << chkX << " " << chkY << " " << chkZ;
DayX_Chunk *NewChunk = new DayX_Chunk;
NewChunk->ChunkPos = PolyVox::Vector3DInt16( secX, secY, secZ );
//Compute The Block Region
PolyVox::Region BlockRegion = PolyVox::Region( chkX*BlocksPerChunkX, chkY*BlocksPerChunkY, chkZ*BlocksPerChunkZ,
(chkX*BlocksPerChunkX)+BlocksPerChunkX, (chkY*BlocksPerChunkY)+BlocksPerChunkY, (chkZ*BlocksPerChunkZ)+BlocksPerChunkZ );
NewChunk->Blocks = BlockRegion;
//Fill Blocks With Initial Density Value
for ( int blkX = BlockRegion.getLowerX(); blkX <= BlockRegion.getUpperX(); ++blkX )
{
for ( int blkZ = BlockRegion.getLowerZ(); blkZ <= BlockRegion.getUpperZ(); ++blkZ )
{
for ( int blkY = BlockRegion.getLowerY(); blkY <= BlockRegion.getUpperY(); ++blkY )
{
volData->setVoxelAt( blkX, blkY, blkZ, PolyVox::MaterialDensityPair44(1, NoiseMap->getMaterial( blkX, blkY-16, blkZ ) ) );
}
}
}
//Add Chunk To Sector
NewSector->Chunks.push_back( NewChunk );
std::cout << " - DONE" << std::endl;
}
}
}
Sectors.push_back(NewSector);
std::cout << "SECTOR DONE" << std::endl;
}
This function sends the needed chunks to clients:
Code:
void StreamSector2( size_t ConnID, PolyVox::Vector3DInt16 VoxelPos_World )
{
DayX_Sector* Sector = GetSectorFromVoxelPos( VoxelPos_World );
if ( Sector != nullptr )
{
for( std::vector<DayX_Chunk*>::iterator Chunk = Sector->Chunks.begin(); Chunk != Sector->Chunks.end(); ++Chunk )
{
//Sending Chunk Data Packet
mn::AddSizeT( sendPacket, OP_LOADCHUNK );
//Chunk Region Lower Corner
mn::AddInt( sendPacket, (*Chunk)->Blocks.getLowerX());
mn::AddInt( sendPacket, (*Chunk)->Blocks.getLowerY());
mn::AddInt( sendPacket, (*Chunk)->Blocks.getLowerZ());
//Chunk Region Upper Corner
mn::AddInt( sendPacket, (*Chunk)->Blocks.getUpperX());
mn::AddInt( sendPacket, (*Chunk)->Blocks.getUpperY());
mn::AddInt( sendPacket, (*Chunk)->Blocks.getUpperZ());
//Fill Density Value For Each Block
for ( int x = (*Chunk)->Blocks.getLowerX(); x <= (*Chunk)->Blocks.getUpperX(); ++x )
{
for ( int z = (*Chunk)->Blocks.getLowerZ(); z <= (*Chunk)->Blocks.getUpperZ(); ++z )
{
for ( int y = (*Chunk)->Blocks.getLowerY(); y <= (*Chunk)->Blocks.getUpperY(); ++y )
{
PolyVox::MaterialDensityPair44 Voxel = volData->getVoxelAt( x, y, z );
mn::AddUnsignedByte( sendPacket, Voxel.getDensity() );
}
}
}
//Send TCP Packet To Client
std::cout << "SEND SECTOR - ";
mn::SendTCP( 0,sendPacket,ConnID,false,false );
std::cout << "SENT" << std::endl;
}
}
}
This function receives the information on the client, adds it into the LargeVolume on the client then creates an Irrlicht Scene Node
Code:
void DayX_ChunkManager::Receive_Chunk( INT_PTR recvPacket )
{
std::cout << "Receive Chunk - ";
//Receive Lower Chunk Voxel Pos
int LowerX = mn::GetInt( recvPacket );
int LowerY = mn::GetInt( recvPacket );
int LowerZ = mn::GetInt( recvPacket );
//Receive Upper Chunk Voxel Pos
int UpperX = mn::GetInt( recvPacket );
int UpperY = mn::GetInt( recvPacket );
int UpperZ = mn::GetInt( recvPacket );
std::cout << LowerX << " " << LowerY << " " << LowerZ << " -- " << UpperX << " " << UpperY << " " << UpperZ;
for ( int32_t blkX = LowerX; blkX <= UpperX; ++blkX )
{
for ( int32_t blkZ = LowerZ; blkZ <= UpperZ; ++blkZ )
{
for ( int32_t blkY = LowerY; blkY <= UpperY; ++blkY )
{
//std::cout << "A ";
uint8_t Density = mn::GetUnsignedByte( recvPacket ) * 255;
PolyVox::MaterialDensityPair44 Voxel = PolyVox::MaterialDensityPair44(1, Density);
//std::cout << "B ";
volData->setVoxelAt( blkX, blkY, blkZ, Voxel );
//std::cout << "C";
}
}
}
std::cout << " - Done" << std::endl;
PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> Mesh_PolyVox;
//Extract A PolyVox Mesh From Our Region
PolyVox::MarchingCubesSurfaceExtractor<PolyVox::LargeVolume<PolyVox::MaterialDensityPair44>> surfaceExtractor(volData, PolyVox::Region(LowerX, LowerY, LowerZ, UpperX, UpperY, UpperZ), &Mesh_PolyVox);
surfaceExtractor.execute();
//Convert PolyVox Mesh To Irrlicht Mesh With A Mesh Buffer
irr::scene::SMesh* IrrlichtMesh = new irr::scene::SMesh;
irr::scene::IMeshBuffer * MeshBuffer = ConvertMesh( Mesh_PolyVox, 1, 1 );
IrrlichtMesh->addMeshBuffer(MeshBuffer);
IrrlichtMesh->recalculateBoundingBox();
//Create A Scene Node From Our New Mesh
//Creating The Scene Node Will Have To Be Done Elsewhere
//When We Implement Dynamic Editing Of The Terrain
//The Nodes Mesh Will Need To Be Updated
//Instead Of Creating A New Node.
irr::scene::IMeshSceneNode* TerrainNode = AppContext.SMGR->addOctreeSceneNode(IrrlichtMesh,0,-1,64,false);
//Make Our SceneNode Bigger!
TerrainNode->setScale(irr::core::vector3df(5,5,5));
//Position Our SceneNode To The Proper Region Position
//std::cout << XPos-16 << " - " << YPos << std::endl;
irr::f32 PosX = (LowerX)*5;
irr::f32 PosY = (LowerY);
irr::f32 PosZ = (LowerZ)*5;
std::cout << "CHK POS - " << PosX << " " << PosY << " " << PosZ << std::endl;
TerrainNode->setPosition(irr::core::vector3df(PosX,PosY,PosZ));
//Enable Full Bright
//TerrainNode->setMaterialFlag(EMF_LIGHTING, false);
TerrainNode->setMaterialFlag(irr::video::EMF_FOG_ENABLE, true);
//Create A New Texture
irr::video::ITexture* NewTex = AppContext.Driver->getTexture("content/materials/grass_1.jpg");
irr::video::ITexture* DetTex = AppContext.Driver->getTexture("content/materials/detailmap3.jpg");
//Scale The Texture
irr::core::matrix4 mat;
mat.setTextureScale(1.0F,1.0F);
TerrainNode->getMaterial(0).setTexture(0,NewTex);
TerrainNode->getMaterial(0).setTextureMatrix(0,mat);
TerrainNode->getMaterial(0).setFlag(irr::video::EMF_LIGHTING, false);
AppContext.SMGR->addCubeSceneNode(10.0f,0,-1,irr::core::vector3df(0,0,0),irr::core::vector3df(0,0,0),irr::core::vector3df(1.0f,1.0f,1.0f));
// create triangle selector for the terrain
//irr::scene::ITriangleSelector* TerrainTriangleSelector = AppContext.SMGR->createOctreeTriangleSelector(IrrlichtMesh, TerrainNode, 16);
//TerrainNode->setTriangleSelector(TerrainTriangleSelector);
//DayX.MetaSelector->addTriangleSelector( TerrainTriangleSelector );
//TerrainTriangleSelector->drop();
}
That should be everything so you can follow my logic, I know it's a lot of code, I'm not asking anyone to go through it, it's only there if you're interested :]
I've been toying with this for a few weeks now getting it to this point, I've tried a lot of things, changing the seed value multiple times, increasing the Y axis to generate higher chunks, adding values to the Y variable sent to ANL to return the density value such as (1,16,128,1024) 128 and 1024 gives me no terrain, also making every voxel have full density gives me no terrain. I've also tried to give a buffer of 1 voxel around the entire volume with 0 density while attempting the latter to which had no effect.