public List <Segment> FindSegments(MyVoxelSegmentationType segmentationType = 2, int mergeIterations = 1) { this.m_segments.Clear(); switch (segmentationType) { case MyVoxelSegmentationType.ExtraSimple: this.CreateSegmentsExtraSimple(); break; case MyVoxelSegmentationType.Simple: this.CreateSegmentsSimple(); break; case MyVoxelSegmentationType.Simple2: this.CreateSegmentsSimple2(); break; default: this.CreateSegments(segmentationType == MyVoxelSegmentationType.Fast); this.m_segments.Sort(new SegmentSizeComparer()); this.RemoveFullyContainedOptimized(); this.ClipSegments(); for (int i = 0; i < mergeIterations; i++) { this.MergeSegments(); } break; } return(this.m_segments); }
public void Collect(MyCubeGrid grid, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary <Vector3I, HkMassElement> massResults) { foreach (MySlimBlock block in grid.GetBlocks()) { if (block.FatBlock is MyCompoundCubeBlock) { this.CollectCompoundBlock((MyCompoundCubeBlock)block.FatBlock, massResults); continue; } this.CollectBlock(block, block.BlockDefinition.PhysicsOption, massResults, true); } this.AddSegmentedParts(grid.GridSize, segmenter, segmentationType); this.m_tmpCubes.Clear(); }
/// <summary> /// Creates segments from voxel data. /// </summary> /// <param name="filledVoxels">Positions on filled voxels (or one material).</param> /// <param name="mergeIterations">Number of post-process merge iterations, one should be always sufficient, algorithm works pretty well with 0 too.</param> /// <param name="fastMethod">Fast method is about 3x faster, but prefers longer boxes instead of cubic and generates about 5 - 10% more segments.</param> /// <returns>List of segments.</returns> public List <Segment> FindSegments(MyVoxelSegmentationType segmentationType = MyVoxelSegmentationType.Optimized, int mergeIterations = 1) { m_segments.Clear(); switch (segmentationType) { case MyVoxelSegmentationType.Simple: ProfilerShort.Begin("Create segments"); CreateSegmentsSimple(); ProfilerShort.End(); break; case MyVoxelSegmentationType.Simple2: ProfilerShort.Begin("Create segments"); CreateSegmentsSimple2(); ProfilerShort.End(); break; case MyVoxelSegmentationType.ExtraSimple: ProfilerShort.Begin("Create simple segments"); CreateSegmentsExtraSimple(); ProfilerShort.End(); break; default: ProfilerShort.Begin("Create segments"); CreateSegments(segmentationType == MyVoxelSegmentationType.Fast); ProfilerShort.End(); ProfilerShort.Begin("Sort segments"); m_segments.Sort(new SegmentSizeComparer()); ProfilerShort.End(); ProfilerShort.Begin("Remove fully contained"); RemoveFullyContainedOptimized(); ProfilerShort.End(); ProfilerShort.Begin("Clip segments"); ClipSegments(); ProfilerShort.End(); ProfilerShort.Begin("Merge segments"); for (int i = 0; i < mergeIterations; i++) { MergeSegments(); // Very optional } ProfilerShort.End(); break; } return(m_segments); }
void AddSegmentedParts(float gridSize, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType) { if (segmenter != null) { int mergeIterations = segmentationType == MyVoxelSegmentationType.Optimized ? 1 : 0; //SegmenterBenchmark(collector, segmenter, mergeIterations); ProfilerShort.Begin("Prepare segmentation"); segmenter.ClearInput(); foreach (var cube in m_tmpCubes) { segmenter.AddInput(cube); } ProfilerShort.End(); ProfilerShort.Begin("Make segments"); var segments = segmenter.FindSegments(segmentationType, mergeIterations); ProfilerShort.End(); ProfilerShort.Begin("Add segments"); foreach (var s in segments) { Vector3 min = s.Min * gridSize - new Vector3(gridSize / 2.0f); Vector3 max = s.Max * gridSize + new Vector3(gridSize / 2.0f); AddBox(s.Min, s.Max, ref min, ref max); } ProfilerShort.End(); } else { ProfilerShort.Begin("Add full cubes"); foreach (var c in m_tmpCubes) { Vector3 min = c * gridSize - new Vector3(gridSize / 2.0f); Vector3 max = c * gridSize + new Vector3(gridSize / 2.0f); AddBox(c, c, ref min, ref max); } ProfilerShort.End(); } }
public void Collect(MyCubeGrid grid, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary <Vector3I, HkMassElement> massResults) { foreach (var block in grid.GetBlocks()) { if (block.FatBlock is MyCompoundCubeBlock) { CollectCompoundBlock((MyCompoundCubeBlock)block.FatBlock, massResults); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); } else { CollectBlock(block, block.BlockDefinition.PhysicsOption, massResults); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); } } AddSegmentedParts(grid.GridSize, segmenter, segmentationType); m_tmpCubes.Clear(); Debug.Assert(Shapes.Count > 0, "Shape count cannot be zero"); Debug.Assert(massResults == null || massResults.Count > 0, "No mass elements, something is wrong!"); }
/// <summary> /// Intended for quite small refreshes (few blocks). /// Collect is faster for large refresh. /// Removes also dirty mass elements. /// </summary> public void CollectArea(MyCubeGrid grid, HashSet <Vector3I> dirtyBlocks, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary <Vector3I, HkMassElement> massResults) { ProfilerShort.Begin("Remove dirty"); foreach (var pos in dirtyBlocks) { if (massResults != null) { massResults.Remove(pos); } var block = grid.GetCubeBlock(pos); if (block != null) { m_tmpRefreshSet.Add(block); } } ProfilerShort.End(); ProfilerShort.Begin("Add new"); foreach (var block in m_tmpRefreshSet) { if (block.FatBlock is MyCompoundCubeBlock) { ProfilerShort.Begin("Collect compound"); CollectCompoundBlock((MyCompoundCubeBlock)block.FatBlock, massResults); //Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); ProfilerShort.End(); } else { ProfilerShort.Begin("Collect block"); CollectBlock(block, block.BlockDefinition.PhysicsOption, massResults); //Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); ProfilerShort.End(); } } ProfilerShort.End(); ProfilerShort.Begin("IsValidTest"); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap! Uncomment upper asserts to find what block caused this"); ProfilerShort.End(); ProfilerShort.Begin("Add segments"); AddSegmentedParts(grid.GridSize, segmenter, segmentationType); ProfilerShort.End(); m_tmpCubes.Clear(); m_tmpRefreshSet.Clear(); // Clear is required, we certainly don't want to hold last reference to blocks }
public void CollectArea(MyCubeGrid grid, HashSet <Vector3I> dirtyBlocks, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary <Vector3I, HkMassElement> massResults) { using (MyUtils.ReuseCollection <MySlimBlock>(ref this.m_tmpRefreshSet)) { foreach (Vector3I vectori in dirtyBlocks) { if (massResults != null) { massResults.Remove(vectori); } MySlimBlock cubeBlock = grid.GetCubeBlock(vectori); if (cubeBlock != null) { this.m_tmpRefreshSet.Add(cubeBlock); } } foreach (MySlimBlock block2 in this.m_tmpRefreshSet) { this.CollectBlock(block2, block2.BlockDefinition.PhysicsOption, massResults, true); } this.AddSegmentedParts(grid.GridSize, segmenter, segmentationType); this.m_tmpCubes.Clear(); } }
private unsafe void AddSegmentedParts(float gridSize, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType) { int num = (int)Math.Floor((double)(40f / gridSize)); Vector3 vector = new Vector3(gridSize * 0.5f); if (segmenter != null) { int mergeIterations = (segmentationType == MyVoxelSegmentationType.Optimized) ? 1 : 0; segmenter.ClearInput(); foreach (Vector3I vectori3 in this.m_tmpCubes) { segmenter.AddInput(vectori3); } foreach (MyVoxelSegmentation.Segment segment in segmenter.FindSegments(segmentationType, mergeIterations)) { Vector3I vectori; vectori.X = segment.Min.X; while (vectori.X <= segment.Max.X) { vectori.Y = segment.Min.Y; while (true) { if (vectori.Y > segment.Max.Y) { int *numPtr3 = (int *)ref vectori.X; numPtr3[0] += num; break; } vectori.Z = segment.Min.Z; while (true) { if (vectori.Z > segment.Max.Z) { int *numPtr2 = (int *)ref vectori.Y; numPtr2[0] += num; break; } Vector3I maxPos = Vector3I.Min((Vector3I)((vectori + num) - 1), segment.Max); Vector3 min = ((Vector3)(vectori * gridSize)) - vector; Vector3 max = (maxPos * gridSize) + vector; this.AddBox(vectori, maxPos, ref min, ref max); int *numPtr1 = (int *)ref vectori.Z; numPtr1[0] += num; } } } } } else { foreach (Vector3I vectori4 in this.m_tmpCubes) { Vector3 min = ((Vector3)(vectori4 * gridSize)) - vector; Vector3 max = (vectori4 * gridSize) + vector; this.AddBox(vectori4, vectori4, ref min, ref max); } } }
public void Collect(MyCubeGrid grid, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary<Vector3I, HkMassElement> massResults) { foreach (var block in grid.GetBlocks()) { if (block.FatBlock is MyCompoundCubeBlock) { CollectCompoundBlock((MyCompoundCubeBlock)block.FatBlock, massResults); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); } else { CollectBlock(block, block.BlockDefinition.PhysicsOption, massResults); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); } } AddSegmentedParts(grid.GridSize, segmenter, segmentationType); m_tmpCubes.Clear(); Debug.Assert(Shapes.Count > 0, "Shape count cannot be zero"); Debug.Assert(massResults == null || massResults.Count > 0, "No mass elements, something is wrong!"); }
/// <summary> /// Intended for quite small refreshes (few blocks). /// Collect is faster for large refresh. /// Removes also dirty mass elements. /// </summary> public void CollectArea(MyCubeGrid grid, HashSet<Vector3I> dirtyBlocks, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType, IDictionary<Vector3I, HkMassElement> massResults) { ProfilerShort.Begin("Remove dirty"); foreach (var pos in dirtyBlocks) { if(massResults != null) massResults.Remove(pos); var block = grid.GetCubeBlock(pos); if (block != null) { m_tmpRefreshSet.Add(block); } } ProfilerShort.End(); ProfilerShort.Begin("Add new"); foreach (var block in m_tmpRefreshSet) { if (block.FatBlock is MyCompoundCubeBlock) { ProfilerShort.Begin("Collect compound"); CollectCompoundBlock((MyCompoundCubeBlock)block.FatBlock, massResults); //Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); ProfilerShort.End(); } else { ProfilerShort.Begin("Collect block"); CollectBlock(block, block.BlockDefinition.PhysicsOption, massResults); //Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap!"); ProfilerShort.End(); } } ProfilerShort.End(); ProfilerShort.Begin("IsValidTest"); Debug.Assert(IsValid(), "Overlapping shapes detected, block shapes cannot overlap! Uncomment upper asserts to find what block caused this"); ProfilerShort.End(); ProfilerShort.Begin("Add segments"); AddSegmentedParts(grid.GridSize, segmenter, segmentationType); ProfilerShort.End(); m_tmpCubes.Clear(); m_tmpRefreshSet.Clear(); // Clear is required, we certainly don't want to hold last reference to blocks }
void AddSegmentedParts(float gridSize, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType) { int maxExCubes = (int)Math.Floor(MAX_BOX_EXTENT/gridSize); Vector3 gridSizeHalf = new Vector3(gridSize*0.5f); if (segmenter != null) { int mergeIterations = segmentationType == MyVoxelSegmentationType.Optimized ? 1 : 0; //SegmenterBenchmark(collector, segmenter, mergeIterations); ProfilerShort.Begin("Prepare segmentation"); segmenter.ClearInput(); foreach (var cube in m_tmpCubes) { segmenter.AddInput(cube); } ProfilerShort.End(); ProfilerShort.Begin("Make segments"); var segments = segmenter.FindSegments(segmentationType, mergeIterations); ProfilerShort.End(); ProfilerShort.Begin("Add segments"); Vector3I it; Vector3I maxI; foreach (var s in segments) { for (it.X = s.Min.X; it.X <= s.Max.X; it.X += maxExCubes) { for (it.Y = s.Min.Y; it.Y <= s.Max.Y; it.Y += maxExCubes) for (it.Z = s.Min.Z; it.Z <= s.Max.Z; it.Z += maxExCubes) { maxI = Vector3I.Min(it + maxExCubes - 1, s.Max); Vector3 min = it * gridSize - gridSizeHalf; Vector3 max = maxI * gridSize + gridSizeHalf; AddBox(it, maxI, ref min, ref max); } } } //foreach (var s in segments) //{ // Vector3 min = s.Min * gridSize - gridSizeHalf; // Vector3 max = s.Max * gridSize + gridSizeHalf; // AddBox(s.Min, s.Max, ref min, ref max); //} ProfilerShort.End(); } else { ProfilerShort.Begin("Add full cubes"); foreach (var c in m_tmpCubes) { Vector3 min = c * gridSize - gridSizeHalf; Vector3 max = c * gridSize + gridSizeHalf; AddBox(c, c, ref min, ref max); } ProfilerShort.End(); } }
void AddSegmentedParts(float gridSize, MyVoxelSegmentation segmenter, MyVoxelSegmentationType segmentationType) { int maxExCubes = (int)Math.Floor(MAX_BOX_EXTENT / gridSize); Vector3 gridSizeHalf = new Vector3(gridSize * 0.5f); if (segmenter != null) { int mergeIterations = segmentationType == MyVoxelSegmentationType.Optimized ? 1 : 0; //SegmenterBenchmark(collector, segmenter, mergeIterations); ProfilerShort.Begin("Prepare segmentation"); segmenter.ClearInput(); foreach (var cube in m_tmpCubes) { segmenter.AddInput(cube); } ProfilerShort.End(); ProfilerShort.Begin("Make segments"); var segments = segmenter.FindSegments(segmentationType, mergeIterations); ProfilerShort.End(); ProfilerShort.Begin("Add segments"); Vector3I it; Vector3I maxI; foreach (var s in segments) { for (it.X = s.Min.X; it.X <= s.Max.X; it.X += maxExCubes) { for (it.Y = s.Min.Y; it.Y <= s.Max.Y; it.Y += maxExCubes) { for (it.Z = s.Min.Z; it.Z <= s.Max.Z; it.Z += maxExCubes) { maxI = Vector3I.Min(it + maxExCubes - 1, s.Max); Vector3 min = it * gridSize - gridSizeHalf; Vector3 max = maxI * gridSize + gridSizeHalf; AddBox(it, maxI, ref min, ref max); } } } } //foreach (var s in segments) //{ // Vector3 min = s.Min * gridSize - gridSizeHalf; // Vector3 max = s.Max * gridSize + gridSizeHalf; // AddBox(s.Min, s.Max, ref min, ref max); //} ProfilerShort.End(); } else { ProfilerShort.Begin("Add full cubes"); foreach (var c in m_tmpCubes) { Vector3 min = c * gridSize - gridSizeHalf; Vector3 max = c * gridSize + gridSizeHalf; AddBox(c, c, ref min, ref max); } ProfilerShort.End(); } }