From 5c0aef32c16ed02e2a90a8818d96a38fbd8d7c52 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 21 Feb 2023 19:56:18 -0600 Subject: [PATCH] Partially fix LODs disappearing when moving --- .../seibel/lod/core/render/LodQuadTree.java | 54 ++++++++++++++++--- .../lod/core/render/LodRenderSection.java | 33 ++++-------- .../lod/core/render/RenderBufferHandler.java | 2 +- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/com/seibel/lod/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/lod/core/render/LodQuadTree.java index 98cf2d423..4fd0a346f 100644 --- a/core/src/main/java/com/seibel/lod/core/render/LodQuadTree.java +++ b/core/src/main/java/com/seibel/lod/core/render/LodQuadTree.java @@ -224,7 +224,7 @@ public class LodQuadTree implements AutoCloseable if (!gridList.getCenter().equals(expectedCenterPos)) { // LOGGER.info("TreeTick: Moving ring list "+sectionDetailLevel+" from "+gridList.getCenter()+" to "+expectedCenterPos); - gridList.moveTo(expectedCenterPos.x, expectedCenterPos.y, LodRenderSection::dispose); + gridList.moveTo(expectedCenterPos.x, expectedCenterPos.y, LodRenderSection::disposeRenderData); } } @@ -550,7 +550,8 @@ public class LodQuadTree implements AutoCloseable } ringList.remove(pos.x, pos.y); - section.dispose(); + section.disposeRenderData(); + return; } else @@ -567,10 +568,15 @@ public class LodQuadTree implements AutoCloseable } - // TODO is this right? - enable rendering if this section is a leaf node in the tree, otherwise disable rendering + // enable rendering if this section is a leaf node in the tree, otherwise disable rendering if (section.childCount == 4) { - section.disableRender(); + // only disable rendering if the next section is ready to render, + // isRenderingEnabled check to prevent calling the recursive method more than necessary + if (section.isRenderingEnabled() && areChildRenderSectionsLoaded(section)) // FIXME: this is an imperfect solution, some sections will still appear/disappear incorrectly + { + section.disableRender(); + } } else if (section.childCount == 0) { @@ -585,7 +591,8 @@ public class LodQuadTree implements AutoCloseable // section validation - LodUtil.assertTrue(section.childCount == 4 || section.childCount == 0); + LodUtil.assertTrue(section.childCount == 4|| section.childCount == 0,"Expected render section to have a child count of 0, or 4. Found value: "+section.childCount); + if (section.pos.sectionDetailLevel == TREE_LOWEST_DETAIL_LEVEL) { // sections at the bottom of the tree (leaves) should have no additional children @@ -621,6 +628,39 @@ public class LodQuadTree implements AutoCloseable }); } } + private boolean areChildRenderSectionsLoaded(LodRenderSection renderSection) + { + if (renderSection == null) + { + // this section isn't loaded + return false; + } + if (renderSection.pos.sectionDetailLevel == TREE_LOWEST_DETAIL_LEVEL) + { + // this section is at the bottom detail level and has no children + return isSectionLoaded(renderSection); + } + else + { + // recursively look for a loaded child + LodRenderSection child0 = this.getChildSection(renderSection.pos, 0); + LodRenderSection child1 = this.getChildSection(renderSection.pos, 1); + LodRenderSection child2 = this.getChildSection(renderSection.pos, 2); + LodRenderSection child3 = this.getChildSection(renderSection.pos, 3); + + // either the child section is loaded, or check the next section down + return (isSectionLoaded(child0) || areChildRenderSectionsLoaded(child0)) + && (isSectionLoaded(child1) || areChildRenderSectionsLoaded(child1)) + && (isSectionLoaded(child2) || areChildRenderSectionsLoaded(child2)) + && (isSectionLoaded(child3) || areChildRenderSectionsLoaded(child3)); + } + } + private static boolean isSectionLoaded(LodRenderSection renderSection) + { + return renderSection != null && renderSection.isLoaded() && !renderSection.getRenderSource().isEmpty(); + } + + /** * Re-creates the color, render data. @@ -636,7 +676,7 @@ public class LodQuadTree implements AutoCloseable MovableGridRingList ringList = this.renderSectionRingLists[sectionDetailLevel-TREE_LOWEST_DETAIL_LEVEL]; if (ringList != null) { - ringList.clear((section) -> section.dispose()); + ringList.clear((section) -> section.disposeRenderData()); LOGGER.info("Finished deleting render files for detail level ["+sectionDetailLevel+"]..."); } @@ -710,7 +750,7 @@ public class LodQuadTree implements AutoCloseable { if (section != null) { - section.dispose(); + section.disposeRenderData(); } }); } diff --git a/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java index e7acb079e..c42a78bb1 100644 --- a/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/lod/core/render/LodRenderSection.java @@ -25,7 +25,7 @@ public class LodRenderSection private CompletableFuture loadFuture; private boolean isRenderEnabled = false; - + // TODO: Should I provide a way to change the render source? private ColumnRenderSource renderSource; private ILodRenderSourceProvider renderSourceProvider = null; @@ -48,7 +48,6 @@ public class LodRenderSection return; } - this.loadFuture = this.renderSourceProvider.read(this.pos); this.isRenderEnabled = true; } @@ -59,20 +58,7 @@ public class LodRenderSection return; } - - if (this.renderSource != null) - { - this.renderSource.disableRender(); - this.renderSource.dispose(); - this.renderSource = null; - } - - if (this.loadFuture != null) - { - this.loadFuture.cancel(true); - this.loadFuture = null; - } - + this.disposeRenderData(); this.isRenderEnabled = false; } @@ -128,15 +114,19 @@ public class LodRenderSection } } - public void dispose() + public void disposeRenderData() { if (this.renderSource != null) { + this.renderSource.disableRender(); this.renderSource.dispose(); + this.renderSource = null; } - else if (this.loadFuture != null) + + if (this.loadFuture != null) { this.loadFuture.cancel(true); + this.loadFuture = null; } } @@ -148,14 +138,11 @@ public class LodRenderSection public boolean shouldRender() { return this.isLoaded() && this.isRenderEnabled; } + public boolean isRenderingEnabled() { return this.isRenderEnabled; } public boolean isLoaded() { return this.renderSource != null; } public boolean isLoading() { return this.loadFuture != null; } - - //FIXME: Used by RenderBufferHandler - public int FIXME_BYPASS_DONT_USE_getChildCount() { return this.childCount; } - public boolean isOutdated() { return this.renderSource != null && !this.renderSource.isValid(); } - + public ColumnRenderSource getRenderSource() { return this.renderSource; } diff --git a/core/src/main/java/com/seibel/lod/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/lod/core/render/RenderBufferHandler.java index 1ce87cef6..16af31b27 100644 --- a/core/src/main/java/com/seibel/lod/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/lod/core/render/RenderBufferHandler.java @@ -288,7 +288,7 @@ public class RenderBufferHandler // TODO: Improve this! (Checking section.isLoaded() as if its not loaded, it can only be because // it has children. (But this logic is... really hard to read!) // FIXME: Above comment is COMPLETELY WRONG! I am an idiot! - boolean sectionHasChildren = section.FIXME_BYPASS_DONT_USE_getChildCount() > 0; + boolean sectionHasChildren = section.childCount > 0; if (sectionHasChildren) { if (this.children == null)