From 0f02005c58bd77213ec6314fcdf52ffb7ed3f9ad Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Wed, 7 Apr 2021 12:53:37 +0200 Subject: [PATCH] Reimplemented uploading of alias model data, which now includes all vertex, triangle index and UV data --- Assets/Scripts/Data/QModel.cs | 20 +++++++++++ Assets/Scripts/Modules/RenderModule.cs | 46 ++++++++++++++++--------- engine/code/gl_mesh.c | 2 -- engine/code/gl_model.c | 6 +++- engine/code/gl_model.h | 2 +- engine/projects/uniquake/mod_uniquake.c | 11 +++--- 6 files changed, 60 insertions(+), 27 deletions(-) diff --git a/Assets/Scripts/Data/QModel.cs b/Assets/Scripts/Data/QModel.cs index c331f9d..7524efa 100644 --- a/Assets/Scripts/Data/QModel.cs +++ b/Assets/Scripts/Data/QModel.cs @@ -172,3 +172,23 @@ public struct QTriVertex [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] v; public byte lightNormalIndex; } + +/// +/// Managed equivalent of mtriangle_t +/// +[StructLayout(LayoutKind.Sequential, Pack = 0)] +public struct QTriangle +{ + public int facesFront; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public int[] vertIndex; +} + +/// +/// Managed equivalent of stvert_t +/// +[StructLayout(LayoutKind.Sequential, Pack = 0)] +public struct QSTVert +{ + public int onSeam; + public int s, t; +} diff --git a/Assets/Scripts/Modules/RenderModule.cs b/Assets/Scripts/Modules/RenderModule.cs index b3cb490..9726902 100644 --- a/Assets/Scripts/Modules/RenderModule.cs +++ b/Assets/Scripts/Modules/RenderModule.cs @@ -7,6 +7,8 @@ using UnityEngine; public class RenderModule : CallbackHandler { + private const int MaxAliasFrames = 256; // Should match MAXALIASFRAMES + private readonly UniQuake uq; public RenderModule(UniQuake uniQuake) @@ -17,42 +19,54 @@ public class RenderModule : CallbackHandler { target = SelfPtr, - ModUploadModel = CreateCallback(Callback_ModUploadModel), + UploadAliasModel = CreateCallback(Callback_UploadAliasModel), }; RegisterCallbacks(callbacks); } /// - /// This matches struct unity_syscalls_s from uniquake.h in native code. + /// This matches unity_modcalls_t from mod_uniquake.c in native code. /// [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { public IntPtr target; - public IntPtr ModUploadModel; + public IntPtr UploadAliasModel; } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void ModUploadModelCallback(IntPtr target, QModel model, QAliasHeader header, IntPtr frames); + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private delegate int UploadAliasModelCallback(IntPtr target, [MarshalAs(UnmanagedType.LPStr)] string name, + QAliasHeader header, IntPtr frames, [MarshalAs(UnmanagedType.LPArray, SizeConst = MaxAliasFrames)] + IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts); - [MonoPInvokeCallback(typeof(ModUploadModelCallback))] - private static void Callback_ModUploadModel(IntPtr target, QModel model, QAliasHeader header, IntPtr frames) + [MonoPInvokeCallback(typeof(UploadAliasModelCallback))] + private static int Callback_UploadAliasModel(IntPtr target, string name, QAliasHeader header, IntPtr frames, IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts) { - if (header != null) + if (header == null) + { + Debug.LogWarning($"Uploading invalid alias model, name = {name}"); + return 0; + } + + if (frames != IntPtr.Zero) header.frames = frames.ToStructArray(header.numFrames); - GetSelf(target).UploadModel(model, header); + var poseVertices = new QTriVertex[header.numFrames][]; + for (int i = 0; i < header.numFrames && i < MaxAliasFrames; ++i) + { + poseVertices[i] = poseVerts[i].ToStructArray(header.numVerts); + } + + return GetSelf(target).UploadAliasModel(name, header, poseVertices, + triangles.ToStructArray(header.numTriangles), + stVerts.ToStructArray(header.numVerts)); } - private void UploadModel(QModel model, QAliasHeader header) + private int UploadAliasModel(string name, QAliasHeader header, QTriVertex[][] poseVertices, QTriangle[] triangles, QSTVert[] stVertices) { - Debug.Log($"Model '{model?.name}' of type {model?.type}, num frames = {header?.numFrames}"); - if (header?.frames != null) - { - string str = string.Join(", ", header.frames.Select(f => f.name)); - Debug.Log($"Frame list: {str}"); - } + Debug.Log($"Alias model '{name}' with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s)"); + return 1; } } diff --git a/engine/code/gl_mesh.c b/engine/code/gl_mesh.c index 6fd56fe..a62fa48 100644 --- a/engine/code/gl_mesh.c +++ b/engine/code/gl_mesh.c @@ -358,7 +358,5 @@ void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) for (i=0 ; inumposes ; i++) for (j=0 ; jname, pheader, poseverts, triangles, stverts); + // // move the complete, relocatable alias model to the cache // diff --git a/engine/code/gl_model.h b/engine/code/gl_model.h index 70c83a7..aca5fab 100644 --- a/engine/code/gl_model.h +++ b/engine/code/gl_model.h @@ -451,6 +451,6 @@ void Mod_TouchModel (char *name); mleaf_t *Mod_PointInLeaf (float *p, model_t *model); byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); -void Mod_UploadModel(model_t *model, aliashdr_t *aliashdr); +int UQ_GL_UploadAliasModel(char *name, aliashdr_t *aliashdr, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts); #endif // __MODEL__ diff --git a/engine/projects/uniquake/mod_uniquake.c b/engine/projects/uniquake/mod_uniquake.c index fd58b8b..4c56c5d 100644 --- a/engine/projects/uniquake/mod_uniquake.c +++ b/engine/projects/uniquake/mod_uniquake.c @@ -7,17 +7,14 @@ typedef struct unity_modcalls_s { void *target; - void(*ModUploadModel)(void *target, model_t *mdl, aliashdr_t *aliashdr, maliasframedesc_t *frames); + int(*UploadAliasModel)(void *target, char *name, aliashdr_t *aliashdr, maliasframedesc_t *frames, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts); } unity_modcalls_t; const unity_modcalls_t *unity_modcalls; -void Mod_UploadModel(model_t *mdl, aliashdr_t *aliashdr) +int UQ_GL_UploadAliasModel(char *name, aliashdr_t *aliashdr, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts) { // C# doesn't really understand this idea of a variable-length embedded array of structs, - // so we pass along the pointer to the first element which allows us to manually marshal the entire array. - if (aliashdr) - unity_modcalls->ModUploadModel(unity_modcalls->target, mdl, aliashdr, &aliashdr->frames[0]); - else - unity_modcalls->ModUploadModel(unity_modcalls->target, mdl, aliashdr, NULL); + // so we pass along the pointer to the first frame struct which allows us to manually marshal the entire array. + return unity_modcalls->UploadAliasModel(unity_modcalls->target, name, aliashdr, &aliashdr->frames[0], poseVerts, triangles, stVerts); }