mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-22 12:01:13 +00:00
ActorModelData cleanup in preparation for decoupled model animations
This commit is contained in:
parent
848dbd4d3d
commit
1a8dfd2dfa
9 changed files with 73 additions and 52 deletions
|
@ -210,8 +210,8 @@ class TObjPtr
|
|||
{
|
||||
union
|
||||
{
|
||||
T pp;
|
||||
DObject *o;
|
||||
mutable T pp;
|
||||
mutable DObject *o;
|
||||
};
|
||||
public:
|
||||
|
||||
|
@ -273,16 +273,22 @@ public:
|
|||
{
|
||||
return GC::ReadBarrier(pp);
|
||||
}
|
||||
constexpr bool operator!=(T u) noexcept
|
||||
|
||||
constexpr const T operator->() const noexcept
|
||||
{
|
||||
return GC::ReadBarrier(pp);
|
||||
}
|
||||
|
||||
constexpr bool operator!=(T u) const noexcept
|
||||
{
|
||||
return GC::ReadBarrier(o) != u;
|
||||
}
|
||||
constexpr bool operator==(T u) noexcept
|
||||
constexpr bool operator==(T u) const noexcept
|
||||
{
|
||||
return GC::ReadBarrier(o) == u;
|
||||
}
|
||||
|
||||
constexpr bool operator==(TObjPtr<T> u) noexcept
|
||||
constexpr bool operator==(TObjPtr<T> u) const noexcept
|
||||
{
|
||||
return ForceGet() == u.ForceGet();
|
||||
}
|
||||
|
|
|
@ -695,12 +695,17 @@ struct ModelOverride
|
|||
TArray<FTextureID> surfaceSkinIDs;
|
||||
};
|
||||
|
||||
enum ModelDataFlags
|
||||
{
|
||||
MODELDATA_HADMODEL = 1 << 0,
|
||||
};
|
||||
|
||||
class DActorModelData : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DActorModelData, DObject);
|
||||
public:
|
||||
FName modelDef;
|
||||
bool hasModel;
|
||||
int flags;
|
||||
TArray<ModelOverride> models;
|
||||
TArray<FTextureID> skinIDs;
|
||||
TArray<int> animationIDs;
|
||||
|
|
|
@ -5088,6 +5088,35 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState)
|
|||
// This function allows the changing of an actor's modeldef, or models and/or skins at a given index
|
||||
//==========================================================================
|
||||
|
||||
static void EnsureModelData(AActor * mobj)
|
||||
{
|
||||
if (mobj->modelData == nullptr)
|
||||
{
|
||||
auto ptr = Create<DActorModelData>();
|
||||
|
||||
ptr->flags = (mobj->hasmodel ? MODELDATA_HADMODEL : 0);
|
||||
ptr->modelDef = NAME_None;
|
||||
|
||||
mobj->modelData = ptr;
|
||||
mobj->hasmodel = true;
|
||||
GC::WriteBarrier(mobj, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void CleanupModelData(AActor * mobj)
|
||||
{
|
||||
if ( mobj->modelData->models.Size() == 0
|
||||
&& mobj->modelData->modelFrameGenerators.Size() == 0
|
||||
&& mobj->modelData->skinIDs.Size() == 0
|
||||
&& mobj->modelData->animationIDs.Size() == 0
|
||||
&& mobj->modelData->modelDef == NAME_None)
|
||||
{
|
||||
mobj->hasmodel = mobj->modelData->flags & MODELDATA_HADMODEL;
|
||||
mobj->modelData->Destroy();
|
||||
mobj->modelData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
enum ChangeModelFlags
|
||||
{
|
||||
CMDL_WEAPONTOPLAYER = 1,
|
||||
|
@ -5139,17 +5168,7 @@ void ChangeModelNative(
|
|||
if (skinpath.Len() != 0 && skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
||||
if (animationpath.Len() != 0 && animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/';
|
||||
|
||||
if (mobj->modelData == nullptr)
|
||||
{
|
||||
auto ptr = Create<DActorModelData>();
|
||||
|
||||
ptr->hasModel = mobj->hasmodel;
|
||||
ptr->modelDef = NAME_None;
|
||||
|
||||
mobj->modelData = ptr;
|
||||
mobj->hasmodel = true;
|
||||
GC::WriteBarrier(mobj, ptr);
|
||||
};
|
||||
EnsureModelData(mobj);
|
||||
|
||||
int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2;
|
||||
int queryAnimation = animation != NAME_None ? FindModel(animationpath.GetChars(), animation.GetChars()) : -1;
|
||||
|
@ -5290,12 +5309,7 @@ void ChangeModelNative(
|
|||
if(!found) savedModelFiles.Push(fullName);
|
||||
}
|
||||
|
||||
if (mobj->modelData->models.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->animationIDs.Size() == 0 && modeldef == NAME_None)
|
||||
{
|
||||
mobj->hasmodel = mobj->modelData->hasModel;
|
||||
mobj->modelData->Destroy();
|
||||
mobj->modelData = nullptr;
|
||||
}
|
||||
CleanupModelData(mobj);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1345,7 +1345,7 @@ void DActorModelData::Serialize(FSerializer& arc)
|
|||
//("surfaceSkinIDs", surfaceSkinIDs)
|
||||
("animationIDs", animationIDs)
|
||||
("modelFrameGenerators", modelFrameGenerators)
|
||||
("hasModel", hasModel);
|
||||
("flags", flags);
|
||||
}
|
||||
|
||||
void DActorModelData::OnDestroy()
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "i_time.h"
|
||||
#include "texturemanager.h"
|
||||
#include "modelrenderer.h"
|
||||
#include "actor.h"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -55,7 +56,7 @@ EXTERN_CVAR (Bool, r_drawvoxels)
|
|||
extern TDeletingArray<FVoxel *> Voxels;
|
||||
extern TDeletingArray<FVoxelDef *> VoxelDefs;
|
||||
|
||||
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, const PClass* ti, FTranslationID translation, AActor* actor);
|
||||
void RenderFrameModels(FModelRenderer* renderer, FLevelLocals* Level, const FSpriteModelFrame *smf, const FState* curState, const int curTics, FTranslationID translation, AActor* actor);
|
||||
|
||||
|
||||
void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor, double ticFrac)
|
||||
|
@ -189,7 +190,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
|
|||
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
|
||||
|
||||
renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0);
|
||||
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, actor->modelData != nullptr ? actor->modelData->modelDef != NAME_None ? PClass::FindActor(actor->modelData->modelDef) : actor->GetClass() : actor->GetClass(), translation, actor);
|
||||
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, translation, actor);
|
||||
renderer->EndDrawModel(actor->RenderStyle, smf);
|
||||
}
|
||||
|
||||
|
@ -248,14 +249,11 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
|
|||
auto trans = psp->GetTranslation();
|
||||
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
|
||||
|
||||
auto callerclass = psp->Caller->modelData != nullptr && psp->Caller->modelData->modelDef != NAME_None ?
|
||||
PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass();
|
||||
|
||||
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), callerclass, trans, psp->Caller);
|
||||
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), trans, psp->Caller);
|
||||
renderer->EndDrawHUDModel(playermo->RenderStyle, smf);
|
||||
}
|
||||
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, FTranslationID translation, AActor* actor)
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
||||
{
|
||||
// [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.
|
||||
|
@ -298,7 +296,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
}
|
||||
}
|
||||
if (nextState && inter != 0.0)
|
||||
smfNext = FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
|
||||
smfNext = FindModelFrame(actor, nextState->sprite, nextState->Frame, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -969,7 +967,7 @@ static void ParseModelDefLump(int Lump)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
|
||||
FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped)
|
||||
{
|
||||
if (GetDefaultByType(ti)->hasmodel)
|
||||
{
|
||||
|
@ -1008,6 +1006,11 @@ FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, boo
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped)
|
||||
{
|
||||
return FindModelFrameRaw((thing->modelData != nullptr && thing->modelData->modelDef != NAME_None) ? PClass::FindActor(thing->modelData->modelDef) : thing->GetClass(), sprite, frame, dropped);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// IsHUDModelForPlayerAvailable
|
||||
|
@ -1022,7 +1025,7 @@ bool IsHUDModelForPlayerAvailable (player_t * player)
|
|||
// [MK] check that at least one psprite uses models
|
||||
for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
|
||||
{
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
if ( smf != nullptr ) return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -62,7 +62,8 @@ enum
|
|||
MDL_FORCECULLBACKFACES = 1<<14,
|
||||
};
|
||||
|
||||
FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
|
||||
FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame, bool dropped);
|
||||
FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped);
|
||||
bool IsHUDModelForPlayerAvailable(player_t * player);
|
||||
|
||||
// Check if circle potentially intersects with node AABB
|
||||
|
|
|
@ -159,7 +159,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
|
|||
{
|
||||
auto &state = cls->GetStates()[i];
|
||||
spritelist[state.sprite].Insert(gltrans, true);
|
||||
FSpriteModelFrame * smf = FindModelFrame(cls, state.sprite, state.Frame, false);
|
||||
FSpriteModelFrame * smf = FindModelFrameRaw(cls, state.sprite, state.Frame, false);
|
||||
if (smf != NULL)
|
||||
{
|
||||
for (int i = 0; i < smf->modelsAmount; i++)
|
||||
|
|
|
@ -783,21 +783,15 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
if (fabs(viewpos.X - vp.Pos.X) < 32 && fabs(viewpos.Y - vp.Pos.Y) < 32) return;
|
||||
}
|
||||
|
||||
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing, spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
|
||||
|
||||
// Too close to the camera. This doesn't look good if it is a sprite.
|
||||
if (fabs(thingpos.X - vp.Pos.X) < 2 && fabs(thingpos.Y - vp.Pos.Y) < 2)
|
||||
{
|
||||
if (vp.Pos.Z >= thingpos.Z - 2 && vp.Pos.Z <= thingpos.Z + thing->Height + 2)
|
||||
{
|
||||
// exclude vertically moving objects from this check.
|
||||
if (!thing->Vel.isZero())
|
||||
{
|
||||
if (!FindModelFrame(thing->GetClass(), spritenum, thing->frame, false))
|
||||
if (fabs(thingpos.X - vp.Pos.X) < 2 && fabs(thingpos.Y - vp.Pos.Y) < 2
|
||||
&& vp.Pos.Z >= thingpos.Z - 2 && vp.Pos.Z <= thingpos.Z + thing->Height + 2
|
||||
&& !thing->Vel.isZero() && !modelframe) // exclude vertically moving objects from this check.
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// don't draw first frame of a player missile
|
||||
if (thing->flags&MF_MISSILE)
|
||||
|
@ -856,8 +850,6 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
z += fz;
|
||||
}
|
||||
|
||||
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->modelData != nullptr ? thing->modelData->modelDef != NAME_None ? PClass::FindActor(thing->modelData->modelDef) : thing->GetClass() : thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
|
||||
|
||||
// don't bother drawing sprite shadows if this is a model (it will never look right)
|
||||
if (modelframe && isSpriteShadow)
|
||||
{
|
||||
|
|
|
@ -707,7 +707,7 @@ void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area)
|
|||
{
|
||||
if (!psp->GetState()) continue;
|
||||
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
|
||||
// This is an 'either-or' proposition. This maybe needs some work to allow overlays with weapon models but as originally implemented this just won't work.
|
||||
if (smf) continue;
|
||||
|
@ -792,7 +792,7 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area)
|
|||
for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
|
||||
{
|
||||
if (!psp->GetState()) continue;
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller->modelData != nullptr ? psp->Caller->modelData->modelDef != NAME_None ? PClass::FindActor(psp->Caller->modelData->modelDef) : psp->Caller->GetClass() : psp->Caller->GetClass(), psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
FSpriteModelFrame *smf = psp->Caller != nullptr ? FindModelFrame(psp->Caller, psp->GetSprite(), psp->GetFrame(), false) : nullptr;
|
||||
|
||||
// This is an 'either-or' proposition. This maybe needs some work to allow overlays with weapon models but as originally implemented this just won't work.
|
||||
if (!smf) continue;
|
||||
|
|
Loading…
Reference in a new issue