From 769d60a64fefc0c8d7260ebb6461c354ec478b11 Mon Sep 17 00:00:00 2001 From: Chernoskill Date: Wed, 24 Feb 2021 21:26:47 +0100 Subject: [PATCH] Dynamic number of models per frame instead of a hard limit of four. (#1298) * Changed model-related arrays to TArrays. * Update models.cpp Used TArray.Alloc to make TArrays have the correct size depending on the number of models. surfaceSkinIDs was two-dimensional and is now a one-dimensional TArray as well, it's size is now (models * MD3_MAX_SURFACES) surfaceSkinIDs was two-dimensional and is now a one-dimensional TArray as well, elements are accessed via [Row + Column * NumRows], in this case sSurfaceIndex + modelIndex * MD3_MAX_SURFACES] * Edited skinSurfaceIDs access for one-dimensional TArray * Edited skinSurfaceIDs access for one-dimensional TArray * Edited skinSurfaceIDs access for one-dimensional TArray * Changed model-related arrays to TArrays. Also removed MAX_MODELS_PER_FRAME. * Used TArray.Alloc to make TArrays have the correct size depending on the number of models. surfaceSkinIDs was two-dimensional and is now a one-dimensional TArray as well, elements are accessed via [Row + Column * NumRows], in this case surfaceIndex + modelIndex * MD3_MAX_SURFACES] * Used TArray.Alloc to make TArrays have the correct size depending on the number of models. surfaceSkinIDs was two-dimensional and is now a one-dimensional TArray as well, elements are accessed via [Row + Column * NumRows], in this case surfaceIndex + modelIndex * MD3_MAX_SURFACES] * Update models.h * Edited MAX_MODELS_MD3 * Update models_obj.cpp --- src/common/models/model.h | 10 ++-- src/common/models/models_md3.cpp | 12 +++-- src/common/models/models_obj.cpp | 10 ++-- src/common/models/models_ue1.cpp | 15 ++++-- src/r_data/models.cpp | 59 +++++++++++++++++++----- src/rendering/hwrenderer/hw_precache.cpp | 2 +- 6 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/common/models/model.h b/src/common/models/model.h index 5fdec020c..52f703570 100644 --- a/src/common/models/model.h +++ b/src/common/models/model.h @@ -15,15 +15,15 @@ void FlushModels(); extern TDeletingArray Models; extern TArray SpriteModelFrames; -#define MAX_MODELS_PER_FRAME 4 #define MD3_MAX_SURFACES 32 struct FSpriteModelFrame { - int modelIDs[MAX_MODELS_PER_FRAME]; - FTextureID skinIDs[MAX_MODELS_PER_FRAME]; - FTextureID surfaceskinIDs[MAX_MODELS_PER_FRAME][MD3_MAX_SURFACES]; - int modelframes[MAX_MODELS_PER_FRAME]; + uint8_t modelsAmount = 0; + TArray modelIDs; + TArray skinIDs; + TArray surfaceskinIDs; + TArray modelframes; float xscale, yscale, zscale; // [BB] Added zoffset, rotation parameters and flags. // Added xoffset, yoffset diff --git a/src/common/models/models_md3.cpp b/src/common/models/models_md3.cpp index 15224e4fe..a81e5c426 100644 --- a/src/common/models/models_md3.cpp +++ b/src/common/models/models_md3.cpp @@ -1,4 +1,4 @@ -// +// //--------------------------------------------------------------------------- // // Copyright(C) 2006-2016 Christoph Oelckers @@ -306,9 +306,10 @@ void FMD3Model::AddSkins(uint8_t *hitlist) { for (unsigned i = 0; i < Surfaces.Size(); i++) { - if (curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) + int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; + if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) { - hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; } MD3Surface * surf = &Surfaces[i]; @@ -357,9 +358,10 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f FGameTexture *surfaceSkin = skin; if (!surfaceSkin) { - if (curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) + int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; + if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) { - surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i], true); + surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); } else if (surf->numSkins > 0 && surf->Skins[0].isValid()) { diff --git a/src/common/models/models_obj.cpp b/src/common/models/models_obj.cpp index 264ffd6ac..07bac6ea9 100644 --- a/src/common/models/models_obj.cpp +++ b/src/common/models/models_obj.cpp @@ -638,9 +638,10 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f FGameTexture *userSkin = skin; if (!userSkin) { - if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) + int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; + if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) { - userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i], true); + userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); } else if (surf->skin.isValid()) { @@ -669,13 +670,14 @@ void FOBJModel::AddSkins(uint8_t* hitlist) { for (size_t i = 0; i < surfaces.Size(); i++) { - if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) + size_t ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; + if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) { // Precache skins manually reassigned by the user. // On OBJs with lots of skins, such as Doom map OBJs exported from GZDB, // there may be too many skins for the user to manually change, unless // the limit is bumped or surfaceskinIDs is changed to a TArray. - hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; return; // No need to precache skin that was replaced } diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index 3066b7759..9fd9b2b50 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -242,8 +242,9 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f FGameTexture *sskin = skin; if ( !sskin ) { - if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) - sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum], true); + int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; + if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); if ( !sskin ) { vofs += vsize; @@ -302,9 +303,13 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) void FUE1Model::AddSkins( uint8_t *hitlist ) { - for ( int i=0; isurfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) - hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].GetIndex()] |= FTextureManager::HIT_Flat; + for (int i = 0; i < numGroups; i++) + { + int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; + if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + } + } FUE1Model::~FUE1Model() diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 0b8a458b4..67ab83636 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -267,8 +267,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr } } } - - for (int i = 0; imodelsAmount; i++) { if (smf->modelIDs[i] != -1) { @@ -317,9 +316,17 @@ void InitModels() FSpriteModelFrame smf; memset(&smf, 0, sizeof(smf)); smf.isVoxel = true; - smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; + + smf.modelsAmount = 1; + smf.modelframes.Alloc(1); + smf.modelframes[0] = -1; + + smf.modelIDs.Alloc(1); smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; + + smf.skinIDs.Alloc(1); smf.skinIDs[0] = md->GetPaletteTexture(); + smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; if (VoxelDefs[i]->PlacedSpin != 0) @@ -345,6 +352,7 @@ void InitModels() } SpriteModelFrames.Push(smf); } + } int Lump; @@ -370,6 +378,7 @@ void InitModels() static void ParseModelDefLump(int Lump) { FScanner sc(Lump); + while (sc.GetString()) { if (sc.Compare("model")) @@ -380,7 +389,6 @@ static void ParseModelDefLump(int Lump) FSpriteModelFrame smf; memset(&smf, 0, sizeof(smf)); - smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.xscale=smf.yscale=smf.zscale=1.f; auto type = PClass::FindClass(sc.String); @@ -389,6 +397,32 @@ static void ParseModelDefLump(int Lump) sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } smf.type = type; + + + FScanner::SavedPos scPos = sc.SavePos(); + + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("model")) + { + sc.MustGetNumber(); + index = sc.Number; + if (index < 0) + { + sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); + } + smf.modelsAmount = index + 1; + } + } + smf.modelIDs.Alloc(smf.modelsAmount); + smf.skinIDs.Alloc(smf.modelsAmount); + smf.surfaceskinIDs.Alloc(smf.modelsAmount * MD3_MAX_SURFACES); + smf.modelframes.Alloc(smf.modelsAmount); + + sc.RestorePos(scPos); + sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -404,17 +438,19 @@ static void ParseModelDefLump(int Lump) { sc.MustGetNumber(); index = sc.Number; - if (index < 0 || index >= MAX_MODELS_PER_FRAME) + if (index < 0 || index >= smf.modelsAmount) { sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); + smf.modelIDs[index] = FindModel(path.GetChars(), sc.String); if (smf.modelIDs[index] == -1) { Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } + } else if (sc.Compare("scale")) { @@ -529,7 +565,7 @@ static void ParseModelDefLump(int Lump) { sc.MustGetNumber(); index=sc.Number; - if (index<0 || index>=MAX_MODELS_PER_FRAME) + if (index<0 || index>= smf.modelsAmount) { sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); } @@ -556,7 +592,7 @@ static void ParseModelDefLump(int Lump) sc.MustGetNumber(); surface = sc.Number; - if (index<0 || index >= MAX_MODELS_PER_FRAME) + if (index<0 || index >= smf.modelsAmount) { sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); } @@ -568,14 +604,15 @@ static void ParseModelDefLump(int Lump) sc.MustGetString(); FixPathSeperator(sc.String); + int ssIndex = surface + index * MD3_MAX_SURFACES; if (sc.Compare("")) { - smf.surfaceskinIDs[index][surface] = FNullTextureID(); + smf.surfaceskinIDs[ssIndex] = FNullTextureID(); } else { - smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String); - if (!smf.surfaceskinIDs[index][surface].isValid()) + smf.surfaceskinIDs[ssIndex] = LoadSkin(path.GetChars(), sc.String); + if (!smf.surfaceskinIDs[ssIndex].isValid()) { Printf("Surface Skin '%s' not found in '%s'\n", sc.String, type->TypeName.GetChars()); @@ -610,7 +647,7 @@ static void ParseModelDefLump(int Lump) sc.MustGetNumber(); index=sc.Number; - if (index<0 || index>=MAX_MODELS_PER_FRAME) + if (index<0 || index>= smf.modelsAmount) { sc.ScriptError("Too many models in %s", type->TypeName.GetChars()); } diff --git a/src/rendering/hwrenderer/hw_precache.cpp b/src/rendering/hwrenderer/hw_precache.cpp index 72b977f80..7ad9192bc 100644 --- a/src/rendering/hwrenderer/hw_precache.cpp +++ b/src/rendering/hwrenderer/hw_precache.cpp @@ -162,7 +162,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false); if (smf != NULL) { - for (int i = 0; i < MAX_MODELS_PER_FRAME; i++) + for (int i = 0; i < smf->modelsAmount; i++) { if (smf->skinIDs[i].isValid()) {