Skip to content

Commit

Permalink
The two TArrays of type FTextureID skinIDs and surfaceskinIDs no long…
Browse files Browse the repository at this point in the history
…er have any null elements. These elements will have a textureid (FTextureID.texnum) of 0.

Re-worded error messages which were unprecise or unfitting before (model index below 0 was not acknowledged at all, or grouped together with a "too many models" message).

modelIDs are given a default value of -1.

Important: A MODELDEF's FrameIndex lines can no longer refer to model indices that are beyond the number of models of that MODELDEF entry. There is in fact a check to avoid going beyond the number of an actor's models which would abort program operation at startup, but it never caught any such occurances.

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.

Also removed MAX_MODELS_PER_FRAME.
Edited skinSurfaceIDs access for one-dimensional TArray

Added MD3_MODELS_MIN
To ensure compatibility with mods, all model-related TArrays (four in total) have a minimum size of 4, defined by MD3_MODELS_MIN.
  • Loading branch information
Chernoskill committed Feb 26, 2021
1 parent e0e0fb0 commit fa20580
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 29 deletions.
11 changes: 6 additions & 5 deletions src/common/models/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ void FlushModels();
extern TDeletingArray<FModel*> Models;
extern TArray<FSpriteModelFrame> SpriteModelFrames;

#define MAX_MODELS_PER_FRAME 4
#define MD3_MAX_SURFACES 32
#define MD3_MIN_MODELS 4

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<int> modelIDs;
TArray<FTextureID> skinIDs;
TArray<FTextureID> surfaceskinIDs;
TArray<int> modelframes;
float xscale, yscale, zscale;
// [BB] Added zoffset, rotation parameters and flags.
// Added xoffset, yoffset
Expand Down
10 changes: 6 additions & 4 deletions src/common/models/models_md3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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())
{
Expand Down
10 changes: 6 additions & 4 deletions src/common/models/models_obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand Down Expand Up @@ -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<FTextureID>.
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
}

Expand Down
14 changes: 9 additions & 5 deletions src/common/models/models_ue1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -302,9 +303,12 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )

void FUE1Model::AddSkins( uint8_t *hitlist )
{
for ( int i=0; i<numGroups; i++ )
if ( curSpriteMDLFrame->surfaceskinIDs[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()
Expand Down
69 changes: 59 additions & 10 deletions src/r_data/models.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
}
}

for (int i = 0; i<MAX_MODELS_PER_FRAME; i++)
for (int i = 0; i < smf->modelsAmount; i++)
{
if (smf->modelIDs[i] != -1)
{
Expand Down Expand Up @@ -317,8 +317,12 @@ 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;
Expand Down Expand Up @@ -380,7 +384,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);
Expand All @@ -389,6 +392,47 @@ 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("Model index must be 0 or greater in %s", type->TypeName.GetChars());
}
smf.modelsAmount = index + 1;
}
}
//Make sure modelsAmount is at least equal to MD3_MIN_MODELS(4) to ensure compatibility with old mods
if (smf.modelsAmount < MD3_MIN_MODELS)
{
smf.modelsAmount = MD3_MIN_MODELS;
}
//Allocate TArrays
smf.modelIDs.Alloc(smf.modelsAmount);
smf.skinIDs.Alloc(smf.modelsAmount);
smf.surfaceskinIDs.Alloc(smf.modelsAmount * MD3_MAX_SURFACES);
smf.modelframes.Alloc(smf.modelsAmount);
//Make sure all modelIDs are -1 by default
for (auto& modelID : smf.modelIDs)
{
modelID = -1;
}
//Make sure no TArray elements of type FTextureID are null. These elements will have a textureid (FTextureID.texnum) of 0.
for (auto& skinID : smf.skinIDs)
{
skinID = FTextureID(FNullTextureID());
}
for (auto& surfaceskinID : smf.surfaceskinIDs)
{
surfaceskinID = FTextureID(FNullTextureID());
}
sc.RestorePos(scPos);
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
Expand All @@ -404,7 +448,11 @@ static void ParseModelDefLump(int Lump)
{
sc.MustGetNumber();
index = sc.Number;
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
if (index < 0)
{
sc.ScriptError("Model index must be 0 or greater in %s", type->TypeName.GetChars());
}
else if (index >= smf.modelsAmount)
{
sc.ScriptError("Too many models in %s", type->TypeName.GetChars());
}
Expand Down Expand Up @@ -529,7 +577,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());
}
Expand All @@ -556,7 +604,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());
}
Expand All @@ -568,14 +616,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());
Expand Down Expand Up @@ -610,7 +659,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());
}
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/hwrenderer/hw_precache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &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())
{
Expand Down

0 comments on commit fa20580

Please sign in to comment.