mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-02-11 05:53:19 +08:00
LOD manager performance improvements
This commit is contained in:
parent
6c76726131
commit
b187ad919b
@ -1321,6 +1321,8 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public uint EntityHash { get; set; } = 0; //used by CW as a unique position+name identifier
|
public uint EntityHash { get; set; } = 0; //used by CW as a unique position+name identifier
|
||||||
|
|
||||||
|
public LinkedList<YmapEntityDef> LodManagerChildren = null;
|
||||||
|
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
@ -1695,6 +1697,21 @@ namespace CodeWalker.GameFiles
|
|||||||
ChildList = null;
|
ChildList = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void LodManagerAddChild(YmapEntityDef child)
|
||||||
|
{
|
||||||
|
if (LodManagerChildren == null)
|
||||||
|
{
|
||||||
|
LodManagerChildren = new LinkedList<YmapEntityDef>();
|
||||||
|
}
|
||||||
|
LodManagerChildren.AddLast(child);
|
||||||
|
}
|
||||||
|
public void LodManagerRemoveChild(YmapEntityDef child)
|
||||||
|
{
|
||||||
|
LodManagerChildren?.Remove(child);//could improve this by caching the list node....
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return _CEntityDef.ToString() + ((ChildList != null) ? (" (" + ChildList.Count.ToString() + " children) ") : " ") + _CEntityDef.lodLevel.ToString();
|
return _CEntityDef.ToString() + ((ChildList != null) ? (" (" + ChildList.Count.ToString() + " children) ") : " ") + _CEntityDef.lodLevel.ToString();
|
||||||
|
@ -1521,6 +1521,13 @@ namespace CodeWalker.Rendering
|
|||||||
renderworldrenderables.Clear();
|
renderworldrenderables.Clear();
|
||||||
VisibleYmaps.Clear();
|
VisibleYmaps.Clear();
|
||||||
|
|
||||||
|
foreach (var ymap in renderworldVisibleYmapDict.Values)
|
||||||
|
{
|
||||||
|
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
||||||
|
VisibleYmaps.Add(ymap);
|
||||||
|
}
|
||||||
|
RenderWorldAdjustMapViewCamera();
|
||||||
|
|
||||||
|
|
||||||
LodManager.MaxLOD = renderworldMaxLOD;
|
LodManager.MaxLOD = renderworldMaxLOD;
|
||||||
LodManager.LodDistMult = renderworldDetailDistMult;
|
LodManager.LodDistMult = renderworldDetailDistMult;
|
||||||
@ -1529,43 +1536,38 @@ namespace CodeWalker.Rendering
|
|||||||
LodManager.ShowScriptedYmaps = ShowScriptedYmaps;
|
LodManager.ShowScriptedYmaps = ShowScriptedYmaps;
|
||||||
LodManager.Update(renderworldVisibleYmapDict, ref camera.Position, currentElapsedTime);
|
LodManager.Update(renderworldVisibleYmapDict, ref camera.Position, currentElapsedTime);
|
||||||
|
|
||||||
if (MapViewEnabled)
|
|
||||||
{
|
|
||||||
|
|
||||||
foreach (var ymap in renderworldVisibleYmapDict.Values)
|
|
||||||
{
|
|
||||||
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
|
||||||
VisibleYmaps.Add(ymap);
|
|
||||||
}
|
|
||||||
RenderWorldAdjustMapViewCamera();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var ymap in LodManager.CurrentYmaps.Values)
|
|
||||||
{
|
|
||||||
if (!RenderWorldYmapIsVisible(ymap)) continue;
|
|
||||||
VisibleYmaps.Add(ymap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var ents = LodManager.VisibleLeaves;// LodManager.GetVisibleEntities(camera);
|
var ents = LodManager.GetVisibleLeaves(camera);
|
||||||
|
|
||||||
|
|
||||||
|
//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)
|
foreach (var ent in ents)
|
||||||
{
|
{
|
||||||
if (!RenderIsEntityFinalRender(ent))
|
if (!RenderIsEntityFinalRender(ent))
|
||||||
{ continue; }
|
{ continue; }
|
||||||
|
|
||||||
if (MapViewEnabled)
|
//if (MapViewEnabled)
|
||||||
{
|
//{
|
||||||
if (!camera.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax))
|
// if (!camera.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax))
|
||||||
{ continue; }
|
// { continue; }
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
if (!camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent))
|
// if (!camera.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent))
|
||||||
{ continue; }
|
// { continue; }
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
renderworldentities.Add(ent);
|
renderworldentities.Add(ent);
|
||||||
|
|
||||||
@ -1597,12 +1599,11 @@ namespace CodeWalker.Rendering
|
|||||||
{
|
{
|
||||||
var ent = renderworldentities[i];
|
var ent = renderworldentities[i];
|
||||||
var arch = ent.Archetype;
|
var arch = ent.Archetype;
|
||||||
var pent = ent.Parent;
|
|
||||||
var drawable = gameFileCache.TryGetDrawable(arch);
|
var drawable = gameFileCache.TryGetDrawable(arch);
|
||||||
Renderable rndbl = TryGetRenderable(arch, drawable);
|
var rndbl = TryGetRenderable(arch, drawable);
|
||||||
if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload))
|
if ((rndbl != null) && rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload))
|
||||||
{
|
{
|
||||||
RenderableEntity rent = new RenderableEntity();
|
var rent = new RenderableEntity();
|
||||||
rent.Entity = ent;
|
rent.Entity = ent;
|
||||||
rent.Renderable = rndbl;
|
rent.Renderable = rndbl;
|
||||||
|
|
||||||
@ -3483,15 +3484,16 @@ namespace CodeWalker.Rendering
|
|||||||
public float MapViewDist = 1.0f;
|
public float MapViewDist = 1.0f;
|
||||||
public bool ShowScriptedYmaps = true;
|
public bool ShowScriptedYmaps = true;
|
||||||
|
|
||||||
|
public Vector3 Position = Vector3.Zero;
|
||||||
|
|
||||||
public Dictionary<MetaHash, YmapFile> CurrentYmaps = new Dictionary<MetaHash, YmapFile>();
|
public Dictionary<MetaHash, YmapFile> CurrentYmaps = new Dictionary<MetaHash, YmapFile>();
|
||||||
private List<MetaHash> RemoveYmaps = new List<MetaHash>();
|
private List<MetaHash> RemoveYmaps = new List<MetaHash>();
|
||||||
public Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>> EntityTree = new Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>>();
|
public Dictionary<YmapEntityDef, YmapEntityDef> RootEntities = new Dictionary<YmapEntityDef, YmapEntityDef>();
|
||||||
private Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>> RootEntities = new Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>>();
|
|
||||||
public Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>> VisibleRoots = new Dictionary<YmapEntityDef, LinkedList<YmapEntityDef>>();
|
|
||||||
public List<YmapEntityDef> VisibleLeaves = new List<YmapEntityDef>();
|
public List<YmapEntityDef> VisibleLeaves = new List<YmapEntityDef>();
|
||||||
|
|
||||||
public void Update(Dictionary<MetaHash, YmapFile> ymaps, ref Vector3 position, float elapsed)
|
public void Update(Dictionary<MetaHash, YmapFile> ymaps, ref Vector3 position, float elapsed)
|
||||||
{
|
{
|
||||||
|
Position = position;
|
||||||
|
|
||||||
foreach (var kvp in ymaps)
|
foreach (var kvp in ymaps)
|
||||||
{
|
{
|
||||||
@ -3530,7 +3532,6 @@ namespace CodeWalker.Rendering
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RemoveYmaps.Clear();
|
RemoveYmaps.Clear();
|
||||||
foreach (var kvp in CurrentYmaps)
|
foreach (var kvp in CurrentYmaps)
|
||||||
{
|
{
|
||||||
@ -3549,15 +3550,11 @@ namespace CodeWalker.Rendering
|
|||||||
for (int i = 0; i < ymap.AllEntities.Length; i++)
|
for (int i = 0; i < ymap.AllEntities.Length; i++)
|
||||||
{
|
{
|
||||||
var ent = ymap.AllEntities[i];
|
var ent = ymap.AllEntities[i];
|
||||||
EntityTree.Remove(ent);
|
|
||||||
RootEntities.Remove(ent);
|
RootEntities.Remove(ent);
|
||||||
|
ent.LodManagerChildren?.Clear();
|
||||||
if ((ent.Parent != null) && (ent.Parent.Ymap != ymap))
|
if ((ent.Parent != null) && (ent.Parent.Ymap != ymap))
|
||||||
{
|
{
|
||||||
LinkedList<YmapEntityDef> clist = null;
|
ent.Parent.LodManagerRemoveChild(ent);
|
||||||
if (EntityTree.TryGetValue(ent.Parent, out clist))
|
|
||||||
{
|
|
||||||
clist.Remove(ent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3577,26 +3574,11 @@ namespace CodeWalker.Rendering
|
|||||||
var ent = ymap.AllEntities[i];
|
var ent = ymap.AllEntities[i];
|
||||||
if (ent.Parent != null)
|
if (ent.Parent != null)
|
||||||
{
|
{
|
||||||
LinkedList<YmapEntityDef> clist = null;
|
ent.Parent.LodManagerAddChild(ent);
|
||||||
if (!EntityTree.TryGetValue(ent.Parent, out clist))
|
|
||||||
{
|
|
||||||
clist = new LinkedList<YmapEntityDef>();
|
|
||||||
EntityTree[ent.Parent] = clist;
|
|
||||||
}
|
|
||||||
clist.AddLast(ent);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LinkedList<YmapEntityDef> clist = null;
|
RootEntities[ent] = ent;
|
||||||
if ((ent._CEntityDef.lodLevel != rage__eLodType.LODTYPES_DEPTH_ORPHANHD) && (ent._CEntityDef.lodLevel != rage__eLodType.LODTYPES_DEPTH_HD))
|
|
||||||
{
|
|
||||||
if (!EntityTree.TryGetValue(ent, out clist))
|
|
||||||
{
|
|
||||||
clist = new LinkedList<YmapEntityDef>();
|
|
||||||
EntityTree[ent] = clist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RootEntities[ent] = clist;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3604,35 +3586,73 @@ namespace CodeWalker.Rendering
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VisibleRoots.Clear();
|
}
|
||||||
|
|
||||||
|
public List<YmapEntityDef> GetVisibleLeaves()
|
||||||
|
{
|
||||||
VisibleLeaves.Clear();
|
VisibleLeaves.Clear();
|
||||||
foreach (var kvp in RootEntities)
|
foreach (var kvp in RootEntities)
|
||||||
{
|
{
|
||||||
var ent = kvp.Key;
|
var ent = kvp.Key;
|
||||||
if (EntityVisibleAtMaxLodLevel(ent))
|
if (EntityVisibleAtMaxLodLevel(ent))
|
||||||
{
|
{
|
||||||
ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - position).Length();
|
ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - Position).Length();
|
||||||
if(ent.Distance <= (ent.LodDist * LodDistMult))
|
if (ent.Distance <= (ent.LodDist * LodDistMult))
|
||||||
{
|
{
|
||||||
VisibleRoots[ent] = kvp.Value;
|
RecurseAddVisibleLeaves(ent);
|
||||||
RecurseAddVisibleLeaves(ent, ref position);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return VisibleLeaves;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
private void RecurseAddVisibleLeaves(YmapEntityDef ent)
|
||||||
private void RecurseAddVisibleLeaves(YmapEntityDef ent, ref Vector3 position)
|
|
||||||
{
|
{
|
||||||
var clist = GetEntityChildren(ent, ref position);
|
var clist = GetEntityChildren(ent);
|
||||||
if (clist != null)
|
if (clist != null)
|
||||||
{
|
{
|
||||||
foreach (var child in clist)
|
var cnode = clist.First;
|
||||||
|
while (cnode != null)
|
||||||
{
|
{
|
||||||
RecurseAddVisibleLeaves(child, ref position);
|
RecurseAddVisibleLeaves(cnode.Value);
|
||||||
|
cnode = cnode.Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisibleLeaves.Add(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<YmapEntityDef> GetVisibleLeaves(Camera cam)
|
||||||
|
{
|
||||||
|
VisibleLeaves.Clear();
|
||||||
|
foreach (var kvp in RootEntities)
|
||||||
|
{
|
||||||
|
var ent = kvp.Key;
|
||||||
|
if (EntityVisibleAtMaxLodLevel(ent) && EntityVisible(ent, cam))
|
||||||
|
{
|
||||||
|
ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - Position).Length();
|
||||||
|
if (ent.Distance <= (ent.LodDist * LodDistMult))
|
||||||
|
{
|
||||||
|
RecurseAddVisibleLeaves(ent, cam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
else
|
||||||
@ -3642,35 +3662,51 @@ namespace CodeWalker.Rendering
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private LinkedList<YmapEntityDef> GetEntityChildren(YmapEntityDef ent, ref Vector3 position)
|
|
||||||
|
private LinkedList<YmapEntityDef> GetEntityChildren(YmapEntityDef ent)
|
||||||
{
|
{
|
||||||
//get the children list for this entity, if all the hcildren are available, and they are within range
|
//get the children list for this entity, if all the hcildren are available, and they are within range
|
||||||
if (!EntityChildrenVisibleAtMaxLodLevel(ent)) return null;
|
if (!EntityChildrenVisibleAtMaxLodLevel(ent)) return null;
|
||||||
LinkedList<YmapEntityDef> clist = null;
|
var clist = ent.LodManagerChildren;
|
||||||
EntityTree.TryGetValue(ent, out clist);
|
|
||||||
if ((clist != null) && (clist.Count >= ent._CEntityDef.numChildren))
|
if ((clist != null) && (clist.Count >= ent._CEntityDef.numChildren))
|
||||||
{
|
{
|
||||||
ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - position).Length();
|
if (ent.Parent != null)//already calculated root entities distance
|
||||||
|
{
|
||||||
|
ent.Distance = MapViewEnabled ? MapViewDist : (ent.Position - Position).Length();
|
||||||
|
}
|
||||||
if (ent.Distance <= (ent.ChildLodDist * LodDistMult))
|
if (ent.Distance <= (ent.ChildLodDist * LodDistMult))
|
||||||
{
|
{
|
||||||
return clist;
|
return clist;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var child in clist)
|
var cnode = clist.First;
|
||||||
|
while (cnode != null)
|
||||||
{
|
{
|
||||||
child.Distance = MapViewEnabled ? MapViewDist : (child.Position - position).Length();
|
var child = cnode.Value;
|
||||||
|
child.Distance = MapViewEnabled ? MapViewDist : (child.Position - Position).Length();
|
||||||
if (child.Distance <= (child.LodDist * LodDistMult))
|
if (child.Distance <= (child.LodDist * LodDistMult))
|
||||||
{
|
{
|
||||||
return clist;
|
return clist;
|
||||||
}
|
}
|
||||||
|
cnode = cnode.Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool EntityVisible(YmapEntityDef ent, Camera cam)
|
||||||
|
{
|
||||||
|
if (MapViewEnabled)
|
||||||
|
{
|
||||||
|
return cam.ViewFrustum.ContainsAABBNoFrontClipNoOpt(ref ent.BBMin, ref ent.BBMax);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cam.ViewFrustum.ContainsAABBNoClip(ref ent.BBCenter, ref ent.BBExtent);
|
||||||
|
}
|
||||||
|
}
|
||||||
private bool EntityVisibleAtMaxLodLevel(YmapEntityDef ent)
|
private bool EntityVisibleAtMaxLodLevel(YmapEntityDef ent)
|
||||||
{
|
{
|
||||||
if (MaxLOD != rage__eLodType.LODTYPES_DEPTH_ORPHANHD)
|
if (MaxLOD != rage__eLodType.LODTYPES_DEPTH_ORPHANHD)
|
||||||
|
@ -688,7 +688,7 @@ namespace CodeWalker.Rendering
|
|||||||
context.OutputMerger.DepthStencilState = dsEnabled;
|
context.OutputMerger.DepthStencilState = dsEnabled;
|
||||||
context.Rasterizer.State = rsSolid;
|
context.Rasterizer.State = rsSolid;
|
||||||
|
|
||||||
float maxdist = 3000.0f;// cascade.IntervalFar * 5.0f;
|
float maxdist = Shadowmap.maxShadowDistance;// 3000.0f;// cascade.IntervalFar * 5.0f;
|
||||||
|
|
||||||
//find the casters within range
|
//find the casters within range
|
||||||
shadowcasters.Clear();
|
shadowcasters.Clear();
|
||||||
|
@ -46,7 +46,7 @@ namespace CodeWalker.Rendering
|
|||||||
Vector3 SceneExtent;
|
Vector3 SceneExtent;
|
||||||
|
|
||||||
float[] fCascadeIntervals = { 7.0f, 20.0f, 65.0f, 160.0f, 600.0f, 3000.0f, 5000.0f, 10000.0f };
|
float[] fCascadeIntervals = { 7.0f, 20.0f, 65.0f, 160.0f, 600.0f, 3000.0f, 5000.0f, 10000.0f };
|
||||||
float maxShadowDistance = 3000.0f;
|
public float maxShadowDistance = 3000.0f;
|
||||||
|
|
||||||
|
|
||||||
long graphicsMemoryUsage = 0;
|
long graphicsMemoryUsage = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user