private void SolidifyLoop(int j, int lastJ, SweepPlanePoint[,] sweepPlane, List<SweepPlanePoint> activePts, HashSet<SweepPlanePoint> inactiveInteriorPts, SweepPlanePoint[] neighboringSweepPlanePts) { for (int i = 0; i < xCellLength; i++) //Iterate across the cross-section plane to add voxel shell and mark active interior points for (int k = 0; k < zCellLength; k++) { SweepPlanePoint pt = sweepPlane[i, k]; Part p = GetPartAtVoxelPos(i, j, k); if (pt == null) //If there is a section of voxel there, but no pt, add a new voxel shell pt to the sweep plane { if ((object)p != null) { sweepPlane[i, k] = new SweepPlanePoint(p, i, k); continue; } } else { if ((object)p == null) //If there is a pt there, but no part listed, this is an interior pt or the cross-section is shrinking { if (pt.mark == SweepPlanePoint.MarkingType.VoxelShell) //label it as active so that it can be determined if it is interior or not once all the points have been updated { activePts.Add(pt); //And add it to the list of active interior pts pt.mark = SweepPlanePoint.MarkingType.Active; } else if (pt.mark == SweepPlanePoint.MarkingType.VoxelShellPreviouslyInterior) //if this shell was previously interior, we need to know so that we can set it to the correct active { activePts.Add(pt); //And add it to the list of active interior pts pt.mark = SweepPlanePoint.MarkingType.ActivePassedThroughInternalShell; } //Only other situation is that it is an inactive point, in which case we do nothing here, because it is already taken care of } else if (pt.mark == SweepPlanePoint.MarkingType.Clear) { pt.mark = SweepPlanePoint.MarkingType.VoxelShell; pt.part = p; } else if (pt.mark != SweepPlanePoint.MarkingType.VoxelShell && pt.mark != SweepPlanePoint.MarkingType.VoxelShellPreviouslyInterior) //only run this if it's not already labeled as part of a voxel shell { //Make sure the point is labeled as a voxel shell if there is already a part there inactiveInteriorPts.Remove(pt); pt.mark = SweepPlanePoint.MarkingType.VoxelShellPreviouslyInterior; //this marks that this point was once part of the voxel shell pt.part = p; pt.jLastInactive = j; } } } for (int i = 0; i < activePts.Count; i++) //Then, iterate through all active points for this section { SweepPlanePoint activeInteriorPt = activePts[i]; //Get active interior pt if (activeInteriorPt.i + 1 < xCellLength) //And all of its 4-neighbors neighboringSweepPlanePts[0] = sweepPlane[activeInteriorPt.i + 1, activeInteriorPt.k]; else neighboringSweepPlanePts[0] = null; if (activeInteriorPt.i - 1 > 0) neighboringSweepPlanePts[1] = sweepPlane[activeInteriorPt.i - 1, activeInteriorPt.k]; else neighboringSweepPlanePts[1] = null; if (activeInteriorPt.k + 1 < zCellLength) neighboringSweepPlanePts[2] = sweepPlane[activeInteriorPt.i, activeInteriorPt.k + 1]; else neighboringSweepPlanePts[2] = null; if (activeInteriorPt.k - 1 > 0) neighboringSweepPlanePts[3] = sweepPlane[activeInteriorPt.i, activeInteriorPt.k - 1]; else neighboringSweepPlanePts[3] = null; bool remove = false; for (int m = 0; m < neighboringSweepPlanePts.Length; m++)// (SweepPlanePoint neighbor in neighboringSweepPlanePts)//Check if the active point is surrounded by all 4 neighbors { SweepPlanePoint neighbor = neighboringSweepPlanePts[m]; if (neighbor == null || neighbor.mark == SweepPlanePoint.MarkingType.Clear) //If any of them are null or marked clear, this active point is not an interior point { //In that case, it should be set to be removed remove = true; break; } } if (remove) //If it is set to be removed... { for (int m = 0; m < neighboringSweepPlanePts.Length; m++)// //Go through all the neighboring points { SweepPlanePoint neighbor = neighboringSweepPlanePts[m]; if (neighbor != null && neighbor.mark == SweepPlanePoint.MarkingType.InactiveInterior) //For the ones that exist, and are inactive interior... { inactiveInteriorPts.Remove(neighbor); //remove them from inactiveInterior neighbor.mark = SweepPlanePoint.MarkingType.Active; //...mark them active activePts.Add(neighbor); //And add them to the end of activePts } } sweepPlane[activeInteriorPt.i, activeInteriorPt.k].mark = SweepPlanePoint.MarkingType.Clear; //Then, set this point to be marked clear in the sweepPlane } else { //If it's surrounded by other points, it's inactive; add it to that list if (activeInteriorPt.mark == SweepPlanePoint.MarkingType.ActivePassedThroughInternalShell) { if (activeInteriorPt.jLastInactive < j) for (int mJ = activeInteriorPt.jLastInactive; mJ < j; mJ++) SetVoxelPointNoLock(activeInteriorPt.i, mJ, activeInteriorPt.k); //used to make sure that internal part boundaries for cargo bays don't result in dips in cross-section else for (int mJ = lastJ; mJ <= activeInteriorPt.jLastInactive; mJ++) SetVoxelPointNoLock(activeInteriorPt.i, mJ, activeInteriorPt.k); //used to make sure that internal part boundaries for cargo bays don't result in dips in cross-section } activeInteriorPt.mark = SweepPlanePoint.MarkingType.InactiveInterior; inactiveInteriorPts.Add(activeInteriorPt); } } activePts.Clear(); //Clear activePts every iteration foreach (SweepPlanePoint inactivePt in inactiveInteriorPts) //Any remaining inactive interior pts are guaranteed to be on the inside of the vehicle { SetVoxelPointNoLock(inactivePt.i, j, inactivePt.k, inactivePt.part); //Get each and update the voxel accordingly } }
private void SolidifyVoxel(int lowJ, int highJ, bool increasingJ) { SweepPlanePoint[,] plane; lock (clearedPlanes) { while (clearedPlanes.Count == 0) Monitor.Wait(clearedPlanes); plane = clearedPlanes.Pop(); } try { int xLength = plane.GetLength(0); int zLength = plane.GetLength(1); if (xLength < xCellLength || zLength < zCellLength) plane = new SweepPlanePoint[Math.Max(xCellLength, xLength), Math.Max(zCellLength, zLength)]; //SweepPlanePoint[,] sweepPlane = new SweepPlanePoint[xCellLength, zCellLength]; List<SweepPlanePoint> activePts = new List<SweepPlanePoint>(); HashSet<SweepPlanePoint> inactiveInteriorPts = new HashSet<SweepPlanePoint>(); SweepPlanePoint[] neighboringSweepPlanePts = new SweepPlanePoint[4]; if (increasingJ) for (int j = lowJ; j < highJ; j++) //Iterate from back of vehicle to front { SolidifyLoop(j, j - 1, plane, activePts, inactiveInteriorPts, neighboringSweepPlanePts); } else for (int j = highJ - 1; j >= lowJ; j--) //Iterate from front of vehicle to back { SolidifyLoop(j, j + 1, plane, activePts, inactiveInteriorPts, neighboringSweepPlanePts); } //Cleanup //sweepPlane = null; activePts = null; inactiveInteriorPts = null; neighboringSweepPlanePts = null; } catch (Exception e) { ThreadSafeDebugLogger.Instance.RegisterException(e); } finally { CleanSweepPlane(plane); lock (clearedPlanes) { clearedPlanes.Push(plane); Monitor.Pulse(clearedPlanes); } } }
private void CleanSweepPlane(SweepPlanePoint[,] sweepPlane) { int lengthX, lengthZ; lengthX = sweepPlane.GetLength(0); lengthZ = sweepPlane.GetLength(1); for (int i = 0; i < lengthX; i++) for (int k = 0; k < lengthZ; k++) { SweepPlanePoint pt = sweepPlane[i, k]; if(pt != null) { pt.Clear(); } } }