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);
}