This commit is contained in:
Christoph Oelckers 2021-03-06 11:32:31 +01:00
commit d18b74b537
6 changed files with 87 additions and 29 deletions

View file

@ -15,15 +15,16 @@ void FlushModels();
extern TDeletingArray<FModel*> Models; extern TDeletingArray<FModel*> Models;
extern TArray<FSpriteModelFrame> SpriteModelFrames; extern TArray<FSpriteModelFrame> SpriteModelFrames;
#define MAX_MODELS_PER_FRAME 4
#define MD3_MAX_SURFACES 32 #define MD3_MAX_SURFACES 32
#define MIN_MODELS 4
struct FSpriteModelFrame struct FSpriteModelFrame
{ {
int modelIDs[MAX_MODELS_PER_FRAME]; uint8_t modelsAmount = 0;
FTextureID skinIDs[MAX_MODELS_PER_FRAME]; TArray<int> modelIDs;
FTextureID surfaceskinIDs[MAX_MODELS_PER_FRAME][MD3_MAX_SURFACES]; TArray<FTextureID> skinIDs;
int modelframes[MAX_MODELS_PER_FRAME]; TArray<FTextureID> surfaceskinIDs;
TArray<int> modelframes;
float xscale, yscale, zscale; float xscale, yscale, zscale;
// [BB] Added zoffset, rotation parameters and flags. // [BB] Added zoffset, rotation parameters and flags.
// Added xoffset, yoffset // Added xoffset, yoffset

View file

@ -306,9 +306,10 @@ void FMD3Model::AddSkins(uint8_t *hitlist)
{ {
for (unsigned i = 0; i < Surfaces.Size(); i++) for (unsigned i = 0; i < Surfaces.Size(); i++)
{ {
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && 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]; MD3Surface * surf = &Surfaces[i];
@ -359,9 +360,10 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f
{ {
if (curSpriteMDLFrame) if (curSpriteMDLFrame)
{ {
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()) else if (surf->numSkins > 0 && surf->Skins[0].isValid())
{ {

View file

@ -638,9 +638,10 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f
FGameTexture *userSkin = skin; FGameTexture *userSkin = skin;
if (!userSkin && curSpriteMDLFrame) if (!userSkin && curSpriteMDLFrame)
{ {
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()) else if (surf->skin.isValid())
{ {
@ -669,13 +670,14 @@ void FOBJModel::AddSkins(uint8_t* hitlist)
{ {
for (size_t i = 0; i < surfaces.Size(); i++) for (size_t i = 0; i < surfaces.Size(); i++)
{ {
if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid()) size_t ssIndex = i + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
{ {
// Precache skins manually reassigned by the user. // Precache skins manually reassigned by the user.
// On OBJs with lots of skins, such as Doom map OBJs exported from GZDB, // 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 // 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>. // 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 return; // No need to precache skin that was replaced
} }

View file

@ -242,8 +242,9 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f
FGameTexture *sskin = skin; FGameTexture *sskin = skin;
if ( !sskin ) if ( !sskin )
{ {
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES;
sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum], true); if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true);
if ( !sskin ) if ( !sskin )
{ {
vofs += vsize; vofs += vsize;
@ -302,9 +303,12 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
void FUE1Model::AddSkins( uint8_t *hitlist ) void FUE1Model::AddSkins( uint8_t *hitlist )
{ {
for ( int i=0; i<numGroups; i++ ) for (int i = 0; i < numGroups; i++)
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() ) {
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].GetIndex()] |= FTextureManager::HIT_Flat; int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES;
if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid())
hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat;
}
} }
FUE1Model::~FUE1Model() FUE1Model::~FUE1Model()

View file

@ -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) if (smf->modelIDs[i] != -1)
{ {
@ -317,8 +317,12 @@ void InitModels()
FSpriteModelFrame smf; FSpriteModelFrame smf;
memset(&smf, 0, sizeof(smf)); memset(&smf, 0, sizeof(smf));
smf.isVoxel = true; 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.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
smf.skinIDs.Alloc(1);
smf.skinIDs[0] = md->GetPaletteTexture(); smf.skinIDs[0] = md->GetPaletteTexture();
smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale;
smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees;
@ -380,7 +384,6 @@ static void ParseModelDefLump(int Lump)
FSpriteModelFrame smf; FSpriteModelFrame smf;
memset(&smf, 0, sizeof(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; smf.xscale=smf.yscale=smf.zscale=1.f;
auto type = PClass::FindClass(sc.String); auto type = PClass::FindClass(sc.String);
@ -389,6 +392,47 @@ static void ParseModelDefLump(int Lump)
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
} }
smf.type = type; 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 MIN_MODELS(4) to ensure compatibility with old mods
if (smf.modelsAmount < MIN_MODELS)
{
smf.modelsAmount = 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("{"); sc.MustGetStringName("{");
while (!sc.CheckString("}")) while (!sc.CheckString("}"))
{ {
@ -404,7 +448,11 @@ static void ParseModelDefLump(int Lump)
{ {
sc.MustGetNumber(); sc.MustGetNumber();
index = sc.Number; 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()); sc.ScriptError("Too many models in %s", type->TypeName.GetChars());
} }
@ -529,7 +577,7 @@ static void ParseModelDefLump(int Lump)
{ {
sc.MustGetNumber(); sc.MustGetNumber();
index=sc.Number; 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.ScriptError("Too many models in %s", type->TypeName.GetChars());
} }
@ -556,7 +604,7 @@ static void ParseModelDefLump(int Lump)
sc.MustGetNumber(); sc.MustGetNumber();
surface = sc.Number; 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()); sc.ScriptError("Too many models in %s", type->TypeName.GetChars());
} }
@ -568,14 +616,15 @@ static void ParseModelDefLump(int Lump)
sc.MustGetString(); sc.MustGetString();
FixPathSeperator(sc.String); FixPathSeperator(sc.String);
int ssIndex = surface + index * MD3_MAX_SURFACES;
if (sc.Compare("")) if (sc.Compare(""))
{ {
smf.surfaceskinIDs[index][surface] = FNullTextureID(); smf.surfaceskinIDs[ssIndex] = FNullTextureID();
} }
else else
{ {
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String); smf.surfaceskinIDs[ssIndex] = LoadSkin(path.GetChars(), sc.String);
if (!smf.surfaceskinIDs[index][surface].isValid()) if (!smf.surfaceskinIDs[ssIndex].isValid())
{ {
Printf("Surface Skin '%s' not found in '%s'\n", Printf("Surface Skin '%s' not found in '%s'\n",
sc.String, type->TypeName.GetChars()); sc.String, type->TypeName.GetChars());
@ -610,7 +659,7 @@ static void ParseModelDefLump(int Lump)
sc.MustGetNumber(); sc.MustGetNumber();
index=sc.Number; 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.ScriptError("Too many models in %s", type->TypeName.GetChars());
} }

View file

@ -162,7 +162,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false); FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false);
if (smf != NULL) 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()) if (smf->skinIDs[i].isValid())
{ {