diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 2ed218e84..a79e05904 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -576,6 +576,7 @@ file( GLOB HEADER_FILES core/input/*.h core/rendering/*.h core/rendering/scene/*.h + core/models/*.h common/audio/sound/thirdparty/*.h common/audio/sound/*.h @@ -630,6 +631,7 @@ file( GLOB HEADER_FILES thirdparty/include/*.hpp thirdparty/imgui/*.h core/textures/*.h + core/models/*.h core/textures/formats/*.h ) @@ -1028,6 +1030,7 @@ set (PCH_SOURCES core/rendering/scene/hw_lighting.cpp core/r_data/gldefs.cpp + core/models/modeldata.cpp core/console/c_notifybuffer.cpp core/console/d_event.cpp @@ -1501,6 +1504,7 @@ source_group("Core\\2D" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/2d source_group("Core\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/console/.+") source_group("Core\\DObject" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/dobject/.+") source_group("Core\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/menu/.+") +source_group("Core\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/models/.+") source_group("Core\\Rendering" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/rendering/.+") source_group("Core\\Rendering\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/rendering/scene/.+") source_group("Platform" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/platform/.+") diff --git a/source/build/include/build.h b/source/build/include/build.h index feedd47cc..011ae73d6 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -25,11 +25,8 @@ typedef int64_t coord_t; enum { - MAXVOXMIPS = 5, - MAXWALLSB = 6144, - MAXVOXELS = 1024, // Maximum number of component tiles in a multi-psky: MAXUNIQHUDID = 256, //Extra slots so HUD models can store animation state without messing game sprites @@ -102,8 +99,6 @@ inline int32_t randomseed; inline uint8_t paletteloaded; inline int32_t g_visibility = 512, g_relvisibility = 0; inline int32_t enginecompatibility_mode; -inline int32_t nextvoxid; -inline FixedBitArrayvoxreserve; void setVideoMode(); @@ -142,62 +137,9 @@ extern bool hw_int_useindexedcolortextures; EXTERN_CVAR(Bool, hw_useindexedcolortextures) EXTERN_CVAR(Bool, r_voxels) -extern int32_t mdtims, omdtims; -extern int32_t r_rorphase; - -// flags bitset: 1 = don't compress -int32_t Ptile2tile(int32_t tile, int32_t palette) ATTRIBUTE((pure)); -int32_t md_loadmodel(const char *fn); -int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags); -// int32_t md_tilehasmodel(int32_t tilenume, int32_t pal); - - -#ifdef USE_OPENGL -// TODO: dynamically allocate this - -typedef struct { FVector3 add; int16_t angadd, flags, fov; } hudtyp; - -typedef struct -{ - // maps build tiles to particular animation frames of a model - int16_t modelid; - int16_t framenum; // calculate the number from the name when declaring - int16_t nexttile; - uint16_t smoothduration; - hudtyp hudmem[2]; - int8_t skinnum; - uint8_t pal; -} tile2model_t; - -# define EXTRATILES (MAXTILES/8) - -inline int32_t mdinited; -inline tile2model_t tile2model[MAXTILES+EXTRATILES]; - -inline int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal) -{ - return mdinited ? tile2model[Ptile2tile(tilenume,pal)].modelid : -1; -} -#endif // defined USE_OPENGL - -int tilehasmodelorvoxel(int const tilenume, int pal); - -int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, - int32_t skinnum, float smoothduration, int32_t pal); -int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, - int32_t fps, int32_t flags); -int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, - int32_t surfnum, float param, float specpower, float specfactor, int32_t flags); -int32_t md_definehud (int32_t modelid, int32_t tilex, FVector3 add, - int32_t angadd, int32_t flags, int32_t fov); -int32_t md_undefinetile(int32_t tile); -int32_t md_undefinemodel(int32_t modelid); - static inline int64_t compat_maybe_truncate_to_int32(int64_t val) { return enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? (int32_t)val : val; } -void updateModelInterpolation(); - #endif // build_h_ diff --git a/source/build/include/mdsprite.h b/source/build/include/mdsprite.h index 9d6de6182..e69de29bb 100644 --- a/source/build/include/mdsprite.h +++ b/source/build/include/mdsprite.h @@ -1,200 +0,0 @@ -#ifndef mdsprite_h_ -# define mdsprite_h_ - -#ifdef USE_OPENGL -#include "palette.h" -#include "gl_hwtexture.h" -#include "model_kvx.h" - -#if defined(_M_IX86) || defined(_M_AMD64) || defined(__i386) || defined(__x86_64) -#define SHIFTMOD32(a) (a) -#else -#define SHIFTMOD32(a) ((a)&31) -#endif - -#define IDP2_MAGIC 0x32504449 -#define IDP3_MAGIC 0x33504449 - -class FGameTexture; - -struct mdmodel_t -{ - - int32_t mdnum, shadeoff; - float scale, bscale, zadd, yoffset; - FGameTexture *texture; - - int32_t flags; -}; - -struct mdanim_t -{ - int32_t startframe, endframe; - int32_t fpssc, flags; - mdanim_t* next; -}; - -struct mdskinmap_t -{ - uint8_t palette, flags, filler[2]; // Build palette number, flags the same as hightiles - int32_t skinnum, surfnum; // Skin identifier, surface number - FTextureID texture; - mdskinmap_t* next; - float param, specpower, specfactor; -}; - -struct idmodel_t : public mdmodel_t -{ - int32_t numframes, cframe, nframe, fpssc, usesalpha; - float oldtime, curtime, interpol; - mdanim_t *animations; - mdskinmap_t *skinmap; - int32_t numskins, skinloaded; -}; - -#define MDANIM_LOOP 0 -#define MDANIM_ONESHOT 1 - - - -//This MD2 code is based on the source code from David Henry (tfc_duke(at)hotmail.com) -// Was at http://tfc.duke.free.fr/us/tutorials/models/md2.htm -// Available from http://web.archive.org/web/20030816010242/http://tfc.duke.free.fr/us/tutorials/models/md2.htm -// Now at http://tfc.duke.free.fr/coding/md2.html (in French) -//He probably wouldn't recognize it if he looked at it though :) - -typedef struct -{ - int32_t id, vers, skinxsiz, skinysiz, framebytes; //id:"IPD2", vers:8 - int32_t numskins, numverts, numuv, numtris, numglcmds, numframes; - int32_t ofsskins, ofsuv, ofstris, ofsframes, ofsglcmds, ofseof; //ofsskins: skin names (64 bytes each) -} md2head_t; - -typedef struct { uint8_t v[3], ni; } md2vert_t; //compressed vertex coords (x,y,z) -typedef struct -{ - FVector3 mul, add; //scale&translation vector - char name[16]; //frame name - md2vert_t verts[1]; //first vertex of this frame -} md2frame_t; - -typedef struct { int16_t u, v; } md2uv_t; -typedef struct -{ - uint16_t v[3]; - uint16_t u[3]; -} md2tri_t; - -struct md2model_t : public idmodel_t -{ - //MD2 specific stuff: - int32_t numverts, numglcmds, framebytes, *glcmds; - char *frames; - char *basepath; // pointer to string of base path - char *skinfn; // pointer to first of numskins 64-char strings - md2uv_t *uv; - md2tri_t* tris; -}; - - -typedef struct { char nam[64]; int32_t i; } md3shader_t; //ascz path of shader, shader index -typedef struct { int32_t i[3]; } md3tri_t; //indices of tri -typedef struct { float u, v; } md3uv_t; -typedef struct { int16_t x, y, z; uint8_t nlat, nlng; } md3xyzn_t; //xyz are [10:6] ints - -typedef struct -{ - FVector3 min, max, cen; //bounding box&origin - float r; //radius of bounding sphere - char nam[16]; //ascz frame name -} md3frame_t; - -typedef struct -{ - char nam[64]; //ascz tag name - FVector3 p, x, y, z; //tag object pos&orient -} md3tag_t; - -typedef struct -{ - int32_t id; //IDP3(0x33806873) - char nam[64]; //ascz surface name - int32_t flags; //? - int32_t numframes, numshaders, numverts, numtris; //numframes same as md3head,max shade=~256,vert=~4096,tri=~8192 - int32_t ofstris; - int32_t ofsshaders; - int32_t ofsuv; - int32_t ofsxyzn; - int32_t ofsend; - // DO NOT read directly to this structure - // the following block is NOT in the file format - // be sure to use the SIZEOF_MD3SURF_T macro - md3tri_t *tris; - md3shader_t *shaders; - md3uv_t *uv; - md3xyzn_t *xyzn; - float *geometry; // used by Polymer -} md3surf_t; - -#define SIZEOF_MD3SURF_T (11*sizeof(int32_t) + 64*sizeof(char)) - -typedef struct -{ - int32_t id, vers; //id=IDP3(0x33806873), vers=15 - char nam[64]; //ascz path in PK3 - int32_t flags; //? - int32_t numframes, numtags, numsurfs, numskins; //max=~1024,~16,~32,numskins=artifact of MD2; use shader field instead - int32_t ofsframes; - int32_t ofstags; - int32_t ofssurfs; - int32_t eof; - // DO NOT read directly to this structure - // the following block is NOT in the file format - // be sure to use the SIZEOF_MD3HEAD_T macro - md3frame_t *frames; - md3tag_t *tags; - md3surf_t *surfs; -} md3head_t; - -#define SIZEOF_MD3HEAD_T (sizeof(md3head_t)-3*sizeof(void*)) - -struct md3model_t : public idmodel_t -{ - - //MD3 specific - md3head_t head; - FVector3 *muladdframes; - - uint16_t *indexes; - uint16_t *vindexes; - - float *maxdepths; - // polymer VBO names after that, allocated per surface - /* - GLuint *indices; - GLuint *texcoords; - GLuint *geometry; - */ -}; - -inline mdmodel_t **models; - -FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact); -void mdinit(void); -void freeallmodels(void); -int32_t polymost_mddraw(tspritetype* tspr); -void md3_vox_calcmat_common(tspritetype* tspr, const FVector3 *a0, float f, float mat[16]); - -inline int32_t mdpause; -inline int32_t nextmodelid; - -#endif // defined USE_OPENGL - -enum { - HUDFLAG_HIDE = 1, - HUDFLAG_NOBOB = 2, - HUDFLAG_FLIPPED = 4, - HUDFLAG_NODEPTH = 8, -}; - -#endif // !mdsprite_h_ diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index 5b7e27529..e69de29bb 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -1,1048 +0,0 @@ -//------------------------------------- MD2/MD3 LIBRARY BEGINS ------------------------------------- - -#ifdef USE_OPENGL - -#include "build.h" -#include "mdsprite.h" -#include "coreactor.h" - -#include "palette.h" -#include "textures.h" -#include "bitmap.h" -#include "v_video.h" -#include "flatvertices.h" -#include "texturemanager.h" -#include "hw_renderstate.h" -#include "printf.h" -#include "hw_voxels.h" - -int32_t mdtims, omdtims; - -#ifdef _MSC_VER -// just make it shut up. Most of this file will go down the drain anyway soon. -#pragma warning(disable:4244) -#pragma warning(disable:4267) -#endif - -static int32_t curextra=MAXTILES; - -#define MIN_CACHETIME_PRINT 10 - -static int32_t addtileP(int32_t ,int32_t tile,int32_t pallet) -{ - // tile >= 0 && tile < MAXTILES - - if (curextra==MAXTILES+EXTRATILES-1) - { - Printf("warning: max EXTRATILES reached\n"); - return curextra; - } - - if (tile2model[tile].modelid==-1) - { - tile2model[tile].pal=pallet; - return tile; - } - - if (tile2model[tile].pal==pallet) - return tile; - - while (tile2model[tile].nexttile!=-1) - { - tile=tile2model[tile].nexttile; - if (tile2model[tile].pal==pallet) - return tile; - } - - tile2model[tile].nexttile=curextra; - tile2model[curextra].pal=pallet; - - return curextra++; -} - -int32_t Ptile2tile(int32_t tile,int32_t palette) -{ - int t = tile; - while ((tile = tile2model[tile].nexttile) != -1) - if (tile2model[tile].pal == palette) - { - t = tile; - break; - } - return t; -} - -#define MODELALLOCGROUP 256 -static int32_t nummodelsalloced = 0; - -static int32_t maxmodelverts = 0, allocmodelverts = 0; -static int32_t maxmodeltris = 0, allocmodeltris = 0; -static FVector3 *vertlist = NULL; //temp array to store interpolated vertices for drawing - -#ifdef USE_GLEXT -static int32_t allocvbos = 0, curvbo = 0; -static GLuint *vertvbos = NULL; -static GLuint *indexvbos = NULL; -#endif - -#ifdef POLYMER -static int32_t *tribuf = NULL; -static int32_t tribufverts = 0; -#endif - -static mdmodel_t *mdload(const char *); -static void mdfree(mdmodel_t *); -static int32_t globalnoeffect=0; - -void freeallmodels() -{ - int32_t i; - - if (models) - { - for (i=0; i= nummodelsalloced) - { - ml = (mdmodel_t **)M_Realloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *)); - models = ml; nummodelsalloced += MODELALLOCGROUP; - } - - vm = mdload(fn); if (!vm) return -1; - models[nextmodelid++] = vm; - return nextmodelid-1; -} - -int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags) -{ - mdmodel_t *m; - - if (!mdinited) mdinit(); - - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - m = models[modelid]; - m->bscale = scale; - m->shadeoff = shadeoff; - m->zadd = zadd; - m->yoffset = yoffset; - m->flags = flags; - - return 0; -} - -static int32_t framename2index(mdmodel_t *vm, const char *nam) -{ - int32_t i = 0; - - switch (vm->mdnum) - { - case 2: - { - md2model_t *m = (md2model_t *)vm; - md2frame_t *fr; - for (i=0; inumframes; i++) - { - fr = (md2frame_t *)&m->frames[i*m->framebytes]; - if (!strcmp(fr->name, nam)) break; - } - } - break; - case 3: - { - md3model_t *m = (md3model_t *)vm; - for (i=0; inumframes; i++) - if (!strcmp(m->head.frames[i].nam,nam)) break; - } - break; - } - return i; -} - -int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal) -{ - md2model_t *m; - int32_t i; - - if (!mdinited) mdinit(); - - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - if ((uint32_t)tilenume >= (uint32_t)MAXTILES) return -2; - if (!framename) return -3; - - tilenume=addtileP(modelid,tilenume,pal); - m = (md2model_t *)models[modelid]; - if (m->mdnum == 1) - { - tile2model[tilenume].modelid = modelid; - tile2model[tilenume].framenum = tile2model[tilenume].skinnum = 0; - return 0; - } - - i = framename2index((mdmodel_t *)m,framename); - if (i == m->numframes) return -3; // frame name invalid - - tile2model[tilenume].modelid = modelid; - tile2model[tilenume].framenum = i; - tile2model[tilenume].skinnum = skinnum; - tile2model[tilenume].smoothduration = xs_CRoundToInt((float)UINT16_MAX * smoothduration); - - return i; -} - -int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags) -{ - md2model_t *m; - mdanim_t ma, *map; - int32_t i; - - if (!mdinited) mdinit(); - - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - - memset(&ma, 0, sizeof(ma)); - m = (md2model_t *)models[modelid]; - if (m->mdnum < 2) return 0; - - //find index of start frame - i = framename2index((mdmodel_t *)m,framestart); - if (i == m->numframes) return -2; - ma.startframe = i; - - //find index of finish frame which must trail start frame - i = framename2index((mdmodel_t *)m,frameend); - if (i == m->numframes) return -3; - ma.endframe = i; - - ma.fpssc = fpssc; - ma.flags = flags; - - map = (mdanim_t *)M_Malloc(sizeof(mdanim_t)); - - memcpy(map, &ma, sizeof(ma)); - - map->next = m->animations; - m->animations = map; - - return 0; -} - -int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor, int32_t flags) -{ - mdskinmap_t *sk, *skl; - md2model_t *m; - - if (!mdinited) mdinit(); - - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - if (!skinfn) return -2; - if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3; - - m = (md2model_t *)models[modelid]; - if (m->mdnum < 2) return 0; - if (m->mdnum == 2) surfnum = 0; - - skl = NULL; - for (sk = m->skinmap; sk; skl = sk, sk = sk->next) - if (sk->palette == (uint8_t)palnum && skinnum == sk->skinnum && surfnum == sk->surfnum) - break; - if (!sk) - { - sk = (mdskinmap_t *)M_Calloc(1,sizeof(mdskinmap_t)); - - if (!skl) m->skinmap = sk; - else skl->next = sk; - } - - sk->palette = (uint8_t)palnum; - sk->flags = (uint8_t)flags; - sk->skinnum = skinnum; - sk->surfnum = surfnum; - sk->param = param; - sk->specpower = specpower; - sk->specfactor = specfactor; - sk->texture = TexMan.CheckForTexture(skinfn, ETextureType::Any); - if (!sk->texture.isValid()) - { - Printf("Unable to load %s as model skin\n", skinfn); - } - - return 0; -} - -int32_t md_definehud(int32_t modelid, int32_t tilex, FVector3 add, int32_t angadd, int32_t flags, int32_t fov) -{ - if (!mdinited) mdinit(); - - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - if ((uint32_t)tilex >= (uint32_t)MAXTILES) return -2; - - hudtyp * const hud = &tile2model[tilex].hudmem[(flags>>2)&1]; - - hud->add = add; - hud->angadd = ((int16_t)angadd)|2048; - hud->flags = (int16_t)flags; - hud->fov = (int16_t)fov; - - return 0; -} - -int32_t md_undefinetile(int32_t tile) -{ - if (!mdinited) return 0; - if ((unsigned)tile >= (unsigned)MAXTILES) return -1; - - tile2model[tile].modelid = -1; - tile2model[tile].nexttile = -1; - return 0; -} - -/* this function is problematic, it leaves NULL holes in model[] - * (which runs from 0 to nextmodelid-1) */ -int32_t md_undefinemodel(int32_t modelid) -{ - int32_t i; - if (!mdinited) return 0; - if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; - - for (i=MAXTILES+EXTRATILES-1; i>=0; i--) - if (tile2model[i].modelid == modelid) - { - tile2model[i].modelid = -1; - } - - if (models) - { - mdfree(models[modelid]); - models[modelid] = NULL; - } - - return 0; -} - - -//Note: even though it says md2model, it works for both md2model&md3model -FGameTexture *mdloadskin(idmodel_t *m, int32_t number, int32_t pal, int32_t surf, bool *exact) -{ - int32_t i; - mdskinmap_t *sk, *skzero = NULL; - - if (m->mdnum == 2) - surf = 0; - - if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) - return 0; - - i = -1; - for (sk = m->skinmap; sk; sk = sk->next) - { - if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) - { - if (exact) *exact = true; - //Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile); - return TexMan.GetGameTexture(sk->texture); - } - //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005) - else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; } - else if ((sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; } - else if ((sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; } - else if ((sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; } - else if ((sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; } - else if ((sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; } - } - - // Special palettes do not get replacements - if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) - return 0; - - if (skzero) - { - //Printf("Using def skin 0,0 as fallback, pal=%d\n", pal); - if (exact) *exact = false; - return TexMan.GetGameTexture(skzero->texture); - } - else - return nullptr; -} - - -//--------------------------------------- MD2 LIBRARY BEGINS --------------------------------------- -static md2model_t *md2load(FileReader & fil, const char *filnam) -{ - md2model_t *m; - md3model_t *m3; - md3surf_t *s; - md2frame_t *f; - md2head_t head; - char st[BMAX_PATH]; - int32_t i, j, k; - - int32_t ournumskins, ournumglcmds; - - m = (md2model_t *)M_Calloc(1,sizeof(md2model_t)); - m->mdnum = 2; m->scale = .01f; - - fil.Read((char *)&head,sizeof(md2head_t)); -#if WORDS_BIGENDIAN - head.id = LittleLong(head.id); head.vers = LittleLong(head.vers); - head.skinxsiz = LittleLong(head.skinxsiz); head.skinysiz = LittleLong(head.skinysiz); - head.framebytes = LittleLong(head.framebytes); head.numskins = LittleLong(head.numskins); - head.numverts = LittleLong(head.numverts); head.numuv = LittleLong(head.numuv); - head.numtris = LittleLong(head.numtris); head.numglcmds = LittleLong(head.numglcmds); - head.numframes = LittleLong(head.numframes); head.ofsskins = LittleLong(head.ofsskins); - head.ofsuv = LittleLong(head.ofsuv); head.ofstris = LittleLong(head.ofstris); - head.ofsframes = LittleLong(head.ofsframes); head.ofsglcmds = LittleLong(head.ofsglcmds); - head.ofseof = LittleLong(head.ofseof); -#endif - - if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { M_Free(m); return 0; } //"IDP2" - - ournumskins = head.numskins ? head.numskins : 1; - ournumglcmds = head.numglcmds ? head.numglcmds : 1; - - m->numskins = head.numskins; - m->numframes = head.numframes; - m->numverts = head.numverts; - m->numglcmds = head.numglcmds; - m->framebytes = head.framebytes; - - m->frames = (char *)M_Malloc(m->numframes*m->framebytes); - m->glcmds = (int32_t *)M_Malloc(ournumglcmds*sizeof(int32_t)); - m->tris = (md2tri_t *)M_Malloc(head.numtris*sizeof(md2tri_t)); - m->uv = (md2uv_t *)M_Malloc(head.numuv*sizeof(md2uv_t)); - - fil.Seek(head.ofsframes,FileReader::SeekSet); - if (fil.Read((char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes) - { M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; } - - if (m->numglcmds > 0) - { - fil.Seek(head.ofsglcmds,FileReader::SeekSet); - if (fil.Read((char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t))) - { M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; } - } - - fil.Seek(head.ofstris,FileReader::SeekSet); - if (fil.Read((char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t))) - { M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; } - - fil.Seek(head.ofsuv,FileReader::SeekSet); - if (fil.Read((char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t))) - { M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; } - -#if WORDS_BIGENDIAN - { - char *f = (char *)m->frames; - int32_t *l,j; - md2frame_t *fr; - - for (i = m->numframes-1; i>=0; i--) - { - fr = (md2frame_t *)f; - l = (int32_t *)&fr->mul; - for (j=5; j>=0; j--) l[j] = LittleLong(l[j]); - f += m->framebytes; - } - - for (i = m->numglcmds-1; i>=0; i--) - { - m->glcmds[i] = LittleLong(m->glcmds[i]); - } - for (i = head.numtris-1; i>=0; i--) - { - m->tris[i].v[0] = LittleShort(m->tris[i].v[0]); - m->tris[i].v[1] = LittleShort(m->tris[i].v[1]); - m->tris[i].v[2] = LittleShort(m->tris[i].v[2]); - m->tris[i].u[0] = LittleShort(m->tris[i].u[0]); - m->tris[i].u[1] = LittleShort(m->tris[i].u[1]); - m->tris[i].u[2] = LittleShort(m->tris[i].u[2]); - } - for (i = head.numuv-1; i>=0; i--) - { - m->uv[i].u = LittleShort(m->uv[i].u); - m->uv[i].v = LittleShort(m->uv[i].v); - } - } -#endif - - strcpy(st,filnam); - for (i=strlen(st)-1; i>0; i--) - if ((st[i] == '/') || (st[i] == '\\')) { i++; break; } - if (i<0) i=0; - st[i] = 0; - m->basepath = (char *)M_Malloc(i+1); - strcpy(m->basepath, st); - - m->skinfn = (char *)M_Malloc(ournumskins*64); - if (m->numskins > 0) - { - fil.Seek(head.ofsskins,FileReader::SeekSet); - if (fil.Read(m->skinfn,64*m->numskins) != 64*m->numskins) - { M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; } - } - - maxmodelverts = max(maxmodelverts, m->numverts); - maxmodeltris = max(maxmodeltris, head.numtris); - - //return m; - - // the MD2 is now loaded internally - let's begin the MD3 conversion process - //Printf("Beginning md3 conversion.\n"); - m3 = (md3model_t *)M_Calloc(1, sizeof(md3model_t)); - m3->mdnum = 3; m3->texture = nullptr; m3->scale = m->scale; - m3->head.id = IDP3_MAGIC; m3->head.vers = 15; - - m3->head.flags = 0; - - m3->head.numframes = m->numframes; - m3->head.numtags = 0; m3->head.numsurfs = 1; - m3->head.numskins = 0; - - m3->numskins = m3->head.numskins; - m3->numframes = m3->head.numframes; - - m3->head.frames = (md3frame_t *)M_Calloc(m3->head.numframes, sizeof(md3frame_t)); - m3->muladdframes = (FVector3 *)M_Calloc(m->numframes * 2, sizeof(FVector3)); - - f = (md2frame_t *)(m->frames); - - // frames converting - i = 0; - while (i < m->numframes) - { - f = (md2frame_t *)&m->frames[i*m->framebytes]; - strcpy(m3->head.frames[i].nam, f->name); - //Printf("Copied frame %s.\n", m3->head.frames[i].nam); - m3->muladdframes[i*2] = f->mul; - m3->muladdframes[i*2+1] = f->add; - i++; - } - - m3->head.tags = NULL; - - m3->head.surfs = (md3surf_t *)M_Calloc(1, sizeof(md3surf_t)); - s = m3->head.surfs; - - // model converting - s->id = IDP3_MAGIC; s->flags = 0; - s->numframes = m->numframes; s->numshaders = 0; - s->numtris = head.numtris; - s->numverts = head.numtris * 3; // oh man talk about memory effectiveness :(((( - // MD2 is actually more accurate than MD3 in term of uv-mapping, because each triangle has a triangle counterpart on the UV-map. - // In MD3, each vertex unique UV coordinates, meaning that you have to duplicate vertices if you need non-seamless UV-mapping. - - maxmodelverts = max(maxmodelverts, s->numverts); - - strcpy(s->nam, "Dummy surface from MD2"); - - s->shaders = NULL; - - s->tris = (md3tri_t *)M_Calloc(head.numtris, sizeof(md3tri_t)); - s->uv = (md3uv_t *)M_Calloc(s->numverts, sizeof(md3uv_t)); - s->xyzn = (md3xyzn_t *)M_Calloc(s->numverts * m->numframes, sizeof(md3xyzn_t)); - - //memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t)); - //Printf("Current model geometry memory usage : %i.\n", memoryusage); - - //Printf("Number of frames : %i\n", m->numframes); - //Printf("Number of triangles : %i\n", head.numtris); - //Printf("Number of vertices : %i\n", s->numverts); - - // triangle converting - i = 0; - while (i < head.numtris) - { - j = 0; - //Printf("Triangle : %i\n", i); - while (j < 3) - { - // triangle vertex indexes - s->tris[i].i[j] = i*3 + j; - - // uv coords - s->uv[i*3+j].u = (float)(m->uv[m->tris[i].u[j]].u) / (float)(head.skinxsiz); - s->uv[i*3+j].v = (float)(m->uv[m->tris[i].u[j]].v) / (float)(head.skinysiz); - - // vertices for each frame - k = 0; - while (k < m->numframes) - { - f = (md2frame_t *)&m->frames[k*m->framebytes]; - s->xyzn[(k*s->numverts) + (i*3) + j].x = (int16_t) (((f->verts[m->tris[i].v[j]].v[0] * f->mul.X) + f->add.X) * 64.f); - s->xyzn[(k*s->numverts) + (i*3) + j].y = (int16_t) (((f->verts[m->tris[i].v[j]].v[1] * f->mul.Y) + f->add.Y) * 64.f); - s->xyzn[(k*s->numverts) + (i*3) + j].z = (int16_t) (((f->verts[m->tris[i].v[j]].v[2] * f->mul.Z) + f->add.Z) * 64.f); - - k++; - } - j++; - } - //Printf("End triangle.\n"); - i++; - } - //Printf("Finished md3 conversion.\n"); - - { - mdskinmap_t *sk; - - sk = (mdskinmap_t *)M_Calloc(1,sizeof(mdskinmap_t)); - sk->palette = 0; - sk->skinnum = 0; - sk->surfnum = 0; - - if (m->numskins > 0) - { - FStringf fn("%s%s", m->basepath, m->skinfn); - sk->texture = TexMan.CheckForTexture(fn, ETextureType::Any); - if (!sk->texture.isValid()) - { - Printf("Unable to load %s as model skin\n", m->skinfn); - } - } - m3->skinmap = sk; - } - - m3->indexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * s->numtris); - m3->vindexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * s->numtris * 3); - m3->maxdepths = (float *)M_Malloc(sizeof(float) * s->numtris); - - // die MD2 ! DIE ! - M_Free(m->skinfn); M_Free(m->basepath); M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); - - return ((md2model_t *)m3); -} -//---------------------------------------- MD2 LIBRARY ENDS ---------------------------------------- - -// DICHOTOMIC RECURSIVE SORTING - USED BY MD3DRAW -static int32_t partition(uint16_t *indexes, float *depths, int32_t f, int32_t l) -{ - int32_t up = f, down = l; - float piv = depths[f]; - uint16_t piv2 = indexes[f]; - do - { - while ((up < l) && (depths[up] <= piv)) - up++; - while ((depths[down] > piv) && (down > f)) - down--; - if (up < down) - { - std::swap(depths[up], depths[down]); - std::swap(indexes[up], indexes[down]); - } - } - while (down > up); - depths[f] = depths[down]; - depths[down] = piv; - indexes[f] = indexes[down]; - indexes[down] = piv2; - return down; -} - -static inline void quicksort(uint16_t *indexes, float *depths, int32_t first, int32_t last) -{ - int32_t pivIndex; - if (first >= last) return; - pivIndex = partition(indexes, depths, first, last); - if (first < (pivIndex-1)) quicksort(indexes, depths, first, (pivIndex-1)); - if ((pivIndex+1) >= last) return; - quicksort(indexes, depths, (pivIndex+1), last); -} -// END OF QUICKSORT LIB - -//--------------------------------------- MD3 LIBRARY BEGINS --------------------------------------- - -static md3model_t *md3load(FileReader & fil) -{ - int32_t i, surfi, ofsurf, offs[4], leng[4]; - int32_t maxtrispersurf; - md3model_t *m; - md3surf_t *s; - - m = (md3model_t *)M_Calloc(1,sizeof(md3model_t)); - m->mdnum = 3; m->texture = nullptr; m->scale = .01f; - - m->muladdframes = NULL; - - fil.Read(&m->head,SIZEOF_MD3HEAD_T); - -#if WORDS_BIGENDIAN - m->head.id = LittleLong(m->head.id); m->head.vers = LittleLong(m->head.vers); - m->head.flags = LittleLong(m->head.flags); m->head.numframes = LittleLong(m->head.numframes); - m->head.numtags = LittleLong(m->head.numtags); m->head.numsurfs = LittleLong(m->head.numsurfs); - m->head.numskins = LittleLong(m->head.numskins); m->head.ofsframes = LittleLong(m->head.ofsframes); - m->head.ofstags = LittleLong(m->head.ofstags); m->head.ofssurfs = LittleLong(m->head.ofssurfs); - m->head.eof = LittleLong(m->head.eof); -#endif - - if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { M_Free(m); return 0; } //"IDP3" - - m->numskins = m->head.numskins; //<- dead code? - m->numframes = m->head.numframes; - - ofsurf = m->head.ofssurfs; - - fil.Seek(m->head.ofsframes,FileReader::SeekSet); i = m->head.numframes*sizeof(md3frame_t); - m->head.frames = (md3frame_t *)M_Malloc(i); - fil.Read(m->head.frames,i); - - if (m->head.numtags == 0) m->head.tags = NULL; - else - { - fil.Seek(m->head.ofstags,FileReader::SeekSet); i = m->head.numtags*sizeof(md3tag_t); - m->head.tags = (md3tag_t *)M_Malloc(i); - fil.Read(m->head.tags,i); - } - - fil.Seek(m->head.ofssurfs,FileReader::SeekSet); - m->head.surfs = (md3surf_t *)M_Calloc(m->head.numsurfs, sizeof(md3surf_t)); - // NOTE: We assume that NULL is represented by all-zeros. - // surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes). - // surfs[i].geometry is for FREE_SURFS_GEOMETRY. - assert(m->head.surfs[0].geometry == NULL); - -#if WORDS_BIGENDIAN - { - int32_t j, *l; - - for (i = m->head.numframes-1; i>=0; i--) - { - l = (int32_t *)&m->head.frames[i].min; - for (j=3+3+3+1-1; j>=0; j--) l[j] = LittleLong(l[j]); - } - - for (i = m->head.numtags-1; i>=0; i--) - { - l = (int32_t *)&m->head.tags[i].p; - for (j=3+3+3+3-1; j>=0; j--) l[j] = LittleLong(l[j]); - } - } -#endif - - maxtrispersurf = 0; - - for (surfi=0; surfihead.numsurfs; surfi++) - { - s = &m->head.surfs[surfi]; - fil.Seek(ofsurf,FileReader::SeekSet); fil.Read(s,SIZEOF_MD3SURF_T); - -#if WORDS_BIGENDIAN - { - int32_t j, *l; - s->id = LittleLong(s->id); - l = (int32_t *)&s->flags; - for (j=1+1+1+1+1+1+1+1+1+1-1; j>=0; j--) l[j] = LittleLong(l[j]); - } -#endif - - offs[0] = ofsurf+s->ofstris; - offs[1] = ofsurf+s->ofsshaders; - offs[2] = ofsurf+s->ofsuv; - offs[3] = ofsurf+s->ofsxyzn; - - leng[0] = s->numtris*sizeof(md3tri_t); - leng[1] = s->numshaders*sizeof(md3shader_t); - leng[2] = s->numverts*sizeof(md3uv_t); - leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t); - - //memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t)); - //Printf("Current model geometry memory usage : %i.\n", memoryusage); - - s->tris = (md3tri_t *)M_Malloc((leng[0] + leng[1]) + (leng[2] + leng[3])); - - s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]); - s->uv = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]); - s->xyzn = (md3xyzn_t *)(((intptr_t)s->uv)+leng[2]); - - fil.Seek(offs[0],FileReader::SeekSet); fil.Read(s->tris ,leng[0]); - fil.Seek(offs[1],FileReader::SeekSet); fil.Read(s->shaders,leng[1]); - fil.Seek(offs[2],FileReader::SeekSet); fil.Read(s->uv ,leng[2]); - fil.Seek(offs[3],FileReader::SeekSet); fil.Read(s->xyzn ,leng[3]); - -#if WORDS_BIGENDIAN - { - int32_t j, *l; - - for (i=s->numtris-1; i>=0; i--) - { - for (j=2; j>=0; j--) s->tris[i].i[j] = LittleLong(s->tris[i].i[j]); - } - for (i=s->numshaders-1; i>=0; i--) - { - s->shaders[i].i = LittleLong(s->shaders[i].i); - } - for (i=s->numverts-1; i>=0; i--) - { - l = (int32_t *)&s->uv[i].u; - l[0] = LittleLong(l[0]); - l[1] = LittleLong(l[1]); - } - for (i=s->numframes*s->numverts-1; i>=0; i--) - { - s->xyzn[i].x = (int16_t)LittleShort((uint16_t)s->xyzn[i].x); - s->xyzn[i].y = (int16_t)LittleShort((uint16_t)s->xyzn[i].y); - s->xyzn[i].z = (int16_t)LittleShort((uint16_t)s->xyzn[i].z); - } - } -#endif - maxmodelverts = max(maxmodelverts, s->numverts); - maxmodeltris = max(maxmodeltris, s->numtris); - maxtrispersurf = max(maxtrispersurf, s->numtris); - ofsurf += s->ofsend; - } - - m->indexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * maxtrispersurf); - m->vindexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * maxtrispersurf * 3); - m->maxdepths = (float *)M_Malloc(sizeof(float) * maxtrispersurf); - - return m; -} - -static void md3postload_common(md3model_t *m) -{ - int framei, surfi, verti; - md3frame_t *frame; - md3xyzn_t *frameverts; - float dist, vec1[3]; - - // apparently we can't trust loaded models bounding box/sphere information, - // so let's compute it ourselves - - framei = 0; - - while (framei < m->head.numframes) - { - frame = &m->head.frames[framei]; - - memset(&frame->min, 0, sizeof(FVector3)); - memset(&frame->max, 0, sizeof(FVector3)); - - frame->r = 0.0f; - - surfi = 0; - while (surfi < m->head.numsurfs) - { - frameverts = &m->head.surfs[surfi].xyzn[framei * m->head.surfs[surfi].numverts]; - - verti = 0; - while (verti < m->head.surfs[surfi].numverts) - { - if (!verti && !surfi) - { - md3xyzn_t const & framevert = frameverts[0]; - - frame->min.X = framevert.x; - frame->min.Y = framevert.y; - frame->min.Z = framevert.z; - - frame->max = frame->min; - } - else - { - md3xyzn_t const & framevert = frameverts[verti]; - - if (frame->min.X > framevert.x) - frame->min.X = framevert.x; - if (frame->max.X < framevert.x) - frame->max.X = framevert.x; - - if (frame->min.Y > framevert.y) - frame->min.Y = framevert.y; - if (frame->max.Y < framevert.y) - frame->max.Y = framevert.y; - - if (frame->min.Z > framevert.z) - frame->min.Z = framevert.z; - if (frame->max.Z < framevert.z) - frame->max.Z = framevert.z; - } - - ++verti; - } - - ++surfi; - } - - frame->cen.X = (frame->min.X + frame->max.X) * .5f; - frame->cen.Y = (frame->min.Y + frame->max.Y) * .5f; - frame->cen.Z = (frame->min.Z + frame->max.Z) * .5f; - - surfi = 0; - while (surfi < m->head.numsurfs) - { - md3surf_t const & surf = m->head.surfs[surfi]; - - frameverts = &surf.xyzn[framei * surf.numverts]; - - verti = 0; - while (verti < surf.numverts) - { - md3xyzn_t const & framevert = frameverts[verti]; - - vec1[0] = framevert.x - frame->cen.X; - vec1[1] = framevert.y - frame->cen.Y; - vec1[2] = framevert.z - frame->cen.Z; - - dist = vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]; - - if (dist > frame->r) - frame->r = dist; - - ++verti; - } - - ++surfi; - } - - frame->r = sqrtf(frame->r); - - ++framei; - } -} - - - -static void md3free(md3model_t *m) -{ - mdanim_t *anim, *nanim = NULL; - mdskinmap_t *sk, *nsk = NULL; - - if (!m) return; - - for (anim=m->animations; anim; anim=nanim) - { - nanim = anim->next; - M_Free(anim); - } - for (sk=m->skinmap; sk; sk=nsk) - { - nsk = sk->next; - M_Free(sk); - } - - if (m->head.surfs) - { - for (int surfi=m->head.numsurfs-1; surfi>=0; surfi--) - { - md3surf_t *s = &m->head.surfs[surfi]; - M_Free(s->tris); - M_Free(s->geometry); // FREE_SURFS_GEOMETRY - } - M_Free(m->head.surfs); - } - M_Free(m->head.tags); - M_Free(m->head.frames); - - M_Free(m->muladdframes); - - M_Free(m->indexes); - M_Free(m->vindexes); - M_Free(m->maxdepths); - - M_Free(m); -} - -//---------------------------------------- MD3 LIBRARY ENDS ---------------------------------------- -//--------------------------------------- MD LIBRARY BEGINS --------------------------------------- - -static mdmodel_t *mdload(const char *filnam) -{ - mdmodel_t *vm; - int32_t i; - - //vm = (mdmodel_t *)voxload(filnam); - //if (vm) return vm; - - auto fil = fileSystem.OpenFileReader(filnam); - - if (!fil.isOpen()) - return NULL; - - fil.Read(&i,4); - fil.Seek(0,FileReader::SeekSet); - - switch (LittleLong(i)) - { - case IDP2_MAGIC: -// Printf("Warning: model \"%s\" is version IDP2; wanted version IDP3\n",filnam); - vm = (mdmodel_t *)md2load(fil,filnam); - break; //IDP2 - case IDP3_MAGIC: - vm = (mdmodel_t *)md3load(fil); - break; //IDP3 - default: - vm = NULL; - break; - } - - if (vm) - { - md3model_t *vm3 = (md3model_t *)vm; - - // smuggle the file name into the model struct. - // head.nam is unused as far as I can tell - strncpy(vm3->head.nam, filnam, sizeof(vm3->head.nam)); - vm3->head.nam[sizeof(vm3->head.nam)-1] = 0; - md3postload_common(vm3); - - } - - return vm; -} - - -void voxfree(voxmodel_t* m) -{ - if (m) delete m; -} - -static void mdfree(mdmodel_t *vm) -{ - if (vm->mdnum == 1) { voxfree((voxmodel_t *)vm); return; } - if (vm->mdnum == 2 || vm->mdnum == 3) { md3free((md3model_t *)vm); return; } -} - -void updateModelInterpolation() -{ - // sigh... - omdtims = mdtims; - mdtims = I_msTime(); - - TSpriteIterator it; - while (auto actor = it.Next()) - { - if ((mdpause && actor->sprext.mdanimtims) || (actor->sprext.renderflags & SPREXT_NOMDANIM)) - actor->sprext.mdanimtims += mdtims - omdtims; - } -} -#endif - -//---------------------------------------- MD LIBRARY ENDS ---------------------------------------- diff --git a/source/common/models/model.cpp b/source/common/models/model.cpp index c4b184f0c..377de6117 100644 --- a/source/common/models/model.cpp +++ b/source/common/models/model.cpp @@ -151,7 +151,7 @@ int ModelFrameHash(FSpriteModelFrame * smf) // //=========================================================================== -unsigned FindModel(const char * path, const char * modelfile) +unsigned FindModel(const char * path, const char * modelfile, bool silent) { FModel * model = nullptr; FString fullname; diff --git a/source/common/models/model.h b/source/common/models/model.h index 48e4ed34a..4422207e7 100644 --- a/source/common/models/model.h +++ b/source/common/models/model.h @@ -81,6 +81,7 @@ public: IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } void DestroyVertexBuffer(); + bool hasSurfaces = false; FString mFileName; private: @@ -88,5 +89,5 @@ private: }; int ModelFrameHash(FSpriteModelFrame* smf); -unsigned FindModel(const char* path, const char* modelfile); +unsigned FindModel(const char* path, const char* modelfile, bool silent = false); diff --git a/source/common/models/models_md3.cpp b/source/common/models/models_md3.cpp index 512794293..e716a6f26 100644 --- a/source/common/models/models_md3.cpp +++ b/source/common/models/models_md3.cpp @@ -133,6 +133,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le auto numFrames = LittleLong(hdr->Num_Frames); auto numSurfaces = LittleLong(hdr->Num_Surfaces); + hasSurfaces = numSurfaces > 1; numTags = LittleLong(hdr->Num_Tags); diff --git a/source/common/models/models_obj.cpp b/source/common/models/models_obj.cpp index 5d6892798..a79caa9e4 100644 --- a/source/common/models/models_obj.cpp +++ b/source/common/models/models_obj.cpp @@ -222,6 +222,8 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length curSurface->faceStart = aggSurfFaceCount; surfaces.Push(*curSurface); delete curSurface; + hasSurfaces = surfaces.Size() > 1; + if (uvs.Size() == 0) { // Needed so that OBJs without UVs can work diff --git a/source/common/models/models_ue1.cpp b/source/common/models/models_ue1.cpp index 416f9a391..70245bc45 100644 --- a/source/common/models/models_ue1.cpp +++ b/source/common/models/models_ue1.cpp @@ -48,6 +48,7 @@ float unpackuvert( uint32_t n, int c ) bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length ) { int lumpnum2; + hasSurfaces = true; FString realfilename = fileSystem.GetFileFullName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { diff --git a/source/common/models/voxels.h b/source/common/models/voxels.h index 7d02bba13..52299434a 100644 --- a/source/common/models/voxels.h +++ b/source/common/models/voxels.h @@ -4,7 +4,10 @@ #include // [RH] Voxels from Build -#define MAXVOXMIPS 5 +enum +{ + MAXVOXMIPS = 5, +}; struct kvxslab_t { diff --git a/source/core/defparser.cpp b/source/core/defparser.cpp index 8d8e37853..e6d54f34c 100644 --- a/source/core/defparser.cpp +++ b/source/core/defparser.cpp @@ -45,6 +45,7 @@ #include "mapinfo.h" #include "hw_voxels.h" #include "psky.h" +#include "models/modeldata.h" int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, bool indexed = false); int tileSetSkybox(int picnum, int palnum, FString* facenames, bool indexed = false); @@ -1655,14 +1656,14 @@ void parseDefineModel(FScanner& sc, FScriptPosition& pos) if (!sc.GetFloat(scale, true)) return; if (!sc.GetNumber(shadeoffs, true)) return; - mdglobal.lastmodelid = md_loadmodel(modelfn); + mdglobal.lastmodelid = modelManager.LoadModel(modelfn); if (mdglobal.lastmodelid < 0) { pos.Message(MSG_WARNING, "definemodel: unable to load model file '%s'", modelfn.GetChars()); } else { - md_setmisc(mdglobal.lastmodelid, (float)scale, shadeoffs, 0.0, 0.0, 0); + modelManager.SetMisc(mdglobal.lastmodelid, (float)scale, shadeoffs, 0.0, 0.0, 0); mdglobal.modelskin = mdglobal.lastmodelskin = 0; mdglobal.seenframe = 0; } @@ -1693,7 +1694,7 @@ void parseDefineModelFrame(FScanner& sc, FScriptPosition& pos) } for (int i = firsttile; i <= lasttile && ok; i++) { - int err = (md_defineframe(mdglobal.lastmodelid, framename, i, max(0, mdglobal.modelskin), 0.0f, 0)); + int err = (modelManager.DefineFrame(mdglobal.lastmodelid, framename, i, max(0, mdglobal.modelskin), 0.0f, 0)); if (err < 0) ok = false; if (err == -2) pos.Message(MSG_ERROR, "Invalid tile number %d", i); else if (err == -3) pos.Message(MSG_ERROR, "Invalid frame name '%s'", framename.GetChars()); @@ -1723,7 +1724,7 @@ void parseDefineModelAnim(FScanner& sc, FScriptPosition& pos) pos.Message(MSG_WARNING, "definemodelframe: Ignoring animation definition outside model."); return; } - int err = (md_defineanimation(mdglobal.lastmodelid, startframe, endframe, (int32_t)(dfps * (65536.0 * .001)), flags)); + int err = (modelManager.DefineAnimation(mdglobal.lastmodelid, startframe, endframe, (int32_t)(dfps * (65536.0 * .001)), flags)); if (err == -2) pos.Message(MSG_ERROR, "Invalid start frame name %s", startframe.GetChars()); else if (err == -3) pos.Message(MSG_ERROR, "Invalid end frame name %s", endframe.GetChars()); } @@ -1747,7 +1748,7 @@ void parseDefineModelSkin(FScanner& sc, FScriptPosition& pos) if (!fileSystem.FileExists(skinfn)) return; - int err = (md_defineskin(mdglobal.lastmodelid, skinfn, palnum, max(0, mdglobal.modelskin), 0, 0.0f, 1.0f, 1.0f, 0)); + int err = (modelManager.DefineSkin(mdglobal.lastmodelid, skinfn, palnum, max(0, mdglobal.modelskin), 0, 0.0f, 1.0f, 1.0f, 0)); if (err == -2) pos.Message(MSG_ERROR, "Invalid skin file name %s", skinfn.GetChars()); else if (err == -3) pos.Message(MSG_ERROR, "Invalid palette %d", palnum); } @@ -1775,7 +1776,7 @@ void parseUndefModel(FScanner& sc, FScriptPosition& pos) int tile; if (!sc.GetNumber(tile, true)) return; if (!ValidateTilenum("undefmodel", tile, pos)) return; - md_undefinetile(tile); + modelManager.UndefineTile(tile); } void parseUndefModelRange(FScanner& sc, FScriptPosition& pos) @@ -1785,7 +1786,7 @@ void parseUndefModelRange(FScanner& sc, FScriptPosition& pos) if (!sc.GetNumber(start, true)) return; if (!sc.GetNumber(end, true)) return; if (!ValidateTileRange("undefmodel", start, end, pos)) return; - for (int i = start; i <= end; i++) md_undefinetile(i); + for (int i = start; i <= end; i++) modelManager.UndefineTile(i); } void parseUndefModelOf(FScanner& sc, FScriptPosition& pos) @@ -1834,7 +1835,7 @@ static bool parseModelFrameBlock(FScanner& sc, FixedBitArray<1024>& usedframes) } for (int i = starttile; i <= endtile && ok; i++) { - int res = md_defineframe(mdglobal.lastmodelid, framename, i, max(0, mdglobal.modelskin), smoothduration, pal); + int res = modelManager.DefineFrame(mdglobal.lastmodelid, framename, i, max(0, mdglobal.modelskin), smoothduration, pal); if (res < 0) { ok = false; @@ -1877,7 +1878,7 @@ static bool parseModelAnimBlock(FScanner& sc) return false; } - int res = md_defineanimation(mdglobal.lastmodelid, startframe, endframe, (int)(fps * (65536.0 * .001)), flags); + int res = modelManager.DefineAnimation(mdglobal.lastmodelid, startframe, endframe, (int)(fps * (65536.0 * .001)), flags); if (res < 0) { if (res == -2) pos.Message(MSG_ERROR, "Invalid start frame name %s", startframe.GetChars()); @@ -1927,7 +1928,7 @@ static bool parseModelSkinBlock(FScanner& sc, int pal) } if (pal == DETAILPAL) param = 1.f / param; - int res = md_defineskin(mdglobal.lastmodelid, filename, pal, max(0, mdglobal.modelskin), surface, param, specpower, specfactor, flags); + int res = modelManager.DefineSkin(mdglobal.lastmodelid, filename, pal, max(0, mdglobal.modelskin), surface, param, specpower, specfactor, flags); if (res < 0) { if (res == -2) pos.Message(MSG_ERROR, "Invalid skin filename %s", filename.GetChars()); @@ -1968,7 +1969,7 @@ static bool parseModelHudBlock(FScanner& sc) for (int i = starttile; i <= endtile; i++) { FVector3 addf = { (float)add.X, (float)add.Y, (float)add.Z }; - int res = md_definehud(mdglobal.lastmodelid, i, addf, angadd, flags, fov); + int res = modelManager.DefineHud(mdglobal.lastmodelid, i, addf, angadd, flags, fov); if (res < 0) { if (res == -2) pos.Message(MSG_ERROR, "Invalid tile number %d", i); @@ -1995,7 +1996,7 @@ void parseModel(FScanner& sc, FScriptPosition& pos) if (sc.StartBraces(&blockend)) return; - mdglobal.lastmodelid = md_loadmodel(modelfn); + mdglobal.lastmodelid = modelManager.LoadModel(modelfn); if (mdglobal.lastmodelid < 0) { pos.Message(MSG_WARNING, "Unable to load model file '%s'", modelfn.GetChars()); @@ -2028,13 +2029,12 @@ void parseModel(FScanner& sc, FScriptPosition& pos) if (mdglobal.lastmodelid >= 0) { pos.Message(MSG_ERROR, "Removing model %d due to errors.", mdglobal.lastmodelid); - md_undefinemodel(mdglobal.lastmodelid); - nextmodelid--; + modelManager.UndefineModel(mdglobal.lastmodelid); } } else { - md_setmisc(mdglobal.lastmodelid, (float)scale, shadeoffs, (float)mzadd, (float)myoffset, flags); + modelManager.SetMisc(mdglobal.lastmodelid, (float)scale, shadeoffs, (float)mzadd, (float)myoffset, flags); mdglobal.modelskin = mdglobal.lastmodelskin = 0; mdglobal.seenframe = 0; } diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index c2a31f97e..5d608e88f 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -631,7 +631,6 @@ int GameMain() TexMan.DeleteAll(); TileFiles.CloseAll(); // delete the texture data before shutting down graphics. I_ShutdownGraphics(); - freeallmodels(); if (gi) { delete gi; @@ -940,7 +939,6 @@ static void InitTextures() TexMan.Init(); TexMan.AddTextures([]() {}, [](BuildInfo&) {}); StartWindow->Progress(); - mdinit(); TileFiles.Init(); TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games. diff --git a/source/core/gamefuncs.cpp b/source/core/gamefuncs.cpp index 4986580aa..d4656f656 100644 --- a/source/core/gamefuncs.cpp +++ b/source/core/gamefuncs.cpp @@ -1251,19 +1251,6 @@ tspritetype* renderAddTsprite(tspriteArray& tsprites, DCoreActor* actor) return tspr; } -//========================================================================== -// -// -// -//========================================================================== - -int tilehasmodelorvoxel(int const tilenume, int pal) -{ - return - (mdinited && hw_models && tile2model[Ptile2tile(tilenume, pal)].modelid != -1) || - (r_voxels && tiletovox[tilenume] != -1); -} - //========================================================================== // // vector serializers diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 82c773a6d..ec7deaa53 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -438,7 +438,7 @@ void Display() screen->FrameTime = I_msTimeFS(); screen->BeginFrame(); screen->SetSceneRenderTarget(gl_ssao != 0); - updateModelInterpolation(); + //updateModelInterpolation(); gi->Render(); DrawFullscreenBlends(); drawMapTitle(); diff --git a/source/core/models/modeldata.cpp b/source/core/models/modeldata.cpp new file mode 100644 index 000000000..5d46ce1cd --- /dev/null +++ b/source/core/models/modeldata.cpp @@ -0,0 +1,243 @@ +#include "basics.h" +#include "model.h" +#include "modeldata.h" +#include "texturemanager.h" +#include "hw_voxels.h" + +#include "build.h" + + +int ModelManager::LoadModel(const char* fn) +{ + unsigned modelid = FindModel(nullptr, fn, true); + + if (modelid == ~0u) + return -1; + + // Note that the descriptor table may contain the same model multiple times! + + int mdid = modelDescs.Reserve(1); + modelDescs.Last() = {}; + modelDescs.Last().modelID = modelid; + return mdid; +} + +int ModelManager::SetMisc(int modelid, float scale, int shadeoff, float zadd, float yoffset, int flags) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + + auto md = &modelDescs[modelid]; + md->bscale = scale; + md->shadeoff = shadeoff; + md->zadd = zadd; + md->yoffset = yoffset; + md->flags = flags; + return 0; +} + +int ModelManager::DefineFrame(int modelid, const char* framename, int tilenum, int skinnum, float smoothduration, int pal) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + if ((uint32_t)tilenum >= MAXTILES) return -2; + if (!framename) return -3; + + ModelTileFrame mframe; + + auto mdesc = &modelDescs[modelid]; + auto model = Models[mdesc->modelID]; + + auto frm = model->FindFrame(framename, true); + if (frm == FErr_NotFound) return -3; + if (frm == FErr_Voxel) skinnum = 0; + if (frm < 0) frm = 0; + + mframe.modelid = modelid; + mframe.framenum = frm; + mframe.skinnum = skinnum; + mframe.smoothduration = smoothduration; + auto key = FrameMapKey(tilenum, pal); + frameMap.Insert(key, mframe); + return key; +} + +int ModelManager::DefineAnimation(int modelid, const char* framestart, const char* frameend, int fpssc, int flags) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + if (!framestart) return -2; + if (!frameend) return -3; + + auto mdesc = &modelDescs[modelid]; + auto model = Models[mdesc->modelID]; + + auto frm = model->FindFrame(framestart, true); + if (frm == FErr_NotFound) return -2; + if (frm < 0) frm = 0; + + auto frme = model->FindFrame(frameend, true); + if (frme == FErr_NotFound) return -3; + if (frme < 0) frme = 0; + + ModelAnimation anm; + + anm.startframe = frm; + anm.endframe = frme; + anm.fpssc = fpssc; + anm.flags = flags; + mdesc->anims.Push(anm); + return 0; +} + +int ModelManager::DefineSkin(int modelid, const char* skinfn, int palnum, int skinnum, int surfnum, float param, float specpower, float specfactor, int flags) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + if (!skinfn) return -2; + if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3; + + auto mdesc = &modelDescs[modelid]; + auto model = Models[mdesc->modelID]; + + if (model->FindFrame("", true) == FErr_Voxel) + return 0; + + if (!model->hasSurfaces) surfnum = 0; + + ModelSkinDef* skdef = nullptr; + + for (auto& sk : mdesc->skins) + { + if (sk.palette == (uint8_t)palnum && skinnum == sk.skinnum && surfnum == sk.surfnum) + { + skdef = &sk; + break; + } + } + if (skdef == nullptr) + { + mdesc->skins.Reserve(1); + skdef = &mdesc->skins.Last(); + } + + skdef->palette = (uint8_t)palnum; + skdef->flags = (uint8_t)flags; + skdef->skinnum = skinnum; + skdef->surfnum = surfnum; + skdef->param = param; + skdef->specpower = specpower; + skdef->specfactor = specfactor; + skdef->texture = TexMan.CheckForTexture(skinfn, ETextureType::Any); + if (!skdef->texture.isValid()) return -2; + return 0; +} + +int ModelManager::DefineHud(int modelid, int tilex, FVector3 add, int angadd, int flags, int fov) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + if ((unsigned)tilex >= (unsigned)MAXTILES) return -1; + + auto mdesc = &modelDescs[modelid]; + auto model = Models[mdesc->modelID]; + + // not implemented yet + + return 0; +} + +int ModelManager::UndefineTile(int tile) +{ + if ((unsigned)tile >= (unsigned)MAXTILES) return -1; + + // delete all entries from the map that reference this tile + for (int i = 0; i < MAXPALOOKUPS; i++) + { + frameMap.Remove(FrameMapKey(tile, i)); + } + return 0; +} + +int ModelManager::UndefineModel(int modelid) +{ + if ((unsigned)modelid >= modelDescs.Size()) return -1; + + auto mdesc = &modelDescs[modelid]; + mdesc->deleted = true; + mdesc->anims.Reset(); + mdesc->skins.Reset(); + if (modelid == (int)modelDescs.Size() - 1) + modelDescs.Pop(); + return 0; +} + +#if 0 // kept as reminders for later. We still need the prioritization code in mdloadskin, the rest needs to be redone + +FGameTexture* mdloadskin(idmodel_t* m, int32_t number, int32_t pal, int32_t surf, bool* exact) +{ + int32_t i; + mdskinmap_t* sk, * skzero = NULL; + + if (m->mdnum == 2) + surf = 0; + + if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) + return 0; + + i = -1; + for (sk = m->skinmap; sk; sk = sk->next) + { + if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) + { + if (exact) *exact = true; + //Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile); + return TexMan.GetGameTexture(sk->texture); + } + //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005) + else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; } + else if ((sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; } + else if ((sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; } + else if ((sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; } + else if ((sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; } + else if ((sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; } + } + + // Special palettes do not get replacements + if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) + return 0; + + if (skzero) + { + //Printf("Using def skin 0,0 as fallback, pal=%d\n", pal); + if (exact) *exact = false; + return TexMan.GetGameTexture(skzero->texture); + } + else + return nullptr; +} + + +void updateModelInterpolation() +{ + // this never worked - only left as a reference to sprext stuff. + omdtims = mdtims; + mdtims = I_msTime(); + + TSpriteIterator it; + while (auto actor = it.Next()) + { + if ((mdpause && actor->sprext.mdanimtims) || (actor->sprext.renderflags & SPREXT_NOMDANIM)) + actor->sprext.mdanimtims += mdtims - omdtims; + } +} +#endif + +//========================================================================== +// +// +// +//========================================================================== + +int tilehasmodelorvoxel(int const tilenume, int pal) +{ + return + (hw_models && modelManager.CheckModel(tilenume, pal)) || + (r_voxels && tiletovox[tilenume] != -1); +} + diff --git a/source/core/models/modeldata.h b/source/core/models/modeldata.h new file mode 100644 index 000000000..ee4b51e0e --- /dev/null +++ b/source/core/models/modeldata.h @@ -0,0 +1,85 @@ +#pragma once + + +#include +#include "vectors.h" + +enum { + HUDFLAG_HIDE = 1, + HUDFLAG_NOBOB = 2, + HUDFLAG_FLIPPED = 4, + HUDFLAG_NODEPTH = 8, +}; + +struct ModelAnimation +{ + int startframe, endframe; + int fpssc, flags; +}; + +struct ModelSkinDef +{ + uint8_t palette, flags; + int32_t skinnum, surfnum; // Skin identifier, surface number + FTextureID texture; + float param, specpower, specfactor; +}; + + +struct ModelDescriptor +{ + unsigned modelID; + + // stuff that can get set from .DEF so we need to keep it. + int shadeoff; + int flags; + float scale, bscale, zadd, yoffset; + bool deleted; + FGameTexture* texture; + TArray anims; + TArray skins; +}; + +struct ModelTileFrame +{ + // maps build tiles to particular animation frames of a model + int modelid; + int framenum; + float smoothduration; + int skinnum; +}; + + + +struct ModelManager +{ + TArray modelDescs; + TMap frameMap; + + unsigned FrameMapKey(unsigned tilenum, unsigned palette) + { + return tilenum + (palette < 16); // good enough for now - should later be redirected to the underlying texture ID. + } + + // Interface for the .def parser + int LoadModel(const char* fn); + int SetMisc(int modelid, float scale, int shadeoff, float zadd, float yoffset, int flags); + int DefineFrame(int modelid, const char* framename, int tilenum, int skinnum, float smoothduration, int pal); + int DefineAnimation(int modelid, const char* framestart, const char* frameend, int fpssc, int flags); + int DefineSkin(int modelid, const char* skinfn, int palnum, int skinnum, int surfnum, float param, float specpower, float specfactor, int flags); + int DefineHud(int modelid, int tilex, FVector3 add, int angadd, int flags, int fov); + int UndefineTile(int tile); + int UndefineModel(int modelid); + bool CheckModel(int tilenum, int pal) + { + return frameMap.CheckKey(FrameMapKey(tilenum, pal)) != nullptr; + } + ModelTileFrame* GetModel(int tilenum, int pal) + { + return frameMap.CheckKey(FrameMapKey(tilenum, pal)); + } +}; + + +int tilehasmodelorvoxel(int const tilenume, int pal); +inline ModelManager modelManager; diff --git a/source/core/precache.cpp b/source/core/precache.cpp index 50eb82aff..42a10aef5 100644 --- a/source/core/precache.cpp +++ b/source/core/precache.cpp @@ -43,6 +43,7 @@ #include "hw_models.h" #include "hw_voxels.h" #include "mapinfo.h" +#include "models/modeldata.h" BEGIN_BLD_NS extern short voxelIndex[MAXTILES]; @@ -68,9 +69,9 @@ static void doprecache(int picnum, int palette) if (!hw_models) return; - int const mid = md_tilehasmodel(picnum, palette); + int const mid = modelManager.CheckModel(picnum, palette); - if (mid < 0 || models[mid]->mdnum < 2) + if (mid < 0) { if (r_voxels) { @@ -86,6 +87,7 @@ static void doprecache(int picnum, int palette) return; } +#if 0 int const surfaces = (models[mid]->mdnum == 3) ? ((md3model_t *)models[mid])->head.numsurfs : 0; for (int i = 0; i <= surfaces; i++) @@ -94,6 +96,7 @@ static void doprecache(int picnum, int palette) int paletteid = TRANSLATION(Translation_Remap + curbasepal, palette); if (skintex) PrecacheTex(skintex, paletteid); } +#endif } diff --git a/source/core/rendering/hw_voxels.cpp b/source/core/rendering/hw_voxels.cpp index fc25640ad..738d6622e 100644 --- a/source/core/rendering/hw_voxels.cpp +++ b/source/core/rendering/hw_voxels.cpp @@ -76,7 +76,7 @@ static voxmodel_t* voxload(int lumpnum) voxmodel_t* vm = new voxmodel_t; *vm = {}; auto pivot = voxel->Mips[0].Pivot; - vm->mdnum = 1; //VOXel model id + //vm->mdnum = 1; //VOXel model id vm->scale = vm->bscale = 1.f; vm->piv.X = float(pivot.X); vm->piv.Y = float(pivot.Y); diff --git a/source/core/rendering/hw_voxels.h b/source/core/rendering/hw_voxels.h index 01b20e613..2111489f2 100644 --- a/source/core/rendering/hw_voxels.h +++ b/source/core/rendering/hw_voxels.h @@ -1,12 +1,16 @@ #pragma once #include -#include "mdsprite.h" +#include "model.h" +#include "model_kvx.h" +#include "intvec.h" -// We still need the relation to mdmodel_t as long as the model code hasn't been redone. -struct voxmodel_t : public mdmodel_t +constexpr int MAXVOXELS = 1024; + +struct voxmodel_t // : public mdmodel_t { FVoxelModel* model = nullptr; + float scale, bscale, zadd, yoffset; vec3_t siz; FVector3 piv; int32_t is8bit; @@ -19,6 +23,9 @@ extern float voxscale[]; extern voxmodel_t* voxmodels[MAXVOXELS]; extern FixedBitArray voxrotate; +inline int32_t nextvoxid; +inline FixedBitArrayvoxreserve; + void voxInit(); void voxClear(); int voxDefine(int voxindex, const char* filename); diff --git a/source/core/rendering/scene/hw_drawinfo.cpp b/source/core/rendering/scene/hw_drawinfo.cpp index c3c91faaf..2840141fc 100644 --- a/source/core/rendering/scene/hw_drawinfo.cpp +++ b/source/core/rendering/scene/hw_drawinfo.cpp @@ -29,7 +29,7 @@ #include "build.h" #include "hw_renderstate.h" #include "hw_drawinfo.h" -//#include "models.h" +#include "models/modeldata.h" #include "hw_clock.h" #include "hw_cvars.h" #include "hw_viewpointbuffer.h" @@ -290,8 +290,8 @@ void HWDrawInfo::DispatchSprites() if (!(actor->sprext.renderflags & SPREXT_NOTMD)) { - int pt = Ptile2tile(tilenum, tspr->pal); - if (hw_models && tile2model[pt].modelid >= 0 && tile2model[pt].framenum >= 0) + auto pt = modelManager.GetModel(tilenum, tspr->pal); + if (hw_models && pt && pt->modelid >= 0 && pt->framenum >= 0) { //HWSprite hwsprite; //if (hwsprite.ProcessModel(pt, tspr)) continue; diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index ac647654b..afdece8ca 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -479,12 +479,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, spritetype &c, spritet FSerializer& Serialize(FSerializer& arc, const char* key, spriteext_t& c, spriteext_t* def) { - if (arc.isWriting() && c.mdanimtims) - { - c.mdanimtims -= mdtims; - if (c.mdanimtims == 0) c.mdanimtims++; - } - def = &zspx; // always delta against 0 if (arc.BeginObject(key)) { @@ -498,7 +492,6 @@ FSerializer& Serialize(FSerializer& arc, const char* key, spriteext_t& c, sprite .EndObject(); } - if (c.mdanimtims) c.mdanimtims += mdtims; return arc; } diff --git a/source/core/textures/buildtiles.cpp b/source/core/textures/buildtiles.cpp index a58b07967..41a35aa35 100644 --- a/source/core/textures/buildtiles.cpp +++ b/source/core/textures/buildtiles.cpp @@ -49,6 +49,7 @@ #include "sc_man.h" #include "gamestruct.h" #include "hw_voxels.h" +#include "models/modeldata.h" #include "hw_renderstate.h" @@ -661,7 +662,7 @@ void tileDelete(int tile) TileFiles.tiledata[tile].texture = TileFiles.tiledata[tile].backup = TexMan.GameByIndex(0); TileFiles.tiledata[tile].replacement = ReplacementType::Art; // whatever this was, now it isn't anymore. (SW tries to nuke camera textures with this, :( ) tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile. - md_undefinetile(tile); + modelManager.UndefineTile(tile); } //========================================================================== diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp index a9b03c1fa..d257ec567 100644 --- a/source/games/blood/src/animatesprite.cpp +++ b/source/games/blood/src/animatesprite.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "v_font.h" #include "hw_voxels.h" #include "gamefuncs.h" +#include "models/modeldata.h" BEGIN_BLD_NS @@ -628,7 +629,7 @@ void viewProcessSprites(tspriteArray& tsprites, const DVector3& cPos, DAngle cA, case 6: case 7: { - if (hw_models && md_tilehasmodel(pTSprite->picnum, pTSprite->pal) >= 0 && !(owneractor->sprext.renderflags & SPREXT_NOTMD)) + if (hw_models && modelManager.CheckModel(pTSprite->picnum, pTSprite->pal) && !(owneractor->sprext.renderflags & SPREXT_NOTMD)) break; // Can be overridden by def script @@ -678,9 +679,9 @@ void viewProcessSprites(tspriteArray& tsprites, const DVector3& cPos, DAngle cA, { int const nRootTile = pTSprite->picnum; int nAnimTile = pTSprite->picnum + tileAnimateOfs(pTSprite->picnum, (pTSprite->ownerActor->GetIndex() & 16383)); + auto pt = modelManager.GetModel(nAnimTile, pTSprite->pal); - if (tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].modelid >= 0 && - tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].framenum >= 0) + if (pt && pt->modelid >= 0 && pt->framenum >= 0) { pTSprite->yoffset += tileTopOffset(nAnimTile); pTSprite->xoffset += tileLeftOffset(nAnimTile); diff --git a/source/games/blood/src/common_game.h b/source/games/blood/src/common_game.h index 52ddef86a..d28c384a1 100644 --- a/source/games/blood/src/common_game.h +++ b/source/games/blood/src/common_game.h @@ -42,7 +42,6 @@ enum kMaxTiles = MAXTILES, kMaxStatus = MAXSTATUS, kMaxPlayers = 8, - kMaxVoxels = MAXVOXELS, kTicRate = 120, kTicsPerFrame = 4, diff --git a/source/games/blood/src/tile.cpp b/source/games/blood/src/tile.cpp index 2b83673c6..e9972cb89 100644 --- a/source/games/blood/src/tile.cpp +++ b/source/games/blood/src/tile.cpp @@ -71,7 +71,7 @@ void GameInterface::LoadGameTextures() } for (int i = 0; i < kMaxTiles; i++) { - if (voxelIndex[i] >= 0 && voxelIndex[i] < kMaxVoxels) + if (voxelIndex[i] >= 0 && voxelIndex[i] < MAXVOXELS) voxreserve.Set(voxelIndex[i]); } } diff --git a/source/games/duke/src/animatesprites_d.cpp b/source/games/duke/src/animatesprites_d.cpp index d4990bede..7d672b59a 100644 --- a/source/games/duke/src/animatesprites_d.cpp +++ b/source/games/duke/src/animatesprites_d.cpp @@ -39,6 +39,7 @@ source as it is released. #include "names_d.h" #include "dukeactor.h" #include "gamefuncs.h" +#include "models/modeldata.h" EXTERN_CVAR(Bool, wt_commentary) @@ -79,7 +80,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi t->xrepeat = t->yrepeat = 0; continue; case CHAIR3: - if (hw_models && md_tilehasmodel(t->picnum, t->pal) >= 0) + if (hw_models && modelManager.CheckModel(t->picnum, t->pal)) { t->cstat &= ~CSTAT_SPRITE_XFLIP; break; @@ -256,7 +257,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi t->picnum = GROWSPARK + ((PlayClock >> 4) & 3); break; case RPG: - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { t->cstat &= ~CSTAT_SPRITE_XFLIP; break; @@ -274,7 +275,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi break; case RECON: - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { t->cstat &= ~CSTAT_SPRITE_XFLIP; break; @@ -363,7 +364,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi if (!h->GetOwner()) { - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { k = 0; t->cstat &= ~CSTAT_SPRITE_XFLIP; @@ -485,7 +486,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi { l = ScriptCode[t4 + 2]; - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { k = 0; t->cstat &= ~CSTAT_SPRITE_XFLIP; @@ -582,7 +583,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi shadowspr->pos.Z = floorz; shadowspr->pal = 4; - if (hw_models && md_tilehasmodel(t->picnum, t->pal) >= 0) + if (hw_models && modelManager.CheckModel(t->picnum, t->pal)) { shadowspr->yrepeat = 0; // 512:trans reverse @@ -652,7 +653,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi t->picnum += (h->spr.shade >> 1); break; case PLAYERONWATER: - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { k = 0; t->cstat &= ~CSTAT_SPRITE_XFLIP; @@ -710,7 +711,7 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi case CAMERA1: case RAT: - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { t->cstat &= ~CSTAT_SPRITE_XFLIP; break; diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index e5f2466ce..f4e8aff7a 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -33,6 +33,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms #include "prediction.h" #include "dukeactor.h" #include "gamefuncs.h" +#include "models/modeldata.h" BEGIN_DUKE_NS @@ -408,7 +409,7 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi if (!h->GetOwner()) { - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { k = 0; t->cstat &= ~CSTAT_SPRITE_XFLIP; @@ -618,7 +619,7 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi { l = ScriptCode[t4 + 2]; - if (hw_models && md_tilehasmodel(h->spr.picnum, h->spr.pal) >= 0) + if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal)) { k = 0; t->cstat &= ~CSTAT_SPRITE_XFLIP; @@ -738,7 +739,7 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi shadowspr->pos.Z = floorz; shadowspr->pal = 4; - if (hw_models && md_tilehasmodel(t->picnum, t->pal) >= 0) + if (hw_models && modelManager.CheckModel(t->picnum, t->pal)) { shadowspr->yrepeat = 0; // 512:trans reverse diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index 010ed7af3..0a8d1d5f1 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -56,6 +56,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "v_draw.h" #include "render.h" #include "razefont.h" +#include "models/modeldata.h" extern DCoreActor* wall_to_sprite_actors[8]; diff --git a/source/games/sw/src/jsector.cpp b/source/games/sw/src/jsector.cpp index 4cff503cb..82dd8f70b 100644 --- a/source/games/sw/src/jsector.cpp +++ b/source/games/sw/src/jsector.cpp @@ -45,6 +45,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "parent.h" #include "v_video.h" #include "render.h" +#include "models/modeldata.h" BEGIN_SW_NS @@ -812,7 +813,7 @@ void JAnalyzeSprites(tspritetype* tspr) // Take care of autosizing DoAutoSize(tspr); - if (md_tilehasmodel(tspr->picnum, 0) >= 0 && hw_models) return; + if (hw_models && modelManager.CheckModel(tspr->picnum, 0)) return; // Check for voxels //if (bVoxelsOn)