From 331aa4bccc2ea5c41927472d2fa08c7c1652a6fd Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Tue, 11 May 2021 22:52:46 +0200 Subject: [PATCH] =?UTF-8?q?Some=20cleanup=20and=20organization:=20-=20Remo?= =?UTF-8?q?ved=20a=20bunch=20of=20dead=20testing=20code=20-=20Provide=20a?= =?UTF-8?q?=20camera=20to=20the=20UniQuake=20script=20which=20the=20render?= =?UTF-8?q?=20module=20can=20then=20manipulate=20-=20Removed=20unused=20fi?= =?UTF-8?q?elds=20from=20QModel,=20which=20also=20fixes=20yet=20another=20?= =?UTF-8?q?text=20decoding=20issue=20in=20Zerst=C3=B6rer=20(the=20=C3=B6?= =?UTF-8?q?=20appears=20in=20the=20map's=20entity=20data)=20-=20Shut=20dow?= =?UTF-8?q?n=20Quake=20engine=20OnApplicationQuit,=20which=20allows=20clea?= =?UTF-8?q?n=20shutdown=20using=20the=20Play=20button=20in=20the=20Unity?= =?UTF-8?q?=20editor=20-=20Use=20QTexture=20pointer=20as=20key=20for=20gro?= =?UTF-8?q?uping=20surfaces,=20which=20removes=20the=20need=20for=20a=20bu?= =?UTF-8?q?nch=20of=20redundant=20data=20marshaling=20-=20Added=20disposal?= =?UTF-8?q?=20function=20for=20brush=20models?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Bootstrap.cs | 6 ++ Assets/Scripts/Data/QModel.cs | 18 +----- Assets/Scripts/Modules/BrushModel.cs | 86 ++++++-------------------- Assets/Scripts/Modules/RenderModule.cs | 18 +++++- Assets/Scripts/UniQuake.cs | 12 +++- 5 files changed, 52 insertions(+), 88 deletions(-) diff --git a/Assets/Scripts/Bootstrap.cs b/Assets/Scripts/Bootstrap.cs index abb3c9b..784fa33 100644 --- a/Assets/Scripts/Bootstrap.cs +++ b/Assets/Scripts/Bootstrap.cs @@ -23,6 +23,7 @@ public class Bootstrap : MonoBehaviour uq.BaseGame = MissionPack.Quake; uq.ModDirectory = mod; uq.AdditionalArguments = ParseArgs(); + uq.Camera = Camera.main; // This can be any one of four cameras for split-screen, each with its own culling layer } if (GUILayout.Button("Start Scourge of Armagon!")) @@ -31,6 +32,7 @@ public class Bootstrap : MonoBehaviour uq.BaseGame = MissionPack.Hipnotic; uq.ModDirectory = mod; uq.AdditionalArguments = ParseArgs(); + uq.Camera = Camera.main; } if (GUILayout.Button("Start Dissolution of Eternity!")) @@ -39,6 +41,7 @@ public class Bootstrap : MonoBehaviour uq.BaseGame = MissionPack.Rogue; uq.ModDirectory = mod; uq.AdditionalArguments = ParseArgs(); + uq.Camera = Camera.main; } GUILayout.Label("Mod directory:"); @@ -64,6 +67,9 @@ public class Bootstrap : MonoBehaviour private string[] ParseArgs() { + if (args == null) + return new string[0]; + return args.Split(new[] {' ', '\t', '\r', '\n'}, StringSplitOptions.RemoveEmptyEntries); } } diff --git a/Assets/Scripts/Data/QModel.cs b/Assets/Scripts/Data/QModel.cs index 7c84afa..994410f 100644 --- a/Assets/Scripts/Data/QModel.cs +++ b/Assets/Scripts/Data/QModel.cs @@ -69,22 +69,8 @@ public class QModel public int numTextures; public IntPtr textures; // Array of texture_t pointers - - public IntPtr visData; // Array of bytes - public IntPtr lightData; // Array of bytes - [MarshalAs(UnmanagedType.LPStr)] public string entities; - - public bool visWarn; - public int bspVersion; - - // VBO data from QuakeSpasm; unused by UniQuake - public uint meshvbo; - public uint meshIndexesVbo; - public int vboIndexOfs; - public int vboXyzOfs; - public int vboStofs; - - public IntPtr userCache; + + // Rest of the fields are unused } /// diff --git a/Assets/Scripts/Modules/BrushModel.cs b/Assets/Scripts/Modules/BrushModel.cs index 37f9b97..4129ca1 100644 --- a/Assets/Scripts/Modules/BrushModel.cs +++ b/Assets/Scripts/Modules/BrushModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; @@ -38,7 +39,7 @@ public class BrushModel var headNode = subModels[modelIdx].GetHeadNode(model); - var surfaceGroups = new Dictionary<(string, int), List>(); + var surfaceGroups = new Dictionary<(IntPtr, int), List>(); GroupSurfaces(headNode, surfaces, surfaceGroups); foreach (var group in surfaceGroups) @@ -51,8 +52,18 @@ public class BrushModel } } } + + public void Dispose() + { + foreach (var mesh in meshes) + { + UnityEngine.Object.Destroy(mesh); + } + + meshes.Clear(); + } - private void GroupSurfaces(QNode node, QSurface[] surfaces, Dictionary<(string, int), List> surfaceGroups) + private void GroupSurfaces(QNode node, QSurface[] surfaces, Dictionary<(IntPtr, int), List> surfaceGroups) { if (node.contents < 0) // Leaf node return; @@ -61,9 +72,9 @@ public class BrushModel { var surface = surfaces[node.firstSurface + surfIdx]; - string texName = surface.TextureInfo.Texture.name; + IntPtr texPtr = surface.TextureInfo.texture; int lightNum = surface.lightmapTextureNum; - var key = (texName, lightNum); + var key = (texPtr, lightNum); if (!surfaceGroups.ContainsKey(key)) surfaceGroups[key] = new List(); @@ -77,64 +88,6 @@ public class BrushModel } } - private void CreateNodeMeshes(QNode node, QSurface[] surfaces, GameObject parentGO) - { - if (node.contents < 0) // Leaf node - return; - - var nodeGO = new GameObject("Node"); - nodeGO.transform.SetParent(parentGO.transform); - - for (int surfIdx = 0; surfIdx < node.numSurfaces; ++surfIdx) - { - var surface = surfaces[node.firstSurface + surfIdx]; - CreateSurfaceMeshes(surface, $"{node.firstSurface + surfIdx}", nodeGO); - } - - foreach (var childNode in node.Children) - { - CreateNodeMeshes(childNode, surfaces, nodeGO); - } - } - - private void CreateSurfaceMeshes(QSurface surface, string key, GameObject nodeGO) - { - foreach (var polyVerts in surface.GetPolygons()) - { - tempVertices.Clear(); - tempTextureUVs.Clear(); - tempLightmapUVs.Clear(); - tempIndices.Clear(); - - for (int vertIdx = 0; vertIdx < polyVerts.Length; ++vertIdx) - { - tempVertices.Add(polyVerts[vertIdx].position.ToVector3().ToUnity()); - tempTextureUVs.Add(polyVerts[vertIdx].textureUV.ToVector2()); - tempLightmapUVs.Add(polyVerts[vertIdx].lightmapUV.ToVector2()); - } - - // Reconstruct triangle fan - for (ushort index = 2; index < polyVerts.Length; ++index) - { - tempIndices.Add(0); - tempIndices.Add((ushort) (index - 1)); - tempIndices.Add(index); - } - - Mesh mesh = new Mesh(); - mesh.name = $"Surface_{key}"; - mesh.SetVertices(tempVertices); - mesh.SetUVs(0, tempTextureUVs); - mesh.SetUVs(1, tempLightmapUVs); - mesh.SetIndices(tempIndices, MeshTopology.Triangles, 0); - mesh.RecalculateNormals(); - mesh.UploadMeshData(true); - meshes.Add(mesh); - - CreateMeshObject(mesh, nodeGO); - } - } - private void CreateMeshFromSurfaces(List surfaces, string key, GameObject parentGO) { tempVertices.Clear(); @@ -182,13 +135,10 @@ public class BrushModel private void CreateMeshObject(Mesh mesh, GameObject parentGO) { - var meshGO = new GameObject(mesh.name); - meshGO.transform.SetParent(parentGO.transform); - - var mf = meshGO.AddComponent(); + var mf = parentGO.AddComponent(); mf.sharedMesh = mesh; - var mr = meshGO.AddComponent(); + var mr = parentGO.AddComponent(); mr.sharedMaterial = debugMaterial; mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; diff --git a/Assets/Scripts/Modules/RenderModule.cs b/Assets/Scripts/Modules/RenderModule.cs index 73d6640..364534e 100644 --- a/Assets/Scripts/Modules/RenderModule.cs +++ b/Assets/Scripts/Modules/RenderModule.cs @@ -5,8 +5,11 @@ using UnityEngine.Rendering; public partial class RenderModule { private readonly UniQuake uq; + private readonly List brushModels = new List(); private readonly List aliasModels = new List(); private readonly Dictionary textures = new Dictionary(); + + private BrushModel worldModel; public RenderModule(UniQuake uniQuake) { @@ -21,6 +24,14 @@ public partial class RenderModule { base.Destroy(); + foreach (var brushModel in brushModels) + { + // brushModel.Dispose(); // TODO: reactivate when done testing in editor + } + + brushModels.Clear(); + worldModel = null; + foreach (var aliasModel in aliasModels) { // aliasModel.Dispose(); // TODO: reactivate when done testing in editor @@ -116,7 +127,7 @@ public partial class RenderModule } xPos += 128f; - return 1; + return aliasModels.Count; } private int UploadBrushModel(QModel model) @@ -126,7 +137,8 @@ public partial class RenderModule var brushModel = new BrushModel(model.name); brushModel.ImportMeshData(model); - return 1; + brushModels.Add(brushModel); + return brushModels.Count; } private uint nextTexNum = 0x10001; @@ -158,7 +170,7 @@ public partial class RenderModule private void SetupView(QVec3 origin, QVec3 angles, QLeaf viewLeaf) { - var cam = Camera.main; + var cam = uq.Camera; if (cam == null) return; diff --git a/Assets/Scripts/UniQuake.cs b/Assets/Scripts/UniQuake.cs index 9f05f3e..3206c22 100644 --- a/Assets/Scripts/UniQuake.cs +++ b/Assets/Scripts/UniQuake.cs @@ -16,6 +16,11 @@ public partial class UniQuake: MonoBehaviour private bool initialized = false; private double startTime; + /// + /// Camera and viewport that this instance of Quake will be rendering to + /// + public Camera Camera { get; set; } + public MissionPack BaseGame { get; set; } public string ModDirectory { get; set; } public string[] AdditionalArguments { get; set; } @@ -138,8 +143,13 @@ public partial class UniQuake: MonoBehaviour Destroy(this); } - private void OnDestroy() + private void OnApplicationQuit() { + Shutdown(); + } + + private void OnDestroy() + { renderModule.Destroy(); systemModule.Destroy();