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.

216 lines
9.0 KiB
HLSL

/*****************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
#ifndef MUDBUN_BRUSH_MASKS_FUNCS
#define MUDBUN_BRUSH_MASKS_FUNCS
#include "BrushMaskDefs.cginc"
#include "AllocationDefs.cginc"
#include "BrushDefs.cginc"
#include "NormalFuncs.cginc"
#include "VoxelDefs.cginc"
int num_brush_mask_ints()
{
return uint(numBrushes + kBitsPerInt - 1) / kBitsPerInt;
}
#define BRUSH_MASK_SET_ALL(mask) \
{ \
for (int iInt = 0, n = num_brush_mask_ints(); iInt < n; ++iInt) \
mask[iInt] = (~0u); \
}
#define BRUSH_MASK_CLEAR_ALL(mask) \
{ \
for (int iInt = 0, n = num_brush_mask_ints(); iInt < n; ++iInt) \
mask[iInt] = 0u; \
}
#define BRUSH_MASK_SET(mask, bit) \
(mask[uint(bit) / kBitsPerInt] |= (1u << (uint(bit) % kBitsPerInt)))
#define BRUSH_MASK_CLEAR(mask, bit) \
(mask[uint(bit) / kBitsPerInt] &= (~(1u << (uint(bit) % kBitsPerInt))))
#define BRUSH_MASK_GET(mask, bit) \
((mask[uint(bit) / kBitsPerInt] & (1u << (uint(bit) % kBitsPerInt))) != 0u)
#define READ_BRUSH_MASK(mask, iMask) \
{ \
int numInts = num_brush_mask_ints(); \
int iBaseInt = iMask * numInts; \
for (int iInt = 0; iInt < numInts; ++iInt) \
mask[iInt] = brushMaskPool[iBaseInt + iInt]; \
}
#define WRITE_BRUSH_MASK(mask, iMask) \
{ \
int numInts = num_brush_mask_ints(); \
int iBaseInt = iMask * numInts; \
for (int iInt = 0; iInt < numInts; ++iInt) \
brushMaskPool[iBaseInt + iInt] = mask[iInt]; \
}
// https://www.geeksforgeeks.org/position-of-rightmost-set-bit/
#define FOR_EACH_BRUSH(iMask, stmt) \
if (iMask >= 0) \
{ \
int numInts = num_brush_mask_ints(); \
int iBaseInt = iMask * numInts; \
int iBrushBase = 0; \
for (int iInt = 0; iInt < numInts; ++iInt, iBrushBase += kBitsPerInt) \
{ \
uint currInt = brushMaskPool[iBaseInt + iInt]; \
while (currInt != 0) \
{ \
int iFirstSetBit = int(log2(currInt & (~currInt + 1u))); \
int iBrush = iBrushBase + iFirstSetBit; \
if (iBrush >= numBrushes) \
break; \
currInt &= ~(1u << iFirstSetBit); \
\
if (aBrush[iBrush].type == kSdfNoOp) \
continue; \
\
if ((aBrush[iBrush].flags & kSdfBrushFlagsHidden) != 0) \
continue; \
\
stmt \
} \
} \
}
// https://www.geeksforgeeks.org/position-of-rightmost-set-bit/
#define FOR_EACH_BRUSH_EXTERN_MASK(mask, stmt) \
{ \
int numInts = num_brush_mask_ints(); \
int iBaseInt = 0; \
int iBrushBase = 0; \
for (int iInt = 0; iInt < numInts; ++iInt, iBrushBase += kBitsPerInt) \
{ \
uint currInt = mask[iBaseInt + iInt]; \
while (currInt != 0) \
{ \
int iFirstSetBit = int(log2(currInt & (~currInt + 1u))); \
int iBrush = iBrushBase + iFirstSetBit; \
if (iBrush >= numBrushes) \
break; \
currInt &= ~(1u << iFirstSetBit); \
\
if (aBrush[iBrush].type == kSdfNoOp) \
continue; \
\
if ((aBrush[iBrush].flags & kSdfBrushFlagsHidden) != 0) \
continue; \
\
stmt \
} \
} \
}
#ifdef MUDBUN_IS_COMPUTE_SHADER
int allocate_brush_mask()
{
int iMask = -1;
InterlockedAdd(aNumAllocation[kNumAllocationsBrushMasks], 1, iMask);
if (iMask >= brushMaskPoolSize)
{
aNumAllocation[kNumAllocationsBrushMasks] = brushMaskPoolSize;
iMask = -1;
}
return iMask;
}
int allocate_node_brush_mask(int iNode, Aabb nodeAabb)
{
int iBrushMask = allocate_brush_mask();
if (iBrushMask < 0)
return -1;
float3 clampedSurfaceShift = max(-aabb_extents(nodeAabb), surfaceShift);
nodeAabb.boundsMin.xyz -= clampedSurfaceShift;
nodeAabb.boundsMax.xyz += clampedSurfaceShift;
BRUSH_MASK(brushMask);
if (forceAllBrushes)
{
BRUSH_MASK_SET_ALL(brushMask);
}
else
{
BRUSH_MASK_CLEAR_ALL(brushMask);
int iParent = nodePool[iNode].iParent;
int iParentMask = iParent >= 0 ? nodePool[iParent].iBrushMask : -1;
if (iParentMask >= 0)
{
float maxBlend = 0.0f;
FOR_EACH_BRUSH(iParentMask,
if (aabb_intersects(nodeAabb, aabbTree[aBrush[iBrush].iProxy].aabb))
maxBlend = max(maxBlend, aBrush[iBrush].blend);
);
nodeAabb.boundsMin -= maxBlend + voxelSize + normalDifferentiationStep;
nodeAabb.boundsMax += maxBlend + voxelSize + normalDifferentiationStep;
FOR_EACH_BRUSH(iParentMask,
if (aabb_intersects(nodeAabb, aabbTree[aBrush[iBrush].iProxy].aabb))
BRUSH_MASK_SET(brushMask, iBrush);
);
}
else
{
float maxBlend = 0.0f;
AABB_TREE_QUERY_AABB(aabbTree, aabbRoot, nodeAabb,
maxBlend = max(maxBlend, aBrush[iData].blend);
);
nodeAabb.boundsMin -= maxBlend + normalDifferentiationStep;
nodeAabb.boundsMax += maxBlend + normalDifferentiationStep;
AABB_TREE_QUERY_AABB(aabbTree, aabbRoot, nodeAabb,
BRUSH_MASK_SET(brushMask, iData);
);
}
}
WRITE_BRUSH_MASK(brushMask, iBrushMask);
return iBrushMask;
}
#endif
int get_brush_mask_index(int iNode)
{
int iBrushMask = nodePool[iNode].iBrushMask;
while (iBrushMask < 0)
{
iNode = nodePool[iNode].iParent;
if (iNode < 0)
break;
iBrushMask = nodePool[iNode].iBrushMask;
}
return iBrushMask;
}
#endif