Browse Source

Pass along alias frame type and correctly count the total number of poses in a model, so that the correct number of pose vertices are marshaled and we can identify models that use group frame animations instead of typical single frames. Quake's model formats are weird.

console
Nico de Poel 5 years ago
parent
commit
428eebb941
  1. 18
      Assets/Scripts/Data/QModel.cs
  2. 8
      Assets/Scripts/Modules/AliasModel.cs
  3. 16
      Assets/Scripts/Modules/RenderModule.Interop.cs
  4. 12
      Assets/Scripts/Modules/RenderModule.cs
  5. 7
      engine/Quake/gl_model.c
  6. 2
      engine/Quake/gl_model.h
  7. 6
      engine/UniQuake/gl_uniquake.c

18
Assets/Scripts/Data/QModel.cs

@ -145,6 +145,24 @@ public enum QSyncType
Rand
}
/// <summary>
/// Managed equivalent of aliasframetype_t
/// </summary>
public enum QAliasFrameType
{
Single = 0,
Group,
}
/// <summary>
/// Managed equivalent of aliasskintype_t
/// </summary>
public enum QAliasSkinType
{
Single = 0,
Group,
}
/// <summary>
/// Managed equivalent of hull_t
/// </summary>

8
Assets/Scripts/Modules/AliasModel.cs

@ -8,11 +8,13 @@ public class AliasModel
private static readonly Regex AnimationRegex = new Regex(@"^[a-zA-Z]+");
private readonly string name;
private readonly QAliasFrameType frameType;
private readonly List<(int, Mesh)> animationMeshes = new List<(int, Mesh)>();
public AliasModel(string name)
public AliasModel(string name, QAliasFrameType frameType)
{
this.name = name;
this.frameType = frameType;
}
public int GetAnimationFrameCount(float frameNum)
@ -139,7 +141,7 @@ public class AliasModel
return;
Array.Resize(ref stVerts, header.numVerts + seamVertices.Count);
for (int frameIdx = 0; frameIdx < header.numFrames; ++frameIdx)
for (int frameIdx = 0; frameIdx < header.numPoses; ++frameIdx)
{
Array.Resize(ref poseVertices[frameIdx], header.numVerts + seamVertices.Count);
}
@ -172,7 +174,7 @@ public class AliasModel
stVerts[newVertIndex] = stVertCopy;
// Clone the vertex position data for all frames
for (int frameIdx = 0; frameIdx < header.numFrames; ++frameIdx)
for (int frameIdx = 0; frameIdx < header.numPoses; ++frameIdx)
{
QTriVertex triVertCopy = poseVertices[frameIdx][vertIndex];
poseVertices[frameIdx][newVertIndex] = triVertCopy;

16
Assets/Scripts/Modules/RenderModule.Interop.cs

@ -34,12 +34,12 @@ public partial class RenderModule: CallbackHandler<RenderModule>
[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);
QAliasHeader header, QAliasFrameType frameType, IntPtr frames,
[MarshalAs(UnmanagedType.LPArray, SizeConst = MaxAliasFrames)] IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts);
[MonoPInvokeCallback(typeof(UploadAliasModelCallback))]
private static int Callback_UploadAliasModel(IntPtr target,
string name, QAliasHeader header, IntPtr frames,
string name, QAliasHeader header, QAliasFrameType frameType, IntPtr frames,
IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts)
{
if (header == null)
@ -54,14 +54,20 @@ public partial class RenderModule: CallbackHandler<RenderModule>
if (frames != IntPtr.Zero)
header.frames = frames.ToStructArray<QAliasFrameDesc>(header.numFrames);
var poseVertices = new QTriVertex[header.numFrames][];
header.numPoses = 0;
for (int i = 0; i < header.numFrames; ++i)
{
header.numPoses += header.frames[i].numPoses;
}
var poseVertices = new QTriVertex[header.numPoses][];
for (int i = 0; i < header.numPoses; ++i)
{
poseVertices[i] = poseVerts[i].ToStructArray<QTriVertex>(header.numVerts);
}
return GetSelf(target).UploadAliasModel(
name, header, poseVertices,
name, header, frameType, poseVertices,
triangles.ToStructArray<QTriangle>(header.numTriangles),
stVerts.ToStructArray<QSTVert>(header.numVerts));
}

12
Assets/Scripts/Modules/RenderModule.cs

@ -27,13 +27,19 @@ public partial class RenderModule
private float xPos = -8f;
private int UploadAliasModel(string name, QAliasHeader header,
private int UploadAliasModel(string name, QAliasHeader header, QAliasFrameType frameType,
QTriVertex[][] poseVertices, QTriangle[] triangles, QSTVert[] stVertices)
{
Debug.Log($"Alias model '{name}' with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s)");
var sb = new System.Text.StringBuilder();
foreach (var frame in header.frames)
{
sb.AppendLine($"- {frame.name} ({frame.numPoses} poses)");
}
Debug.Log($"Alias model '{name}' (frame type {frameType}) with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s), {header.numPoses} pose(s):\n{sb}");
string modelName = System.IO.Path.GetFileNameWithoutExtension(name);
AliasModel aliasModel = new AliasModel(modelName);
AliasModel aliasModel = new AliasModel(modelName, frameType);
aliasModel.ImportMeshData(header, poseVertices, triangles, stVertices);
aliasModels.Add(aliasModel);

7
engine/Quake/gl_model.c

@ -2634,10 +2634,11 @@ void Mod_LoadAliasModel (qmodel_t *mod, void *buffer)
posenum = 0;
pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
aliasframetype_t frametype;
frametype = (aliasframetype_t)LittleLong(pframetype->type);
for (i=0 ; i<numframes ; i++)
{
aliasframetype_t frametype;
frametype = (aliasframetype_t) LittleLong (pframetype->type);
if (frametype == ALIAS_SINGLE)
pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
else
@ -2657,7 +2658,7 @@ void Mod_LoadAliasModel (qmodel_t *mod, void *buffer)
//
GL_MakeAliasModelDisplayLists (mod, pheader);
UQ_GL_UploadAliasModel(mod, pheader, poseverts, triangles, stverts);
UQ_GL_UploadAliasModel(mod, pheader, frametype, poseverts, triangles, stverts);
//
// move the complete, relocatable alias model to the cache

2
engine/Quake/gl_model.h

@ -516,7 +516,7 @@ byte *Mod_NoVisPVS (qmodel_t *model);
void Mod_SetExtraFlags (qmodel_t *mod);
int UQ_GL_UploadAliasModel(qmodel_t *model, aliashdr_t *aliashdr, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts);
int UQ_GL_UploadAliasModel(qmodel_t *model, aliashdr_t *aliashdr, aliasframetype_t frametype, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts);
int UQ_GL_UploadBrushModel(qmodel_t *model);
#endif // __MODEL__

6
engine/UniQuake/gl_uniquake.c

@ -7,17 +7,17 @@ typedef struct unity_glcalls_s
{
void *target;
int(*UploadAliasModel)(void *target, const char *name, aliashdr_t *aliashdr, maliasframedesc_t *frames, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts);
int(*UploadAliasModel)(void *target, const char *name, aliashdr_t *aliashdr, aliasframetype_t frametype, maliasframedesc_t *frames, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts);
int(*UploadBrushModel)(void *target, qmodel_t *model);
} unity_glcalls_t;
const unity_glcalls_t *unity_glcalls;
int UQ_GL_UploadAliasModel(qmodel_t *model, aliashdr_t *aliashdr, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts)
int UQ_GL_UploadAliasModel(qmodel_t *model, aliashdr_t *aliashdr, aliasframetype_t frametype, 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 frame struct which allows us to manually marshal the entire array.
return unity_glcalls->UploadAliasModel(unity_glcalls->target, model->name, aliashdr, &aliashdr->frames[0], poseVerts, triangles, stVerts);
return unity_glcalls->UploadAliasModel(unity_glcalls->target, model->name, aliashdr, frametype, &aliashdr->frames[0], poseVerts, triangles, stVerts);
}
int UQ_GL_UploadBrushModel(qmodel_t *model)

Loading…
Cancel
Save