public void CreatePruningTree(string mapName) { int num = 0; int num2 = this.Resolution / HeightmapNode.HEIGHTMAP_LEAF_SIZE; while (num2 != 1) { if ((num2 % HeightmapNode.HEIGHTMAP_BRANCH_FACTOR) != 0) { object[] args = new object[] { mapName }; MyLog.Default.Error("Cannot build prunning tree for heightmap face {0}!", args); object[] objArray2 = new object[] { HeightmapNode.HEIGHTMAP_BRANCH_FACTOR, HeightmapNode.HEIGHTMAP_LEAF_SIZE }; MyLog.Default.Error("Heightmap resolution must be divisible by {1}, and after that a power of {0}. Failing to achieve so will disable several important optimizations!!", objArray2); return; } num++; num2 /= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; } this.PruningTree = new HeightmapLevel[num]; int rowStart = this.GetRowStart(0); if (num == 0) { float positiveInfinity = float.PositiveInfinity; float negativeInfinity = float.NegativeInfinity; int num10 = rowStart; int num11 = 0; while (num11 < HeightmapNode.HEIGHTMAP_LEAF_SIZE) { int num12 = 0; while (true) { if (num12 >= HeightmapNode.HEIGHTMAP_LEAF_SIZE) { num10 += this.m_realResolution; num11++; break; } float num13 = this.Data[num10 + num12] * 1.525902E-05f; if (positiveInfinity > num13) { positiveInfinity = num13; } if (negativeInfinity < num13) { negativeInfinity = num13; } num12++; } } this.Root.Max = negativeInfinity; this.Root.Min = positiveInfinity; } else { int num1 = HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; num2 = this.Resolution / HeightmapNode.HEIGHTMAP_LEAF_SIZE; this.PruningTree[0].Nodes = new HeightmapNode[num2 * num2]; this.PruningTree[0].Res = (uint)num2; int index = 0; int num14 = 0; while (num14 < num2) { int num15 = rowStart; int num16 = 0; while (true) { if (num16 >= num2) { rowStart += HeightmapNode.HEIGHTMAP_LEAF_SIZE * this.m_realResolution; num14++; break; } float num17 = float.PositiveInfinity; float num18 = float.NegativeInfinity; int num19 = num15 - this.m_realResolution; int num20 = -1; while (true) { if (num20 > HeightmapNode.HEIGHTMAP_LEAF_SIZE) { HeightmapNode node = new HeightmapNode { Max = num18, Min = num17 }; this.PruningTree[0].Nodes[index] = node; index++; num15 += HeightmapNode.HEIGHTMAP_LEAF_SIZE; num16++; break; } int num21 = -1; while (true) { if (num21 > HeightmapNode.HEIGHTMAP_LEAF_SIZE) { num19 += this.m_realResolution; num20++; break; } float num22 = this.Data[num19 + num21] * 1.525902E-05f; if (num17 > num22) { num17 = num22; } if (num18 < num22) { num18 = num22; } num21++; } } } } int num5 = 0; int num23 = 1; while (num23 < num) { rowStart = 0; int num24 = num2 / HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; this.PruningTree[num23].Nodes = new HeightmapNode[num24 * num24]; this.PruningTree[num23].Res = (uint)num24; index = 0; int num25 = 0; while (true) { if (num25 >= num24) { num5++; num2 = num24; num23++; break; } int num26 = rowStart; int num27 = 0; while (true) { if (num27 >= num24) { rowStart += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR * num2; num25++; break; } float min = float.PositiveInfinity; float max = float.NegativeInfinity; int num30 = num26; int num31 = 0; while (true) { if (num31 >= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR) { this.PruningTree[num23].Nodes[index] = new HeightmapNode { Max = max, Min = min }; index++; num26 += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; num27++; break; } int num32 = 0; while (true) { if (num32 >= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR) { num30 += num2; num31++; break; } HeightmapNode node2 = this.PruningTree[num5].Nodes[num30 + num32]; if (min > node2.Min) { min = node2.Min; } if (max < node2.Max) { max = node2.Max; } num32++; } } } } } float positiveInfinity = float.PositiveInfinity; float negativeInfinity = float.NegativeInfinity; rowStart = 0; int num33 = 0; while (num33 < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR) { int num34 = 0; while (true) { if (num34 >= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR) { num33++; break; } rowStart++; HeightmapNode node3 = this.PruningTree[num - 1].Nodes[rowStart]; if (positiveInfinity > node3.Min) { positiveInfinity = node3.Min; } if (negativeInfinity < node3.Max) { negativeInfinity = node3.Max; } num34++; } } this.Root.Max = negativeInfinity; this.Root.Min = positiveInfinity; } }
public void CreatePruningTree(string mapName) { int depth = 0; int res = Resolution; res /= HeightmapNode.HEIGHTMAP_LEAF_SIZE; // check if we get an even tree, for now we will rely on that. while (res != 1) { if (res % HeightmapNode.HEIGHTMAP_BRANCH_FACTOR != 0) { MyDebug.FailRelease("Cannot build prunning tree for heightmap face {0}!", mapName); MyDebug.FailRelease("Heightmap resolution must be divisible by {1}, and after that a power of {0}. Failing to achieve so will disable several important optimizations!!", HeightmapNode.HEIGHTMAP_BRANCH_FACTOR, HeightmapNode.HEIGHTMAP_LEAF_SIZE); return; } depth++; res /= HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; } PruningTree = new HeightmapLevel[depth]; int offset = GetRowStart(0); if (depth == 0) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = offset; for (int y = 0; y < HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++x) { float value = ((float)Data[localOffset + x] * MyCubemapHelpers.USHORT_RECIP); if (min > value) { min = value; } if (max < value) { max = value; } } localOffset += m_real_resolution; } Root.Max = max; Root.Min = min; return; } int nodes = HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; res = Resolution / HeightmapNode.HEIGHTMAP_LEAF_SIZE; // prepare leaf level PruningTree[0].Nodes = new HeightmapNode[res * res]; PruningTree[0].Res = (uint)res; int cell = 0; for (int j = 0; j < res; ++j) { int coffset = offset; for (int i = 0; i < res; ++i) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = coffset - m_real_resolution; for (int y = -1; y <= HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++y) { for (int x = -1; x <= HeightmapNode.HEIGHTMAP_LEAF_SIZE; ++x) { float value = ((float)Data[localOffset + x] * MyCubemapHelpers.USHORT_RECIP); if (min > value) { min = value; } if (max < value) { max = value; } } localOffset += m_real_resolution; } PruningTree[0].Nodes[cell] = new HeightmapNode() { Max = max, Min = min }; cell++; coffset += HeightmapNode.HEIGHTMAP_LEAF_SIZE; } offset += HeightmapNode.HEIGHTMAP_LEAF_SIZE * m_real_resolution; } int l = 0; for (int k = 1; k < depth; k++) { offset = 0; int levelRes = res / HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; PruningTree[k].Nodes = new HeightmapNode[levelRes * levelRes]; PruningTree[k].Res = (uint)levelRes; cell = 0; for (int j = 0; j < levelRes; ++j) { int coffset = offset; for (int i = 0; i < levelRes; ++i) { float min = float.PositiveInfinity; float max = float.NegativeInfinity; int localOffset = coffset; for (int y = 0; y < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++x) { HeightmapNode n = PruningTree[l].Nodes[localOffset + x]; if (min > n.Min) { min = n.Min; } if (max < n.Max) { max = n.Max; } } localOffset += res; } PruningTree[k].Nodes[cell] = new HeightmapNode() { Max = max, Min = min }; cell++; coffset += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; } offset += HeightmapNode.HEIGHTMAP_BRANCH_FACTOR * res; } // previous level l++; res = levelRes; } float tmin = float.PositiveInfinity; float tmax = float.NegativeInfinity; offset = 0; for (int y = 0; y < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++y) { for (int x = 0; x < HeightmapNode.HEIGHTMAP_BRANCH_FACTOR; ++x) { HeightmapNode n = PruningTree[depth - 1].Nodes[offset++]; if (tmin > n.Min) { tmin = n.Min; } if (tmax < n.Max) { tmax = n.Max; } } } Root.Max = tmax; Root.Min = tmin; }
public unsafe void GetBounds(ref BoundingBox query) { float num = Math.Max(query.Width, query.Height); if (((num >= this.m_pixelSizeFour) && (this.PruningTree != null)) && (this.PruningTree.Length != 0)) { double num2 = Math.Log((double)(((float)this.Resolution) / (num * HeightmapNode.HEIGHTMAP_LEAF_SIZE))) / Math.Log((double)HeightmapNode.HEIGHTMAP_BRANCH_FACTOR); uint index = ((uint)(this.PruningTree.Length - 1)) - ((uint)MathHelper.Clamp(num2, 0.0, (double)(this.PruningTree.Length - 1))); Box2I other = new Box2I(Vector2I.Zero, new Vector2I(((int)this.PruningTree[index].Res) - 1)); Box2I boxi2 = new Box2I(ref query, this.PruningTree[index].Res); boxi2.Intersect(ref other); query.Min.Z = float.PositiveInfinity; query.Max.Z = float.NegativeInfinity; int res = (int)this.PruningTree[index].Res; int y = boxi2.Min.Y; while (y <= boxi2.Max.Y) { int x = boxi2.Min.X; while (true) { if (x > boxi2.Max.X) { y++; break; } HeightmapNode node = this.PruningTree[index].Nodes[(y * res) + x]; if (query.Min.Z > node.Min) { query.Min.Z = node.Min; } if (query.Max.Z < node.Max) { query.Max.Z = node.Max; } x++; } } } else { ushort num5; Box2I boxi3 = new Box2I(ref query, (uint)this.Resolution); Vector2I *vectoriPtr1 = (Vector2I *)ref boxi3.Min; vectoriPtr1[0] -= 1; Vector2I *vectoriPtr2 = (Vector2I *)ref boxi3.Max; vectoriPtr2[0] += 1; boxi3.Intersect(ref this.m_bounds); this.GetValue(boxi3.Min.X, boxi3.Min.Y, out num5); int num6 = 0xffff; int num7 = 0; int y = boxi3.Min.Y; while (y <= boxi3.Max.Y) { int x = boxi3.Min.X; while (true) { if (x > boxi3.Max.X) { y++; break; } this.GetValue(x, y, out num5); if (num5 > num7) { num7 = num5; } if (num5 < num6) { num6 = num5; } x++; } } int num8 = ((num7 - num6) * 2) / 3; num7 += num8; num6 -= num8; query.Min.Z = num6 * 1.525902E-05f; query.Max.Z = num7 * 1.525902E-05f; } }