diff --git a/Makefile b/Makefile index 9306473..c2e8017 100644 --- a/Makefile +++ b/Makefile @@ -350,6 +350,7 @@ REFVK_OBJS_ := \ src/vk/vk_warp.o \ src/vk/vk_util.o \ src/vk/volk/volk.o \ + src/files/models.o \ src/files/pcx.o \ src/files/stb.o \ src/files/wal.o \ diff --git a/src/common/header/ref_shared.h b/src/common/header/ref_shared.h index 918d834..bd9c1aa 100644 --- a/src/common/header/ref_shared.h +++ b/src/common/header/ref_shared.h @@ -75,4 +75,15 @@ extern void GetM8Info(char *name, int *width, int *height); extern float Mod_RadiusFromBounds(const vec3_t mins, const vec3_t maxs); extern const byte* Mod_DecompressVis(const byte *in, int row); + +/* Shared models load */ +typedef struct image_s* (*findimage_t)(char *name, imagetype_t type); +extern void *Mod_LoadMD2 (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); +extern void *Mod_LoadSP2 (const char *mod_name, const void *buffer, int modfilelen, + struct image_s **skins, findimage_t find_image, modtype_t *type); +extern int Mod_ReLoadSkins(struct image_s **skins, findimage_t find_image, + void *extradata, modtype_t type); + #endif /* SRC_CLIENT_REFRESH_REF_SHARED_H_ */ diff --git a/src/files/models.c b/src/files/models.c new file mode 100644 index 0000000..88dd9d3 --- /dev/null +++ b/src/files/models.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 1997-2001 Id Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * ======================================================================= + * + * The models file format + * + * ======================================================================= + */ + +#include "../common/header/ref_shared.h" + +/* +================= +Mod_LoadAliasModel/Mod_LoadMD2 +================= +*/ +void * +Mod_LoadMD2 (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) +{ + dmdl_t *pinmodel, *pheader; + dtriangle_t *pintri, *pouttri; + dstvert_t *pinst, *poutst; + int *pincmd, *poutcmd; + void *extradata; + int version; + int ofs_end; + int i, j; + + pinmodel = (dmdl_t *)buffer; + + version = LittleLong (pinmodel->version); + if (version != ALIAS_VERSION) + { + R_Printf(PRINT_ALL, "%s: %s has wrong version number (%i should be %i)", + __func__, mod_name, version, ALIAS_VERSION); + return NULL; + } + + ofs_end = LittleLong(pinmodel->ofs_end); + if (ofs_end < 0 || ofs_end > modfilelen) + { + R_Printf(PRINT_ALL, "%s: model %s file size(%d) too small, should be %d", + __func__, mod_name, modfilelen, ofs_end); + return NULL; + } + + extradata = Hunk_Begin(modfilelen); + pheader = Hunk_Alloc(ofs_end); + + // byte swap the header fields and sanity check + for (i=0 ; iskinheight > 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 (pheader->num_xyz <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no vertices", + __func__, mod_name); + return NULL; + } + + if (pheader->num_xyz > MAX_VERTS) + { + R_Printf(PRINT_ALL, "%s: model %s has too many vertices", + __func__, mod_name); + return NULL; + } + + if (pheader->num_st <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no st vertices", + __func__, mod_name); + return NULL; + } + + if (pheader->num_tris <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no triangles", + __func__, mod_name); + return NULL; + } + + if (pheader->num_frames <= 0) + { + R_Printf(PRINT_ALL, "%s: model %s has no frames", + __func__, mod_name); + return NULL; + } + + // + // 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); + } + + // + // 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]); + } + } + + // + // 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)); + } + + // + // 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]); + } + + // register all skins + memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, + pheader->num_skins*MAX_SKINNAME); + 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; +} + +/* +============================================================================== + +SPRITE MODELS + +============================================================================== +*/ + +/* +================= +Mod_LoadSP2 + +support for .sp2 sprites +==== +*/ +void * +Mod_LoadSP2 (const char *mod_name, const void *buffer, int modfilelen, + struct image_s **skins, findimage_t find_image, modtype_t *type) +{ + dsprite_t *sprin, *sprout; + void *extradata; + int i; + + sprin = (dsprite_t *)buffer; + extradata = Hunk_Begin(modfilelen); + sprout = Hunk_Alloc(modfilelen); + + sprout->ident = LittleLong(sprin->ident); + sprout->version = LittleLong(sprin->version); + sprout->numframes = LittleLong(sprin->numframes); + + if (sprout->version != SPRITE_VERSION) + { + R_Printf(PRINT_ALL, "%s has wrong version number (%i should be %i)", + mod_name, sprout->version, SPRITE_VERSION); + return NULL; + } + + if (sprout->numframes > MAX_MD2SKINS) + { + R_Printf(PRINT_ALL, "%s has too many frames (%i > %i)", + mod_name, sprout->numframes, MAX_MD2SKINS); + return NULL; + } + + /* byte swap everything */ + for (i = 0; i < sprout->numframes; i++) + { + sprout->frames[i].width = LittleLong(sprin->frames[i].width); + sprout->frames[i].height = LittleLong(sprin->frames[i].height); + sprout->frames[i].origin_x = LittleLong(sprin->frames[i].origin_x); + sprout->frames[i].origin_y = LittleLong(sprin->frames[i].origin_y); + memcpy(sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); + + skins[i] = find_image((char *)sprout->frames[i].name, it_sprite); + } + + *type = mod_sprite; + + return extradata; +} + +/* +================= +Mod_ReLoad + +Reload images in SP2/MD2 (mark registration_sequence) +================= +*/ +int +Mod_ReLoadSkins(struct image_s **skins, findimage_t find_image, void *extradata, + modtype_t type) +{ + if (type == mod_sprite) + { + dsprite_t *sprout; + int i; + + sprout = (dsprite_t *)extradata; + for (i=0 ; inumframes ; i++) + skins[i] = find_image (sprout->frames[i].name, it_sprite); + return sprout->numframes; + } + else if (type == mod_alias) + { + dmdl_t *pheader; + int i; + + pheader = (dmdl_t *)extradata; + for (i=0 ; inum_skins ; i++) + skins[i] = find_image ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); + return pheader->num_frames; + } + // Unknow format, no images associated with it + return 0; +} diff --git a/src/vk/vk_model.c b/src/vk/vk_model.c index b4fff8c..9eb4947 100644 --- a/src/vk/vk_model.c +++ b/src/vk/vk_model.c @@ -1007,229 +1007,6 @@ Mod_LoadBrushModel (model_t *loadmodel, const void *buffer, int modfilelen) Mod_LoadSubmodels (loadmodel, mod_base, &header->lumps[LUMP_MODELS]); } -/* -============================================================================== - -ALIAS MODELS - -============================================================================== -*/ - -/* -================= -Mod_LoadAliasModel -================= -*/ -static void -Mod_LoadAliasModel (model_t *mod, const void *buffer, int modfilelen) -{ - int i, j; - dmdl_t *pinmodel, *pheader; - dstvert_t *pinst, *poutst; - dtriangle_t *pintri, *pouttri; - int *pincmd, *poutcmd; - int version; - int ofs_end; - - pinmodel = (dmdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - { - ri.Sys_Error(ERR_DROP, "%s: %s has wrong version number (%i should be %i)", - __func__, mod->name, version, ALIAS_VERSION); - } - - ofs_end = LittleLong(pinmodel->ofs_end); - if (ofs_end < 0 || ofs_end > modfilelen) - { - ri.Sys_Error(ERR_DROP, "%s: model %s file size(%d) too small, should be %d", - __func__, mod->name, modfilelen, ofs_end); - } - - mod->extradata = Hunk_Begin(modfilelen); - pheader = Hunk_Alloc(ofs_end); - - // byte swap the header fields and sanity check - for (i=0 ; iskinheight > MAX_LBM_HEIGHT) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has a skin taller than %d", - __func__, mod->name, MAX_LBM_HEIGHT); - } - - if (pheader->num_xyz <= 0) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has no vertices", - __func__, mod->name); - } - - if (pheader->num_xyz > MAX_VERTS) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has too many vertices", - __func__, mod->name); - } - - if (pheader->num_st <= 0) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has no st vertices", - __func__, mod->name); - } - - if (pheader->num_tris <= 0) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has no triangles", - __func__, mod->name); - } - - if (pheader->num_frames <= 0) - { - ri.Sys_Error(ERR_DROP, "%s: model %s has no frames", - __func__, mod->name); - } - - // - // 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); - } - - // - // 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]); - } - } - - // - // 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->type = mod_alias; - - // - // 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]); - } - - // register all skins - memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, - pheader->num_skins*MAX_SKINNAME); - for (i=0 ; inum_skins ; i++) - { - mod->skins[i] = Vk_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME - , it_skin); - } - - mod->mins[0] = -32; - mod->mins[1] = -32; - mod->mins[2] = -32; - mod->maxs[0] = 32; - mod->maxs[1] = 32; - mod->maxs[2] = 32; -} - -/* -============================================================================== - -SPRITE MODELS - -============================================================================== -*/ - -/* -================= -Mod_LoadSpriteModel -================= -*/ -static void -Mod_LoadSpriteModel (model_t *mod, const void *buffer, int modfilelen) -{ - dsprite_t *sprin, *sprout; - int i; - - sprin = (dsprite_t *)buffer; - mod->extradata = Hunk_Begin(modfilelen); - sprout = Hunk_Alloc(modfilelen); - - sprout->ident = LittleLong (sprin->ident); - sprout->version = LittleLong (sprin->version); - sprout->numframes = LittleLong (sprin->numframes); - - if (sprout->version != SPRITE_VERSION) - { - ri.Sys_Error(ERR_DROP, "%s: %s has wrong version number (%i should be %i)", - __func__, mod->name, sprout->version, SPRITE_VERSION); - } - - if (sprout->numframes > MAX_MD2SKINS) - { - ri.Sys_Error(ERR_DROP, "%s: %s has too many frames (%i > %i)", - __func__, mod->name, sprout->numframes, MAX_MD2SKINS); - } - - // byte swap everything - for (i=0 ; inumframes ; i++) - { - sprout->frames[i].width = LittleLong (sprin->frames[i].width); - sprout->frames[i].height = LittleLong (sprin->frames[i].height); - sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x); - sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y); - memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); - mod->skins[i] = Vk_FindImage (sprout->frames[i].name, - it_sprite); - } - - mod->type = mod_sprite; -} - //============================================================================= /* @@ -1243,7 +1020,7 @@ static model_t * Mod_ForName (const char *name, model_t *parent_model, qboolean crash) { model_t *mod; - unsigned *buf; + void *buf; int i, modfilelen; if (!name[0]) @@ -1325,11 +1102,30 @@ Mod_ForName (const char *name, model_t *parent_model, qboolean crash) switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: - Mod_LoadAliasModel(mod, buf, modfilelen); + { + mod->extradata = Mod_LoadMD2(mod->name, buf, modfilelen, + mod->mins, mod->maxs, + (struct image_s **)mod->skins, (findimage_t)Vk_FindImage, + &(mod->type)); + if (!mod->extradata) + { + ri.Sys_Error(ERR_DROP, "%s: Failed to load %s", + __func__, mod->name); + } + }; break; case IDSPRITEHEADER: - Mod_LoadSpriteModel(mod, buf, modfilelen); + { + mod->extradata = Mod_LoadSP2(mod->name, buf, modfilelen, + (struct image_s **)mod->skins, (findimage_t)Vk_FindImage, + &(mod->type)); + if (!mod->extradata) + { + ri.Sys_Error(ERR_DROP, "%s: Failed to load %s", + __func__, mod->name); + } + } break; case IDBSPHEADER: @@ -1342,7 +1138,14 @@ Mod_ForName (const char *name, model_t *parent_model, qboolean crash) break; } - mod->extradatasize = Hunk_End (); + if (mod->extradata) + { + mod->extradatasize = Hunk_End (); + } + else + { + mod->extradatasize = 0; + } ri.FS_FreeFile(buf); @@ -1394,35 +1197,22 @@ struct model_s *RE_RegisterModel (char *name) mod = Mod_ForName (name, r_worldmodel, false); if (mod) { - int i; - mod->registration_sequence = registration_sequence; // register any images used by the models - if (mod->type == mod_sprite) + if (mod->type == mod_brush) { - dsprite_t *sprout; + int i; - sprout = (dsprite_t *)mod->extradata; - for (i=0 ; inumframes ; i++) - mod->skins[i] = Vk_FindImage (sprout->frames[i].name, it_sprite); - } - else if (mod->type == mod_alias) - { - dmdl_t *pheader; - - pheader = (dmdl_t *)mod->extradata; - for (i=0 ; inum_skins ; i++) - mod->skins[i] = Vk_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); -//PGM - mod->numframes = pheader->num_frames; -//PGM - } - else if (mod->type == mod_brush) - { for (i=0 ; inumtexinfo ; i++) mod->texinfo[i].image->registration_sequence = registration_sequence; } + else + { + /* numframes is unused for SP2 but lets set it also */ + mod->numframes = Mod_ReLoadSkins((struct image_s **)mod->skins, + (findimage_t)Vk_FindImage, mod->extradata, mod->type); + } } return mod; }