You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.2 KiB
Plaintext
162 lines
4.2 KiB
Plaintext
2 weeks ago
|
/******************************************************************************/
|
||
|
/*
|
||
|
Project - MudBun
|
||
|
Publisher - Long Bunny Labs
|
||
|
http://LongBunnyLabs.com
|
||
|
Author - Ming-Lun "Allen" Chou
|
||
|
http://AllenChou.net
|
||
|
*/
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#ifndef MUDBUN_VOXEL_HASH_FUNCS
|
||
|
#define MUDBUN_VOXEL_HASH_FUNCS
|
||
|
|
||
|
#include "VoxelHashDefs.cginc"
|
||
|
|
||
|
#include "AabbTreeFuncs.cginc"
|
||
|
#include "BrushFuncs.cginc"
|
||
|
#include "Math/Codec.cginc"
|
||
|
#include "RenderModeDefs.cginc"
|
||
|
#include "VoxelFuncs.cginc"
|
||
|
|
||
|
// https://nosferalatu.com/SimpleGPUHashTable.html
|
||
|
int register_alloc_top_node(float3 center, int3 iCenter)
|
||
|
{
|
||
|
float halfSize = 0.5f * currentNodeSize;
|
||
|
|
||
|
uint key = top_node_key(iCenter);
|
||
|
uint slot = key % nodeHashTableSize;
|
||
|
|
||
|
int i = 0;
|
||
|
while (i++ < kMaxVoxelHashCollisions)
|
||
|
{
|
||
|
uint prev = kNullVoxelHashKey;
|
||
|
InterlockedCompareExchange(nodeHashTable[slot].key, kNullVoxelHashKey, key, prev);
|
||
|
if (prev == kNullVoxelHashKey)
|
||
|
{
|
||
|
// newly registered
|
||
|
int iNode = allocate_node(center, 0, -1, key);
|
||
|
if (iNode < 0)
|
||
|
{
|
||
|
aNumNodesAllocated[0] = nodeHashTableSize;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
nodeHashTable[slot].iNode = iNode;
|
||
|
|
||
|
int prevNumAllocated = 0;
|
||
|
InterlockedAdd(aNumAllocation[kNumAllocationsVoxelHash], 1, prevNumAllocated);
|
||
|
|
||
|
if (renderMode == kRenderModeRayTracedVoxels)
|
||
|
{
|
||
|
int prevTopNodeAllocated = 0;
|
||
|
InterlockedAdd(indirectDrawArgs[0], 36, prevTopNodeAllocated);
|
||
|
}
|
||
|
|
||
|
Aabb nodeAabb = make_aabb(center - halfSize, center + halfSize);
|
||
|
nodePool[iNode].iBrushMask = allocate_node_brush_mask(iNode, nodeAabb);
|
||
|
return iNode;
|
||
|
}
|
||
|
|
||
|
if (key == nodeHashTable[slot].key)
|
||
|
{
|
||
|
// already registered
|
||
|
return -1; // already registered
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// collision
|
||
|
slot = (slot + 1) % nodeHashTableSize;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void register_brush_aabb(int iBrush)
|
||
|
{
|
||
|
int op = aBrush[iBrush].op;
|
||
|
float blend = aBrush[iBrush].blend;
|
||
|
float maxDistFromCenter = currentNodeSize + blend;
|
||
|
int iProxy = aBrush[iBrush].iProxy;
|
||
|
Aabb aabb = aabbTree[iProxy].aabb;
|
||
|
float3 clampedSurfaceShift = max(-aabb_extents(aabb), surfaceShift);
|
||
|
aabb.boundsMin.xyz -= clampedSurfaceShift;
|
||
|
aabb.boundsMax.xyz += clampedSurfaceShift;
|
||
|
int3 iBoundsMin = int3(floor(aabb.boundsMin.xyz / currentNodeSize));
|
||
|
int3 iBoundsMax = int3(floor(aabb.boundsMax.xyz / currentNodeSize));
|
||
|
float halfNodeSize = 0.5f * currentNodeSize;
|
||
|
for (int z = iBoundsMin.z; z <= iBoundsMax.z; ++z)
|
||
|
for (int y = iBoundsMin.y; y <= iBoundsMax.y; ++y)
|
||
|
for (int x = iBoundsMin.x; x <= iBoundsMax.x; ++x)
|
||
|
{
|
||
|
if (enable2dMode && z != 0)
|
||
|
continue;
|
||
|
|
||
|
float3 center = (float3(x, y, z) + 0.5f) * currentNodeSize;
|
||
|
|
||
|
// profiler says it's faster if we don't do this extra brush evaluation
|
||
|
/*
|
||
|
float d = sdf_brush(kInfinity, center, aBrush[iBrush]);
|
||
|
if (op == kSdfUnion)
|
||
|
{
|
||
|
if (abs(d) > maxDistFromCenter)
|
||
|
continue;
|
||
|
}
|
||
|
else if (op == kSdfSubtract)
|
||
|
{
|
||
|
if (d > maxDistFromCenter)
|
||
|
continue;
|
||
|
}
|
||
|
else if (op == kSdfIntersect)
|
||
|
{
|
||
|
if (-d > maxDistFromCenter)
|
||
|
continue;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
register_alloc_top_node(center, int3(x, y, z));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int register_alloc_child_node(float3 center, float size, int depth, int iParent, uint3 childNodeCoord)
|
||
|
{
|
||
|
uint key = nodePool[iParent].key;
|
||
|
key = concat_node_key(key, childNodeCoord);
|
||
|
uint slot = key % nodeHashTableSize;
|
||
|
|
||
|
int i = 0;
|
||
|
while (i++ < kMaxVoxelHashCollisions)
|
||
|
{
|
||
|
uint prev = kNullVoxelHashKey;
|
||
|
InterlockedCompareExchange(nodeHashTable[slot].key, kNullVoxelHashKey, key, prev);
|
||
|
if (prev == kNullVoxelHashKey)
|
||
|
{
|
||
|
// newly registered
|
||
|
int iNode = allocate_node(center, depth, iParent, key);
|
||
|
if (iNode < 0)
|
||
|
{
|
||
|
aNumNodesAllocated[0] = nodeHashTableSize;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
nodeHashTable[slot].iNode = iNode;
|
||
|
return iNode;
|
||
|
}
|
||
|
|
||
|
if (key == nodeHashTable[slot].key)
|
||
|
{
|
||
|
// already registered
|
||
|
return -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// collision
|
||
|
slot = (slot + 1) % nodeHashTableSize;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|