From 1af436b4036d56c4126183e1865611e9496336c4 Mon Sep 17 00:00:00 2001 From: dexy Date: Tue, 8 Jan 2019 18:57:24 +1100 Subject: [PATCH] Stopped HD ytd's getting loaded when HD texture not enabled, changed cache stacks to queues, added distance property to entity --- .../GameFiles/FileTypes/YmapFile.cs | 1 + CodeWalker.Core/GameFiles/GameFileCache.cs | 10 +- Rendering/RenderableCache.cs | 32 ++--- Rendering/Renderer.cs | 120 ++++++++++++------ 4 files changed, 105 insertions(+), 58 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs index ed35b44..116d377 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs @@ -1248,6 +1248,7 @@ namespace CodeWalker.GameFiles public MetaWrapper[] Extensions { get; set; } public int Index { get; set; } + public float Distance { get; set; } //used for rendering public bool IsVisible; //used for rendering public bool ChildrenVisible; //used for rendering public bool ChildrenRendered; //used when rendering ymap mode to reduce LOD flashing... diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index 95a87c8..1b95d71 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -18,7 +18,7 @@ namespace CodeWalker.GameFiles private Action ErrorLog; public int MaxItemsPerLoop = 1; //to keep things flowing... - private ConcurrentStack requestQueue = new ConcurrentStack(); + private ConcurrentQueue requestQueue = new ConcurrentQueue(); ////dynamic cache private Cache mainCache; @@ -135,7 +135,7 @@ namespace CodeWalker.GameFiles textureLookup.Clear(); GameFile queueclear; - while (requestQueue.TryPop(out queueclear)) + while (requestQueue.TryDequeue(out queueclear)) { } //empty the old queue out... } @@ -1486,9 +1486,9 @@ namespace CodeWalker.GameFiles private void TryLoadEnqueue(GameFile gf) { - if (((!gf.Loaded)) && (requestQueue.Count < 5))//(!gf.LoadQueued) && + if (((!gf.Loaded)) && (requestQueue.Count < 10))// && (!gf.LoadQueued) { - requestQueue.Push(gf); + requestQueue.Enqueue(gf); gf.LoadQueued = true; } } @@ -1870,7 +1870,7 @@ namespace CodeWalker.GameFiles int itemcount = 0; - while (requestQueue.TryPop(out req) && (itemcount < MaxItemsPerLoop)) + while (requestQueue.TryDequeue(out req) && (itemcount < MaxItemsPerLoop)) { //process content requests. if (req.Loaded) diff --git a/Rendering/RenderableCache.cs b/Rendering/RenderableCache.cs index e109b33..d05194a 100644 --- a/Rendering/RenderableCache.cs +++ b/Rendering/RenderableCache.cs @@ -253,10 +253,10 @@ namespace CodeWalker.Rendering public class RenderableCacheLookup where TVal: RenderableCacheItem, new() { - private ConcurrentStack itemsToLoad = new ConcurrentStack(); - private ConcurrentStack itemsToUnload = new ConcurrentStack(); - private ConcurrentStack itemsToInvalidate = new ConcurrentStack(); - private ConcurrentStack keysToInvalidate = new ConcurrentStack(); + private ConcurrentQueue itemsToLoad = new ConcurrentQueue(); + private ConcurrentQueue itemsToUnload = new ConcurrentQueue(); + private ConcurrentQueue itemsToInvalidate = new ConcurrentQueue(); + private ConcurrentQueue keysToInvalidate = new ConcurrentQueue(); private LinkedList loadeditems = new LinkedList();//only use from content thread! private Dictionary cacheitems = new Dictionary();//only use from render thread! public long CacheLimit; @@ -296,16 +296,16 @@ namespace CodeWalker.Rendering public void Clear() { - itemsToLoad.Clear(); + itemsToLoad = new ConcurrentQueue(); foreach (TVal rnd in loadeditems) { rnd.Unload(); } loadeditems.Clear(); cacheitems.Clear(); - itemsToUnload.Clear(); - itemsToInvalidate.Clear(); - keysToInvalidate.Clear(); + itemsToUnload = new ConcurrentQueue(); + itemsToInvalidate = new ConcurrentQueue(); + keysToInvalidate = new ConcurrentQueue(); } @@ -313,7 +313,7 @@ namespace CodeWalker.Rendering { TVal item; LoadedCount = 0; - while (itemsToLoad.TryPop(out item)) + while (itemsToLoad.TryDequeue(out item)) { if (item.IsLoaded) continue; //don't load it again... LoadedCount++; @@ -337,7 +337,7 @@ namespace CodeWalker.Rendering } if (LoadedCount >= maxitemsperloop) break; } - while (itemsToInvalidate.TryPop(out item)) + while (itemsToInvalidate.TryDequeue(out item)) { try { @@ -363,7 +363,7 @@ namespace CodeWalker.Rendering if ((now - lu).TotalSeconds > CacheTime) { var nextnode = rnode.Next; - itemsToUnload.Push(rnode.Value); + itemsToUnload.Enqueue(rnode.Value); loadeditems.Remove(rnode); rnode = nextnode; } @@ -380,18 +380,18 @@ namespace CodeWalker.Rendering LastFrameTime = DateTime.UtcNow.ToBinary(); TVal item; TKey key; - while (keysToInvalidate.TryPop(out key)) + while (keysToInvalidate.TryDequeue(out key)) { if (cacheitems.TryGetValue(key, out item)) { item.Unload(); item.Init(key); item.LoadQueued = true; - itemsToInvalidate.Push(item); + itemsToInvalidate.Enqueue(item); Interlocked.Add(ref CacheUse, -item.DataSize); } } - while (itemsToUnload.TryPop(out item)) + while (itemsToUnload.TryDequeue(out item)) { if ((item.Key != null) && (cacheitems.ContainsKey(item.Key))) { @@ -418,7 +418,7 @@ namespace CodeWalker.Rendering if ((!item.IsLoaded) && (!item.LoadQueued))// || { item.LoadQueued = true; - itemsToLoad.Push(item); + itemsToLoad.Enqueue(item); } return item; } @@ -428,7 +428,7 @@ namespace CodeWalker.Rendering { if (key == null) return; - keysToInvalidate.Push(key); + keysToInvalidate.Enqueue(key); } diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index 95b350f..6c23c86 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -1721,6 +1721,7 @@ namespace CodeWalker.Rendering } + ent.Distance = dist; ent.IsVisible = (dist <= loddist); ent.ChildrenVisible = (dist <= cloddist) && (ent.CEntityDef.numChildren > 0); @@ -2009,6 +2010,7 @@ namespace CodeWalker.Rendering bool usechild = false; Vector3 camrel = entity.Position - camera.Position; float dist = (camrel + entity.BSCenter).Length(); + entity.Distance = dist; float rad = arch.BSRadius; float loddist = entity.CEntityDef.lodDist; if (loddist < 1.0f) @@ -2380,6 +2382,7 @@ namespace CodeWalker.Rendering Vector3 bbmax = (arche != null) ? arche.BBMax : rndbl.Key.BoundingBoxMax.XYZ(); Vector3 bscen = (arche != null) ? arche.BSCenter : rndbl.Key.BoundingCenter; float radius = (arche != null) ? arche.BSRadius : rndbl.Key.BoundingSphereRadius; + float distance = 0;// (camrel + bscen).Length(); if (entity != null) { position = entity.Position; @@ -2390,9 +2393,12 @@ namespace CodeWalker.Rendering bbmax = entity.BBMax; bscen = entity.BSCenter; camrel += position; + distance = entity.Distance; + } + else + { + distance = (camrel + bscen).Length(); } - float distance = (camrel + bscen).Length(); - //bool usehdtxd = renderhdtextures && ((dist - bsrad) <= arche._BaseArchetypeDef.hdTextureDist); @@ -2660,13 +2666,14 @@ namespace CodeWalker.Rendering var yptTexDict = (drawable.Owner as YptFile)?.PtfxList?.TextureDictionary; - - if (rndbl.SDtxds == null) + bool cacheSD = (rndbl.SDtxds == null); + bool cacheHD = (renderhdtextures && (rndbl.HDtxds == null)); + if (cacheSD || cacheHD) { //cache the txd hierarchies for this renderable tryGetRenderableSDtxds.Clear(); tryGetRenderableHDtxds.Clear(); - if (arche != null) //try get HD txd for the asset + if (cacheHD && (arche != null)) //try get HD txd for the asset { MetaHash hdtxd = gameFileCache.TryGetHDTextureHash(arche._BaseArchetypeDef.assetName); if (hdtxd != arche._BaseArchetypeDef.assetName) @@ -2680,59 +2687,71 @@ namespace CodeWalker.Rendering } if (texDict != 0) { - var txdytd = gameFileCache.GetYtd(texDict); - if (txdytd != null) + if (cacheSD) { - tryGetRenderableSDtxds.Add(txdytd); - } - MetaHash hdtxd = gameFileCache.TryGetHDTextureHash(texDict); - if (hdtxd != texDict) - { - var txdhdytd = gameFileCache.GetYtd(hdtxd); - if (txdhdytd != null) + var txdytd = gameFileCache.GetYtd(texDict); + if (txdytd != null) { - tryGetRenderableHDtxds.Add(txdhdytd); + tryGetRenderableSDtxds.Add(txdytd); + } + } + if (cacheHD) + { + MetaHash hdtxd = gameFileCache.TryGetHDTextureHash(texDict); + if (hdtxd != texDict) + { + var txdhdytd = gameFileCache.GetYtd(hdtxd); + if (txdhdytd != null) + { + tryGetRenderableHDtxds.Add(txdhdytd); + } } } MetaHash ptxdname = gameFileCache.TryGetParentYtdHash(texDict); while (ptxdname != 0) //look for parent HD txds { - var pytd = gameFileCache.GetYtd(ptxdname); - if (pytd != null) + if (cacheSD) { - tryGetRenderableSDtxds.Add(pytd); - } - MetaHash phdtxdname = gameFileCache.TryGetHDTextureHash(ptxdname); - if (phdtxdname != ptxdname) - { - var phdytd = gameFileCache.GetYtd(phdtxdname); - if (phdytd != null) + var pytd = gameFileCache.GetYtd(ptxdname); + if (pytd != null) { - tryGetRenderableHDtxds.Add(phdytd); + tryGetRenderableSDtxds.Add(pytd); + } + } + if (cacheHD) + { + MetaHash phdtxdname = gameFileCache.TryGetHDTextureHash(ptxdname); + if (phdtxdname != ptxdname) + { + var phdytd = gameFileCache.GetYtd(phdtxdname); + if (phdytd != null) + { + tryGetRenderableHDtxds.Add(phdytd); + } } } ptxdname = gameFileCache.TryGetParentYtdHash(ptxdname); } } - rndbl.SDtxds = tryGetRenderableSDtxds.ToArray(); - rndbl.HDtxds = tryGetRenderableHDtxds.ToArray(); + if (cacheSD) rndbl.SDtxds = tryGetRenderableSDtxds.ToArray(); + if (cacheHD) rndbl.HDtxds = tryGetRenderableHDtxds.ToArray(); } - + //bool alltexsloaded = true; for (int mi = 0; mi < rndbl.AllModels.Length; mi++) { var model = rndbl.AllModels[mi]; - //if (!RenderIsModelFinalRender(model) && !renderproxies) - //{ - // continue; //filter out reflection proxy models... - //} + if (!RenderIsModelFinalRender(model) && !renderproxies) + { + continue; //filter out reflection proxy models... + } foreach (var geom in model.Geometries) @@ -2753,7 +2772,7 @@ namespace CodeWalker.Rendering dtex = yptTexDict.Lookup(tex.NameHash); } - else //if (texDict != 0) + if (dtex == null) //else //if (texDict != 0) { if (rndbl.SDtxds != null) @@ -2772,13 +2791,13 @@ namespace CodeWalker.Rendering } if (dtex != null) break; } - if (dtex == null)// rndbl.SDtxds.Length == 0)//ytd not found.. + if (dtex == null)// rndbl.SDtxds.Length == 0)//texture not found.. { if (drawable.ShaderGroup.TextureDictionary != null)//check any embedded texdict { dtex = drawable.ShaderGroup.TextureDictionary.Lookup(tex.NameHash); if (dtex != null) - { } + { } //this shouldn't really happen as embedded textures should already be loaded! (not as TextureRef) } } } @@ -2806,11 +2825,16 @@ namespace CodeWalker.Rendering } - if (ttex != null) //ensure embedded renderable texture + if (ttex != null) //ensure renderable texture { rdtex = renderableCache.GetRenderableTexture(ttex); } + //if ((rdtex != null) && (rdtex.IsLoaded == false)) + //{ + // alltexsloaded = false; + //} + geom.RenderableTextures[i] = rdtex; @@ -2856,7 +2880,29 @@ namespace CodeWalker.Rendering } } - rndbl.AllTexturesLoaded = true;// alltexsloaded || (missingtexcount < 2); + //if (rndbl.SDtxds != null) + //{ + // for (int i = 0; i < rndbl.SDtxds.Length; i++) + // { + // if (!rndbl.SDtxds[i].Loaded) + // { + // alltexsloaded = false; + // } + // } + //} + //if (rndbl.HDtxds != null) + //{ + // for (int i = 0; i < rndbl.HDtxds.Length; i++) + // { + // if (!rndbl.HDtxds[i].Loaded) + // { + // rndbl.AllTexturesLoaded = false; + // } + // } + //} + + rndbl.AllTexturesLoaded = true;// alltexsloaded;// || (missingtexcount < 2); + return rndbl; }