From 5d0a3334a8776a43c52c492db2d9a5b4c1bf1099 Mon Sep 17 00:00:00 2001 From: dexy Date: Mon, 9 Dec 2019 00:41:35 +1100 Subject: [PATCH] LOD manager immersion improvement --- .../GameFiles/FileTypes/YmapFile.cs | 1 + Rendering/Renderer.cs | 175 ++++++++++-------- 2 files changed, 97 insertions(+), 79 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs index 55124a9..0f56b23 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs @@ -1322,6 +1322,7 @@ namespace CodeWalker.GameFiles public uint EntityHash { get; set; } = 0; //used by CW as a unique position+name identifier public LinkedList LodManagerChildren = null; + public object LodManagerRenderable = null; public string Name diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index fb4e460..9b96390 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -86,6 +86,9 @@ namespace CodeWalker.Rendering private List renderworldentities = new List(); //used when rendering world view. private List renderworldrenderables = new List(); + private Dictionary ArchetypeRenderables = new Dictionary(); + private Dictionary RequiredParents = new Dictionary(); + private List RenderEntities = new List(); public Dictionary HideEntities = new Dictionary();//dictionary of entities to hide, for cutscenes to use @@ -1520,6 +1523,9 @@ namespace CodeWalker.Rendering renderworldentities.Clear(); renderworldrenderables.Clear(); VisibleYmaps.Clear(); + ArchetypeRenderables.Clear(); + RequiredParents.Clear(); + RenderEntities.Clear(); foreach (var ymap in renderworldVisibleYmapDict.Values) { @@ -1534,46 +1540,64 @@ namespace CodeWalker.Rendering LodManager.MapViewEnabled = MapViewEnabled; LodManager.MapViewDist = camera.OrthographicSize / MapViewDetail; LodManager.ShowScriptedYmaps = ShowScriptedYmaps; - LodManager.Update(renderworldVisibleYmapDict, ref camera.Position, currentElapsedTime); + LodManager.Update(renderworldVisibleYmapDict, camera, currentElapsedTime); - var ents = LodManager.GetVisibleLeaves(camera); + var ents = LodManager.GetVisibleLeaves(); - - //foreach (var ent in ents) - //{ - // if (!RenderIsEntityFinalRender(ent)) - // { continue; } - // var arch = ent.Archetype; - // var drawable = gameFileCache.TryGetDrawable(arch); - // var rndbl = TryGetRenderable(arch, drawable); - // var ready = ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)); - //} - - foreach (var ent in ents) + for (int i = 0; i < ents.Count; i++) { + var ent = ents[i]; + if (!RenderIsEntityFinalRender(ent)) { continue; } - //if (MapViewEnabled) - //{ - // if (!camera.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax)) - // { continue; } - //} - //else - //{ - // if (!camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent)) - // { continue; } - //} - - - - renderworldentities.Add(ent); - - if (renderinteriors && ent.IsMlo && (ent.MloInstance != null)) //render Mlo child entities... + if (ent.IsMlo) { - RenderWorldAddInteriorEntities(ent); + if (renderinteriors && (ent.MloInstance != null) && !MapViewEnabled) //render Mlo child entities... + { + RenderWorldAddInteriorEntities(ent); + } + } + else + { + var rndbl = GetArchetypeRenderable(ent.Archetype); + ent.LodManagerRenderable = rndbl; + if (rndbl != null) + { + RenderEntities.Add(ent); + } + + var pent = ent.Parent; + if (waitforchildrentoload && (pent != null)) + { + if (!RequiredParents.ContainsKey(pent)) + { + bool allok = true; + var pcnode = pent.LodManagerChildren?.First; + while (pcnode != null) + { + var pcent = pcnode.Value; + var pcrndbl = (pcent == ent) ? rndbl : GetArchetypeRenderable(pcent.Archetype); + pcent.LodManagerRenderable = pcrndbl; + pcnode = pcnode.Next; + allok = allok && (pcrndbl != null); + } + if (!allok) + { + rndbl = GetArchetypeRenderable(pent.Archetype); + pent.LodManagerRenderable = rndbl; + if (rndbl != null) + { + RenderEntities.Add(pent); + } + } + RequiredParents[pent] = rndbl; + } + } + + } } @@ -1598,10 +1622,21 @@ namespace CodeWalker.Rendering for (int i = 0; i < renderworldentities.Count; i++) { var ent = renderworldentities[i]; - var arch = ent.Archetype; - var drawable = gameFileCache.TryGetDrawable(arch); - var rndbl = TryGetRenderable(arch, drawable); - if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)) + var rndbl = GetArchetypeRenderable(ent.Archetype); + ent.LodManagerRenderable = rndbl; + if (rndbl != null) + { + RenderEntities.Add(ent); + } + } + + for (int i = 0; i < RenderEntities.Count; i++) + { + var ent = RenderEntities[i]; + + var rndbl = ent.LodManagerRenderable as Renderable; + + if (rndbl != null) { var rent = new RenderableEntity(); rent.Entity = ent; @@ -1609,7 +1644,7 @@ namespace CodeWalker.Rendering if (HideEntities.ContainsKey(ent.EntityHash)) continue; //don't render hidden entities! - RenderArchetype(arch, ent, rent.Renderable, false); + RenderArchetype(ent.Archetype, ent, rent.Renderable, false); } } } @@ -2115,6 +2150,21 @@ namespace CodeWalker.Rendering + private Renderable GetArchetypeRenderable(Archetype arch) + { + Renderable rndbl = null; + if (!ArchetypeRenderables.TryGetValue(arch, out rndbl)) + { + var drawable = gameFileCache.TryGetDrawable(arch); + rndbl = TryGetRenderable(arch, drawable); + ArchetypeRenderables[arch] = rndbl; + } + if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload)) + { + return rndbl; + } + return null; + } @@ -3484,6 +3534,7 @@ namespace CodeWalker.Rendering public float MapViewDist = 1.0f; public bool ShowScriptedYmaps = true; + public Camera Camera = null; public Vector3 Position = Vector3.Zero; public Dictionary CurrentYmaps = new Dictionary(); @@ -3491,9 +3542,10 @@ namespace CodeWalker.Rendering public Dictionary RootEntities = new Dictionary(); public List VisibleLeaves = new List(); - public void Update(Dictionary ymaps, ref Vector3 position, float elapsed) + public void Update(Dictionary ymaps, Camera camera, float elapsed) { - Position = position; + Camera = camera; + Position = camera.Position; foreach (var kvp in ymaps) { @@ -3594,7 +3646,7 @@ namespace CodeWalker.Rendering foreach (var kvp in RootEntities) { var ent = kvp.Key; - if (EntityVisibleAtMaxLodLevel(ent)) + if (EntityVisibleAtMaxLodLevel(ent) && EntityVisible(ent)) { ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - Position).Length(); if (ent.Distance <= (ent.LodDist * LodDistMult)) @@ -3619,46 +3671,11 @@ namespace CodeWalker.Rendering } else { - VisibleLeaves.Add(ent); - } - } - - public List GetVisibleLeaves(Camera cam) - { - VisibleLeaves.Clear(); - foreach (var kvp in RootEntities) - { - var ent = kvp.Key; - if (EntityVisibleAtMaxLodLevel(ent) && EntityVisible(ent, cam)) + if ((ent.Parent == null) || EntityVisible(ent)) { - ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - Position).Length(); - if (ent.Distance <= (ent.LodDist * LodDistMult)) - { - RecurseAddVisibleLeaves(ent, cam); - } + VisibleLeaves.Add(ent); } } - return VisibleLeaves; - } - private void RecurseAddVisibleLeaves(YmapEntityDef ent, Camera cam) - { - var clist = GetEntityChildren(ent); - if (clist != null) - { - var cnode = clist.First; - while (cnode != null) - { - if (EntityVisible(cnode.Value, cam)) - { - RecurseAddVisibleLeaves(cnode.Value, cam); - } - cnode = cnode.Next; - } - } - else - { - VisibleLeaves.Add(ent); - } } @@ -3696,15 +3713,15 @@ namespace CodeWalker.Rendering return null; } - private bool EntityVisible(YmapEntityDef ent, Camera cam) + private bool EntityVisible(YmapEntityDef ent) { if (MapViewEnabled) { - return cam.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax); + return Camera.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax); } else { - return cam.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent); + return Camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent); } } private bool EntityVisibleAtMaxLodLevel(YmapEntityDef ent)