mirror of
https://github.com/GTA-ASM/SanAndreasUnity
synced 2024-11-26 05:50:18 +00:00
reuse existing static geometry
This commit is contained in:
parent
25a0093c8f
commit
8e08c8b1c8
5 changed files with 187 additions and 19 deletions
|
@ -20,9 +20,6 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
private MapObject[] m_cars;
|
||||
private List<EntranceExitMapObject> m_enexes;
|
||||
|
||||
private bool m_createdStaticGeometry = false;
|
||||
private bool m_initializedStaticGeometry = false;
|
||||
|
||||
public IReadOnlyList<int> CellIds { get; } = Enumerable.Range(0, 19).ToList();
|
||||
|
||||
public bool ignoreLodObjectsWhenInitializing = false;
|
||||
|
@ -140,23 +137,136 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
}
|
||||
|
||||
|
||||
private static string GetKey(StaticGeometry sg)
|
||||
{
|
||||
return $"{sg.SerializedObjectDefinitionId}_{sg.SerializedInstancePosition}_{sg.SerializedInstanceRotation}";
|
||||
}
|
||||
|
||||
private static string GetKey(Instance inst)
|
||||
{
|
||||
return $"{inst.ObjectId}_{inst.Position}_{inst.Rotation}";
|
||||
}
|
||||
|
||||
public void CreateStaticGeometry ()
|
||||
{
|
||||
if (m_createdStaticGeometry)
|
||||
return;
|
||||
|
||||
m_createdStaticGeometry = true;
|
||||
/*var gr = Item.GetPlacements<Instance>(CellIds.ToArray())
|
||||
.GroupBy(_ => $"{_.ObjectId}_{_.Position}_{_.Rotation}")
|
||||
.Where(g => g.ElementAtOrDefault(1) != default)
|
||||
.ToList();*/
|
||||
|
||||
var placements = Item.GetPlacements<Instance>(CellIds.ToArray());
|
||||
|
||||
m_insts = new Dictionary<Instance,StaticGeometry> (48 * 1024);
|
||||
foreach (var plcm in placements) {
|
||||
// find existing objects
|
||||
|
||||
var existingObjects = new Dictionary<string, object>(this.transform.childCount);
|
||||
|
||||
foreach(var sg in this.gameObject.GetFirstLevelChildrenSingleComponent<StaticGeometry>())
|
||||
{
|
||||
string key = GetKey(sg);
|
||||
|
||||
if (existingObjects.TryGetValue(key, out object obj))
|
||||
{
|
||||
if (obj is List<StaticGeometry> list)
|
||||
{
|
||||
list.Add(sg);
|
||||
}
|
||||
else
|
||||
{
|
||||
list = new List<StaticGeometry>();
|
||||
list.Add(sg);
|
||||
existingObjects[key] = list;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
existingObjects.Add(key, sg);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"Found {existingObjects.Count} existing objects");
|
||||
|
||||
// create new, or update existing objects
|
||||
|
||||
m_insts = new Dictionary<Instance, StaticGeometry> (48 * 1024);
|
||||
|
||||
int numObjectsReused = 0;
|
||||
|
||||
foreach (var plcm in placements)
|
||||
{
|
||||
if (this.ignoreLodObjectsWhenInitializing && plcm.IsLod)
|
||||
continue;
|
||||
|
||||
m_insts.Add (plcm, StaticGeometry.Create ());
|
||||
string key = GetKey(plcm);
|
||||
if (existingObjects.TryGetValue(key, out object obj))
|
||||
{
|
||||
StaticGeometry sg;
|
||||
|
||||
if (obj is List<StaticGeometry> list)
|
||||
{
|
||||
sg = list.RemoveFirst();
|
||||
if (list.Count == 0)
|
||||
existingObjects.Remove(key);
|
||||
}
|
||||
//m_insts = placements.ToDictionary(x => x, x => StaticGeometry.Create());
|
||||
else
|
||||
{
|
||||
sg = (StaticGeometry) obj;
|
||||
existingObjects.Remove(key);
|
||||
}
|
||||
|
||||
m_insts.Add(plcm, sg);
|
||||
|
||||
numObjectsReused++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_insts.Add(plcm, StaticGeometry.Create());
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"Reused {numObjectsReused} existing objects");
|
||||
|
||||
// delete unused existing objects
|
||||
|
||||
foreach (var pair in existingObjects)
|
||||
{
|
||||
if (pair.Value is List<StaticGeometry> list)
|
||||
list.ForEach(sg => F.DestroyEvenInEditMode(sg.gameObject));
|
||||
else
|
||||
F.DestroyEvenInEditMode(((StaticGeometry)pair.Value).gameObject);
|
||||
}
|
||||
|
||||
Debug.Log($"Deleted {existingObjects.Count} existing objects");
|
||||
|
||||
|
||||
/*
|
||||
// gather existing objects, and destroy invalid ones
|
||||
|
||||
var toDestroy = new List<StaticGeometry>();
|
||||
|
||||
foreach (var sg in this.gameObject.GetFirstLevelChildrenSingleComponent<StaticGeometry>())
|
||||
{
|
||||
if (sg.SerializedObjectDefinitionId <= 0
|
||||
|| !placements.TryGetValue(sg.SerializedObjectDefinitionId, out var plcm)
|
||||
|| (this.ignoreLodObjectsWhenInitializing && plcm.IsLod))
|
||||
toDestroy.Add(sg);
|
||||
else
|
||||
m_insts.Add(plcm, sg);
|
||||
}
|
||||
|
||||
toDestroy.ForEach(sg => F.DestroyEvenInEditMode(sg.gameObject));
|
||||
|
||||
// add new objects
|
||||
|
||||
foreach (var pair in placements)
|
||||
{
|
||||
var plcm = pair.Value;
|
||||
|
||||
if (this.ignoreLodObjectsWhenInitializing && plcm.IsLod)
|
||||
continue;
|
||||
|
||||
if (!m_insts.ContainsKey(plcm))
|
||||
m_insts.Add(plcm, StaticGeometry.Create());
|
||||
}*/
|
||||
|
||||
UnityEngine.Debug.Log("Num static geometries " + m_insts.Count);
|
||||
|
||||
|
@ -171,11 +281,6 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
|
||||
public void InitStaticGeometry ()
|
||||
{
|
||||
if (m_initializedStaticGeometry)
|
||||
return;
|
||||
|
||||
m_initializedStaticGeometry = true;
|
||||
|
||||
foreach (var inst in m_insts)
|
||||
{
|
||||
var staticGeometry = inst.Value;
|
||||
|
|
|
@ -34,6 +34,21 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
|
||||
public ISimpleObjectDefinition ObjectDefinition { get; private set; }
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private int m_serializedObjectDefinitionId = -1;
|
||||
public int SerializedObjectDefinitionId => m_serializedObjectDefinitionId;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Vector3 m_serializedInstancePosition;
|
||||
public Vector3 SerializedInstancePosition => m_serializedInstancePosition;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Quaternion m_serializedInstanceRotation;
|
||||
public Quaternion SerializedInstanceRotation => m_serializedInstanceRotation;
|
||||
|
||||
private bool _canLoad;
|
||||
private bool _isGeometryLoaded = false;
|
||||
private bool _isFading;
|
||||
|
@ -89,6 +104,10 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
public void Initialize(Instance inst, Dictionary<Instance, StaticGeometry> dict)
|
||||
{
|
||||
Instance = inst;
|
||||
m_serializedObjectDefinitionId = inst.ObjectId;
|
||||
m_serializedInstancePosition = inst.Position;
|
||||
m_serializedInstanceRotation = inst.Rotation;
|
||||
|
||||
ObjectDefinition = Item.GetDefinition<Importing.Items.Definitions.ISimpleObjectDefinition>(inst.ObjectId);
|
||||
|
||||
if (ObjectDefinition is TimeObjectDef)
|
||||
|
@ -104,6 +123,10 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
|
||||
name = _canLoad ? ObjectDefinition.ModelName : string.Format("Unknown ({0})", Instance.ObjectId);
|
||||
|
||||
if (LodChild != null)
|
||||
LodChild.LodParent = null;
|
||||
LodChild = null;
|
||||
|
||||
if (_canLoad && Instance.LodInstance != null)
|
||||
{
|
||||
if (dict.TryGetValue(Instance.LodInstance, out StaticGeometry dictValue))
|
||||
|
@ -124,6 +147,9 @@ namespace SanAndreasUnity.Behaviours.World
|
|||
|
||||
if (!_canLoad) return;
|
||||
|
||||
if (null != this.GetComponent<MeshFilter>()) // already loaded - this also works in edit mode
|
||||
return;
|
||||
|
||||
Profiler.BeginSample ("StaticGeometry.OnLoad", this);
|
||||
|
||||
|
||||
|
|
21
Assets/Scripts/Utilities/CollectionExtensions.cs
Normal file
21
Assets/Scripts/Utilities/CollectionExtensions.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace SanAndreasUnity.Utilities
|
||||
{
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
public static T RemoveLast<T>(this IList<T> list)
|
||||
{
|
||||
T lastElement = list[list.Count - 1];
|
||||
list.RemoveAt(list.Count - 1);
|
||||
return lastElement;
|
||||
}
|
||||
|
||||
public static T RemoveFirst<T>(this IList<T> list)
|
||||
{
|
||||
T firstElement = list[0];
|
||||
list.RemoveAt(0);
|
||||
return firstElement;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/Utilities/CollectionExtensions.cs.meta
Normal file
11
Assets/Scripts/Utilities/CollectionExtensions.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d1a08f49d78741c47838f4a11e35ecc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -292,6 +292,11 @@ namespace SanAndreasUnity.Utilities
|
|||
return go.transform.GetFirstLevelChildren().SelectMany(c => c.GetComponents<T>());
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetFirstLevelChildrenSingleComponent<T>(this GameObject go) where T : Component
|
||||
{
|
||||
return go.transform.GetFirstLevelChildren().Select(c => c.GetComponent<T>()).Where(_ => _ != null);
|
||||
}
|
||||
|
||||
public static void SetY(this Transform t, float yPos) {
|
||||
Vector3 pos = t.position;
|
||||
pos.y = yPos;
|
||||
|
|
Loading…
Reference in a new issue