allow modeldef flags to be overriden

This commit is contained in:
Ricardo Luís Vaz Silva 2024-01-05 09:46:15 -03:00 committed by Rachael Alexanderson
parent d789676b26
commit 98e6330eaa
11 changed files with 156 additions and 46 deletions

View file

@ -41,7 +41,9 @@ struct FSpriteModelFrame
float xrotate, yrotate, zrotate;
float rotationCenterX, rotationCenterY, rotationCenterZ;
float rotationSpeed;
private:
unsigned int flags;
public:
const void* type; // used for hashing, must point to something usable as identifier for the model's owner.
short sprite;
short frame;
@ -50,6 +52,9 @@ struct FSpriteModelFrame
// added pithoffset, rolloffset.
float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float.
bool isVoxel;
unsigned int getFlags(class DActorModelData * defs) const;
friend void InitModels();
friend void ParseModelDefLump(int Lump);
};

View file

@ -10,15 +10,15 @@ public:
virtual ModelRendererType GetType() const = 0;
virtual void BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0;
virtual void EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) = 0;
virtual void BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored) = 0;
virtual void EndDrawModel(FRenderStyle style, int smf_flags) = 0;
virtual IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) = 0;
virtual VSMatrix GetViewToWorldMatrix() = 0;
virtual void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, FSpriteModelFrame *smf) = 0;
virtual void EndDrawHUDModel(FRenderStyle style, FSpriteModelFrame *smf) = 0;
virtual void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags) = 0;
virtual void EndDrawHUDModel(FRenderStyle style, int smf_flags) = 0;
virtual void SetInterpolation(double interpolation) = 0;
virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) = 0;

View file

@ -719,18 +719,21 @@ struct ModelOverride
enum EModelDataFlags
{
MODELDATA_HADMODEL = 1 << 0,
MODELDATA_OVERRIDE_FLAGS = 1 << 1,
};
class DActorModelData : public DObject
{
DECLARE_CLASS(DActorModelData, DObject);
public:
FName modelDef;
PClass * modelDef;
TArray<ModelOverride> models;
TArray<FTextureID> skinIDs;
TArray<int> animationIDs;
TArray<int> modelFrameGenerators;
int flags;
int overrideFlagsSet;
int overrideFlagsClear;
AnimOverride curAnim;
AnimOverride prevAnim; // used for interpolation when switching anims

View file

@ -5096,7 +5096,7 @@ static void EnsureModelData(AActor * mobj)
auto ptr = Create<DActorModelData>();
ptr->flags = (mobj->hasmodel ? MODELDATA_HADMODEL : 0);
ptr->modelDef = NAME_None;
ptr->modelDef = nullptr;
mobj->modelData = ptr;
mobj->hasmodel = true;
@ -5111,7 +5111,8 @@ static void CleanupModelData(AActor * mobj)
&& mobj->modelData->modelFrameGenerators.Size() == 0
&& mobj->modelData->skinIDs.Size() == 0
&& mobj->modelData->animationIDs.Size() == 0
&& mobj->modelData->modelDef == NAME_None)
&& mobj->modelData->modelDef == nullptr
&&(mobj->modelData->flags & ~MODELDATA_HADMODEL) == 0 )
{
mobj->hasmodel = mobj->modelData->flags & MODELDATA_HADMODEL;
mobj->modelData->Destroy();
@ -5123,6 +5124,8 @@ enum ESetAnimationFlags
{
SAF_INSTANT = 1 << 0,
SAF_LOOP = 1 << 1,
SAF_USEACTORROLL = 1 << 2,
SAF_USEACTORPITCH = 1 << 3,
};
void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int interpolateTics, int flags, double ticFrac)
@ -5265,6 +5268,32 @@ void SetAnimationFrameRateUINative(AActor * self, double framerate)
SetAnimationFrameRateInternal(self, framerate, I_GetTimeFrac());
}
void SetModelFlag(AActor * self, int flag)
{
EnsureModelData(self);
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsSet |= flag;
self->modelData->overrideFlagsClear &= ~flag;
}
void ClearModelFlag(AActor * self, int flag)
{
EnsureModelData(self);
self->modelData->flags |= MODELDATA_OVERRIDE_FLAGS;
self->modelData->overrideFlagsClear |= flag;
self->modelData->overrideFlagsSet &= ~flag;
}
void ResetModelFlags(AActor * self)
{
if(self->modelData)
{
self->modelData->overrideFlagsClear = 0;
self->modelData->overrideFlagsSet = 0;
self->modelData->flags &= ~MODELDATA_OVERRIDE_FLAGS;
}
}
enum ChangeModelFlags
{
CMDL_WEAPONTOPLAYER = 1 << 0,
@ -5291,14 +5320,16 @@ void ChangeModelNative(
) {
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
FName modeldef { ENamedName(i_modeldef) };
FName n_modeldef { ENamedName(i_modeldef) };
FName model { ENamedName(i_model) };
FName skin { ENamedName(i_skin) };
FName animation { ENamedName(i_animation) };
if (modeldef != NAME_None && PClass::FindClass(modeldef.GetChars()) == nullptr)
PClass * modeldef = nullptr;
if (n_modeldef != NAME_None && (modeldef = PClass::FindActor(n_modeldef.GetChars())) == nullptr)
{
Printf("Attempt to pass invalid modeldef name %s in %s.", modeldef.GetChars(), self->GetCharacterName());
Printf("Attempt to pass invalid modeldef name %s in %s.", n_modeldef.GetChars(), self->GetCharacterName());
return;
}
@ -5533,6 +5564,35 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetAnimationFrameRateUI, SetAnimationFrame
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, SetModelFlag, SetModelFlag)
{
PARAM_ACTION_PROLOGUE(AActor);
PARAM_INT(flag);
SetModelFlag(self, flag);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearModelFlag, ClearModelFlag)
{
PARAM_ACTION_PROLOGUE(AActor);
PARAM_INT(flag);
ClearModelFlag(self, flag);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, ResetModelFlags, ResetModelFlags)
{
PARAM_ACTION_PROLOGUE(AActor);
ResetModelFlags(self);
return 0;
}
// This needs to account for the fact that internally renderstyles are stored as a series of operations,
// but the script side only cares about symbolic constants.
DEFINE_ACTION_FUNCTION(AActor, GetRenderStyle)

View file

@ -63,8 +63,10 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
{
// Setup transformation.
int smf_flags = smf->getFlags(actor->modelData);
FTranslationID translation = NO_TRANSLATION;
if (!(smf->flags & MDL_IGNORETRANSLATION))
if (!(smf_flags & MDL_IGNORETRANSLATION))
translation = actor->Translation;
// y scale for a sprite means height, i.e. z in the world!
@ -82,7 +84,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
float angle = angles.Yaw.Degrees();
// [BB] Workaround for the missing pitch information.
if ((smf->flags & MDL_PITCHFROMMOMENTUM))
if ((smf_flags & MDL_PITCHFROMMOMENTUM))
{
const double x = actor->Vel.X;
const double y = actor->Vel.Y;
@ -102,7 +104,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
}
}
if (smf->flags & MDL_ROTATING)
if (smf_flags & MDL_ROTATING)
{
if (smf->rotationSpeed > 0.0000000001 || smf->rotationSpeed < -0.0000000001)
{
@ -118,13 +120,13 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
// If both flags MDL_USEACTORPITCH and MDL_PITCHFROMMOMENTUM are set, the pitch sums up the actor pitch and the velocity vector pitch.
if (smf->flags & MDL_USEACTORPITCH)
if (smf_flags & MDL_USEACTORPITCH)
{
double d = angles.Pitch.Degrees();
if (smf->flags & MDL_BADROTATION) pitch += d;
if (smf_flags & MDL_BADROTATION) pitch += d;
else pitch -= d;
}
if (smf->flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees();
if (smf_flags & MDL_USEACTORROLL) roll += angles.Roll.Degrees();
VSMatrix objectToWorldMatrix;
objectToWorldMatrix.loadIdentity();
@ -140,7 +142,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
// [MK] distortions might happen depending on when the pixel stretch is compensated for
// so we make the "undistorted" behavior opt-in
if (smf->flags & MDL_CORRECTPIXELSTRETCH)
if (smf_flags & MDL_CORRECTPIXELSTRETCH)
{
stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
objectToWorldMatrix.scale(1, stretch, 1);
@ -148,14 +150,14 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
// Applying model transformations:
// 1) Applying actor angle, pitch and roll to the model
if (smf->flags & MDL_USEROTATIONCENTER)
if (smf_flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterZ/stretch, smf->rotationCenterY);
}
objectToWorldMatrix.rotate(-angle, 0, 1, 0);
objectToWorldMatrix.rotate(pitch, 0, 0, 1);
objectToWorldMatrix.rotate(-roll, 1, 0, 0);
if (smf->flags & MDL_USEROTATIONCENTER)
if (smf_flags & MDL_USEROTATIONCENTER)
{
objectToWorldMatrix.translate(-smf->rotationCenterX, -smf->rotationCenterZ/stretch, -smf->rotationCenterY);
}
@ -163,7 +165,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
// 2) Applying Doomsday like rotation of the weapon pickup models
// The rotation angle is based on the elapsed time.
if (smf->flags & MDL_ROTATING)
if (smf_flags & MDL_ROTATING)
{
objectToWorldMatrix.translate(smf->rotationCenterX, smf->rotationCenterY/stretch, smf->rotationCenterZ);
objectToWorldMatrix.rotate(rotateOffset, smf->xrotate, smf->yrotate, smf->zrotate);
@ -181,7 +183,7 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
objectToWorldMatrix.rotate(smf->pitchoffset, 0, 0, 1);
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
if (!(smf->flags & MDL_CORRECTPIXELSTRETCH))
if (!(smf_flags & MDL_CORRECTPIXELSTRETCH))
{
stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor(actor->Level->info->pixelstretch) : 1.f) / actor->Level->info->pixelstretch;
objectToWorldMatrix.scale(1, stretch, 1);
@ -189,15 +191,17 @@ void RenderModel(FModelRenderer *renderer, float x, float y, float z, FSpriteMod
float orientation = scaleFactorX * scaleFactorY * scaleFactorZ;
renderer->BeginDrawModel(actor->RenderStyle, smf, objectToWorldMatrix, orientation < 0);
renderer->BeginDrawModel(actor->RenderStyle, smf_flags, objectToWorldMatrix, orientation < 0);
RenderFrameModels(renderer, actor->Level, smf, actor->state, actor->tics, translation, actor);
renderer->EndDrawModel(actor->RenderStyle, smf);
renderer->EndDrawModel(actor->RenderStyle, smf_flags);
}
void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translation, FVector3 rotation, FVector3 rotation_pivot, FSpriteModelFrame *smf)
{
AActor * playermo = players[consoleplayer].camera;
int smf_flags = smf->getFlags(psp->Caller->modelData);
// [BB] No model found for this sprite, so we can't render anything.
if (smf == nullptr)
return;
@ -208,7 +212,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
// [Nash] Optional scale weapon FOV
float fovscale = 1.0f;
if (smf->flags & MDL_SCALEWEAPONFOV)
if (smf_flags & MDL_SCALEWEAPONFOV)
{
fovscale = tan(players[consoleplayer].DesiredFOV * (0.5f * M_PI / 180.f));
fovscale = 1.f + (fovscale - 1.f) * cl_scaleweaponfov;
@ -245,12 +249,12 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
float orientation = smf->xscale * smf->yscale * smf->zscale;
renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0, smf);
renderer->BeginDrawHUDModel(playermo->RenderStyle, objectToWorldMatrix, orientation < 0, smf_flags);
auto trans = psp->GetTranslation();
if ((psp->Flags & PSPF_PLAYERTRANSLATED)) trans = psp->Owner->mo->Translation;
RenderFrameModels(renderer, playermo->Level, smf, psp->GetState(), psp->GetTics(), trans, psp->Caller);
renderer->EndDrawHUDModel(playermo->RenderStyle, smf);
renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags);
}
double getCurrentFrame(const AnimOverride &anim, double tic)
@ -295,6 +299,9 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
{
// [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.
int smf_flags = smf->getFlags(actor->modelData);
const FSpriteModelFrame * smfNext = nullptr;
double inter = 0.;
double inter_main = -1.f;
@ -334,7 +341,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
}
}
}
else if (gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION))
else if (gl_interpolate_model_frames && !(smf_flags & MDL_NOINTERPOLATION))
{
FState *nextState = curState->GetNextState();
if (curState != nextState && nextState)
@ -356,7 +363,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 ((smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES))
if ((smf_flags & MDL_INTERPOLATEDOUBLEDFRAMES))
{
const FState *prevState = curState - 1;
if ((curState->sprite == prevState->sprite) && (curState->Frame == prevState->Frame))
@ -522,7 +529,7 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
}
// [RL0] while per-model animations aren't done, DECOUPLEDANIMATIONS does the same as MODELSAREATTACHMENTS
if ((!(smf->flags & MDL_MODELSAREATTACHMENTS) && !is_decoupled) || !evaluatedSingle)
if ((!(smf_flags & MDL_MODELSAREATTACHMENTS) && !is_decoupled) || !evaluatedSingle)
{
if (animationid >= 0)
{
@ -576,7 +583,7 @@ static TArray<int> SpriteModelHash;
//
//===========================================================================
static void ParseModelDefLump(int Lump);
void ParseModelDefLump(int Lump);
void InitModels()
{
@ -658,7 +665,7 @@ void InitModels()
}
}
static void ParseModelDefLump(int Lump)
void ParseModelDefLump(int Lump)
{
FScanner sc(Lump);
while (sc.GetString())
@ -1117,11 +1124,11 @@ FSpriteModelFrame * FindModelFrame(const AActor * thing, int sprite, int frame,
if(thing->flags9 & MF9_DECOUPLEDANIMATIONS)
{
return &BaseSpriteModelFrames[thing->GetClass()];
return &BaseSpriteModelFrames[(thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass()];
}
else
{
return FindModelFrameRaw((thing->modelData != nullptr && thing->modelData->modelDef != NAME_None) ? PClass::FindActor(thing->modelData->modelDef) : thing->GetClass(), sprite, frame, dropped);
return FindModelFrameRaw((thing->modelData != nullptr && thing->modelData->modelDef != nullptr) ? thing->modelData->modelDef : thing->GetClass(), sprite, frame, dropped);
}
}
@ -1143,3 +1150,9 @@ bool IsHUDModelForPlayerAvailable (player_t * player)
}
return false;
}
unsigned int FSpriteModelFrame::getFlags(class DActorModelData * defs) const
{
return (defs && defs->flags & MODELDATA_OVERRIDE_FLAGS)? (flags | defs->overrideFlagsSet) & ~(defs->overrideFlagsClear) : flags;
}

View file

@ -53,7 +53,7 @@ VSMatrix FHWModelRenderer::GetViewToWorldMatrix()
return objectToWorldMatrix;
}
void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
void FHWModelRenderer::BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored)
{
state.SetDepthFunc(DF_LEqual);
state.EnableTexture(true);
@ -61,7 +61,7 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf
// This solves a few of the problems caused by the lack of depth sorting.
// [Nash] Don't do back face culling if explicitly specified in MODELDEF
// TO-DO: Implement proper depth sorting.
if ((smf->flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)))
if ((smf_flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf_flags & MDL_DONTCULLBACKFACES)))
{
state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CCW : Cull_CW);
}
@ -70,16 +70,16 @@ void FHWModelRenderer::BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf
state.EnableModelMatrix(true);
}
void FHWModelRenderer::EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf)
void FHWModelRenderer::EndDrawModel(FRenderStyle style, int smf_flags)
{
state.SetBoneIndexBase(-1);
state.EnableModelMatrix(false);
state.SetDepthFunc(DF_Less);
if ((smf->flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)))
if ((smf_flags & MDL_FORCECULLBACKFACES) || (!(style == DefaultRenderStyle()) && !(smf_flags & MDL_DONTCULLBACKFACES)))
state.SetCulling(Cull_None);
}
void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, FSpriteModelFrame *smf)
void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags)
{
state.SetDepthFunc(DF_LEqual);
state.SetDepthClamp(true);
@ -87,7 +87,7 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj
// [BB] In case the model should be rendered translucent, do back face culling.
// This solves a few of the problems caused by the lack of depth sorting.
// TO-DO: Implement proper depth sorting.
if (!(style == DefaultRenderStyle()) || (smf->flags & MDL_FORCECULLBACKFACES))
if (!(style == DefaultRenderStyle()) || (smf_flags & MDL_FORCECULLBACKFACES))
{
state.SetCulling((mirrored ^ portalState.isMirrored()) ? Cull_CW : Cull_CCW);
}
@ -96,13 +96,13 @@ void FHWModelRenderer::BeginDrawHUDModel(FRenderStyle style, const VSMatrix &obj
state.EnableModelMatrix(true);
}
void FHWModelRenderer::EndDrawHUDModel(FRenderStyle style, FSpriteModelFrame *smf)
void FHWModelRenderer::EndDrawHUDModel(FRenderStyle style, int smf_flags)
{
state.SetBoneIndexBase(-1);
state.EnableModelMatrix(false);
state.SetDepthFunc(DF_Less);
if (!(style == DefaultRenderStyle()) || (smf->flags & MDL_FORCECULLBACKFACES))
if (!(style == DefaultRenderStyle()) || (smf_flags & MDL_FORCECULLBACKFACES))
state.SetCulling(Cull_None);
}

View file

@ -46,12 +46,12 @@ public:
FHWModelRenderer(HWDrawInfo *d, FRenderState &st, int mli) : modellightindex(mli), di(d), state(st)
{}
ModelRendererType GetType() const override { return GLModelRendererType; }
void BeginDrawModel(FRenderStyle style, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawModel(FRenderStyle style, FSpriteModelFrame *smf) override;
void BeginDrawModel(FRenderStyle style, int smf_flags, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
void EndDrawModel(FRenderStyle style, int smf_flags) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;
VSMatrix GetViewToWorldMatrix() override;
void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, FSpriteModelFrame *smf) override;
void EndDrawHUDModel(FRenderStyle style, FSpriteModelFrame *smf) override;
void BeginDrawHUDModel(FRenderStyle style, const VSMatrix &objectToWorldMatrix, bool mirrored, int smf_flags) override;
void EndDrawHUDModel(FRenderStyle style, int smf_flags) override;
void SetInterpolation(double interpolation) override;
void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) override;
void DrawArrays(int start, int count) override;

View file

@ -365,6 +365,7 @@ public:
PalEntry ThingColor; // thing's own color
FColormap Colormap;
FSpriteModelFrame * modelframe;
int modelframeflags;
FRenderStyle RenderStyle;
int OverrideShader;

View file

@ -507,7 +507,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp)
inline void HWSprite::PutSprite(HWDrawInfo *di, bool translucent)
{
// That's a lot of checks...
if (modelframe && !modelframe->isVoxel && !(modelframe->flags & MDL_NOPERPIXELLIGHTING) && RenderStyle.BlendOp != STYLEOP_Shadow && gl_light_sprites && di->Level->HasDynamicLights && !di->isFullbrightScene() && !fullbright)
if (modelframe && !modelframe->isVoxel && !(modelframeflags & MDL_NOPERPIXELLIGHTING) && RenderStyle.BlendOp != STYLEOP_Shadow && gl_light_sprites && di->Level->HasDynamicLights && !di->isFullbrightScene() && !fullbright)
{
hw_GetDynModelLight(actor, lightdata);
dynlightindex = screen->mLights->UploadLights(lightdata);
@ -797,6 +797,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
}
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing, spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
modelframeflags = modelframe ? modelframe->getFlags(thing->modelData) : 0;
// 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

View file

@ -1300,6 +1300,10 @@ class Actor : Thinker native
native version("4.12") void SetAnimationFrameRate(double framerate);
native version("4.12") ui void SetAnimationFrameRateUI(double framerate);
native version("4.12") void SetModelFlag(int flag);
native version("4.12") void ClearModelFlag(int flag);
native version("4.12") void ResetModelFlags();
int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0)
{
return ACS_Execute(-int(script), mapnum, arg1, arg2, arg3);

View file

@ -1470,3 +1470,26 @@ const WATER_SINK_FACTOR = 0.125;
const WATER_SINK_SMALL_FACTOR = 0.25;
const WATER_SINK_SPEED = 0.5;
const WATER_JUMP_SPEED = 3.5;
// for SetModelFlag/ClearModelFlag
enum EModelFlags
{
// [BB] Color translations for the model skin are ignored. This is
// useful if the skin texture is not using the game palette.
MDL_IGNORETRANSLATION = 1<<0,
MDL_PITCHFROMMOMENTUM = 1<<1,
MDL_ROTATING = 1<<2,
MDL_INTERPOLATEDOUBLEDFRAMES = 1<<3,
MDL_NOINTERPOLATION = 1<<4,
MDL_USEACTORPITCH = 1<<5,
MDL_USEACTORROLL = 1<<6,
MDL_BADROTATION = 1<<7,
MDL_DONTCULLBACKFACES = 1<<8,
MDL_USEROTATIONCENTER = 1<<9,
MDL_NOPERPIXELLIGHTING = 1<<10, // forces a model to not use per-pixel lighting. useful for voxel-converted-to-model objects.
MDL_SCALEWEAPONFOV = 1<<11, // scale weapon view model with higher user FOVs
MDL_MODELSAREATTACHMENTS = 1<<12, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0
MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied
MDL_FORCECULLBACKFACES = 1<<14,
};