From e20dd0a717d2732757d38b48ff3a8b7e064783af Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Mon, 23 Jan 2023 00:44:48 +0200 Subject: [PATCH] Add fm/heretic2 model support Save additional list of meshes between dmdl_t and list of skins. https://sourceforge.net/p/quark/code/HEAD/tree/runtime/trunk/plugins/ie_fm_import.py --- src/common/header/files.h | 19 ++ src/files/models.c | 481 +++++++++++++++++++++++++++++++++----- src/vk/vk_mesh.c | 215 +++++++++++------ src/vk/vk_model.c | 2 + 4 files changed, 583 insertions(+), 134 deletions(-) diff --git a/src/common/header/files.h b/src/common/header/files.h index aa5ea9c..c6e5c0f 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -184,6 +184,25 @@ typedef struct int ofs_end; /* end of file */ } dmdl_t; +/* .FM triangle model file format */ + +#define RAVENFMHEADER (('d'<<24)+('a'<<16)+('e'<<8)+'h') + +typedef struct +{ + int skinwidth; + int skinheight; + int framesize; /* byte size of each frame */ + + int num_skins; + int num_xyz; + int num_st; /* greater than num_xyz for seams */ + int num_tris; + int num_glcmds; /* dwords in strip/fan command list */ + int num_frames; + int num_mesh_nodes; +} fmheader_t; + /* .SP2 sprite file format */ #define IDSPRITEHEADER (('2' << 24) + ('S' << 16) + ('D' << 8) + 'I') /* little-endian "IDS2" */ diff --git a/src/files/models.c b/src/files/models.c index b0b979f..9c81ddb 100644 --- a/src/files/models.c +++ b/src/files/models.c @@ -26,6 +26,114 @@ #include "../common/header/ref_shared.h" +/* +================= +Mod_LoadSTvertList + +load base s and t vertices (not used in gl version) +================= +*/ +static void +Mod_LoadSTvertList (dmdl_t *pheader, dstvert_t *pinst) +{ + dstvert_t *poutst; + int i; + + poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); + + for (i=0 ; inum_st ; i++) + { + poutst[i].s = LittleShort (pinst[i].s); + poutst[i].t = LittleShort (pinst[i].t); + } +} + +/* +================= +Mod_LoadCmdList + +Load the glcmds +================= +*/ +static void +Mod_LoadCmdList (const char *mod_name, dmdl_t *pheader, int *pincmd) +{ + int *poutcmd; + int i; + + poutcmd = (int *)((char*)pheader + pheader->ofs_glcmds); + for (i = 0; i < pheader->num_glcmds; i++) + { + poutcmd[i] = LittleLong (pincmd[i]); + } + + if (poutcmd[pheader->num_glcmds-1] != 0) + { + R_Printf(PRINT_ALL, "%s: Entity %s has possible last element issues with %d verts.\n", + __func__, mod_name, poutcmd[pheader->num_glcmds-1]); + } +} + +/* +================= +Mod_LoadFrames + +Load the frames +================= +*/ +static void +Mod_LoadFrames (dmdl_t *pheader, byte *src) +{ + int i; + + for (i=0 ; inum_frames ; i++) + { + daliasframe_t *pinframe, *poutframe; + int j; + + pinframe = (daliasframe_t *) (src + i * pheader->framesize); + poutframe = (daliasframe_t *) ((byte *)pheader + + pheader->ofs_frames + i * pheader->framesize); + + memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name)); + for (j=0 ; j<3 ; j++) + { + poutframe->scale[j] = LittleFloat (pinframe->scale[j]); + poutframe->translate[j] = LittleFloat (pinframe->translate[j]); + } + // verts are all 8 bit, so no swapping needed + memcpy (poutframe->verts, pinframe->verts, + pheader->num_xyz*sizeof(dtrivertx_t)); + } +} + +/* +================= +Mod_LoadDTriangleList + +Load triangle lists +================= +*/ +static void +Mod_LoadDTriangleList (dmdl_t *pheader, dtriangle_t *pintri) +{ + dtriangle_t *pouttri; + int i; + + pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); + + for (i=0 ; inum_tris ; i++) + { + int j; + + for (j=0 ; j<3 ; j++) + { + pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]); + pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); + } + } +} + /* ================= Mod_LoadMDL @@ -332,7 +440,7 @@ Mod_LoadMDL (const char *mod_name, const void *buffer, int modfilelen, /* ================= -Mod_LoadAliasModel/Mod_LoadMD2 +Mod_LoadMD2 ================= */ static void * @@ -341,13 +449,13 @@ Mod_LoadMD2 (const char *mod_name, const void *buffer, int modfilelen, modtype_t *type) { dmdl_t *pinmodel, *pheader; - dtriangle_t *pintri, *pouttri; - dstvert_t *pinst, *poutst; - int *pincmd, *poutcmd; + dtriangle_t *pintri; + dstvert_t *pinst; + int *pincmd; void *extradata; int version; int ofs_end; - int i, j; + int i; pinmodel = (dmdl_t *)buffer; @@ -420,67 +528,24 @@ Mod_LoadMD2 (const char *mod_name, const void *buffer, int modfilelen, // load base s and t vertices (not used in gl version) // pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st); - poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); - - for (i=0 ; inum_st ; i++) - { - poutst[i].s = LittleShort (pinst[i].s); - poutst[i].t = LittleShort (pinst[i].t); - } + Mod_LoadSTvertList (pheader, pinst); // // load triangle lists // pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris); - pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); - - for (i=0 ; inum_tris ; i++) - { - for (j=0 ; j<3 ; j++) - { - pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]); - pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); - } - } + Mod_LoadDTriangleList (pheader, pintri); // // load the frames // - for (i=0 ; inum_frames ; i++) - { - daliasframe_t *pinframe, *poutframe; - - pinframe = (daliasframe_t *) ((byte *)pinmodel - + pheader->ofs_frames + i * pheader->framesize); - poutframe = (daliasframe_t *) ((byte *)pheader - + pheader->ofs_frames + i * pheader->framesize); - - memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name)); - for (j=0 ; j<3 ; j++) - { - poutframe->scale[j] = LittleFloat (pinframe->scale[j]); - poutframe->translate[j] = LittleFloat (pinframe->translate[j]); - } - // verts are all 8 bit, so no swapping needed - memcpy (poutframe->verts, pinframe->verts, - pheader->num_xyz*sizeof(dtrivertx_t)); - } + Mod_LoadFrames (pheader, (byte *)pinmodel + pheader->ofs_frames); // // load the glcmds // pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds); - poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); - for (i=0; i < pheader->num_glcmds; i++) - { - poutcmd[i] = LittleLong (pincmd[i]); - } - - if (poutcmd[pheader->num_glcmds-1] != 0) - { - R_Printf(PRINT_ALL, "%s: Entity %s has possible last element issues with %d verts.\n", - __func__, mod_name, poutcmd[pheader->num_glcmds-1]); - } + Mod_LoadCmdList (mod_name, pheader, pincmd); // register all skins memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, @@ -503,6 +568,292 @@ Mod_LoadMD2 (const char *mod_name, const void *buffer, int modfilelen, return extradata; } + +/* +============= +Mod_LoadFlexModel +============= +*/ +static void * +Mod_LoadFlexModel(const char *mod_name, const void *buffer, int modfilelen, + vec3_t mins, vec3_t maxs, struct image_s **skins, findimage_t find_image, + modtype_t *type) +{ + char *src = (char *)buffer; + int version, size, i; + void *extradata; + dmdl_t *pheader = NULL; + + while (modfilelen > 0) + { + char blockname[32]; + + memcpy(blockname, src, sizeof(blockname)); + + src += sizeof(blockname); + version = *(int*)src; + src += sizeof(version); + size = *(int*)src; + src += sizeof(size); + modfilelen = modfilelen - sizeof(blockname) - sizeof(version) - sizeof(size); + + if (Q_strncasecmp(blockname, "header", sizeof(blockname)) == 0) + { + dmdl_t dmdlheader; + fmheader_t *header = (fmheader_t *)src; + + if (sizeof(fmheader_t) > size) + { + R_Printf(PRINT_ALL, "%s: Too short header", __func__); + return NULL; + } + + if (version != 2) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + + /* copy back all values */ + dmdlheader.ident = IDALIASHEADER; + dmdlheader.version = ALIAS_VERSION; + dmdlheader.skinwidth = LittleLong (header->skinwidth); + dmdlheader.skinheight = LittleLong (header->skinheight); + dmdlheader.framesize = LittleLong (header->framesize); + + dmdlheader.num_skins = LittleLong (header->num_skins); + dmdlheader.num_xyz = LittleLong (header->num_xyz); + dmdlheader.num_st = LittleLong (header->num_st); + dmdlheader.num_tris = LittleLong (header->num_tris); + dmdlheader.num_glcmds = LittleLong (header->num_glcmds); + dmdlheader.num_frames = LittleLong (header->num_frames); + + // just skip header and meshes + dmdlheader.ofs_skins = sizeof(dmdl_t) + sizeof(short) * 2 * LittleLong (header->num_mesh_nodes); + dmdlheader.ofs_st = dmdlheader.ofs_skins + dmdlheader.num_skins * MAX_SKINNAME; + dmdlheader.ofs_tris = dmdlheader.ofs_st + dmdlheader.num_st * sizeof(dstvert_t); + dmdlheader.ofs_frames = dmdlheader.ofs_tris + dmdlheader.num_tris * sizeof(dtriangle_t); + dmdlheader.ofs_glcmds = dmdlheader.ofs_frames + dmdlheader.num_frames * dmdlheader.framesize; + dmdlheader.ofs_end = dmdlheader.ofs_glcmds + dmdlheader.num_glcmds * sizeof(int); + + if (dmdlheader.skinheight > MAX_LBM_HEIGHT) + { + R_Printf(PRINT_ALL, "%s: model %s has a skin taller than %d", + __func__, mod_name, MAX_LBM_HEIGHT); + return NULL; + } + + if (dmdlheader.num_xyz <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no vertices", + __func__, mod_name); + return NULL; + } + + if (dmdlheader.num_xyz > MAX_VERTS) + { + R_Printf(PRINT_ALL, "%s: model %s has too many vertices", + __func__, mod_name); + return NULL; + } + + if (dmdlheader.num_st <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no st vertices", + __func__, mod_name); + return NULL; + } + + if (dmdlheader.num_tris <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no triangles", + __func__, mod_name); + return NULL; + } + + if (dmdlheader.num_frames <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no frames", + __func__, mod_name); + return NULL; + } + + extradata = Hunk_Begin(dmdlheader.ofs_end); + pheader = Hunk_Alloc(dmdlheader.ofs_end); + + memcpy(pheader, &dmdlheader, sizeof(dmdl_t)); + } + else { + if (!pheader) + { + R_Printf(PRINT_ALL, "%s: %s has broken header.", + __func__, mod_name); + return NULL; + } + else if (Q_strncasecmp(blockname, "skin", sizeof(blockname)) == 0) + { + if (version != 1) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + if (size != (pheader->num_skins * MAX_SKINNAME)) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + memcpy((char*) pheader + pheader->ofs_skins, src, size); + } + else if (Q_strncasecmp(blockname, "st coord", sizeof(blockname)) == 0) + { + if (version != 1) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + if (size != (pheader->num_st * sizeof(dstvert_t))) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + + Mod_LoadSTvertList (pheader, (dstvert_t *)src); + } + else if (Q_strncasecmp(blockname, "tris", sizeof(blockname)) == 0) + { + if (version != 1) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + if (size != (pheader->num_tris * sizeof(dtriangle_t))) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + + Mod_LoadDTriangleList (pheader, (dtriangle_t *) src); + } + else if (Q_strncasecmp(blockname, "frames", sizeof(blockname)) == 0) + { + if (version != 1) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + if (size != (pheader->num_frames * pheader->framesize)) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + + Mod_LoadFrames (pheader, (byte *)src); + } + else if (Q_strncasecmp(blockname, "glcmds", sizeof(blockname)) == 0) + { + if (version != 1) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + if (size != (pheader->num_glcmds * sizeof(int))) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + + Mod_LoadCmdList (mod_name, pheader, (int *)src); + } + else if (Q_strncasecmp(blockname, "mesh nodes", sizeof(blockname)) == 0) + { + int num_mesh_nodes; + + num_mesh_nodes = (pheader->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2; + + if (version != 3) + { + R_Printf(PRINT_ALL, "%s: Invalid %s version %d", + __func__, blockname, version); + return NULL; + } + /* 516 mesh node size */ + if (size != (num_mesh_nodes * 516)) + { + R_Printf(PRINT_ALL, "%s: Invalid %s size", + __func__, blockname); + return NULL; + } + + if (num_mesh_nodes > 0) + { + short *mesh_nodes; + char *in_mesh = src; + int i; + + mesh_nodes = (short *)((char*)pheader + sizeof(dmdl_t)); + for (i = 0; i < num_mesh_nodes; i++) + { + /* 256 bytes of tri data */ + /* 256 bytes of vert data */ + /* 2 bytes of start */ + /* 2 bytes of number commands */ + in_mesh += 512; + mesh_nodes[i * 2] = LittleShort(*(short *)in_mesh); + in_mesh += 2; + mesh_nodes[i * 2 + 1] = LittleShort(*(short *)in_mesh); + in_mesh += 2; + } + } + } + else if (Q_strncasecmp(blockname, "normals", sizeof(blockname)) == 0 || + Q_strncasecmp(blockname, "short frames", sizeof(blockname)) == 0 || + Q_strncasecmp(blockname, "comp data", sizeof(blockname)) == 0 || + Q_strncasecmp(blockname, "skeleton", sizeof(blockname)) == 0 || + Q_strncasecmp(blockname, "references", sizeof(blockname)) == 0) + { + /* skipped block */ + } + else + { + R_Printf(PRINT_ALL, "%s: %s Unknown block %s\n", + __func__, mod_name, blockname); + return NULL; + } + } + modfilelen -= size; + src += size; + } + + // Load in our skins. + for (i=0 ; inum_skins ; i++) + { + skins[i] = find_image((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, + it_skin); + } + + *type = mod_alias; + + mins[0] = -32; + mins[1] = -32; + mins[2] = -32; + maxs[0] = 32; + maxs[1] = 32; + maxs[2] = 32; + + return extradata; +} + /* ================= Mod_LoadAliasModel @@ -515,14 +866,17 @@ Mod_LoadAliasModel (const char *mod_name, const void *buffer, int modfilelen, { switch (LittleLong(*(unsigned *)buffer)) { - case IDALIASHEADER: - return Mod_LoadMD2(mod_name, buffer, modfilelen, mins, maxs, skins, - find_image, type); + case RAVENFMHEADER: + return Mod_LoadFlexModel(mod_name, buffer, modfilelen, mins, maxs, skins, + find_image, type); - case IDMDLHEADER: - return Mod_LoadMDL(mod_name, buffer, modfilelen, mins, maxs, skins, - find_image, type); + case IDALIASHEADER: + return Mod_LoadMD2(mod_name, buffer, modfilelen, mins, maxs, skins, + find_image, type); + case IDMDLHEADER: + return Mod_LoadMDL(mod_name, buffer, modfilelen, mins, maxs, skins, + find_image, type); } return NULL; @@ -615,7 +969,8 @@ Mod_LoadFile(char *name, void **buffer) return -1; } - if (!strcmp(ext, "md2") || + if (!strcmp(ext, "fm") || + !strcmp(ext, "md2") || !strcmp(ext, "mdl")) { char namewe[256], newname[256]; @@ -631,6 +986,14 @@ Mod_LoadFile(char *name, void **buffer) memset(namewe, 0, 256); memcpy(namewe, name, len - (strlen(ext) + 1)); + /* Check Heretic2 model */ + snprintf(newname, sizeof(newname), "%s.fm", namewe); + filesize = ri.FS_LoadFile (newname, buffer); + if (filesize > 0) + { + return filesize; + } + /* Check Quake 2 model */ snprintf(newname, sizeof(newname), "%s.md2", namewe); filesize = ri.FS_LoadFile (newname, buffer); diff --git a/src/vk/vk_mesh.c b/src/vk/vk_mesh.c index e9a2ea6..f59807d 100644 --- a/src/vk/vk_mesh.c +++ b/src/vk/vk_mesh.c @@ -268,73 +268,11 @@ static void Vk_LerpVerts( int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx } -/* -============= -Vk_DrawAliasFrameLerp - -interpolates between two frames and origins -FIXME: batch lerp all vertexes -============= -*/ -static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *skin, float *modelMatrix, int leftHandOffset, int translucentIdx, entity_t *currententity) +static void +Vk_DrawAliasFrameLerpCommands (entity_t *currententity, int *order, int *order_end, + float alpha, image_t *skin, float *modelMatrix, int leftHandOffset, int translucentIdx, + dtrivertx_t *verts) { - daliasframe_t *frame, *oldframe; - dtrivertx_t *v, *ov, *verts; - int *order; - float frontlerp; - float alpha; - vec3_t move, delta, vectors[3]; - vec3_t frontv, backv; - int i; - float *lerp; - - frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames - + currententity->frame * paliashdr->framesize); - verts = v = frame->verts; - - oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames - + currententity->oldframe * paliashdr->framesize); - ov = oldframe->verts; - - order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); - - if (currententity->flags & RF_TRANSLUCENT) - alpha = currententity->alpha; - else - alpha = 1.0; - - frontlerp = 1.0 - backlerp; - - // move should be the delta back to the previous frame * backlerp - VectorSubtract (currententity->oldorigin, currententity->origin, delta); - AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]); - - move[0] = DotProduct (delta, vectors[0]); // forward - move[1] = -DotProduct (delta, vectors[1]); // left - move[2] = DotProduct (delta, vectors[2]); // up - - VectorAdd (move, oldframe->translate, move); - - for (i=0 ; i<3 ; i++) - { - move[i] = backlerp*move[i] + frontlerp*frame->translate[i]; - } - - for (i=0 ; i<3 ; i++) - { - frontv[i] = frontlerp*frame->scale[i]; - backv[i] = backlerp*oldframe->scale[i]; - } - - if (Mesh_VertsRealloc(paliashdr->num_xyz)) - { - ri.Sys_Error(ERR_FATAL, "%s: can't allocate memory", __func__); - } - - lerp = s_lerped[0]; - - Vk_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv, currententity ); - int vertCounts[2] = { 0, 0 }; int pipeCounters[2] = { 0, 0 }; VkDeviceSize maxTriangleFanIdxCnt = 0; @@ -358,8 +296,11 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s // get the vertex count and primitive type count = *order++; - if (!count) - break; // done + if (!count || order >= order_end) + { + break; /* done */ + } + if (count < 0) { count = -count; @@ -489,6 +430,8 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s if (p == TRIANGLE_STRIP) { + int i; + vkCmdBindIndexBuffer(vk_activeCmdbuffer, QVk_GetTriangleStripIbo(maxTriangleFanIdxCnt), 0, VK_INDEX_TYPE_UINT16); for (i = 0; i < pipeCounters[p]; i++) @@ -498,6 +441,8 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s } else { + int i; + vkCmdBindIndexBuffer(vk_activeCmdbuffer, QVk_GetTriangleFanIbo(maxTriangleFanIdxCnt), 0, VK_INDEX_TYPE_UINT16); for (i = 0; i < pipeCounters[p]; i++) @@ -508,15 +453,109 @@ static void Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *s } } +/* +============= +Vk_DrawAliasFrameLerp + +interpolates between two frames and origins +FIXME: batch lerp all vertexes +============= +*/ +static void +Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *skin, + float *modelMatrix, int leftHandOffset, int translucentIdx, entity_t *currententity) +{ + daliasframe_t *frame, *oldframe; + dtrivertx_t *v, *ov, *verts; + int *order; + float frontlerp; + float alpha; + vec3_t move, delta, vectors[3]; + vec3_t frontv, backv; + int i; + float *lerp; + int num_mesh_nodes; + short *mesh_nodes; + + frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + + currententity->frame * paliashdr->framesize); + verts = v = frame->verts; + + oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + + currententity->oldframe * paliashdr->framesize); + ov = oldframe->verts; + + order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); + + if (currententity->flags & RF_TRANSLUCENT) + alpha = currententity->alpha; + else + alpha = 1.0; + + frontlerp = 1.0 - backlerp; + + // move should be the delta back to the previous frame * backlerp + VectorSubtract (currententity->oldorigin, currententity->origin, delta); + AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]); + + move[0] = DotProduct (delta, vectors[0]); // forward + move[1] = -DotProduct (delta, vectors[1]); // left + move[2] = DotProduct (delta, vectors[2]); // up + + VectorAdd (move, oldframe->translate, move); + + for (i=0 ; i<3 ; i++) + { + move[i] = backlerp*move[i] + frontlerp*frame->translate[i]; + } + + for (i=0 ; i<3 ; i++) + { + frontv[i] = frontlerp*frame->scale[i]; + backv[i] = backlerp*oldframe->scale[i]; + } + + if (Mesh_VertsRealloc(paliashdr->num_xyz)) + { + ri.Sys_Error(ERR_FATAL, "%s: can't allocate memory", __func__); + } + + lerp = s_lerped[0]; + + Vk_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv, currententity ); + + num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2; + mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t)); + + if (num_mesh_nodes > 0) + { + int i; + for (i = 0; i < num_mesh_nodes; i++) + { + Vk_DrawAliasFrameLerpCommands(currententity, + order + mesh_nodes[i * 2], + order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]), + alpha, skin, + modelMatrix, leftHandOffset, translucentIdx, verts); + } + } + else + { + Vk_DrawAliasFrameLerpCommands(currententity, + order, order + paliashdr->num_glcmds, alpha, skin, + modelMatrix, leftHandOffset, translucentIdx, verts); + } +} + /* ============= Vk_DrawAliasShadow ============= */ -static void Vk_DrawAliasShadow (dmdl_t *paliashdr, int posenum, float *modelMatrix, entity_t *currententity) +static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum, + float *modelMatrix, entity_t *currententity) { - int *order; vec3_t point; float height, lheight; @@ -524,8 +563,6 @@ static void Vk_DrawAliasShadow (dmdl_t *paliashdr, int posenum, float *modelMatr height = 0; - order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); - height = -lheight + 1.0; uint32_t uboOffset; @@ -541,8 +578,11 @@ static void Vk_DrawAliasShadow (dmdl_t *paliashdr, int posenum, float *modelMatr i = 0; // get the vertex count and primitive type count = *order++; - if (!count) - break; // done + if (!count || order >= order_end) + { + break; /* done */ + } + if (count < 0) { count = -count; @@ -988,9 +1028,34 @@ void R_DrawAliasModel (entity_t *currententity, model_t *currentmodel) if (vk_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL))) { + int num_mesh_nodes; + short *mesh_nodes; float model[16]; + int *order; + Mat_Identity(model); R_RotateForEntity(currententity, model); - Vk_DrawAliasShadow (paliashdr, currententity->frame, model, currententity); + + order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); + + num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2; + mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t)); + + if (num_mesh_nodes > 0) + { + int i; + for (i = 0; i < num_mesh_nodes; i++) + { + Vk_DrawAliasShadow ( + order + mesh_nodes[i * 2], + order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]), + currententity->frame, model, currententity); + } + } + else + { + Vk_DrawAliasShadow (order, order + paliashdr->num_glcmds, + currententity->frame, model, currententity); + } } } diff --git a/src/vk/vk_model.c b/src/vk/vk_model.c index 471a46a..3b70e19 100644 --- a/src/vk/vk_model.c +++ b/src/vk/vk_model.c @@ -751,6 +751,8 @@ Mod_ForName (const char *name, model_t *parent_model, qboolean crash) switch (LittleLong(*(unsigned *)buf)) { + case RAVENFMHEADER: + /* fall through */ case IDALIASHEADER: /* fall through */ case IDMDLHEADER: