using System.Collections; using System.Collections.Generic; using Godot; using System; namespace Rokojori { public class OcTreeCell:OcTreeNode { OcTreeCell _parent; public OcTreeCell parent => _parent; OcTree _tree; public OcTree tree => _tree; List> _cells; public List> cells => _cells; public int numCells => _cells == null ? 0 : cells.Count; List _values; public List values => _values; int _depth; public int depth => _depth; Vector3 _center; public Vector3 center => _center; Vector3 _size; public Vector3 size => _size; bool _isCombined = false; public bool isCombined => _isCombined; public bool canBeCombined => ! isLeaf && ! isCombined && numCells > 0; public bool isRoot => _parent == null; public bool isEmpty => _cells == null || _cells.Count == 0; public bool isLeaf => _depth == tree.maxDepth; Box3 _box; public Box3 box => _box; int _rootCellIndex = -1; public int rootCellIndex => _rootCellIndex; public static OcTreeCell Create( OcTree tree, Vector3 min, Vector3 max, int rootIndex ) { var cell = new OcTreeCell(); cell._tree = tree; cell._center = (max + min ) / 2f; cell._size = ( max - min ); cell._depth = 0; cell._box = Box3.Create( min, max ); cell._rootCellIndex = rootIndex; return cell; } public static OcTreeCell Create( OcTreeCell parent, int depth, Vector3 min, Vector3 max ) { var cell = new OcTreeCell(); cell._parent = parent; cell._tree = parent.tree; cell._center = (max + min ) / 2f; cell._size = ( max - min ); cell._depth = depth; cell._box = Box3.Create( min, max ); cell._rootCellIndex = parent.rootCellIndex; return cell; } public Vector3 GetPointWithPolarUVW( Vector3 polarUVW ) { var halfSize = _size / 2f; return _center + halfSize * polarUVW; } public bool Insert( T data ) { if ( isLeaf ) { if ( _values == null ) { _values = new List(); } values.Add( data ); return true; } Nest(); var position = tree.GetPosition( data ); var cell = GetChildCellFor( position ); if ( cell == null ) { RJLog.Log( "No cell found in:", this.depth, this.center, ">> for: ", position ); return false; } return cell.Insert( data ); } public void SmoothDown( float amount ) { if ( isLeaf || cells == null ) { return; } cells.ForEach( ( c )=> { c._values = tree.SmoothPoints( c.values, values, amount ); } ); } public void Combine() { if ( isLeaf || isCombined ) { return; } if ( numCells == 0 ) { _isCombined = true; return; } var cellPoints = new List(); cells.ForEach( c => { if ( c.values == null ) { return; } cellPoints.AddRange( c.values ); } ); _values = tree.CombinePoints( cellPoints ); _isCombined = true; } public OcTreeCell GetChildCellFor( Vector3 position ) { return _cells.Find( c => c.box.ContainsPoint( position ) ); } public void Nest() { if ( _cells != null && _cells.Count == 8 ) { return; } _cells = new List>(); for ( int x = -1; x < 1; x ++ ) { var x0 = x; var x1 = x + 1; for ( int y = -1; y < 1; y ++ ) { var y0 = y; var y1 = y + 1; for ( int z = -1; z < 1; z ++ ) { var z0 = z; var z1 = z + 1; var min = GetPointWithPolarUVW( new Vector3( x0, y0, z0 ) ); var max = GetPointWithPolarUVW( new Vector3( x1, y1, z1 ) ); _cells.Add( Create( this, depth + 1, min, max ) ); } } } } } }