Hi there!
In my octree-based voxel terrain engine, to prevent cracks, each octree node (chunk) must know the LoDs/sizes of its neighbors.
Currently, this info is stored as 18-bit adjacency masks (for 6 face- and 12 edge-adjacent nodes), with costly neighbor finding to update those masks, for each octree node (like four hundred nodes translating into two thousand checks!).
I'd like to avoid maintaining adjacency masks and instead use an algorithmic approach.
I need a fast function for checking if an octree node at the given position and with the given LoD/size exists in the octree, without walking the entire hierarchy.
The function should preferably be integer-based (i.e. not use floating-point) and cause a square, clipmap-style node arrangement.
Here's the function I use for updating the octree; it ensures 2:1 LOD transitions, but sometimes creates rectangular 'rings' instead of cubic:
/// returns true if the given node requires splitting
bool Node_Should_Be_Split( const OctreeNode& _node, const OctreeWorld::Observer& _eye )
{
const UINT nodeLoD = _node.id.GetLOD();
const UINT nodeSize = (1u << nodeLoD);
const UINT nodeRadius = nodeSize / 2u;
const UInt3 nodeCenterCoords = (_node.id.ToUInt3() * nodeSize) + UInt3(nodeRadius);
const UINT distance = Chebyshev_Distance( Int3::FromXYZ(_eye.coordsInChunksGrid), Int3::FromXYZ(nodeCenterCoords) );
// Chebyshev distance is the 'smallest' norm: max(|dx|, |dy|, |dz|) <= distance(dx,dy,dz) <= |dx| + |dy| + |dz|.
return distance < nodeSize * LOD_RANGE + nodeRadius; // this node is far away
}
/// Chebyshev distance (aka "[Tchebychev|Chessboard|Center] Distance" or "maximum [metric|norm]"):
/// the maximum of the absolute rank- and file-distance of both squares.
template< typename TYPE >
TYPE Chebyshev_Distance( const Tuple3< TYPE >& _a, const Tuple3< TYPE >& _b )
{
return Max3( Abs(_a.x - _b.x), Abs(_a.y - _b.y), Abs(_a.z - _b.z) );
}