rj-action-library/Runtime/LOD/NTree/OcTree/OcTreeCell.cs

202 lines
4.1 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
public class OcTreeCell<T>:OcTreeNode<T>
{
OcTreeCell<T> _parent;
public OcTreeCell<T> parent => _parent;
OcTree<T> _tree;
public OcTree<T> tree => _tree;
List<OcTreeCell<T>> _cells;
public List<OcTreeCell<T>> cells => _cells;
public int numCells => _cells == null ? 0 : cells.Count;
List<T> _values;
public List<T> 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<T> Create( OcTree<T> tree, Vector3 min, Vector3 max, int rootIndex )
{
var cell = new OcTreeCell<T>();
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<T> Create( OcTreeCell<T> parent, int depth, Vector3 min, Vector3 max )
{
var cell = new OcTreeCell<T>();
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<T>();
}
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<T>();
cells.ForEach(
c =>
{
if ( c.values == null )
{
return;
}
cellPoints.AddRange( c.values );
}
);
_values = tree.CombinePoints( cellPoints );
_isCombined = true;
}
public OcTreeCell<T> GetChildCellFor( Vector3 position )
{
return _cells.Find( c => c.box.ContainsPoint( position ) );
}
public void Nest()
{
if ( _cells != null && _cells.Count == 8 )
{
return;
}
_cells = new List<OcTreeCell<T>>();
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 ) );
}
}
}
}
}
}