Exemplo n.º 1
0
        public VoxelizationOutput Voxelize(VoxelizationInput input, Action <VoxelizationProgress> progress)
        {
            // Setup VBO state
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.IndexArray);

            m_input = input;

            VoxelizationOutput output = new VoxelizationOutput();

            output.Octree = input.Octree;

            VoxelizationProgress vp = new VoxelizationProgress();

            vp.Status = "Voxelizing mesh with " + input.Octree.MaxLevels + " subdivision levels";
            progress(vp);

            GL.PushAttrib(AttribMask.AllAttribBits);
            for (int i = 0; i <= input.Octree.MaxLevels; i++)
            {
                vp.Progress = (i / (input.Octree.MaxLevels + 1.0f));
                vp.Status   = "Voxelizing octree level " + i;
                progress(vp);
                RecursiveSolveStatus(input.Octree.Root, i);
            }
            GL.PopAttrib();

            vp.Progress = 1;
            vp.Status   = "Done voxelizing mesh";
            progress(vp);

            return(output);
        }
        public VoxelizationOutput Voxelize(VoxelizationInput input, Action<VoxelizationProgress> progress)
        {
            // Setup VBO state
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.IndexArray);

            m_input = input;

            VoxelizationOutput output = new VoxelizationOutput();
            output.Octree = input.Octree;

            VoxelizationProgress vp = new VoxelizationProgress();
            vp.Status = "Voxelizing mesh with " + input.Octree.MaxLevels + " subdivision levels";
            progress(vp);

            GL.PushAttrib(AttribMask.AllAttribBits);
            for (int i = 0; i <= input.Octree.MaxLevels; i++)
            {
                vp.Progress = (i / (input.Octree.MaxLevels + 1.0f));
                vp.Status = "Voxelizing octree level " + i;
                progress(vp);
                RecursiveSolveStatus(input.Octree.Root, i);
            }
            GL.PopAttrib();

            vp.Progress = 1;
            vp.Status = "Done voxelizing mesh";
            progress(vp);

            return output;
        }
        public virtual VoxelizationOutput Generate(VoxelizationInput input, Action<VoxelizationProgress> progress)
        {
            VoxelizationProgress vp = new VoxelizationProgress();

            DateTime start = DateTime.Now;

            vp.Status = "Building voxel field from octree";
            progress(vp);

            VoxelField voxelField = new VoxelField(input.Octree);

            Byte fillByte = 2;
            float oldPercent = 1.0f;
            float newPercent = 1.0f;

            List<Occluder> occluders = new List<Occluder>();

            vp.Status = "Calculating original mesh silhouette coverage";
            progress(vp);

            SilhouetteOcclusionValidator sov = new SilhouetteOcclusionValidator(1024, 1024);

            long groundSideCoverage, groundTopCoverage;
            sov.ComputeCoverage(input.OriginalMesh, input.Octree.MeshBounds, out groundSideCoverage, out groundTopCoverage);
            long totalCoverage = groundSideCoverage + groundTopCoverage;
            if (totalCoverage == 0)
                totalCoverage = 1;

            vp.Status = "Fitting boxes into mesh...";
            progress(vp);

            long oldOcclusion = 0;

            do
            {
                Vector3i densestVoxel = FindHighestDensityVoxel(voxelField);

                AABBi occluderBounds;
                if (input.Type == OcclusionType.BoxExpansion)
                {
                    occluderBounds = ExpandAndFillBox(voxelField, ref densestVoxel, fillByte);
                }
                //else if (input.Type == OcclusionType.SimulatedAnnealing)
                //{
                //    occluderBounds = SimulatedAnnealingFill(input, sov, voxelField, ref densestVoxel, fillByte, occluders);
                //}
                else if (input.Type == OcclusionType.BruteForce)
                {
                    occluderBounds = BruteForceFill(input, sov, voxelField, densestVoxel, fillByte, occluders);
                }
                else
                {
                    throw new Exception("Unknown occluder generation type!");
                }

                List<AABBi> relevantOccluders = GetRelevantOccluders(input, occluders);
                relevantOccluders.Add(occluderBounds);

                long newOcclusion = MeasureOccluderOcclusion(sov, input, relevantOccluders);

                Occluder occluder = new Occluder();
                occluder.Bounds = occluderBounds;
                occluder.DeltaOcclusion = (newOcclusion - oldOcclusion) / (double)totalCoverage;

                occluders.Add(occluder);

                if (occluder.DeltaOcclusion > input.MinimumOcclusion)
                    oldOcclusion = newOcclusion;

                Debug.WriteLine("Coverage " + occluder.DeltaOcclusion);
                Debug.WriteLine("Bounds (" + occluder.Bounds.MinX + "x" + occluder.Bounds.MaxX + " " + occluder.Bounds.MinY + "x" + occluder.Bounds.MaxY + " " + occluder.Bounds.MinZ + "x" + occluder.Bounds.MaxZ + ")");

                oldPercent = newPercent;
                newPercent = MeasureUnboxedVoxels(voxelField);

                Debug.WriteLine("(" + densestVoxel.X + "," + densestVoxel.Y + "," + densestVoxel.Z + ")\tCoverage=" + ((1 - newPercent) * 100) + "%\tDelta=" + ((oldPercent - newPercent) * 100) + "%");

                vp.Progress = Math.Min(((1 - newPercent) / input.MinimumVolume), 1.0f);
                vp.SilhouetteCoverage = oldOcclusion / (double)totalCoverage;
                vp.VolumeCoverage = 1 - newPercent;
                vp.Status = String.Format("Occlusion Progress : {0:0.##}%", (100 * vp.Progress));

                progress(vp);

            } while (newPercent > (1 - input.MinimumVolume));

            Mesh mesh = BuildMeshFromBoxes(input, GetRelevantOccluders(input, occluders));

            VoxelizationOutput output = new VoxelizationOutput();

            if (input.Retriangulate)
            {
                vp.Status = "Retriangulating occluder mesh";
                progress(vp);

                Mesh triangulatedMesh = MeshOptimizer.Retriangulate(input, mesh, out output.DebugLines);
                if (triangulatedMesh != null)
                    mesh = triangulatedMesh;
            }

            vp.Status = "Filtering polygons";
            progress(vp);

            mesh = PolygonFilter.Filter(input, mesh);

            vp.Status = "Generating final occlusion mesh";
            progress(vp);

            // Prepare the output
            output.Octree = input.Octree;
            output.TimeTaken = DateTime.Now - start;
            output.VolumeCoverage = 1 - newPercent;
            output.SilhouetteCoverage = oldOcclusion / (double)totalCoverage;
            output.OccluderMesh = new RenderableMesh(mesh, true);

            vp.Status = "Cleanup...";
            progress(vp);

            sov.Dispose();

            return output;
        }
Exemplo n.º 4
0
        public virtual VoxelizationOutput Generate(VoxelizationInput input, Action <VoxelizationProgress> progress)
        {
            VoxelizationProgress vp = new VoxelizationProgress();

            DateTime start = DateTime.Now;

            vp.Status = "Building voxel field from octree";
            progress(vp);

            VoxelField voxelField = new VoxelField(input.Octree);

            Byte  fillByte   = 2;
            float oldPercent = 1.0f;
            float newPercent = 1.0f;

            List <Occluder> occluders = new List <Occluder>();

            vp.Status = "Calculating original mesh silhouette coverage";
            progress(vp);

            SilhouetteOcclusionValidator sov = new SilhouetteOcclusionValidator(1024, 1024);

            long groundSideCoverage, groundTopCoverage;

            sov.ComputeCoverage(input.OriginalMesh, input.Octree.MeshBounds, out groundSideCoverage, out groundTopCoverage);
            long totalCoverage = groundSideCoverage + groundTopCoverage;

            if (totalCoverage == 0)
            {
                totalCoverage = 1;
            }

            vp.Status = "Fitting boxes into mesh...";
            progress(vp);

            long oldOcclusion = 0;

            do
            {
                Vector3i densestVoxel = FindHighestDensityVoxel(voxelField);

                AABBi occluderBounds;
                if (input.Type == OcclusionType.BoxExpansion)
                {
                    occluderBounds = ExpandAndFillBox(voxelField, ref densestVoxel, fillByte);
                }
                //else if (input.Type == OcclusionType.SimulatedAnnealing)
                //{
                //    occluderBounds = SimulatedAnnealingFill(input, sov, voxelField, ref densestVoxel, fillByte, occluders);
                //}
                else if (input.Type == OcclusionType.BruteForce)
                {
                    occluderBounds = BruteForceFill(input, sov, voxelField, densestVoxel, fillByte, occluders);
                }
                else
                {
                    throw new Exception("Unknown occluder generation type!");
                }

                List <AABBi> relevantOccluders = GetRelevantOccluders(input, occluders);
                relevantOccluders.Add(occluderBounds);

                long newOcclusion = MeasureOccluderOcclusion(sov, input, relevantOccluders);

                Occluder occluder = new Occluder();
                occluder.Bounds         = occluderBounds;
                occluder.DeltaOcclusion = (newOcclusion - oldOcclusion) / (double)totalCoverage;

                occluders.Add(occluder);

                if (occluder.DeltaOcclusion > input.MinimumOcclusion)
                {
                    oldOcclusion = newOcclusion;
                }

                Debug.WriteLine("Coverage " + occluder.DeltaOcclusion);
                Debug.WriteLine("Bounds (" + occluder.Bounds.MinX + "x" + occluder.Bounds.MaxX + " " + occluder.Bounds.MinY + "x" + occluder.Bounds.MaxY + " " + occluder.Bounds.MinZ + "x" + occluder.Bounds.MaxZ + ")");

                oldPercent = newPercent;
                newPercent = MeasureUnboxedVoxels(voxelField);

                Debug.WriteLine("(" + densestVoxel.X + "," + densestVoxel.Y + "," + densestVoxel.Z + ")\tCoverage=" + ((1 - newPercent) * 100) + "%\tDelta=" + ((oldPercent - newPercent) * 100) + "%");

                vp.Progress           = Math.Min(((1 - newPercent) / input.MinimumVolume), 1.0f);
                vp.SilhouetteCoverage = oldOcclusion / (double)totalCoverage;
                vp.VolumeCoverage     = 1 - newPercent;
                vp.Status             = String.Format("Occlusion Progress : {0:0.##}%", (100 * vp.Progress));

                progress(vp);
            } while (newPercent > (1 - input.MinimumVolume));

            Mesh mesh = BuildMeshFromBoxes(input, GetRelevantOccluders(input, occluders));

            VoxelizationOutput output = new VoxelizationOutput();

            if (input.Retriangulate)
            {
                vp.Status = "Retriangulating occluder mesh";
                progress(vp);

                Mesh triangulatedMesh = MeshOptimizer.Retriangulate(input, mesh, out output.DebugLines);
                if (triangulatedMesh != null)
                {
                    mesh = triangulatedMesh;
                }
            }

            vp.Status = "Filtering polygons";
            progress(vp);

            mesh = PolygonFilter.Filter(input, mesh);

            vp.Status = "Generating final occlusion mesh";
            progress(vp);

            // Prepare the output
            output.Octree             = input.Octree;
            output.TimeTaken          = DateTime.Now - start;
            output.VolumeCoverage     = 1 - newPercent;
            output.SilhouetteCoverage = oldOcclusion / (double)totalCoverage;
            output.OccluderMesh       = new RenderableMesh(mesh, true);

            vp.Status = "Cleanup...";
            progress(vp);

            sov.Dispose();

            return(output);
        }
Exemplo n.º 5
0
        public VoxelizationOutput Generate(VoxelizationInput input, Action<VoxelizationProgress> progress)
        {
            this.input = input;
            VoxelizationOutput output = new VoxelizationOutput();
            output.Octree = input.Octree;

            List<List<VoxelizingOctreeCell>> cellList = new List<List<VoxelizingOctreeCell>>();
            input.Octree.AccumulateChildren(out cellList);

            VolumeAccumulator volume = new VolumeAccumulator();
            VolumeAccumulator[] volumeAtLevel = new VolumeAccumulator[input.Octree.MaxLevels];
            for (int i = 0; i < input.Octree.MaxLevels; i++)
            {
                List<VoxelizingOctreeCell> childernAtDepth = cellList[i];

                VolumeAccumulator levelVolumeTotal = new VolumeAccumulator();

                Parallel.For(0, childernAtDepth.Count, () => new VolumeAccumulator(), (n, loop, partial) =>
                {
                    VoxelizingOctreeCell cell = childernAtDepth[n];
                    float sideLength = cell.Length;

                    switch (cell.Status)
                    {
                        case CellStatus.Inside:
                            partial.InsideTotal += (sideLength * sideLength * sideLength);
                            break;
                        case CellStatus.Outside:
                            partial.OutsideTotal += (sideLength * sideLength * sideLength);
                            break;
                        case CellStatus.Intersecting:
                        case CellStatus.IntersectingBounds:
                            if (cell.IsLeaf)
                                partial.IntersectingTotal += (sideLength * sideLength * sideLength);
                            break;
                    }

                    return partial;
                },
                partial =>
                {
                    lock (levelVolumeTotal)
                    {
                        levelVolumeTotal.InsideTotal += partial.InsideTotal;
                        levelVolumeTotal.OutsideTotal += partial.OutsideTotal;
                        levelVolumeTotal.IntersectingTotal += partial.IntersectingTotal;
                    }
                });

                volume.InsideTotal += levelVolumeTotal.InsideTotal;
                volume.OutsideTotal += levelVolumeTotal.OutsideTotal;
                volume.IntersectingTotal += levelVolumeTotal.IntersectingTotal;

                volumeAtLevel[i] = levelVolumeTotal;
            }

            Debug.WriteLine("Percentage of inner volume at each octree level");
            for (int i = 0; i < input.Octree.MaxLevels; i++)
            {
                Debug.WriteLine("Level {0}: Inner Volume {1}%", i, (volumeAtLevel[i].InsideTotal / volume.InsideTotal) * 100);
            }

            // A good check to perform is to compare the ratio of intersecting volume leaf nodes to the total volume
            // we've determined is inside.  A tool could use this ratio to automatically determine a good octree level
            // by iterative optimization.  If a mesh for example fails to get at least a 1 : 0.5 ratio of intersecting:inner
            // volume ratio it's a good bet that the octree does not subdivide enough levels in order to find enough inner volume
            // to meet our occlusion needs.  If further subdivision up to some maximum, lets say 8 fails to ever meet this ratio
            // one could say the mesh is not a good candidate for automating occluder generation.
            Debug.WriteLine("");
            float intersecting_inside_ratio = volume.InsideTotal / volume.IntersectingTotal;
            Debug.WriteLine("Intersecting : Inner = 1:{0}", intersecting_inside_ratio);
            Debug.WriteLine("Inner / (Inner + Intersecting) = {0}", volume.InsideTotal / (volume.InsideTotal + volume.IntersectingTotal));

            const float MINIMUM_INTERSECTING_TO_INSIDE_RATIO = 0.25f;

            AABBf meshBounds = input.Octree.MeshBounds;
            double dX = meshBounds.MaxX - meshBounds.MinX;
            double dY = meshBounds.MaxY - meshBounds.MinY;
            double dZ = meshBounds.MaxZ - meshBounds.MinZ;

            double reduction = 0.5;
            for (int i = 0; i <= input.Octree.MaxLevels * 2; i++)
                reduction *= 0.5;

            dX = dX * reduction;
            dY = dY * reduction;
            dZ = dZ * reduction;

            if (intersecting_inside_ratio > MINIMUM_INTERSECTING_TO_INSIDE_RATIO)
            {
                List<AABBi> innerBounds = new List<AABBi>();
                float innerVolumeGathered = 0.0f;
                for (int i = 0; i < input.Octree.MaxLevels; i++)
                {
                    for (int n = 0; n < cellList[i].Count; n++)
                    {
                        if (cellList[i][n].Status == CellStatus.Inside)
                        {
                            AABBf bound = cellList[i][n].Bounds;

                            AABBi bi = new AABBi();
                            bi.MaxX = (int)Math.Round(((double)bound.MaxX - (double)meshBounds.MinX) / dX, MidpointRounding.AwayFromZero);
                            bi.MaxY = (int)Math.Round(((double)bound.MaxY - (double)meshBounds.MinY) / dY, MidpointRounding.AwayFromZero);
                            bi.MaxZ = (int)Math.Round(((double)bound.MaxZ - (double)meshBounds.MinZ) / dZ, MidpointRounding.AwayFromZero);
                            bi.MinX = (int)Math.Round(((double)bound.MinX - (double)meshBounds.MinX) / dX, MidpointRounding.AwayFromZero);
                            bi.MinY = (int)Math.Round(((double)bound.MinY - (double)meshBounds.MinY) / dY, MidpointRounding.AwayFromZero);
                            bi.MinZ = (int)Math.Round(((double)bound.MinZ - (double)meshBounds.MinZ) / dZ, MidpointRounding.AwayFromZero);
                            innerBounds.Add(bi);
                        }
                    }

                    innerVolumeGathered += volumeAtLevel[i].InsideTotal / volume.InsideTotal;
                    if (innerVolumeGathered > input.MinimumVolume)
                    {
                        break;
                    }
                }

                Debug.WriteLine("Enough inner volume found {0}%", innerVolumeGathered * 100.0f);

                Mesh mesh = MeshBuilder.BuildMesh(innerBounds);

                for (int i = 0; i < mesh.Vertices.Length; i++)
                {
                    mesh.Vertices[i].X = (float)(((double)meshBounds.MinX) + (mesh.Vertices[i].X * dX));
                    mesh.Vertices[i].Y = (float)(((double)meshBounds.MinY) + (mesh.Vertices[i].Y * dY));
                    mesh.Vertices[i].Z = (float)(((double)meshBounds.MinZ) + (mesh.Vertices[i].Z * dZ));
                }

                if (input.Retriangulate)
                {
                    Mesh triangulatedMesh = MeshOptimizer.Retriangulate(input, mesh, out output.DebugLines);
                    if (triangulatedMesh != null)
                        mesh = triangulatedMesh;
                }

                mesh = PolygonFilter.Filter(input, mesh);

                output.OccluderMesh = new RenderableMesh(mesh, true);
            }
            else
            {
                Debug.WriteLine("Not enough inner volume found to continue.");
            }

            return output;
        }
Exemplo n.º 6
0
        public VoxelizationOutput Generate(VoxelizationInput input, Action <VoxelizationProgress> progress)
        {
            this.input = input;
            VoxelizationOutput output = new VoxelizationOutput();

            output.Octree = input.Octree;

            List <List <VoxelizingOctreeCell> > cellList = new List <List <VoxelizingOctreeCell> >();

            input.Octree.AccumulateChildren(out cellList);

            VolumeAccumulator volume = new VolumeAccumulator();

            VolumeAccumulator[] volumeAtLevel = new VolumeAccumulator[input.Octree.MaxLevels];
            for (int i = 0; i < input.Octree.MaxLevels; i++)
            {
                List <VoxelizingOctreeCell> childernAtDepth = cellList[i];

                VolumeAccumulator levelVolumeTotal = new VolumeAccumulator();

                Parallel.For(0, childernAtDepth.Count, () => new VolumeAccumulator(), (n, loop, partial) =>
                {
                    VoxelizingOctreeCell cell = childernAtDepth[n];
                    float sideLength          = cell.Length;

                    switch (cell.Status)
                    {
                    case CellStatus.Inside:
                        partial.InsideTotal += (sideLength * sideLength * sideLength);
                        break;

                    case CellStatus.Outside:
                        partial.OutsideTotal += (sideLength * sideLength * sideLength);
                        break;

                    case CellStatus.Intersecting:
                    case CellStatus.IntersectingBounds:
                        if (cell.IsLeaf)
                        {
                            partial.IntersectingTotal += (sideLength * sideLength * sideLength);
                        }
                        break;
                    }

                    return(partial);
                },
                             partial =>
                {
                    lock (levelVolumeTotal)
                    {
                        levelVolumeTotal.InsideTotal       += partial.InsideTotal;
                        levelVolumeTotal.OutsideTotal      += partial.OutsideTotal;
                        levelVolumeTotal.IntersectingTotal += partial.IntersectingTotal;
                    }
                });

                volume.InsideTotal       += levelVolumeTotal.InsideTotal;
                volume.OutsideTotal      += levelVolumeTotal.OutsideTotal;
                volume.IntersectingTotal += levelVolumeTotal.IntersectingTotal;

                volumeAtLevel[i] = levelVolumeTotal;
            }


            Debug.WriteLine("Percentage of inner volume at each octree level");
            for (int i = 0; i < input.Octree.MaxLevels; i++)
            {
                Debug.WriteLine("Level {0}: Inner Volume {1}%", i, (volumeAtLevel[i].InsideTotal / volume.InsideTotal) * 100);
            }

            // A good check to perform is to compare the ratio of intersecting volume leaf nodes to the total volume
            // we've determined is inside.  A tool could use this ratio to automatically determine a good octree level
            // by iterative optimization.  If a mesh for example fails to get at least a 1 : 0.5 ratio of intersecting:inner
            // volume ratio it's a good bet that the octree does not subdivide enough levels in order to find enough inner volume
            // to meet our occlusion needs.  If further subdivision up to some maximum, lets say 8 fails to ever meet this ratio
            // one could say the mesh is not a good candidate for automating occluder generation.
            Debug.WriteLine("");
            float intersecting_inside_ratio = volume.InsideTotal / volume.IntersectingTotal;

            Debug.WriteLine("Intersecting : Inner = 1:{0}", intersecting_inside_ratio);
            Debug.WriteLine("Inner / (Inner + Intersecting) = {0}", volume.InsideTotal / (volume.InsideTotal + volume.IntersectingTotal));

            const float MINIMUM_INTERSECTING_TO_INSIDE_RATIO = 0.25f;

            AABBf  meshBounds = input.Octree.MeshBounds;
            double dX         = meshBounds.MaxX - meshBounds.MinX;
            double dY         = meshBounds.MaxY - meshBounds.MinY;
            double dZ         = meshBounds.MaxZ - meshBounds.MinZ;

            double reduction = 0.5;

            for (int i = 0; i <= input.Octree.MaxLevels * 2; i++)
            {
                reduction *= 0.5;
            }

            dX = dX * reduction;
            dY = dY * reduction;
            dZ = dZ * reduction;

            if (intersecting_inside_ratio > MINIMUM_INTERSECTING_TO_INSIDE_RATIO)
            {
                List <AABBi> innerBounds         = new List <AABBi>();
                float        innerVolumeGathered = 0.0f;
                for (int i = 0; i < input.Octree.MaxLevels; i++)
                {
                    for (int n = 0; n < cellList[i].Count; n++)
                    {
                        if (cellList[i][n].Status == CellStatus.Inside)
                        {
                            AABBf bound = cellList[i][n].Bounds;

                            AABBi bi = new AABBi();
                            bi.MaxX = (int)Math.Round(((double)bound.MaxX - (double)meshBounds.MinX) / dX, MidpointRounding.AwayFromZero);
                            bi.MaxY = (int)Math.Round(((double)bound.MaxY - (double)meshBounds.MinY) / dY, MidpointRounding.AwayFromZero);
                            bi.MaxZ = (int)Math.Round(((double)bound.MaxZ - (double)meshBounds.MinZ) / dZ, MidpointRounding.AwayFromZero);
                            bi.MinX = (int)Math.Round(((double)bound.MinX - (double)meshBounds.MinX) / dX, MidpointRounding.AwayFromZero);
                            bi.MinY = (int)Math.Round(((double)bound.MinY - (double)meshBounds.MinY) / dY, MidpointRounding.AwayFromZero);
                            bi.MinZ = (int)Math.Round(((double)bound.MinZ - (double)meshBounds.MinZ) / dZ, MidpointRounding.AwayFromZero);
                            innerBounds.Add(bi);
                        }
                    }

                    innerVolumeGathered += volumeAtLevel[i].InsideTotal / volume.InsideTotal;
                    if (innerVolumeGathered > input.MinimumVolume)
                    {
                        break;
                    }
                }

                Debug.WriteLine("Enough inner volume found {0}%", innerVolumeGathered * 100.0f);

                Mesh mesh = MeshBuilder.BuildMesh(innerBounds);

                for (int i = 0; i < mesh.Vertices.Length; i++)
                {
                    mesh.Vertices[i].X = (float)(((double)meshBounds.MinX) + (mesh.Vertices[i].X * dX));
                    mesh.Vertices[i].Y = (float)(((double)meshBounds.MinY) + (mesh.Vertices[i].Y * dY));
                    mesh.Vertices[i].Z = (float)(((double)meshBounds.MinZ) + (mesh.Vertices[i].Z * dZ));
                }

                if (input.Retriangulate)
                {
                    Mesh triangulatedMesh = MeshOptimizer.Retriangulate(input, mesh, out output.DebugLines);
                    if (triangulatedMesh != null)
                    {
                        mesh = triangulatedMesh;
                    }
                }

                mesh = PolygonFilter.Filter(input, mesh);

                output.OccluderMesh = new RenderableMesh(mesh, true);
            }
            else
            {
                Debug.WriteLine("Not enough inner volume found to continue.");
            }

            return(output);
        }
Exemplo n.º 7
0
        public WaitHandle GenerateOccluder(Action <VoxelizationProgress> progress, Action done)
        {
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            if (Context == null || Context.OriginalMesh == null)
            {
                Logger.DisplayError("Please Open a mesh first.");
                waitHandle.Set();
                return(waitHandle);
            }

            Input.Octree       = Context.Octree;
            Input.OriginalMesh = Context.OriginalMesh;

            VoxelizationInput  input  = Input.Clone();
            VoxelizationOutput output = null;

            IOccluderGenerator occluder;

            switch (input.Type)
            {
            case OcclusionType.Octree:
                occluder = new OccluderOctree();
                break;

            case OcclusionType.BoxExpansion:
                occluder = new OccluderBoxExpansion();
                break;

            //case OcclusionType.SimulatedAnnealing:
            //    occluder = new OccluderBoxExpansion();
            //    break;
            case OcclusionType.BruteForce:
                occluder = new OccluderBoxExpansion();
                break;

            default:
                throw new Exception("Unknown occluder type.");
            }

            Thread thread = new Thread(() =>
            {
                INativeWindow window = new OpenTK.NativeWindow();
                IGraphicsContext gl  = new GraphicsContext(new GraphicsMode(32, 24, 8), window.WindowInfo);
                gl.MakeCurrent(window.WindowInfo);

                while (window.Exists)
                {
                    window.ProcessEvents();

                    try
                    {
                        RobustVoxelizer voxelizer = new RobustVoxelizer(512, 512);
                        output = voxelizer.Voxelize(input, progress);
                        voxelizer.Dispose();

                        output = occluder.Generate(input, progress);
                    }
                    catch (System.Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    }

                    window.Close();
                    break;
                }

                gl.MakeCurrent(null);

                if (Context.OccluderMesh != null)
                {
                    Context.OccluderMesh.Dispose();
                }

                Context.Octree             = output.Octree;
                Context.OccluderMesh       = output.OccluderMesh;
                Context.VoxelizationOutput = output;

                waitHandle.Set();

                done();
            });

            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();

            return(waitHandle);
        }