static void smooth(DenseGrid2f grid, DenseGrid2f tmp, float alpha, int rounds) { if (tmp == null) { tmp = new DenseGrid2f(grid.ni, grid.nj, 0); } int ni = grid.ni, nj = grid.nj; for (int k = 0; k < rounds; ++k) { tmp.assign_border(1, 1); for (int j = 1; j < nj - 1; ++j) { for (int i = 1; i < ni - 1; ++i) { float avg = grid[i - 1, j] + grid[i - 1, j + 1] + grid[i, j + 1] + grid[i + 1, j + 1] + grid[i + 1, j] + grid[i + 1, j - 1] + grid[i, j - 1] + grid[i - 1, j - 1]; avg /= 8.0f; tmp[i, j] = (1 - alpha) * grid[i, j] + (alpha) * avg; } } grid.copy(tmp); } }
static void diffuse(DenseGrid2f grid, float t, Func <int, int, bool> skipF) { int ni = grid.ni, nj = grid.nj; DenseGrid2f dilated = new DenseGrid2f(grid); for (int j = 1; j < nj - 1; ++j) { for (int i = 1; i < ni - 1; ++i) { if (skipF != null && skipF(i, j)) { continue; } if (grid[i, j] < 0) { foreach (Vector2i o in gIndices.GridOffsets8) { float df = (o.LengthSquared > 1) ? -1f : -0.707f; df *= t; dilated[i + o.x, j + o.y] = Math.Min(dilated[i + o.x, j + o.y], df); //dilated[i + o.x, j + o.y] += df; } } } } grid.swap(dilated); }
static DenseGrid2i binarize(DenseGrid2f grid, float thresh = 0) { DenseGrid2i result = new DenseGrid2i(); result.resize(grid.ni, grid.nj); int size = result.size; for (int k = 0; k < size; ++k) { result[k] = (grid[k] < thresh) ? 1 : 0; } return(result); }
void process_version2(DenseGrid3f supportGrid, DenseGridTrilinearImplicit distanceField) { int ni = supportGrid.ni, nj = supportGrid.nj, nk = supportGrid.nk; float dx = (float)CellSize; Vector3f origin = this.GridOrigin; // sweep values down layer by layer DenseGrid2f prev = supportGrid.get_slice(nj - 1, 1); DenseGrid2f tmp = new DenseGrid2f(prev); Bitmap3 bmp = new Bitmap3(new Vector3i(ni, nj, nk)); for (int j = nj - 2; j >= 0; j--) { // skeletonize prev layer DenseGrid2i prev_skel = binarize(prev, 0.0f); skeletonize(prev_skel, null, 2); //dilate_loners(prev_skel, null, 2); if (j == 0) { dilate(prev_skel, null, true); dilate(prev_skel, null, true); } for (int k = 1; k < nk - 1; ++k) { for (int i = 1; i < ni - 1; ++i) { bmp[new Vector3i(i, j, k)] = (prev_skel[i, k] == 1) ? true : false; } } smooth(prev, tmp, 0.5f, 5); DenseGrid2f cur = supportGrid.get_slice(j, 1); cur.set_min(prev); for (int k = 1; k < nk - 1; ++k) { for (int i = 1; i < ni - 1; ++i) { float skelf = prev_skel[i, k] > 0 ? -1.0f : int.MaxValue; cur[i, k] = Math.Min(cur[i, k], skelf); if (cur[i, k] < 0) { Vector3d cell_center = new Vector3f(i * dx, j * dx, k * dx) + origin; if (distanceField.Value(ref cell_center) < -CellSize) { cur[i, k] = 1; } } } } for (int k = 1; k < nk - 1; ++k) { for (int i = 1; i < ni - 1; ++i) { if (is_loner(prev_skel, i, k)) { foreach (Vector2i d in gIndices.GridOffsets8) { float f = 1.0f / (float)Math.Sqrt(d.x * d.x + d.y * d.y); cur[i + d.x, k + d.y] += -0.25f * f; } } } } for (int k = 1; k < nk - 1; ++k) { for (int i = 1; i < ni - 1; ++i) { supportGrid[i, j, k] = cur[i, k]; } } prev.swap(cur); } VoxelSurfaceGenerator gen = new VoxelSurfaceGenerator() { Voxels = bmp }; gen.Generate(); Util.WriteDebugMesh(gen.Meshes[0], "c:\\scratch\\binary.obj"); }