- fixed destructive logic and memory allocation issues in RenderFrameModels.
This completely avoids modification of the model data, instead using local variables.
This commit is contained in:
parent
0665a28253
commit
76c8214d67
13 changed files with 66 additions and 57 deletions
|
|
@ -230,13 +230,11 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, float ofsX, float o
|
|||
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation, AActor* actor)
|
||||
{
|
||||
//[SM] - Create a temporary sprite model frame, which prevents data from being overwritten
|
||||
FSpriteModelFrame* tempsmf = new FSpriteModelFrame(*smf);
|
||||
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
|
||||
// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
|
||||
FSpriteModelFrame * smfNext = nullptr;
|
||||
double inter = 0.;
|
||||
if (gl_interpolate_model_frames && !(tempsmf->flags & MDL_NOINTERPOLATION))
|
||||
if (gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION))
|
||||
{
|
||||
FState *nextState = curState->GetNextState();
|
||||
if (curState != nextState && nextState)
|
||||
|
|
@ -258,7 +256,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
{
|
||||
// [BB] Workaround for actors that use the same frame twice in a row.
|
||||
// Most of the standard Doom monsters do this in their see state.
|
||||
if ((tempsmf->flags & MDL_INTERPOLATEDOUBLEDFRAMES))
|
||||
if ((smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES))
|
||||
{
|
||||
const FState *prevState = curState - 1;
|
||||
if ((curState->sprite == prevState->sprite) && (curState->Frame == prevState->Frame))
|
||||
|
|
@ -278,61 +276,75 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
}
|
||||
}
|
||||
|
||||
int modelsamount = smf->modelsAmount;
|
||||
//[SM] - if we added any models for the frame to also render, then we also need to update modelsAmount for this smf
|
||||
if (actor->modelData != nullptr)
|
||||
{
|
||||
if (tempsmf->modelsAmount < actor->modelData->modelIDs.Size())
|
||||
{
|
||||
tempsmf->modelsAmount = actor->modelData->modelIDs.Size();
|
||||
while (tempsmf->modelframes.Size() < actor->modelData->modelIDs.Size()) tempsmf->modelframes.Push(-1);
|
||||
while (smfNext->modelframes.Size() < actor->modelData->modelIDs.Size()) smfNext->modelframes.Push(-1);
|
||||
}
|
||||
modelsamount = actor->modelData->modelIDs.Size();
|
||||
}
|
||||
|
||||
for (int i = 0; i < tempsmf->modelsAmount; i++)
|
||||
TArray<FTextureID> surfaceskinids;
|
||||
|
||||
for (int i = 0; i < modelsamount; i++)
|
||||
{
|
||||
int modelid = -1;
|
||||
int modelframe = -1;
|
||||
int modelframenext = -1;
|
||||
FTextureID skinid; skinid.SetInvalid();
|
||||
|
||||
surfaceskinids.Clear();
|
||||
bool surfaceskinsswapped = false;
|
||||
if (actor->modelData != nullptr)
|
||||
{
|
||||
if (i < (int)actor->modelData->modelIDs.Size())
|
||||
{
|
||||
if (actor->modelData->modelIDs[i] != -1)
|
||||
tempsmf->modelIDs[i] = actor->modelData->modelIDs[i];
|
||||
}
|
||||
modelid = actor->modelData->modelIDs[i];
|
||||
|
||||
if (i < (int)actor->modelData->modelFrameGenerators.Size())
|
||||
{
|
||||
//[SM] - We will use this little snippet to allow a modder to specify a model index to clone. It's also pointless to clone something that clones something else in this case. And causes me headaches.
|
||||
if (actor->modelData->modelFrameGenerators[i] >= 0 && smf->modelframes[i] != -1)
|
||||
if (actor->modelData->modelFrameGenerators[i] >= 0 && smf->modelframes.Size() < (unsigned)i && smf->modelframes[i] != -1)
|
||||
{
|
||||
tempsmf->modelframes[i] = tempsmf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
if (smfNext) smfNext->modelframes[i] = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
}
|
||||
}
|
||||
if (i < (int)actor->modelData->skinIDs.Size())
|
||||
{
|
||||
if (actor->modelData->skinIDs[i].isValid())
|
||||
tempsmf->skinIDs[i] = actor->modelData->skinIDs[i];
|
||||
skinid = actor->modelData->skinIDs[i];
|
||||
}
|
||||
for (int surface = i * MD3_MAX_SURFACES; surface < (i + 1) * MD3_MAX_SURFACES; surface++)
|
||||
{
|
||||
if (surface < (int)actor->modelData->surfaceSkinIDs.Size())
|
||||
{
|
||||
if (actor->modelData->surfaceSkinIDs[surface].isValid())
|
||||
tempsmf->surfaceskinIDs[surface] = actor->modelData->surfaceSkinIDs[surface];
|
||||
{
|
||||
// only make a copy of the surfaceskinIDs array if really needed
|
||||
if (surfaceskinids.Size() == 0) surfaceskinids = smf->surfaceskinIDs;
|
||||
surfaceskinids[surface] = actor->modelData->surfaceSkinIDs[surface];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tempsmf->modelIDs[i] >= 0)
|
||||
if (i < smf->modelsAmount)
|
||||
{
|
||||
FModel * mdl = Models[tempsmf->modelIDs[i]];
|
||||
auto tex = tempsmf->skinIDs[i].isValid() ? TexMan.GetGameTexture(tempsmf->skinIDs[i], true) : nullptr;
|
||||
if (modelid == -1) modelid = smf->modelIDs[i];
|
||||
if (modelframe == -1) modelframe = smf->modelframes[i];
|
||||
if (modelframenext == -1 && smfNext) modelframenext = smfNext->modelframes[i];
|
||||
if (!skinid.isValid()) skinid = smf->skinIDs[i];
|
||||
}
|
||||
|
||||
if (modelid >= 0)
|
||||
{
|
||||
FModel * mdl = Models[modelid];
|
||||
auto tex = skinid.isValid() ? TexMan.GetGameTexture(skinid, true) : nullptr;
|
||||
mdl->BuildVertexBuffer(renderer);
|
||||
|
||||
mdl->PushSpriteMDLFrame(tempsmf, i);
|
||||
mdl->PushSpriteMDLFrame(smf, i);
|
||||
|
||||
if (smfNext && tempsmf->modelframes[i] != smfNext->modelframes[i])
|
||||
mdl->RenderFrame(renderer, tex, tempsmf->modelframes[i], smfNext->modelframes[i], inter, translation);
|
||||
if (smfNext && modelframe != modelframenext)
|
||||
mdl->RenderFrame(renderer, tex, modelframe, modelframenext, inter, translation, surfaceskinids.Size() > 0? surfaceskinids : smf->surfaceskinIDs);
|
||||
else
|
||||
mdl->RenderFrame(renderer, tex, tempsmf->modelframes[i], tempsmf->modelframes[i], 0.f, translation);
|
||||
mdl->RenderFrame(renderer, tex, modelframe, modelframe, 0.f, translation, surfaceskinids.Size() > 0 ? surfaceskinids : smf->surfaceskinIDs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue