- rewrote the model storage code.

Using proper C++ containers now.
This commit is contained in:
Christoph Oelckers 2022-09-30 16:25:21 +02:00
parent 8bc34f3dac
commit a4dd5bb4ce
29 changed files with 401 additions and 1374 deletions

View file

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

View file

@ -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.

View file

@ -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

View file

@ -438,7 +438,7 @@ void Display()
screen->FrameTime = I_msTimeFS();
screen->BeginFrame();
screen->SetSceneRenderTarget(gl_ssao != 0);
updateModelInterpolation();
//updateModelInterpolation();
gi->Render();
DrawFullscreenBlends();
drawMapTitle();

View file

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

View file

@ -0,0 +1,85 @@
#pragma once
#include <stdint.h>
#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<ModelAnimation> anims;
TArray<ModelSkinDef> skins;
};
struct ModelTileFrame
{
// maps build tiles to particular animation frames of a model
int modelid;
int framenum;
float smoothduration;
int skinnum;
};
struct ModelManager
{
TArray<ModelDescriptor> modelDescs;
TMap<unsigned, ModelTileFrame> 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;

View file

@ -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
}

View file

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

View file

@ -1,12 +1,16 @@
#pragma once
#include <stdint.h>
#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<MAXVOXELS> voxrotate;
inline int32_t nextvoxid;
inline FixedBitArray<MAXVOXELS>voxreserve;
void voxInit();
void voxClear();
int voxDefine(int voxindex, const char* filename);

View file

@ -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;

View file

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

View file

@ -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);
}
//==========================================================================