Пример #1
0
        static void smooth(DenseGrid3f grid, DenseGrid3f tmp, float alpha, int iters, int min_j = 1)
        {
            if (tmp == null)
            {
                tmp = new DenseGrid3f(grid);
            }

            int ni = grid.ni, nj = grid.nj, nk = grid.nk;

            for (int iter = 0; iter < iters; ++iter)
            {
                for (int j = min_j; j < nj - 1; ++j)
                {
                    for (int k = 1; k < nk - 1; ++k)
                    {
                        for (int i = 1; i < ni - 1; ++i)
                        {
                            float avg = 0;
                            foreach (Vector3i o in gIndices.GridOffsets26)
                            {
                                int   xi = i + o.x, yi = j + o.y, zi = k + o.z;
                                float f = grid[xi, yi, zi];
                                avg += f;
                            }
                            avg         /= 26.0f;
                            tmp[i, j, k] = (1 - alpha) * grid[i, j, k] + (alpha) * avg;
                        }
                    }
                }

                grid.swap(tmp);
            }
        }
Пример #2
0
        void process_version1(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, column by column
            for (int k = 0; k < nk; ++k)
            {
                for (int i = 0; i < ni; ++i)
                {
                    bool in_support = false;
                    for (int j = nj - 1; j >= 0; j--)
                    {
                        float fcur = supportGrid[i, j, k];
                        if (fcur >= 0)
                        {
                            Vector3d cell_center = new Vector3f(i * dx, j * dx, k * dx) + origin;
                            if (in_support)
                            {
                                bool is_inside = distanceField.Value(ref cell_center) < 0;
                                if (is_inside)
                                {
                                    supportGrid[i, j, k] = -3;
                                    in_support           = false;
                                }
                                else
                                {
                                    supportGrid[i, j, k] = -1;
                                }
                            }
                        }
                        else
                        {
                            in_support = true;
                        }
                    }
                }
            }


            // skeletonize each layer
            // todo: would be nice to skeletonize the 3D volume.. ?
            DenseGrid3i binary = new DenseGrid3i(ni, nj, nk, 0);

            foreach (Vector3i idx in binary.Indices())
            {
                binary[idx] = (supportGrid[idx] < 0) ? 1 : 0;
            }
            for (int j = 0; j < nj; ++j)
            {
                skeletonize_layer(binary, j);
            }


            // debug thing
            //VoxelSurfaceGenerator voxgen = new VoxelSurfaceGenerator() {
            //    Voxels = binary.get_bitmap()
            //};
            //voxgen.Generate();
            //Util.WriteDebugMesh(voxgen.makemesh(), "c:\\scratch\\binary.obj");


            // for skeleton voxels, we add some power
            for (int j = 0; j < nj; ++j)
            {
                for (int k = 1; k < nk - 1; ++k)
                {
                    for (int i = 1; i < ni - 1; ++i)
                    {
                        if (binary[i, j, k] > 0)
                        {
                            supportGrid[i, j, k] = -3;
                        }
                        //else
                        //    supportGrid[i, j, k] = 1;   // clear non-skeleton voxels
                    }
                }
            }


            // power up the ground-plane voxels
            for (int k = 0; k < nk; ++k)
            {
                for (int i = 0; i < ni; ++i)
                {
                    if (supportGrid[i, 0, k] < 0)
                    {
                        supportGrid[i, 0, k] = -5;
                    }
                }
            }


#if true
            DenseGrid3f smoothed   = new DenseGrid3f(supportGrid);
            float       nbr_weight = 0.5f;
            for (int iter = 0; iter < 15; ++iter)
            {
                // add some mass to skeleton voxels
                for (int j = 0; j < nj; ++j)
                {
                    for (int k = 1; k < nk - 1; ++k)
                    {
                        for (int i = 1; i < ni - 1; ++i)
                        {
                            if (binary[i, j, k] > 0)
                            {
                                supportGrid[i, j, k] = supportGrid[i, j, k] - nbr_weight / 25.0f;
                            }
                        }
                    }
                }

                for (int j = 0; j < nj; ++j)
                {
                    for (int k = 1; k < nk - 1; ++k)
                    {
                        for (int i = 1; i < ni - 1; ++i)
                        {
                            int   neg = 0;
                            float avg = 0, w = 0;
                            for (int n = 0; n < 8; ++n)
                            {
                                int   xi = i + gIndices.GridOffsets8[n].x;
                                int   zi = k + gIndices.GridOffsets8[n].y;
                                float f  = supportGrid[xi, j, zi];
                                if (f < 0)
                                {
                                    neg++;
                                }
                                avg += nbr_weight * f;
                                w   += nbr_weight;
                            }
                            if (neg > -1)
                            {
                                avg += supportGrid[i, j, k];
                                w   += 1.0f;
                                smoothed[i, j, k] = avg / w;
                            }
                            else
                            {
                                smoothed[i, j, k] = supportGrid[i, j, k];
                            }
                        }
                    }
                }
                supportGrid.swap(smoothed);
            }
#endif


            // hard-enforce that skeleton voxels stay inside
            //for (int j = 0; j < nj; ++j) {
            //    for (int k = 1; k < nk - 1; ++k) {
            //        for (int i = 1; i < ni - 1; ++i) {
            //            if (binary[i, j, k] > 0)
            //                supportGrid[i, j, k] = Math.Min(supportGrid[i, j, k], - 1);
            //        }
            //    }
            //}
        }