public static unsafe void ReplaceValues <TKey>(Dictionary <TKey, MyOctreeNode> nodeCollection, Dictionary <byte, byte> oldToNewValueMap) { KeyValuePair <TKey, MyOctreeNode>[] pairArray = nodeCollection.ToArray <KeyValuePair <TKey, MyOctreeNode> >(); int index = 0; while (index < pairArray.Length) { KeyValuePair <TKey, MyOctreeNode> pair = pairArray[index]; MyOctreeNode node = pair.Value; int num2 = 0; while (true) { byte num3; if (num2 >= 8) { nodeCollection[pair.Key] = node; index++; break; } if (oldToNewValueMap.TryGetValue(&node.Data.FixedElementField[num2], out num3)) { &node.Data.FixedElementField[num2] = num3; } num2++; } } }
private unsafe void WriteRange <TOperator>(MyCellCoord cell, byte defaultData, ref TOperator source, MyStorageDataTypeEnum type, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max) where TOperator : struct, IVoxelOperator { MyOctreeNode node; uint key = cell.PackId32(); if (!this.m_nodes.TryGetValue(key, out node)) { for (int i = 0; i < 8; i++) { &node.Data.FixedElementField[i] = defaultData; } } if (cell.Lod == 0) { Vector3I vectori = cell.CoordInLod << 1; for (int i = 0; i < 8; i++) { Vector3I vectori2; this.ComputeChildCoord(i, out vectori2); Vector3I position = (Vector3I)(vectori + vectori2); if (position.IsInsideInclusiveEnd(ref min, ref max)) { position = (Vector3I)((position - min) + readOffset); source.Op(ref position, type, ref (byte)ref (&node.Data.FixedElementField + i)); } } this.m_nodes[key] = node; } else { Vector3I vectori4 = cell.CoordInLod << 1; Vector3I vectori6 = (min >> cell.Lod) - vectori4; Vector3I vectori7 = (max >> cell.Lod) - vectori4; for (int i = 0; i < 8; i++) { Vector3I vectori5; this.ComputeChildCoord(i, out vectori5); if (vectori5.IsInsideInclusiveEnd(ref vectori6, ref vectori7)) { MyCellCoord coord = new MyCellCoord(cell.Lod - 1, (Vector3I)(vectori4 + vectori5)); this.WriteRange <TOperator>(coord, &node.Data.FixedElementField[i], ref source, type, ref readOffset, ref min, ref max); uint num5 = coord.PackId32(); MyOctreeNode node2 = this.m_nodes[num5]; if (node2.HasChildren || !MyOctreeNode.AllDataSame(&node2.Data.FixedElementField)) { node.SetChild(i, true); &node.Data.FixedElementField[i] = this.m_nodeFilter(&node2.Data.FixedElementField, cell.Lod); } else { node.SetChild(i, false); &node.Data.FixedElementField[i] = node2.Data.FixedElementField; this.m_nodes.Remove(num5); } } } this.m_nodes[key] = node; } }
internal unsafe void WriteTo(Stream stream) { stream.WriteNoAlloc(this.m_treeHeight); stream.WriteNoAlloc(this.m_defaultContent); foreach (KeyValuePair <uint, MyOctreeNode> pair in this.m_nodes) { stream.WriteNoAlloc(pair.Key); MyOctreeNode node = pair.Value; stream.WriteNoAlloc(node.ChildMask); stream.WriteNoAlloc(&node.Data.FixedElementField, 0, 8); } }
private static unsafe void UpdateLodDataInternal(int lod, byte[] dataArray, MyOctreeNode.FilterFunction filter) { int offset = 0; for (int i = 0; i < lod - 1; ++i) { offset += Volume >> (i + i + i); } var sx = Size >> lod; var sy = sx * sx; var sz = sy * sx; var psx = Size >> (lod - 1); var psy = psx * psx; var psz = psy * psx; ulong dataBit; byte* data = (byte*)&dataBit; fixed (byte* fixedDataArray = dataArray) { byte* voxel = fixedDataArray + offset; byte* store = voxel + psz; for (int z = 0; z < sz; z += sy) { int z0 = z << 3, z1 = (z << 3) + psy; for (int y = 0; y < sy; y += sx) { int y0 = y << 2, y1 = (y << 2) + psx; for (int x = 0; x < sx; ++x) { // precompute corner indices, moar readable int x0 = x << 1, x1 = (x << 1) + 1; data[0] = voxel[z0 + y0 + x0]; data[1] = voxel[z0 + y0 + x1]; data[2] = voxel[z0 + y1 + x0]; data[3] = voxel[z0 + y1 + x1]; data[4] = voxel[z1 + y0 + x0]; data[5] = voxel[z1 + y0 + x1]; data[6] = voxel[z1 + y1 + x0]; data[7] = voxel[z1 + y1 + x1]; store[x + y + z] = filter(data, lod); } } } } }
private unsafe void BuildNode <TDataEnum>(ref StackData <TDataEnum> stack, out MyOctreeNode builtNode) where TDataEnum : struct, IEnumerator <byte> { MyOctreeNode defaultNode = stack.DefaultNode; if (stack.Cell.Lod == 0) { for (int i = 0; i < 8; i++) { stack.Data.MoveNext(); &defaultNode.Data.FixedElementField[i] = stack.Data.Current; } } else { int *numPtr1 = (int *)ref stack.Cell.Lod; numPtr1[0]--; Vector3I coordInLod = stack.Cell.CoordInLod; Vector3I vectori2 = coordInLod << 1; int childIdx = 0; while (true) { Vector3I vectori3; MyOctreeNode node2; if (childIdx >= 8) { int *numPtr2 = (int *)ref stack.Cell.Lod; numPtr2[0]++; stack.Cell.CoordInLod = coordInLod; break; } this.ComputeChildCoord(childIdx, out vectori3); stack.Cell.CoordInLod = (Vector3I)(vectori2 + vectori3); this.BuildNode <TDataEnum>(ref stack, out node2); if (!node2.HasChildren && MyOctreeNode.AllDataSame(&node2.Data.FixedElementField)) { defaultNode.SetChild(childIdx, false); &defaultNode.Data.FixedElementField[childIdx] = node2.Data.FixedElementField; } else { defaultNode.SetChild(childIdx, true); &defaultNode.Data.FixedElementField[childIdx] = this.m_nodeFilter(&node2.Data.FixedElementField, stack.Cell.Lod); this.m_nodes.Add(stack.Cell.PackId32(), node2); } childIdx++; } } builtNode = defaultNode; }
private unsafe void BuildNode <TDataEnum>(ref StackData <TDataEnum> stack, out MyOctreeNode builtNode) where TDataEnum : struct, IEnumerator <TLeafData> { var currentNode = stack.DefaultNode; if (stack.Cell.Lod == 0) { // bottom level containing leaf data for (int i = 0; i < 8; ++i) { bool movedNext = stack.Data.MoveNext(); Debug.Assert(movedNext); currentNode.Data[i] = stack.Data.Current; } } else { --stack.Cell.Lod; Vector3I currentPosition = stack.Cell.CoordInLod; Vector3I childBase = currentPosition << 1; Vector3I childOffset; MyOctreeNode childNode; for (int i = 0; i < 8; ++i) { ComputeChildCoord(i, out childOffset); stack.Cell.CoordInLod = childBase + childOffset; BuildNode(ref stack, out childNode); if (!childNode.HasChildren && MyOctreeNode.AllDataSame(childNode.Data)) { currentNode.SetChild(i, false); currentNode.Data[i] = childNode.Data[0]; } else { currentNode.SetChild(i, true); currentNode.Data[i] = m_nodeFilter(childNode.Data, stack.Cell.Lod); m_nodes.Add(stack.Cell.PackId32(), childNode); } } ++stack.Cell.Lod; stack.Cell.CoordInLod = currentPosition; } builtNode = currentNode; }
private void CheckData <T>(ref T data, MyCellCoord cell) where T : struct, IEnumerator <byte> { uint num = cell.PackId32(); MyOctreeNode node = this.m_nodes[num]; for (int i = 0; i < 8; i++) { if (node.HasChild(i)) { Vector3I vectori; this.ComputeChildCoord(i, out vectori); } else { int num3 = 1 << ((3 * cell.Lod) & 0x1f); for (int j = 0; j < num3; j++) { } } } }
private static void WriteRange( ref WriteRangeArgs args, byte defaultData, int lodIdx, Vector3I lodCoord, ref Vector3I min, ref Vector3I max) { MyOctreeNode node = new MyOctreeNode(); { MyCellCoord leaf = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord); var leafKey = leaf.PackId64(); if (args.Leaves.ContainsKey(leafKey)) { args.Leaves.Remove(leafKey); var childBase = lodCoord << 1; Vector3I childOffset; MyCellCoord child = new MyCellCoord(); child.Lod = leaf.Lod - 1; var leafSize = LeafSizeInVoxels << child.Lod; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; var childCopy = child; childCopy.Lod += LeafLodCount; IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy); args.Leaves.Add(child.PackId64(), octreeLeaf); node.SetChild(i, true); node.SetData(i, octreeLeaf.GetFilteredValue()); } } else { leaf.Lod -= 1; // changes to node coord instead of leaf coord var nodeKey = leaf.PackId64(); if (!args.Nodes.TryGetValue(nodeKey, out node)) { for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) node.SetData(i, defaultData); } } } if (lodIdx == (LeafLodCount + 1)) { MyCellCoord child = new MyCellCoord(); Vector3I childBase = lodCoord << 1; Vector3I minInLod = min >> LeafLodCount; Vector3I maxInLod = max >> LeafLodCount; Vector3I leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1); Vector3I childOffset; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod)) continue; var childMin = child.CoordInLod << LeafLodCount; var childMax = childMin + LeafSizeInVoxels - 1; Vector3I.Max(ref childMin, ref min, out childMin); Vector3I.Min(ref childMax, ref max, out childMax); var readOffset = childMin - min; IMyOctreeLeafNode leaf; var leafKey = child.PackId64(); var startInChild = childMin - (child.CoordInLod << LeafLodCount); var endInChild = childMax - (child.CoordInLod << LeafLodCount); args.Leaves.TryGetValue(leafKey, out leaf); byte uniformValue; bool uniformLeaf; { // ensure leaf exists and is writable // the only writable leaf type is MicroOctree at this point byte childDefaultData = node.GetData(i); if (leaf == null) { var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(childDefaultData); leaf = octree; } if (leaf.ReadOnly) { var rangeEnd = new Vector3I(LeafSizeInVoxels - 1); m_temporaryCache.Resize(Vector3I.Zero, rangeEnd); leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd); var inCell = startInChild; for (var it2 = new Vector3I.RangeIterator(ref startInChild, ref endInChild); it2.IsValid(); it2.GetNext(out inCell)) { var read = readOffset + (inCell - startInChild); m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read)); } var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(m_temporaryCache); leaf = octree; } else { leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild); } uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue); } if (!uniformLeaf) { args.Leaves[leafKey] = leaf; node.SetChild(i, true); } else { args.Leaves.Remove(leafKey); node.SetChild(i, false); } node.SetData(i, leaf.GetFilteredValue()); } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } else { MyCellCoord child = new MyCellCoord(); child.Lod = lodIdx - 2 - LeafLodCount; var childBase = lodCoord << 1; Vector3I childOffset; var minInChild = (min >> (lodIdx-1)) - childBase; var maxInChild = (max >> (lodIdx-1)) - childBase; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild)) continue; child.CoordInLod = childBase + childOffset; WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max); var childKey = child.PackId64(); var childNode = args.Nodes[childKey]; if (!childNode.HasChildren && childNode.AllDataSame()) { node.SetChild(i, false); node.SetData(i, childNode.GetData(0)); args.Nodes.Remove(childKey); } else { node.SetChild(i, true); node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter)); } } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } }
private unsafe void WriteRange( MyCellCoord cell, TLeafData defaultData, MyStorageData source, MyStorageDataTypeEnum type, ref Vector3I readOffset, ref Vector3I min, ref Vector3I max) { var nodeKey = cell.PackId32(); MyOctreeNode node; if (!m_nodes.TryGetValue(nodeKey, out node)) { for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { node.Data[i] = defaultData; } } if (cell.Lod == 0) { var childBase = cell.CoordInLod << 1; Vector3I childOffset; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); var child = childBase + childOffset; if (!child.IsInsideInclusive(ref min, ref max)) { continue; } child -= min; child += readOffset; node.Data[i] = source.Get(type, ref child); } m_nodes[nodeKey] = node; } else { var childBase = cell.CoordInLod << 1; Vector3I childOffset; var minInChild = (min >> cell.Lod) - childBase; var maxInChild = (max >> cell.Lod) - childBase; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild)) { continue; } var childCell = new MyCellCoord(cell.Lod - 1, childBase + childOffset); WriteRange(childCell, node.Data[i], source, type, ref readOffset, ref min, ref max); var childKey = childCell.PackId32(); var childNode = m_nodes[childKey]; if (!childNode.HasChildren && MyOctreeNode.AllDataSame(childNode.Data)) { node.SetChild(i, false); node.Data[i] = childNode.Data[0]; m_nodes.Remove(childKey); } else { node.SetChild(i, true); node.Data[i] = m_nodeFilter(childNode.Data, cell.Lod); } } m_nodes[nodeKey] = node; } }
internal unsafe void ReadRange <TOperator>(ref TOperator target, MyStorageDataTypeEnum type, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) where TOperator : struct, IVoxelOperator { try { MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))]; MyCellCoord coord = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero); int index = 0 + 1; coordPtr[index] = coord; while (index > 0) { coord = coordPtr[--index]; MyOctreeNode node = this.m_nodes[coord.PackId32()]; int num3 = coord.Lod - lodIndex; Vector3I vectori4 = coord.CoordInLod << 1; Vector3I min = (minInLod >> num3) - vectori4; Vector3I max = (maxInLod >> num3) - vectori4; for (int i = 0; i < 8; i++) { Vector3I vectori; this.ComputeChildCoord(i, out vectori); if (vectori.IsInsideInclusiveEnd(ref min, ref max)) { if ((lodIndex < coord.Lod) && node.HasChild(i)) { index++; coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori4 + vectori)); } else { byte inOutContent = &node.Data.FixedElementField[i]; Vector3I result = (Vector3I)(vectori4 + vectori); if (num3 == 0) { Vector3I position = (Vector3I)((writeOffset + result) - minInLod); target.Op(ref position, type, ref inOutContent); } else { result = result << num3; Vector3I vectori7 = (Vector3I)((result + (1 << (num3 & 0x1f))) - 1); Vector3I *vectoriPtr1 = (Vector3I *)ref result; Vector3I.Max(ref (Vector3I) ref vectoriPtr1, ref minInLod, out result); Vector3I *vectoriPtr2 = (Vector3I *)ref vectori7; Vector3I.Min(ref (Vector3I) ref vectoriPtr2, ref maxInLod, out vectori7); int z = result.Z; while (z <= vectori7.Z) { int y = result.Y; while (true) { if (y > vectori7.Y) { z++; break; } int x = result.X; while (true) { if (x > vectori7.X) { y++; break; } Vector3I position = writeOffset; int * numPtr1 = (int *)ref position.X; numPtr1[0] += x - minInLod.X; int *numPtr2 = (int *)ref position.Y; numPtr2[0] += y - minInLod.Y; int *numPtr3 = (int *)ref position.Z; numPtr3[0] += z - minInLod.Z; target.Op(ref position, type, ref inOutContent); x++; } } } } } } } } } finally { } }
internal unsafe ContainmentType Intersect(ref BoundingBoxI box, int lod, bool exhaustiveContainmentCheck = true) { MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))]; MyCellCoord coord = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero); int index = 0 + 1; coordPtr[index] = coord; Vector3I min = box.Min; Vector3I max = box.Max; ContainmentType disjoint = ContainmentType.Disjoint; while (index > 0) { coord = coordPtr[--index]; MyOctreeNode node = this.m_nodes[coord.PackId32()]; int num3 = coord.Lod; Vector3I vectori6 = coord.CoordInLod << 1; Vector3I vectori4 = (min >> num3) - vectori6; Vector3I vectori5 = (max >> num3) - vectori6; for (int i = 0; i < 8; i++) { Vector3I vectori3; this.ComputeChildCoord(i, out vectori3); if (vectori3.IsInsideInclusiveEnd(ref vectori4, ref vectori5)) { if ((coord.Lod > 0) && node.HasChild(i)) { index++; coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori6 + vectori3)); } else { byte num5 = &node.Data.FixedElementField[i]; if (num3 == 0) { if (num5 != 0) { return(ContainmentType.Intersects); } } else { BoundingBoxI xi; bool flag; xi.Min = (Vector3I)(vectori6 + vectori3); Vector3I *vectoriPtr1 = (Vector3I *)ref xi.Min; vectoriPtr1[0] = vectoriPtr1[0] << num3; BoundingBoxI *xiPtr1 = (BoundingBoxI *)ref xi; xiPtr1->Max = (Vector3I)((xi.Min + (1 << (num3 & 0x1f))) - 1); Vector3I.Max(ref xi.Min, ref min, out xi.Min); Vector3I.Min(ref xi.Max, ref max, out xi.Max); ((BoundingBoxI *)ref xi).Intersects(ref xi, out flag); if (flag) { return(ContainmentType.Intersects); } } } } } } return(disjoint); }
internal unsafe byte GetFilteredValue() { MyOctreeNode node = this.m_nodes[this.ComputeRootKey()]; return(this.m_nodeFilter(&node.Data.FixedElementField, this.m_treeHeight)); }
internal unsafe void DebugDraw(IMyDebugDrawBatchAabb batch, Vector3 worldPos, MyVoxelDebugDrawMode mode) { Color?nullable; if (mode == MyVoxelDebugDrawMode.Content_MicroNodes) { foreach (KeyValuePair <uint, MyOctreeNode> pair in this.m_nodes) { MyCellCoord coord = new MyCellCoord(); coord.SetUnpack(pair.Key); MyOctreeNode node = pair.Value; for (int i = 0; i < 8; i++) { if (!node.HasChild(i) || (coord.Lod == 0)) { Vector3I vectori; BoundingBoxD xd; this.ComputeChildCoord(i, out vectori); Vector3I vectori2 = (Vector3I)((coord.CoordInLod << (coord.Lod + 1)) + (vectori << coord.Lod)); xd.Min = worldPos + (vectori2 * 1f); BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref xd; xdPtr1->Max = xd.Min + (1f * (1 << (coord.Lod & 0x1f))); if (node.GetData(i) != 0) { nullable = null; batch.Add(ref xd, nullable); } } } } return; } else if (mode != MyVoxelDebugDrawMode.Content_MicroNodesScaled) { return; } foreach (KeyValuePair <uint, MyOctreeNode> pair2 in this.m_nodes) { MyCellCoord coord2 = new MyCellCoord(); coord2.SetUnpack(pair2.Key); MyOctreeNode node2 = pair2.Value; for (int i = 0; i < 8; i++) { if (!node2.HasChild(i)) { Vector3I vectori3; this.ComputeChildCoord(i, out vectori3); float num3 = ((float)node2.GetData(i)) / 255f; if (num3 != 0f) { BoundingBoxD xd2; num3 = (float)Math.Pow(num3 * 1.0, 0.3333); Vector3I vectori4 = (Vector3I)((coord2.CoordInLod << (coord2.Lod + 1)) + (vectori3 << coord2.Lod)); float num4 = 1f * (1 << (coord2.Lod & 0x1f)); Vector3 vector = (worldPos + (vectori4 * 1f)) + (0.5f * num4); xd2.Min = vector - ((0.5f * num3) * num4); xd2.Max = vector + ((0.5f * num3) * num4); nullable = null; batch.Add(ref xd2, nullable); } } } } }
private static void WriteRange( ref WriteRangeArgs args, byte defaultData, int lodIdx, Vector3I lodCoord, ref Vector3I min, ref Vector3I max) { MyOctreeNode node = new MyOctreeNode(); { MyCellCoord leaf = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord); var leafKey = leaf.PackId64(); if (args.Leaves.ContainsKey(leafKey)) { args.Leaves.Remove(leafKey); var childBase = lodCoord << 1; Vector3I childOffset; MyCellCoord child = new MyCellCoord(); child.Lod = leaf.Lod - 1; var leafSize = LeafSizeInVoxels << child.Lod; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; var childCopy = child; childCopy.Lod += LeafLodCount; IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy); args.Leaves.Add(child.PackId64(), octreeLeaf); node.SetChild(i, true); node.SetData(i, octreeLeaf.GetFilteredValue()); } } else { leaf.Lod -= 1; // changes to node coord instead of leaf coord var nodeKey = leaf.PackId64(); if (!args.Nodes.TryGetValue(nodeKey, out node)) { for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { node.SetData(i, defaultData); } } } } if (lodIdx == (LeafLodCount + 1)) { MyCellCoord child = new MyCellCoord(); Vector3I childBase = lodCoord << 1; Vector3I minInLod = min >> LeafLodCount; Vector3I maxInLod = max >> LeafLodCount; Vector3I leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1); Vector3I childOffset; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); child.CoordInLod = childBase + childOffset; if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod)) { continue; } var childMin = child.CoordInLod << LeafLodCount; var childMax = childMin + LeafSizeInVoxels - 1; Vector3I.Max(ref childMin, ref min, out childMin); Vector3I.Min(ref childMax, ref max, out childMax); var readOffset = childMin - min; IMyOctreeLeafNode leaf; var leafKey = child.PackId64(); var startInChild = childMin - (child.CoordInLod << LeafLodCount); var endInChild = childMax - (child.CoordInLod << LeafLodCount); args.Leaves.TryGetValue(leafKey, out leaf); byte uniformValue; bool uniformLeaf; { // ensure leaf exists and is writable // the only writable leaf type is MicroOctree at this point byte childDefaultData = node.GetData(i); if (leaf == null) { var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(childDefaultData); leaf = octree; } if (leaf.ReadOnly) { var rangeEnd = new Vector3I(LeafSizeInVoxels - 1); m_temporaryCache.Resize(Vector3I.Zero, rangeEnd); leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd); var inCell = startInChild; for (var it2 = new Vector3I.RangeIterator(ref startInChild, ref endInChild); it2.IsValid(); it2.GetNext(out inCell)) { var read = readOffset + (inCell - startInChild); m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read)); } var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount)); octree.BuildFrom(m_temporaryCache); leaf = octree; } else { leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild); } uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue); } if (!uniformLeaf) { args.Leaves[leafKey] = leaf; node.SetChild(i, true); } else { args.Leaves.Remove(leafKey); node.SetChild(i, false); } node.SetData(i, leaf.GetFilteredValue()); } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } else { MyCellCoord child = new MyCellCoord(); child.Lod = lodIdx - 2 - LeafLodCount; var childBase = lodCoord << 1; Vector3I childOffset; var minInChild = (min >> (lodIdx - 1)) - childBase; var maxInChild = (max >> (lodIdx - 1)) - childBase; for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i) { ComputeChildCoord(i, out childOffset); if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild)) { continue; } child.CoordInLod = childBase + childOffset; WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max); var childKey = child.PackId64(); var childNode = args.Nodes[childKey]; if (!childNode.HasChildren && childNode.AllDataSame()) { node.SetChild(i, false); node.SetData(i, childNode.GetData(0)); args.Nodes.Remove(childKey); } else { node.SetChild(i, true); node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter)); } } args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node; } }