/******************************************************************************/ /* Project - MudBun Publisher - Long Bunny Labs http://LongBunnyLabs.com Author - Ming-Lun "Allen" Chou http://AllenChou.net */ /******************************************************************************/ #ifndef MUDBUN_MARCHING_CUBES_FUNCS #define MUDBUN_MARCHING_CUBES_FUNCS #include "MarchingCubesDefs.cginc" #include "BrushFuncs.cginc" #include "NormalFuncs.cginc" #include "SDF/SDF.cginc" // cubeMat = whole-cube properties (for flat normal mode only) // tStmtPre = statements pre-processing "iTri" for new triangle // vStmt = statements processing "iVert", "aVertPos", "aVertNorm", and "aVertaMat" for new triangle // tStmtPost = statements post-processing "iTri" a new triangle #define MARCHING_CUBES( \ center, size, sdf_func, iBrushMask, smoothNormal, cubeMat, \ tStmtPre, vStmt, tStmtPost \ ) \ { \ int cubeIndex = 0; \ float d[8]; \ SdfBrushMaterial aMat[8]; \ cubeMat = init_brush_material(); \ { \ [loop] for (int iVert = 0; iVert < 8; ++iVert) \ { \ float3 vertPos = center + size * vertPosLs[iVert]; \ d[iVert] = sdf_func(vertPos, iBrushMask, aMat[iVert]); \ cubeIndex |= (int(step(0.0f, -d[iVert])) << iVert); \ } \ \ if (!smoothNormal) \ cubeMat = aMat[0]; \ } \ \ int iTriListBase = cubeIndex * 16; \ [loop] for (int iTri = 0; iTri < kMarchingCubesTrisPerVoxel; ++iTri) \ { \ int iTriBase = iTri * 3; \ int aiEdge[3]; \ aiEdge[0] = triTable[iTriListBase + iTriBase]; \ if (aiEdge[0] < 0) \ break; \ \ aiEdge[1] = triTable[iTriListBase + iTriBase + 1]; \ aiEdge[2] = triTable[iTriListBase + iTriBase + 2]; \ \ tStmtPre \ \ float3 aVertPos[3]; \ float3 aVertNorm[3]; \ float3 aEdgeCenter[3]; \ float3 goodNorm = float3(0.0f, 0.0f, 0.0f); \ SdfBrushMaterial aVertMat[3]; \ [loop] for (int jVert = 0; jVert < 3; ++jVert) \ { \ int iEdgeVert0 = vertTable[aiEdge[jVert] * 2]; \ int iEdgeVert1 = vertTable[aiEdge[jVert] * 2 + 1]; \ float3 p0Ls = vertPosLs[iEdgeVert0]; \ float3 p1Ls = vertPosLs[iEdgeVert1]; \ float t = -d[iEdgeVert0] / (d[iEdgeVert1] - d[iEdgeVert0]); \ aVertPos[jVert] = center + size * lerp(p0Ls, p1Ls, t); \ aEdgeCenter[jVert] = center + size * 0.5f * (p0Ls + p1Ls); \ if (smoothNormal) \ { \ aVertMat[jVert] = lerp(aMat[iEdgeVert0], aMat[iEdgeVert1], t); \ SDF_NORMAL(aVertNorm[jVert], aVertPos[jVert], sdf_func, iBrushMask, normalDifferentiationStep); \ if (dot(aVertNorm[jVert], aVertNorm[jVert]) > kEpsilon) \ goodNorm = aVertNorm[jVert]; \ } \ } \ \ if (smoothNormal) \ { \ for (int kVert = 0; kVert < 3; ++kVert) \ { \ if (dot(aVertNorm[kVert], aVertNorm[kVert]) <= kEpsilon) \ aVertNorm[kVert] = goodNorm; \ } \ } \ else \ { \ float3 flatNorm = \ normalize \ ( \ cross(aVertPos[1] - aVertPos[0], aVertPos[2] - aVertPos[0]) \ ); \ for (int kVert = 0; kVert < 3; ++kVert) \ aVertNorm[kVert] = flatNorm; \ } \ \ for (int iVert = 0; iVert < 3; ++iVert) \ { \ vStmt \ } \ \ tStmtPost \ } \ } // cubeMat = whole-cube properties (for flat normal mode only) // tStmtPre = statements pre-processing "iTri" for new triangle // vStmt = statements processing "iVert", "aVertPos", "aVertNorm", and "aVertaMat" for new triangle // tStmtPost = statements post-processing "iTri" a new triangle #define MARCHING_CUBES_2D( \ center, size, sdf_func, iBrushMask, smoothNormal, cubeMat, \ tStmtPre, vStmt, tStmtPost \ ) \ { \ int squareIndex = 0; \ float d[4]; \ float dCenter; \ SdfBrushMaterial aMat[4]; \ cubeMat = init_brush_material(); \ { \ [loop] for (int iVert = 0; iVert < 4; ++iVert) \ { \ float3 vertPos = center + size * vertPosLs2d[iVert]; \ d[iVert] = sdf_func(vertPos, iBrushMask, aMat[iVert]); \ squareIndex |= (int(step(0.0f, -d[iVert])) << iVert); \ } \ } \ if (!smoothNormal) \ dCenter = sdf_func(center, iBrushMask, cubeMat); \ \ int iTriListBase = squareIndex * 12; \ [loop] for (int iTri = 0; iTri < 4; ++iTri) \ { \ int iTriBase = iTri * 3; \ int aiVert[3]; \ aiVert[0] = triTable2d[iTriListBase + iTriBase]; \ if (aiVert[0] < 0) \ break; \ \ aiVert[1] = triTable2d[iTriListBase + iTriBase + 1]; \ aiVert[2] = triTable2d[iTriListBase + iTriBase + 2]; \ \ tStmtPre \ \ float3 aVertPos[3]; \ float3 aVertNorm[3]; \ float aVertSdfValue[3]; \ SdfBrushMaterial aVertMat[3]; \ [loop] for (int jVert = 0; jVert < 3; ++jVert) \ { \ if (aiVert[jVert] < 4) \ { \ aVertPos[jVert] = center + size * vertPosLs2d[aiVert[jVert]]; \ aVertMat[jVert] = aMat[aiVert[jVert]]; \ aVertSdfValue[jVert] = d[aiVert[jVert]]; \ } \ else \ { \ int iVert0 = aiVert[jVert] - 4; \ int iVert1 = ((aiVert[jVert] == 7) ? 0 : (aiVert[jVert] - 3)); \ float3 p0Ls = vertPosLs2d[iVert0]; \ float3 p1Ls = vertPosLs2d[iVert1]; \ float t = -d[iVert0] / (d[iVert1] - d[iVert0]); \ aVertPos[jVert] = center + size * lerp(p0Ls, p1Ls, t); \ aVertMat[jVert] = lerp(aMat[iVert0], aMat[iVert1], t); \ aVertSdfValue[jVert] = lerp(d[iVert0], d[iVert1], t); \ } \ } \ \ float3 aVertNorm2d[3]; \ float3 norm; \ float3 norm2d; \ if (!smoothNormal) \ { \ SDF_NORMAL_2D(norm2d, center, sdf_func, iBrushMask, normalDifferentiationStep); \ norm = normal_2d_blend(norm2d, dCenter); \ } \ for (int kVert = 0; kVert < 3; ++kVert) \ { \ int iVertNorm = aiVert[kVert]; \ if (smoothNormal) \ { \ SDF_NORMAL_2D(norm2d, aVertPos[kVert], sdf_func, iBrushMask, normalDifferentiationStep); \ norm = normal_2d_blend(norm2d, d[iVertNorm]); \ } \ aVertNorm[kVert] = norm; \ aVertNorm2d[kVert] = norm2d; \ } \ \ for (int iVert = 0; iVert < 3; ++iVert) \ { \ vStmt \ } \ \ tStmtPost \ } \ } #endif