bool IsFlatAndFilled(CornerSet cS) { if (!cS.Filled) { return(false); } var z = GetPos(_verts[cS.cornerIndices[0].Value]).Z; var zFL = GetPos(_verts[cS.iFL]).Z; if (z != zFL) { return(false); } var zFR = GetPos(_verts[cS.iFR]).Z; if (z != zFR) { return(false); } var zBL = GetPos(_verts[cS.iBL]).Z; if (z != zBL) { return(false); } var zBR = GetPos(_verts[cS.iBR]).Z; if (z != zBR) { return(false); } var zF = GetPos(_verts[cS.iF]).Z; if (z != zF) { return(false); } var zB = GetPos(_verts[cS.iB]).Z; if (z != zB) { return(false); } var zL = GetPos(_verts[cS.iL]).Z; if (z != zL) { return(false); } var zR = GetPos(_verts[cS.iR]).Z; if (z != zR) { return(false); } return(true); }
void MarkForRemove(CornerSet cS) { Debug.Assert(cS.cornerIndices[0].HasValue); { var c0 = cS.cornerIndices[0].Value; _indicesToRemove[c0] = 0; _indicesToRemove[c0 + 1] = 0; _indicesToRemove[c0 + 2] = 0; _indicesToRemove[c0 + 3] = 0; } Debug.Assert(cS.cornerIndices[1].HasValue); { var c1 = cS.cornerIndices[1].Value; _indicesToRemove[c1] = 0; _indicesToRemove[c1 - 1] = 0; _indicesToRemove[c1 - 2] = 0; _indicesToRemove[c1 - 3] = 0; } Debug.Assert(cS.cornerIndices[2].HasValue); { var c2 = cS.cornerIndices[2].Value; _indicesToRemove[c2] = 0; _indicesToRemove[c2 - 1] = 0; _indicesToRemove[c2 + 1] = 0; _indicesToRemove[c2 + 2] = 0; } Debug.Assert(cS.cornerIndices[3].HasValue); { var c3 = cS.cornerIndices[3].Value; _indicesToRemove[c3] = 0; _indicesToRemove[c3 - 1] = 0; _indicesToRemove[c3 - 2] = 0; _indicesToRemove[c3 + 1] = 0; } }
bool IsRemoved(CornerSet cS, Corners cornersToIgnore) { if ((cornersToIgnore & Corners.BR) == 0) { if (cS.cornerIndices[0].HasValue) { var c0 = cS.cornerIndices[0].Value; if (_indicesToRemove.ContainsKey(c0)) { return(true); } if (_indicesToRemove.ContainsKey(c0 + 1)) { return(true); } if (_indicesToRemove.ContainsKey(c0 + 2)) { return(true); } if (_indicesToRemove.ContainsKey(c0 + 3)) { return(true); } } } if ((cornersToIgnore & Corners.FR) == 0) { if (cS.cornerIndices[1].HasValue) { var c1 = cS.cornerIndices[1].Value; if (_indicesToRemove.ContainsKey(c1)) { return(true); } if (_indicesToRemove.ContainsKey(c1 - 1)) { return(true); } if (_indicesToRemove.ContainsKey(c1 - 2)) { return(true); } if (_indicesToRemove.ContainsKey(c1 - 3)) { return(true); } } } if ((cornersToIgnore & Corners.BL) == 0) { if (cS.cornerIndices[2].HasValue) { var c2 = cS.cornerIndices[2].Value; if (_indicesToRemove.ContainsKey(c2)) { return(true); } if (_indicesToRemove.ContainsKey(c2 - 1)) { return(true); } if (_indicesToRemove.ContainsKey(c2 + 1)) { return(true); } if (_indicesToRemove.ContainsKey(c2 + 2)) { return(true); } } } if ((cornersToIgnore & Corners.FL) == 0) { if (cS.cornerIndices[3].HasValue) { var c3 = cS.cornerIndices[3].Value; if (_indicesToRemove.ContainsKey(c3)) { return(true); } if (_indicesToRemove.ContainsKey(c3 - 1)) { return(true); } if (_indicesToRemove.ContainsKey(c3 - 2)) { return(true); } if (_indicesToRemove.ContainsKey(c3 + 1)) { return(true); } } } return(false); }
public Terrain.TerrainVertex_FD[] Optimize() { for (int i = 0; i < _numVerts; i++) { Terrain.TerrainVertex_FD v = _verts[i]; Vector3 pos = GetPos(v); int corner = (int)((v.faceAndCorner & 0xff00) >> 8); if (_posToCSs.ContainsKey(pos)) { //Debug.Assert(_posToCSs[pos].cornerIndices[corner] == null); _posToCSs[pos].cornerIndices[corner] = i; } else { CornerSet cS = new CornerSet(); cS.cornerIndices = new int?[4]; cS.cornerIndices[corner] = i; _posToCSs.Add(pos, cS); } } // Doesn't seem to be used... //var toEmpty = new HashSet<CornerSet>(); List <Terrain.TerrainVertex_FD> toAdd = new List <Terrain.TerrainVertex_FD>(); foreach (CornerSet cS in _posToCSs.Values) { if (!IsRemoved(cS, Corners.None) && IsFlatAndFilled(cS)) { MarkForRemove(cS); //Traverse up the Y dir CornerSet bCS = cS; CornerSet nBCS = GetCornerSet(cS.iB); int bTraversals = 0; while (!IsRemoved(nBCS, Corners.FL | Corners.FR) && IsFlatAndFilled(nBCS) && bTraversals < maxYTraversals) { bTraversals++; bCS = nBCS; MarkForRemove(bCS); nBCS = GetCornerSet(nBCS.iB); } //Traverse up the X dir CornerSet rCS = cS; CornerSet brCS = bCS; CornerSet nRCS = GetCornerSet(rCS.iR); int rTraversals = 0; while (!IsRemoved(nRCS, Corners.FL | Corners.BL) && IsFlatAndFilled(nRCS) && rTraversals < maxXTraversals) { rTraversals++; List <CornerSet> tenativeToEmpty = new List <CornerSet>(); bool bTraversalsCompleted = true; CornerSet nBRCS = nRCS; nBCS = nRCS; for (int i = 0; i < bTraversals; i++) { nBCS = GetCornerSet(nBCS.iB); if (!IsRemoved(nBCS, Corners.FL | Corners.FR | Corners.BL) && IsFlatAndFilled(nBCS)) { tenativeToEmpty.Add(nBCS); nBRCS = nBCS; } else { bTraversalsCompleted = false; break; } } if (bTraversalsCompleted) { brCS = nBRCS; rCS = nRCS; MarkForRemove(rCS); for (int i = 0; i < tenativeToEmpty.Count; i++) { MarkForRemove(tenativeToEmpty[i]); } nRCS = GetCornerSet(nRCS.iR); } else { break; } } Terrain.TerrainVertex_FD vFL = _verts[cS.iFL]; Terrain.TerrainVertex_FD vBL = _verts[bCS.iBL]; Terrain.TerrainVertex_FD vBR = _verts[brCS.iBR]; Terrain.TerrainVertex_FD vFR = _verts[rCS.iFR]; toAdd.Add(vFL); toAdd.Add(vFR); toAdd.Add(vBR); toAdd.Add(vBL); } } for (int i = 0; i < _numVerts; i++) { if (!_indicesToRemove.ContainsKey(i)) { toAdd.Add(_verts[i]); } } Terrain.TerrainVertex_FD[] result = toAdd.ToArray(); return(result); }