using System.Collections; using System.Collections.Generic; using Godot; using System; using System.Threading.Tasks; namespace Rokojori.PointClouds { public class PointCloudOcTree:OcTree { List compressedNormals = new List() { Vector3.Up, Vector3.Down, Vector3.Forward, Vector3.Back, Vector3.Right, Vector3.Left }; public bool normalSeperation = false; public PointCloudOcTree( Vector3 min, Vector3 max, float rootCellSize, int maxDepth ) :base( null, min, max, rootCellSize, maxDepth ) { this._getPosition = GetPointPosition; this._combinePoints = CombinePoints; this._smoothPoints = SmoothPoints; } protected Vector3 GetPointPosition( Point p ) { return p.position; } protected int GetNormalIndex( Vector3 normal ) { var closest = -1; var closestDistance = 100f; for ( int i = 0; i < compressedNormals.Count; i++ ) { var d = compressedNormals[ i ].DistanceSquaredTo( normal ); if ( d < closestDistance ) { closestDistance = d; closest = i; } } return closest; } protected List CombinePoints( List points ) { if ( normalSeperation ) { var lists = compressedNormals.Map( c => new List() ); points.ForEach( ( p )=> { var normalIndex = GetNormalIndex( p.normal ); lists[ normalIndex ].Add( p ); } ); lists = lists.Filter( n => n.Count > 0 ); return lists.Map( l => Point.AsAverage( l ) ); } return new List(){ Point.AsAverage( points ) }; } protected List SmoothPoints( List targets, List points, float amount ) { if ( targets == null || points == null ) { return targets; } var average = Point.AsAverage( points ); return targets.Map( t => t.Lerp( average, amount ) );; } } }