quad tree for visibility wip

This commit is contained in:
2016-12-25 14:56:41 +07:00
parent a7f4fee821
commit 864727a50d
11 changed files with 542 additions and 440 deletions

View File

@@ -7,12 +7,60 @@ using UnityEngine.Profiling;
namespace IsoTools.Internal {
public class IsoScreenSolver {
Vector2 _minIsoXY = Vector2.zero;
IsoAssocList<IsoObject> _curVisibles = new IsoAssocList<IsoObject>();
IsoAssocList<IsoObject> _oldVisibles = new IsoAssocList<IsoObject>();
IsoGrid<IsoObject> _visibleGrid = new IsoGrid<IsoObject>(new IsoGridItemAdapter(), 47);
IsoGridLookUpper _gridLookUpper = new IsoGridLookUpper();
List<Renderer> _tmpRenderers = new List<Renderer>();
Vector2 _minIsoXY = Vector2.zero;
IsoAssocList<IsoObject> _oldVisibles = new IsoAssocList<IsoObject>();
IsoAssocList<IsoObject> _curVisibles = new IsoAssocList<IsoObject>();
IsoQuadTree<IsoObject> _quadTree = new IsoQuadTree<IsoObject>(47);
IsoGrid<IsoObject> _screenGrid = new IsoGrid<IsoObject>(new IsoGridItemAdapter(), 47);
IsoQTBoundsLookUpper _qtBoundsLU = new IsoQTBoundsLookUpper();
IsoQTContentLookUpper _qtContentLU = new IsoQTContentLookUpper();
IsoGridLookUpper _screenGridLU = new IsoGridLookUpper();
// ---------------------------------------------------------------------
//
// IsoQTBoundsLookUpper
//
// ---------------------------------------------------------------------
class IsoQTBoundsLookUpper : IsoQuadTree<IsoObject>.IBoundsLookUpper {
public void LookUp(IsoRect bounds) {
#if UNITY_EDITOR
IsoUtils.DrawRect(bounds, Color.blue);
#endif
}
}
// ---------------------------------------------------------------------
//
// IsoQTContentLookUpper
//
// ---------------------------------------------------------------------
class IsoQTContentLookUpper : IsoQuadTree<IsoObject>.IContentLookUpper {
Camera[] _tmpCameras = new Camera[8];
IsoScreenSolver _screenSolver = null;
public void LookUp(IsoObject iso_object) {
iso_object.Internal.Placed = false;
_screenSolver._oldVisibles.Add(iso_object);
}
public void LookUpForVisibility(IsoScreenSolver screen_solver) {
_screenSolver = screen_solver;
var cam_count = Camera.GetAllCameras(_tmpCameras);
for ( var i = 0; i < cam_count; ++i ) {
var camera = _tmpCameras[i];
var vp_rect = camera.rect;
var wrl_min = camera.ViewportToWorldPoint(new Vector3(vp_rect.xMin, vp_rect.yMin));
var wrl_max = camera.ViewportToWorldPoint(new Vector3(vp_rect.xMax, vp_rect.yMax));
_screenSolver._quadTree.VisitItemsByBounds(new IsoRect(wrl_min, wrl_max), this);
}
_screenSolver = null;
System.Array.Clear(_tmpCameras, 0, _tmpCameras.Length);
}
}
// ---------------------------------------------------------------------
//
@@ -46,15 +94,18 @@ namespace IsoTools.Internal {
IsoObject _isoObject;
public void LookUp(IsoList<IsoObject> items) {
LookUpSectorDepends(_isoObject, items);
LookUpSectorRDepends(_isoObject, items);
LookUpCellForLDepends(_isoObject, items);
LookUpCellForRDepends(_isoObject, items);
}
public void Setup(IsoObject iso_object) {
public void LookUpForDepends(
IsoScreenSolver screen_solver, IsoObject iso_object)
{
_isoObject = iso_object;
}
public void Reset() {
screen_solver._screenGrid.LookUpCells(
iso_object.Internal.MinGridCell,
iso_object.Internal.MaxGridCell,
this);
_isoObject = null;
}
}
@@ -69,14 +120,14 @@ namespace IsoTools.Internal {
get { return _minIsoXY; }
}
public IsoAssocList<IsoObject> curVisibles {
get { return _curVisibles; }
}
public IsoAssocList<IsoObject> oldVisibles {
get { return _oldVisibles; }
}
public IsoAssocList<IsoObject> curVisibles {
get { return _curVisibles; }
}
// ---------------------------------------------------------------------
//
// Callbacks
@@ -84,15 +135,22 @@ namespace IsoTools.Internal {
// ---------------------------------------------------------------------
public void OnAddInstance(IsoObject iso_object) {
_quadTree.AddItem(
iso_object.Internal.ScreenBounds,
iso_object);
}
public void OnRemoveInstance(IsoObject iso_object) {
_oldVisibles.Remove(iso_object);
_curVisibles.Remove(iso_object);
_quadTree.RemoveItem(iso_object);
ClearIsoObjectDepends(iso_object);
}
public bool OnMarkDirtyInstance(IsoObject iso_object) {
_quadTree.MoveItem(
iso_object.Internal.ScreenBounds,
iso_object);
if ( !iso_object.Internal.Dirty && _curVisibles.Contains(iso_object) ) {
iso_object.Internal.Dirty = true;
return true;
@@ -102,6 +160,7 @@ namespace IsoTools.Internal {
#if UNITY_EDITOR
public void OnDrawGizmos(IsoWorld iso_world) {
_quadTree.VisitAllBounds(_qtBoundsLU);
/*
for ( int y = 0, ye = (int)_sectorsNumPosCount.y; y < ye; ++y ) {
for ( int x = 0, xe = (int)_sectorsNumPosCount.x; x < xe; ++x ) {
@@ -126,32 +185,27 @@ namespace IsoTools.Internal {
// ---------------------------------------------------------------------
public void StepSortingAction(IsoWorld iso_world, IsoAssocList<IsoObject> instances) {
Profiler.BeginSample("ResolveVisibles");
Profiler.BeginSample("IsoScreenSolver.ResolveVisibles");
ResolveVisibles(instances);
Profiler.EndSample();
Profiler.BeginSample("ResolveVisibleGrid");
Profiler.BeginSample("IsoScreenSolver.ResolveVisibleGrid");
ResolveVisibleGrid(iso_world);
Profiler.EndSample();
}
public void PostStepSortingAction() {
_tmpRenderers.Clear();
}
public void Clear() {
_curVisibles.Clear();
_oldVisibles.Clear();
_visibleGrid.ClearGrid();
_curVisibles.Clear();
_quadTree.Clear();
_screenGrid.ClearGrid();
}
public void SetupIsoObjectDepends(IsoObject iso_object) {
ClearIsoObjectDepends(iso_object);
_gridLookUpper.Setup(iso_object);
_visibleGrid.LookUpCells(
iso_object.Internal.MinGridCell,
iso_object.Internal.MaxGridCell,
_gridLookUpper);
_gridLookUpper.Reset();
_screenGridLU.LookUpForDepends(this, iso_object);
}
public void ClearIsoObjectDepends(IsoObject iso_object) {
@@ -173,7 +227,15 @@ namespace IsoTools.Internal {
// ---------------------------------------------------------------------
void ResolveVisibles(IsoAssocList<IsoObject> instances) {
_oldVisibles.Clear();
Profiler.BeginSample("ProcessAllInstances");
ProcessAllInstances(instances);
Profiler.EndSample();
Profiler.BeginSample("ProcessNewVisibles");
ProcessNewVisibles();
Profiler.EndSample();
}
void ProcessAllInstances(IsoAssocList<IsoObject> instances) {
if ( instances.Count > 0 ) {
_minIsoXY.Set(float.MaxValue, float.MaxValue);
for ( int i = 0, e = instances.Count; i < e; ++i ) {
@@ -191,36 +253,22 @@ namespace IsoTools.Internal {
{
iso_object.FixIsoPosition();
}
if ( IsIsoObjectVisible(iso_object) ) {
iso_object.Internal.Placed = false;
_oldVisibles.Add(iso_object);
}
}
} else {
_minIsoXY.Set(0.0f, 0.0f);
}
var temp_visibles = _curVisibles;
}
void ProcessNewVisibles() {
_oldVisibles.Clear();
_qtContentLU.LookUpForVisibility(this);
SwapCurrentVisibles();
}
void SwapCurrentVisibles() {
var swap_tmp = _curVisibles;
_curVisibles = _oldVisibles;
_oldVisibles = temp_visibles;
}
bool IsIsoObjectVisible(IsoObject iso_object) {
var renderers = GetIsoObjectRenderers(iso_object);
for ( int i = 0, e = renderers.Count; i < e; ++i ) {
if ( renderers[i].isVisible ) {
return true;
}
}
return false;
}
List<Renderer> GetIsoObjectRenderers(IsoObject iso_object) {
if ( iso_object.cacheRenderers ) {
return iso_object.Internal.Renderers;
} else {
iso_object.GetComponentsInChildren<Renderer>(_tmpRenderers);
return _tmpRenderers;
}
_oldVisibles = swap_tmp;
}
// ---------------------------------------------------------------------
@@ -230,24 +278,24 @@ namespace IsoTools.Internal {
// ---------------------------------------------------------------------
void ResolveVisibleGrid(IsoWorld iso_world) {
_visibleGrid.ClearItems();
_screenGrid.ClearItems();
for ( int i = 0, e = _curVisibles.Count; i < e; ++i ) {
var iso_object = _curVisibles[i];
_visibleGrid.AddItem(iso_object);
_screenGrid.AddItem(iso_object);
}
var min_sector_size = IsoUtils.Vec2MaxF(
iso_world.IsoToScreen(IsoUtils.vec3OneXY) -
iso_world.IsoToScreen(Vector3.zero));
_visibleGrid.RebuildGrid(min_sector_size);
_screenGrid.RebuildGrid(min_sector_size);
}
// ---------------------------------------------------------------------
//
// LookUpSectorDepends
// LookUpCellForDepends
//
// ---------------------------------------------------------------------
static void LookUpSectorDepends(IsoObject obj_a, IsoList<IsoObject> others) {
static void LookUpCellForLDepends(IsoObject obj_a, IsoList<IsoObject> others) {
for ( int i = 0, e = others.Count; i < e; ++i ) {
var obj_b = others[i];
if ( obj_a != obj_b && !obj_b.Internal.Dirty && IsIsoObjectDepends(obj_a, obj_b) ) {
@@ -257,7 +305,7 @@ namespace IsoTools.Internal {
}
}
static void LookUpSectorRDepends(IsoObject obj_a, IsoList<IsoObject> others) {
static void LookUpCellForRDepends(IsoObject obj_a, IsoList<IsoObject> others) {
for ( int i = 0, e = others.Count; i < e; ++i ) {
var obj_b = others[i];
if ( obj_a != obj_b && !obj_b.Internal.Dirty && IsIsoObjectDepends(obj_b, obj_a) ) {
@@ -293,9 +341,13 @@ namespace IsoTools.Internal {
var dB_y = b_max.y - a_min.y;
var dB_z = a_max.z - b_min.z;
var dP_x = a_size.x + b_size.x - Mathf.Abs(dA_x - dB_x);
var dP_y = a_size.y + b_size.y - Mathf.Abs(dA_y - dB_y);
var dP_z = a_size.z + b_size.z - Mathf.Abs(dA_z - dB_z);
var dD_x = dB_x - dA_x;
var dD_y = dB_y - dA_y;
var dD_z = dB_z - dA_z;
var dP_x = a_size.x + b_size.x - (dD_x > 0.0f ? dD_x : -dD_x);
var dP_y = a_size.y + b_size.y - (dD_y > 0.0f ? dD_y : -dD_y);
var dP_z = a_size.z + b_size.z - (dD_z > 0.0f ? dD_z : -dD_z);
if ( dP_x <= dP_y && dP_x <= dP_z ) {
return dA_x > dB_x;