//detailed x, z //dx ~ (0, setting.maxX * power(2, subdivision)), dx ~ (0, setting.maxZ * power(2, subdivision)) public void Reset(uint header, int dx, int dz, uint ih, int sub, int maxSub, float centerx, float centerz, ulong val) { SliceHeader = header; HIdx = ih; Subdivision = sub; X = centerx; Z = centerz; HeightGrade = SliceAccessor.heightGrade(val); Flag = SliceAccessor.flag(val); mSlopeU = SliceAccessor.slopeUGrade(val) / SliceAccessor.slopeMagnify; mSlopeV = SliceAccessor.slopeVGrade(val) / SliceAccessor.slopeMagnify; //boundary BoundaryXMin = 0; BoundaryZMin = 0; int detail = 1 << sub; if (sub == 0) { BoundaryXMin = dx; BoundaryZMin = dz; } else { for (int s = maxSub; s >= sub; --s) { detail = 1 << s; int u = dx >> s; // x / power(2, subdivision); int v = dz >> s; BoundaryXMin += u * detail; BoundaryZMin += v * detail; dx -= u * detail; dz -= v * detail; } } BoundaryXMax = BoundaryXMin + detail; BoundaryZMax = BoundaryZMin + detail; BoundaryXMin -= 1; BoundaryZMin -= 1; }
private QuadTreeLeaf Combine(float dx, float dz, float sliceThickness, float slopeErr) { if (Children[0] == null || !(Children[0] is QuadTreeLeaf)) { return(null); } QuadTreeLeaf leaf = (QuadTreeLeaf)Children[0]; for (int i = 1; i < Children.Length; ++i) { if (Children[i] == null || !(Children[i] is QuadTreeLeaf)) { return(null); } if (!leaf.IsCombinable((QuadTreeLeaf)Children[i])) { return(null); } } for (int s = 0; s < leaf.Slices.Length; ++s) { ulong leafS = leaf.Slices[s]; byte flag = SliceAccessor.flag(leafS); //x axis short slopeU = GetSlope(leafS, ((QuadTreeLeaf)Children[1]).Slices[s], dx, sliceThickness); short slopeU1 = GetSlope(((QuadTreeLeaf)Children[2]).Slices[s], ((QuadTreeLeaf)Children[3]).Slices[s], dx, sliceThickness); if ((slopeU != 0 && slopeU1 != 0 && Math.Abs(slopeU1 - slopeU) > slopeErr * SliceAccessor.slopeMagnify)) { return(null); } slopeU += slopeU1; slopeU /= 2; //z axis short slopeV = GetSlope(leafS, ((QuadTreeLeaf)Children[2]).Slices[s], dz, sliceThickness); short slopeV1 = GetSlope(((QuadTreeLeaf)Children[1]).Slices[s], ((QuadTreeLeaf)Children[3]).Slices[s], dz, sliceThickness); if ((slopeV != 0 && slopeV1 != 0 && Math.Abs(slopeV1 - slopeV) > slopeErr * SliceAccessor.slopeMagnify)) { return(null); } slopeV += slopeV1; slopeV /= 2; ushort updateH = 0; for (int i = 0; i < Children.Length; ++i) { QuadTreeLeaf l = (QuadTreeLeaf)Children[i]; ulong lS = l.Slices[s]; if (leaf.HashVal != l.HashVal) { byte f = SliceAccessor.flag(lS); short sU = SliceAccessor.slopeUGrade(lS); short sV = SliceAccessor.slopeVGrade(lS); //floor cant match ceiling if (flag != f) { return(null); } //slope error if ((sU != 0 && Math.Abs(sU - slopeU) > slopeErr * SliceAccessor.slopeMagnify) || (sV != 0 && Math.Abs(sV - slopeV) > slopeErr * SliceAccessor.slopeMagnify)) { return(null); } } updateH += SliceAccessor.heightGrade(lS); } updateH >>= 2;//average height leaf.Slices[s] = SliceAccessor.packVal(updateH, slopeU, slopeV, flag); } leaf.RefreshHash(); return(leaf); }