This commit is contained in:
Christoph Oelckers 2018-05-22 21:36:52 +02:00
commit df6a50872d
22 changed files with 500 additions and 479 deletions

View file

@ -120,9 +120,26 @@ Note: All <bool> fields default to false unless mentioned otherwise.
blockhitscan = <bool>; // Line blocks hitscan attacks blockhitscan = <bool>; // Line blocks hitscan attacks
locknumber = <int>; // Line special is locked locknumber = <int>; // Line special is locked
arg0str = <string>; // Alternate string-based version of arg0 arg0str = <string>; // Alternate string-based version of arg0
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25) transparent = <bool>; // true = line is a Strife transparent line (alpha 0.25)
automapstyle = <integer>; // Explicit automap style. Possible values can be
// 0: Automap style is based on line properties (default).
// 1: One-sided wall.
// 2: Two-sided wall.
// 3: Floor levels of front and back sectors are different.
// 4: Ceiling levels of front and back sectors are different.
// 5: 3D floor border.
// 6: Wall with special non-door action.
// 7: Secret door.
// 8: Wall not seen yet.
// 9: Locked door.
// 10: Intra-level teleporter.
// 11: Inter-level or game-ending teleporter.
// 12: Unexplored secret wall.
// 13: Portal line.
revealed = <bool>; // true = line is initially visible on automap.
* Note about arg0str * Note about arg0str
@ -171,14 +188,14 @@ Note: All <bool> fields default to false unless mentioned otherwise.
yscaleceiling = <float>; // Y texture scale of ceiling texture, Default = 1.0. yscaleceiling = <float>; // Y texture scale of ceiling texture, Default = 1.0.
rotationfloor = <float>; // Rotation of floor texture in degrees, Default = 0.0. rotationfloor = <float>; // Rotation of floor texture in degrees, Default = 0.0.
rotationceiling = <float>; // Rotation of ceiling texture in degrees, Default = 0.0. rotationceiling = <float>; // Rotation of ceiling texture in degrees, Default = 0.0.
ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'.
ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment. ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment.
ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given. ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given.
ceilingplane_d = <float>; ceilingplane_d = <float>;
floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'.
floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment. floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment.
floorplane_c = <float>; // The plane equation will only be used if all 4 values are given. floorplane_c = <float>; // The plane equation will only be used if all 4 values are given.
floorplane_d = <float>; floorplane_d = <float>;
lightfloor = <integer>; // The floor's light level. Default is 0. lightfloor = <integer>; // The floor's light level. Default is 0.
lightceiling = <integer>; // The ceiling's light level. Default is 0. lightceiling = <integer>; // The ceiling's light level. Default is 0.
lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is
@ -196,8 +213,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
fadecolor = <integer>; // Sector's fog color as RRGGBB value, default = 0x000000. fadecolor = <integer>; // Sector's fog color as RRGGBB value, default = 0x000000.
desaturation = <float>; // Color desaturation factor. 0 = none, 1 = full, default = 0. desaturation = <float>; // Color desaturation factor. 0 = none, 1 = full, default = 0.
silent = <bool>; // Actors in this sector make no sound, silent = <bool>; // Actors in this sector make no sound,
nofallingdamage = <bool>; // Falling damage is disabled in this sector nofallingdamage = <bool>; // Falling damage is disabled in this sector
noattack = <bool>; // Blocks monster attacks in this sector. noattack = <bool>; // Blocks monster attacks in this sector.
dropactors = <bool>; // Actors drop with instantly moving floors (*) dropactors = <bool>; // Actors drop with instantly moving floors (*)
norespawn = <bool>; // Players can not respawn in this sector norespawn = <bool>; // Players can not respawn in this sector
soundsequence = <string>; // The sound sequence to play when this sector moves. Placing a soundsequence = <string>; // The sound sequence to play when this sector moves. Placing a
@ -215,21 +232,21 @@ Note: All <bool> fields default to false unless mentioned otherwise.
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false. damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.'
ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
floor_reflect = <float>; // reflectiveness of floor (OpenGL only, not functional on sloped sectors) floor_reflect = <float>; // reflectiveness of floor (OpenGL only, not functional on sloped sectors)
ceiling_reflect = <float>; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors) ceiling_reflect = <float>; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors)
fogdensity = <integer>; // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510, fogdensity = <integer>; // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510,
// 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of // 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of
// a light level of 0. (OpenGL only) // a light level of 0. (OpenGL only)
floorglowcolor = <integer>; // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only) floorglowcolor = <integer>; // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
floorglowheight = <float>; // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only) floorglowheight = <float>; // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
ceilingglowcolor = <integer>; // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only) ceilingglowcolor = <integer>; // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing. (OpenGL 3.x and newer only)
ceilingglowheight = <float>; // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only) ceilingglowheight = <float>; // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow. (OpenGL 3.x and newer only)
color_floor = <int>; // Material color of sector's floor. Default is white (0xffffff) color_floor = <int>; // Material color of sector's floor. Default is white (0xffffff)
color_ceiling = <int>; // Material color of sector's ceiling. Default is white (0xffffff) color_ceiling = <int>; // Material color of sector's ceiling. Default is white (0xffffff)
color_walltop = <int>; // Material color of top of sector's sidedefs. In OpenGL 2.x and the software renderer this will define the entire wall's color) Default is white (0xffffff) color_walltop = <int>; // Material color of top of sector's sidedefs. In OpenGL 2.x and the software renderer this will define the entire wall's color) Default is white (0xffffff)
color_wallbottom = <int>; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff) color_wallbottom = <int>; // Material color of bottom of sector's sidedefs (OpenGL 3.x and later only) Default is white (0xffffff)
color_sprites = <int>; // Material color of sprites in sector. Default is white (0xffffff) color_sprites = <int>; // Material color of sprites in sector. Default is white (0xffffff)
portal_ceil_blocksound = <bool> // ceiling portal blocks sound. portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
portal_ceil_disabled = <bool> // ceiling portal disabled. portal_ceil_disabled = <bool> // ceiling portal disabled.
@ -241,8 +258,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
portal_floor_nopass = <bool> // ceiling portal blocks movement if true. portal_floor_nopass = <bool> // ceiling portal blocks movement if true.
portal_floor_norender = <bool> // ceiling portal not rendered. portal_floor_norender = <bool> // ceiling portal not rendered.
portal_floor_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent". portal_floor_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent".
* Note about dropactors * Note about dropactors
The spec requires this to be false by default. Currently, however, ZDoom assumes this to be true The spec requires this to be false by default. Currently, however, ZDoom assumes this to be true
@ -253,37 +270,37 @@ Note: All <bool> fields default to false unless mentioned otherwise.
thing thing
{ {
skill# = <bool> // Unlike the base spec, # can range from 1-16. skill# = <bool> // Unlike the base spec, # can range from 1-16.
class# = <bool> // Unlike the base spec, # can range from 1-16. class# = <bool> // Unlike the base spec, # can range from 1-16.
conversation = <int> // Assigns a conversation dialogue to this thing. conversation = <int> // Assigns a conversation dialogue to this thing.
// Parameter is the conversation ID, 0 meaning none. // Parameter is the conversation ID, 0 meaning none.
countsecret = <bool>; // Picking up this actor counts as a secret. countsecret = <bool>; // Picking up this actor counts as a secret.
arg0str = <string>; // Alternate string-based version of arg0 arg0str = <string>; // Alternate string-based version of arg0
gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property, gravity = <float>; // Set per-actor gravity. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1.0. // negative values are used as their absolute. Default = 1.0.
health = <float>; // Set per-actor health. Positive values are multiplied with the class's property, health = <float>; // Set per-actor health. Positive values are multiplied with the class's property,
// negative values are used as their absolute. Default = 1. // negative values are used as their absolute. Default = 1.
renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal", renderstyle = <string>; // Set per-actor render style, overriding the class default. Possible values can be "normal",
// "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil", // "none", "add" or "additive", "subtract" or "subtractive", "stencil", "translucentstencil",
// "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow". // "addstencil", "shaded", "addshaded", "translucent", "fuzzy", "optfuzzy", "soultrans" and "shadow".
// Default is an empty string for no change. // Default is an empty string for no change.
fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000. fillcolor = <integer>; // Fill color used by the "stencil", "addstencil" and "translucentstencil" rendestyles, as RRGGBB value, default = 0x000000.
alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0. alpha = <float>; // Translucency of this actor (if applicable to renderstyle), default is 1.0.
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0. score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal). pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal). roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored). scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored). scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored). scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default). floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).
* Note about arg0str * Note about arg0str
For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it
will be used as the name of the script to execute, and arg0 will be ignored. will be used as the name of the script to execute, and arg0 will be ignored.
On dynamic lights, arg0str can be used to set a color by name, this will supersede all args which are normally used to define a color. On dynamic lights, arg0str can be used to set a color by name, this will supersede all args which are normally used to define a color.
} }
@ -430,6 +447,10 @@ sector material colors.
1.29 04.02.2018 1.29 04.02.2018
arg0str in dynamic lights. arg0str in dynamic lights.
1.30 20.05.2018
Added automapstyle and revealed linedef properties.
Replaced tabs with spaces.
=============================================================================== ===============================================================================
EOF EOF
=============================================================================== ===============================================================================

View file

@ -36,6 +36,7 @@ class FGLModelRenderer : public FModelRenderer
public: public:
FGLModelRenderer(int mli) : modellightindex(mli) FGLModelRenderer(int mli) : modellightindex(mli)
{} {}
ModelRendererType GetType() const override { return GLModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -120,9 +120,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mCustomPostProcessShaders = nullptr; mCustomPostProcessShaders = nullptr;
} }
void gl_LoadModels();
void gl_FlushModels();
void FGLRenderer::Initialize(int width, int height) void FGLRenderer::Initialize(int width, int height)
{ {
mBuffers = new FGLRenderBuffers(); mBuffers = new FGLRenderBuffers();
@ -174,7 +171,6 @@ void FGLRenderer::Initialize(int width, int height)
SetupLevel(); SetupLevel();
mShaderManager = new FShaderManager; mShaderManager = new FShaderManager;
mSamplerManager = new FSamplerManager; mSamplerManager = new FSamplerManager;
gl_LoadModels();
GLPortal::Initialize(); GLPortal::Initialize();
} }
@ -183,7 +179,7 @@ FGLRenderer::~FGLRenderer()
{ {
GLPortal::Shutdown(); GLPortal::Shutdown();
gl_FlushModels(); FlushModels();
AActor::DeleteAllAttachedLights(); AActor::DeleteAllAttachedLights();
FMaterial::FlushAll(); FMaterial::FlushAll();
if (legacyShaders) delete legacyShaders; if (legacyShaders) delete legacyShaders;

View file

@ -488,7 +488,7 @@ void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
gl_RenderState.EnableFog(false); gl_RenderState.EnableFog(false);
// [BB] HUD models need to be rendered here. // [BB] HUD models need to be rendered here.
const bool renderHUDModel = gl_IsHUDModelForPlayerAvailable( players[consoleplayer].camera->player ); const bool renderHUDModel = IsHUDModelForPlayerAvailable( players[consoleplayer].camera->player );
if ( renderHUDModel ) if ( renderHUDModel )
{ {
// [BB] The HUD model should be drawn over everything else already drawn. // [BB] The HUD model should be drawn over everything else already drawn.
@ -517,7 +517,7 @@ void GLSceneDrawer::EndDrawScene(FDrawInfo *di, sector_t * viewsector)
void GLSceneDrawer::DrawEndScene2D(FDrawInfo *di, sector_t * viewsector) void GLSceneDrawer::DrawEndScene2D(FDrawInfo *di, sector_t * viewsector)
{ {
const bool renderHUDModel = gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
// This should be removed once all 2D stuff is really done through the 2D interface. // This should be removed once all 2D stuff is really done through the 2D interface.
gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mViewMatrix.loadIdentity();

View file

@ -449,7 +449,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
// exclude vertically moving objects from this check. // exclude vertically moving objects from this check.
if (!thing->Vel.isZero()) if (!thing->Vel.isZero())
{ {
if (!gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, false)) if (!FindModelFrame(thing->GetClass(), spritenum, thing->frame, false))
{ {
return; return;
} }
@ -510,7 +510,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
z += fz; z += fz;
} }
modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (!modelframe) if (!modelframe)
{ {
bool mirror; bool mirror;

View file

@ -252,14 +252,13 @@ bool HUDSprite::GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t *
auto rs = psp->GetRenderStyle(playermo->RenderStyle, playermo->Alpha); auto rs = psp->GetRenderStyle(playermo->RenderStyle, playermo->Alpha);
visstyle_t vis; visstyle_t vis;
float trans = 0.f;
vis.RenderStyle = STYLE_Count; vis.RenderStyle = STYLE_Count;
vis.Alpha = rs.second; vis.Alpha = rs.second;
vis.Invert = false; vis.Invert = false;
playermo->AlterWeaponSprite(&vis); playermo->AlterWeaponSprite(&vis);
if (!(psp->Flags & PSPF_FORCEALPHA)) trans = vis.Alpha; alpha = (psp->Flags & PSPF_FORCEALPHA) ? 0.f : vis.Alpha;
if (vis.RenderStyle != STYLE_Count && !(psp->Flags & PSPF_FORCESTYLE)) if (vis.RenderStyle != STYLE_Count && !(psp->Flags & PSPF_FORCESTYLE))
{ {
@ -303,14 +302,10 @@ bool HUDSprite::GetWeaponRenderStyle(DPSprite *psp, AActor *playermo, sector_t *
{ {
alpha = 1.f; alpha = 1.f;
} }
else if (trans == 0.f) else if (alpha == 0.f)
{ {
alpha = vis.Alpha; alpha = vis.Alpha;
} }
else
{
alpha = trans;
}
if (!RenderStyle.IsVisible(alpha)) return false; // if it isn't visible skip the rest. if (!RenderStyle.IsVisible(alpha)) return false; // if it isn't visible skip the rest.
PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff;
@ -430,7 +425,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
bool brightflash = false; bool brightflash = false;
AActor * playermo = players[consoleplayer].camera; AActor * playermo = players[consoleplayer].camera;
player_t * player = playermo->player; player_t * player = playermo->player;
const bool hudModelStep = gl_IsHUDModelForPlayerAvailable(player); const bool hudModelStep = IsHUDModelForPlayerAvailable(player);
AActor *camera = r_viewpoint.camera; AActor *camera = r_viewpoint.camera;
@ -453,7 +448,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) for (DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext())
{ {
if (!psp->GetState()) continue; if (!psp->GetState()) continue;
FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false) : nullptr; FSpriteModelFrame *smf = playermo->player->ReadyWeapon ? FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->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. // 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 && !hudModelStep) continue; if (smf && !hudModelStep) continue;
if (!smf && hudModelStep) continue; if (!smf && hudModelStep) continue;

View file

@ -119,7 +119,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitl
{ {
auto &state = cls->GetStates()[i]; auto &state = cls->GetStates()[i];
spritelist[state.sprite].Insert(gltrans, true); spritelist[state.sprite].Insert(gltrans, true);
FSpriteModelFrame * smf = gl_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 < MAX_MODELS_PER_FRAME; i++)

View file

@ -33,9 +33,6 @@
#include "actorinlines.h" #include "actorinlines.h"
#include "i_time.h" #include "i_time.h"
void gl_FlushModels();
bool polymodelsInUse;
void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
{ {
PolyModelRenderer renderer(thread, worldToClip, stencilValue); PolyModelRenderer renderer(thread, worldToClip, stencilValue);
@ -52,11 +49,6 @@ void PolyRenderHUDModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint
PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), StencilValue(stencilValue) PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue) : Thread(thread), WorldToClip(worldToClip), StencilValue(stencilValue)
{ {
if (!polymodelsInUse)
{
gl_FlushModels();
polymodelsInUse = true;
}
} }
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)

View file

@ -34,6 +34,8 @@ class PolyModelRenderer : public FModelRenderer
public: public:
PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue); PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue);
ModelRendererType GetType() const override { return PolyModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -60,7 +60,7 @@ void RenderPolyPlayerSprites::Render(PolyRenderThread *thread)
(r_deathcamera && viewpoint.camera->health <= 0)) (r_deathcamera && viewpoint.camera->health <= 0))
return; return;
renderHUDModel = r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); renderHUDModel = r_models && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
PolyTransferHeights fakeflat(viewpoint.camera->subsector); PolyTransferHeights fakeflat(viewpoint.camera->subsector);

View file

@ -78,7 +78,7 @@ void RenderPolySprite::Render(PolyRenderThread *thread, AActor *thing, subsector
{ {
int spritenum = thing->sprite; int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid(); bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe) if (modelframe)
{ {
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint; const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;

View file

@ -94,8 +94,8 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
if (smf->flags & MDL_ROTATING) if (smf->flags & MDL_ROTATING)
{ {
const double time = smf->rotationSpeed*GetTimeFloat() / 200.; double turns = (I_GetTime() % 200 + I_GetTimeFrac()) / 200.0;
rotateOffset = double((time - xs_FloorToInt(time)) *360.); rotateOffset = turns * 360.0;
} }
// Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing. // Added MDL_USEACTORPITCH and MDL_USEACTORROLL flags processing.
@ -164,14 +164,14 @@ void FModelRenderer::RenderModel(float x, float y, float z, FSpriteModelFrame *s
objectToWorldMatrix.scale(1, stretch, 1); objectToWorldMatrix.scale(1, stretch, 1);
BeginDrawModel(actor, smf, objectToWorldMatrix); BeginDrawModel(actor, smf, objectToWorldMatrix);
RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), nullptr, translation); RenderFrameModels(smf, actor->state, actor->tics, actor->GetClass(), translation);
EndDrawModel(actor, smf); EndDrawModel(actor, smf);
} }
void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY) void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
{ {
AActor * playermo = players[consoleplayer].camera; AActor * playermo = players[consoleplayer].camera;
FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false); FSpriteModelFrame *smf = FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->GetState()->sprite, psp->GetState()->GetFrame(), false);
// [BB] No model found for this sprite, so we can't render anything. // [BB] No model found for this sprite, so we can't render anything.
if (smf == nullptr) if (smf == nullptr)
@ -200,16 +200,11 @@ void FModelRenderer::RenderHUDModel(DPSprite *psp, float ofsX, float ofsY)
objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0); objectToWorldMatrix.rotate(-smf->rolloffset, 1, 0, 0);
BeginDrawHUDModel(playermo, objectToWorldMatrix); BeginDrawHUDModel(playermo, objectToWorldMatrix);
RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), nullptr, 0); RenderFrameModels(smf, psp->GetState(), psp->GetTics(), playermo->player->ReadyWeapon->GetClass(), 0);
EndDrawHUDModel(playermo); EndDrawHUDModel(playermo);
} }
void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation)
const FState *curState,
const int curTics,
const PClass *ti,
Matrix3x4 *normaltransform,
int translation)
{ {
// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation // [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. // and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
@ -225,14 +220,13 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
// [BB] In case the tic counter is frozen we have to leave ticFraction at zero. // [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN)) if (ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN))
{ {
double time = GetTimeFloat(); ticFraction = I_GetTimeFrac();
ticFraction = (time - static_cast<int>(time));
} }
inter = static_cast<double>(curState->Tics - curTics - ticFraction) / static_cast<double>(curState->Tics); inter = static_cast<double>(curState->Tics - curTics + ticFraction) / static_cast<double>(curState->Tics);
// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics. // [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
// In this case inter is negative and we need to set it to zero. // In this case inter is negative and we need to set it to zero.
if (inter < 0.) if (curState->Tics < curTics)
inter = 0.; inter = 0.;
else else
{ {
@ -253,7 +247,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
} }
} }
if (inter != 0.0) if (inter != 0.0)
smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false); smfNext = FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
} }
} }
} }
@ -265,7 +259,7 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
FModel * mdl = Models[smf->modelIDs[i]]; FModel * mdl = Models[smf->modelIDs[i]];
FTexture *tex = smf->skinIDs[i].isValid() ? TexMan(smf->skinIDs[i]) : nullptr; FTexture *tex = smf->skinIDs[i].isValid() ? TexMan(smf->skinIDs[i]) : nullptr;
mdl->BuildVertexBuffer(this); mdl->BuildVertexBuffer(this);
SetVertexBuffer(mdl->mVBuf); SetVertexBuffer(mdl->GetVertexBuffer(this));
mdl->PushSpriteMDLFrame(smf, i); mdl->PushSpriteMDLFrame(smf, i);
@ -279,24 +273,9 @@ void FModelRenderer::RenderFrameModels(const FSpriteModelFrame *smf,
} }
} }
double FModelRenderer::GetTimeFloat()
{
return (double)I_msTime() * (double)TICRATE / 1000.;
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
void gl_LoadModels() void FlushModels()
{
/*
for (int i = Models.Size() - 1; i >= 0; i--)
{
Models[i]->BuildVertexBuffer();
}
*/
}
void gl_FlushModels()
{ {
for (int i = Models.Size() - 1; i >= 0; i--) for (int i = Models.Size() - 1; i >= 0; i--)
{ {
@ -306,9 +285,24 @@ void gl_FlushModels()
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
FModel::FModel()
{
for (int i = 0; i < NumModelRendererTypes; i++)
mVBuf[i] = nullptr;
}
FModel::~FModel() FModel::~FModel()
{ {
if (mVBuf != nullptr) delete mVBuf; DestroyVertexBuffer();
}
void FModel::DestroyVertexBuffer()
{
for (int i = 0; i < NumModelRendererTypes; i++)
{
delete mVBuf[i];
mVBuf[i] = nullptr;
}
} }
static TArray<FSpriteModelFrame> SpriteModelFrames; static TArray<FSpriteModelFrame> SpriteModelFrames;
@ -475,22 +469,15 @@ static unsigned FindModel(const char * path, const char * modelfile)
//=========================================================================== //===========================================================================
// //
// gl_InitModels // InitModels
// //
//=========================================================================== //===========================================================================
void gl_InitModels() static void ParseModelDefLump(int Lump);
void InitModels()
{ {
int Lump, lastLump; for (unsigned i = 0; i < Models.Size(); i++)
FString path;
int index, surface;
int i;
FSpriteModelFrame smf;
lastLump = 0;
for(unsigned i=0;i<Models.Size();i++)
{ {
delete Models[i]; delete Models[i];
} }
@ -508,6 +495,7 @@ void gl_InitModels()
for (unsigned i = 0; i < VoxelDefs.Size(); i++) for (unsigned i = 0; i < VoxelDefs.Size(); i++)
{ {
FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex]; FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex];
FSpriteModelFrame smf;
memset(&smf, 0, sizeof(smf)); memset(&smf, 0, sizeof(smf));
smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
@ -539,302 +527,11 @@ void gl_InitModels()
} }
} }
memset(&smf, 0, sizeof(smf)); int Lump;
smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; int lastLump = 0;
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
{ {
FScanner sc(Lump); ParseModelDefLump(Lump);
while (sc.GetString())
{
if (sc.Compare("model"))
{
path = "";
sc.MustGetString();
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.type = PClass::FindClass(sc.String);
if (!smf.type || smf.type->Defaults == nullptr)
{
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
}
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("path"))
{
sc.MustGetString();
FixPathSeperator(sc.String);
path = sc.String;
if (path[(int)path.Len()-1]!='/') path+='/';
}
else if (sc.Compare("model"))
{
sc.MustGetNumber();
index = sc.Number;
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
if (smf.modelIDs[index] == -1)
{
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
}
}
else if (sc.Compare("scale"))
{
sc.MustGetFloat();
smf.xscale = sc.Float;
sc.MustGetFloat();
smf.yscale = sc.Float;
sc.MustGetFloat();
smf.zscale = sc.Float;
}
// [BB] Added zoffset reading.
// Now it must be considered deprecated.
else if (sc.Compare("zoffset"))
{
sc.MustGetFloat();
smf.zoffset=sc.Float;
}
// Offset reading.
else if (sc.Compare("offset"))
{
sc.MustGetFloat();
smf.xoffset = sc.Float;
sc.MustGetFloat();
smf.yoffset = sc.Float;
sc.MustGetFloat();
smf.zoffset = sc.Float;
}
// angleoffset, pitchoffset and rolloffset reading.
else if (sc.Compare("angleoffset"))
{
sc.MustGetFloat();
smf.angleoffset = sc.Float;
}
else if (sc.Compare("pitchoffset"))
{
sc.MustGetFloat();
smf.pitchoffset = sc.Float;
}
else if (sc.Compare("rolloffset"))
{
sc.MustGetFloat();
smf.rolloffset = sc.Float;
}
// [BB] Added model flags reading.
else if (sc.Compare("ignoretranslation"))
{
smf.flags |= MDL_IGNORETRANSLATION;
}
else if (sc.Compare("pitchfrommomentum"))
{
smf.flags |= MDL_PITCHFROMMOMENTUM;
}
else if (sc.Compare("inheritactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
}
else if (sc.Compare("inheritactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("useactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH;
}
else if (sc.Compare("useactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("rotating"))
{
smf.flags |= MDL_ROTATING;
smf.xrotate = 0.;
smf.yrotate = 1.;
smf.zrotate = 0.;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
smf.rotationSpeed = 1.;
}
else if (sc.Compare("rotation-speed"))
{
sc.MustGetFloat();
smf.rotationSpeed = sc.Float;
}
else if (sc.Compare("rotation-vector"))
{
sc.MustGetFloat();
smf.xrotate = sc.Float;
sc.MustGetFloat();
smf.yrotate = sc.Float;
sc.MustGetFloat();
smf.zrotate = sc.Float;
}
else if (sc.Compare("rotation-center"))
{
sc.MustGetFloat();
smf.rotationCenterX = sc.Float;
sc.MustGetFloat();
smf.rotationCenterY = sc.Float;
sc.MustGetFloat();
smf.rotationCenterZ = sc.Float;
}
else if (sc.Compare("interpolatedoubledframes"))
{
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
}
else if (sc.Compare("nointerpolation"))
{
smf.flags |= MDL_NOINTERPOLATION;
}
else if (sc.Compare("skin"))
{
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.skinIDs[index]=FNullTextureID();
}
else
{
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
if (!smf.skinIDs[index].isValid())
{
Printf("Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("surfaceskin"))
{
sc.MustGetNumber();
index = sc.Number;
sc.MustGetNumber();
surface = sc.Number;
if (index<0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (surface<0 || surface >= MD3_MAX_SURFACES)
{
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.surfaceskinIDs[index][surface] = FNullTextureID();
}
else
{
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
if (!smf.surfaceskinIDs[index][surface].isValid())
{
Printf("Surface Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("frameindex") || sc.Compare("frame"))
{
bool isframe=!!sc.Compare("frame");
sc.MustGetString();
smf.sprite = -1;
for (i = 0; i < (int)sprites.Size (); ++i)
{
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
{
if (sprites[i].numframes==0)
{
//sc.ScriptError("Sprite %s has no frames", sc.String);
}
smf.sprite = i;
break;
}
}
if (smf.sprite==-1)
{
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FString framechars = sc.String;
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (isframe)
{
sc.MustGetString();
if (smf.modelIDs[index] != -1)
{
FModel *model = Models[smf.modelIDs[index]];
smf.modelframes[index] = model->FindFrame(sc.String);
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
}
else smf.modelframes[index] = -1;
}
else
{
sc.MustGetNumber();
smf.modelframes[index] = sc.Number;
}
for(i=0; framechars[i]>0; i++)
{
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int c = toupper(framechars[i])-'A';
if (c<0 || c>=29)
{
sc.ScriptError("Invalid frame character %c found", c+'A');
}
if (map[c]) continue;
smf.frame=c;
SpriteModelFrames.Push(smf);
GetDefaultByType(smf.type)->hasmodel = true;
map[c]=1;
}
}
else if (sc.Compare("dontcullbackfaces"))
{
smf.flags |= MDL_DONTCULLBACKFACES;
}
else if (sc.Compare("userotationcenter"))
{
smf.flags |= MDL_USEROTATIONCENTER;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
}
else
{
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
}
}
}
}
} }
// create a hash table for quick access // create a hash table for quick access
@ -842,7 +539,7 @@ void gl_InitModels()
atterm(DeleteModelHash); atterm(DeleteModelHash);
memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int));
for (i = 0; i < (int)SpriteModelFrames.Size (); i++) for (unsigned int i = 0; i < SpriteModelFrames.Size (); i++)
{ {
int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size ();
@ -851,13 +548,323 @@ void gl_InitModels()
} }
} }
static void ParseModelDefLump(int Lump)
{
FScanner sc(Lump);
while (sc.GetString())
{
if (sc.Compare("model"))
{
int index, surface;
FString path = "";
sc.MustGetString();
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;
smf.type = PClass::FindClass(sc.String);
if (!smf.type || smf.type->Defaults == nullptr)
{
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
}
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("path"))
{
sc.MustGetString();
FixPathSeperator(sc.String);
path = sc.String;
if (path[(int)path.Len()-1]!='/') path+='/';
}
else if (sc.Compare("model"))
{
sc.MustGetNumber();
index = sc.Number;
if (index < 0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
if (smf.modelIDs[index] == -1)
{
Printf("%s: model not found in %s\n", sc.String, path.GetChars());
}
}
else if (sc.Compare("scale"))
{
sc.MustGetFloat();
smf.xscale = sc.Float;
sc.MustGetFloat();
smf.yscale = sc.Float;
sc.MustGetFloat();
smf.zscale = sc.Float;
}
// [BB] Added zoffset reading.
// Now it must be considered deprecated.
else if (sc.Compare("zoffset"))
{
sc.MustGetFloat();
smf.zoffset=sc.Float;
}
// Offset reading.
else if (sc.Compare("offset"))
{
sc.MustGetFloat();
smf.xoffset = sc.Float;
sc.MustGetFloat();
smf.yoffset = sc.Float;
sc.MustGetFloat();
smf.zoffset = sc.Float;
}
// angleoffset, pitchoffset and rolloffset reading.
else if (sc.Compare("angleoffset"))
{
sc.MustGetFloat();
smf.angleoffset = sc.Float;
}
else if (sc.Compare("pitchoffset"))
{
sc.MustGetFloat();
smf.pitchoffset = sc.Float;
}
else if (sc.Compare("rolloffset"))
{
sc.MustGetFloat();
smf.rolloffset = sc.Float;
}
// [BB] Added model flags reading.
else if (sc.Compare("ignoretranslation"))
{
smf.flags |= MDL_IGNORETRANSLATION;
}
else if (sc.Compare("pitchfrommomentum"))
{
smf.flags |= MDL_PITCHFROMMOMENTUM;
}
else if (sc.Compare("inheritactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
}
else if (sc.Compare("inheritactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("useactorpitch"))
{
smf.flags |= MDL_USEACTORPITCH;
}
else if (sc.Compare("useactorroll"))
{
smf.flags |= MDL_USEACTORROLL;
}
else if (sc.Compare("rotating"))
{
smf.flags |= MDL_ROTATING;
smf.xrotate = 0.;
smf.yrotate = 1.;
smf.zrotate = 0.;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
smf.rotationSpeed = 1.;
}
else if (sc.Compare("rotation-speed"))
{
sc.MustGetFloat();
smf.rotationSpeed = sc.Float;
}
else if (sc.Compare("rotation-vector"))
{
sc.MustGetFloat();
smf.xrotate = sc.Float;
sc.MustGetFloat();
smf.yrotate = sc.Float;
sc.MustGetFloat();
smf.zrotate = sc.Float;
}
else if (sc.Compare("rotation-center"))
{
sc.MustGetFloat();
smf.rotationCenterX = sc.Float;
sc.MustGetFloat();
smf.rotationCenterY = sc.Float;
sc.MustGetFloat();
smf.rotationCenterZ = sc.Float;
}
else if (sc.Compare("interpolatedoubledframes"))
{
smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
}
else if (sc.Compare("nointerpolation"))
{
smf.flags |= MDL_NOINTERPOLATION;
}
else if (sc.Compare("skin"))
{
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.skinIDs[index]=FNullTextureID();
}
else
{
smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
if (!smf.skinIDs[index].isValid())
{
Printf("Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("surfaceskin"))
{
sc.MustGetNumber();
index = sc.Number;
sc.MustGetNumber();
surface = sc.Number;
if (index<0 || index >= MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (surface<0 || surface >= MD3_MAX_SURFACES)
{
sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FixPathSeperator(sc.String);
if (sc.Compare(""))
{
smf.surfaceskinIDs[index][surface] = FNullTextureID();
}
else
{
smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
if (!smf.surfaceskinIDs[index][surface].isValid())
{
Printf("Surface Skin '%s' not found in '%s'\n",
sc.String, smf.type->TypeName.GetChars());
}
}
}
else if (sc.Compare("frameindex") || sc.Compare("frame"))
{
bool isframe=!!sc.Compare("frame");
sc.MustGetString();
smf.sprite = -1;
for (int i = 0; i < (int)sprites.Size (); ++i)
{
if (strnicmp (sprites[i].name, sc.String, 4) == 0)
{
if (sprites[i].numframes==0)
{
//sc.ScriptError("Sprite %s has no frames", sc.String);
}
smf.sprite = i;
break;
}
}
if (smf.sprite==-1)
{
sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
}
sc.MustGetString();
FString framechars = sc.String;
sc.MustGetNumber();
index=sc.Number;
if (index<0 || index>=MAX_MODELS_PER_FRAME)
{
sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
}
if (isframe)
{
sc.MustGetString();
if (smf.modelIDs[index] != -1)
{
FModel *model = Models[smf.modelIDs[index]];
smf.modelframes[index] = model->FindFrame(sc.String);
if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
}
else smf.modelframes[index] = -1;
}
else
{
sc.MustGetNumber();
smf.modelframes[index] = sc.Number;
}
for(int i=0; framechars[i]>0; i++)
{
char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int c = toupper(framechars[i])-'A';
if (c<0 || c>=29)
{
sc.ScriptError("Invalid frame character %c found", c+'A');
}
if (map[c]) continue;
smf.frame=c;
SpriteModelFrames.Push(smf);
GetDefaultByType(smf.type)->hasmodel = true;
map[c]=1;
}
}
else if (sc.Compare("dontcullbackfaces"))
{
smf.flags |= MDL_DONTCULLBACKFACES;
}
else if (sc.Compare("userotationcenter"))
{
smf.flags |= MDL_USEROTATIONCENTER;
smf.rotationCenterX = 0.;
smf.rotationCenterY = 0.;
smf.rotationCenterZ = 0.;
}
else
{
sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
}
}
}
// This code is commented out because Gene Tech has broken include statements that blocks this feature..
/*else if (sc.Compare("#include"))
{
sc.MustGetString();
// This is not using sc.Open because it can print a more useful error message when done here
int includelump = Wads.CheckNumForFullName(sc.String, true);
if (includelump == -1)
sc.ScriptError("Lump '%s' not found", sc.String);
else
ParseModelDefLump(includelump);
}*/
}
}
//=========================================================================== //===========================================================================
// //
// gl_FindModelFrame // FindModelFrame
// //
//=========================================================================== //===========================================================================
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped) FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped)
{ {
if (GetDefaultByType(ti)->hasmodel) if (GetDefaultByType(ti)->hasmodel)
{ {
@ -898,11 +905,11 @@ FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame,
//=========================================================================== //===========================================================================
// //
// gl_IsHUDModelForPlayerAvailable // IsHUDModelForPlayerAvailable
// //
//=========================================================================== //===========================================================================
bool gl_IsHUDModelForPlayerAvailable (player_t * player) bool IsHUDModelForPlayerAvailable (player_t * player)
{ {
if (player == nullptr || player->ReadyWeapon == nullptr) if (player == nullptr || player->ReadyWeapon == nullptr)
return false; return false;
@ -913,7 +920,7 @@ bool gl_IsHUDModelForPlayerAvailable (player_t * player)
return false; return false;
FState* state = psp->GetState(); FState* state = psp->GetState();
FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false); FSpriteModelFrame *smf = FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false);
return ( smf != nullptr ); return ( smf != nullptr );
} }

View file

@ -46,6 +46,14 @@ FTextureID LoadSkin(const char * path, const char * fn);
struct FSpriteModelFrame; struct FSpriteModelFrame;
class IModelVertexBuffer; class IModelVertexBuffer;
enum ModelRendererType
{
GLModelRendererType,
SWModelRendererType,
PolyModelRendererType,
NumModelRendererTypes
};
class FModelRenderer class FModelRenderer
{ {
public: public:
@ -54,6 +62,8 @@ public:
void RenderModel(float x, float y, float z, FSpriteModelFrame *modelframe, AActor *actor); void RenderModel(float x, float y, float z, FSpriteModelFrame *modelframe, AActor *actor);
void RenderHUDModel(DPSprite *psp, float ofsx, float ofsy); void RenderHUDModel(DPSprite *psp, float ofsx, float ofsy);
virtual ModelRendererType GetType() const = 0;
virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0; virtual void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) = 0;
virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0; virtual void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) = 0;
@ -73,8 +83,7 @@ public:
virtual void DrawElements(int numIndices, size_t offset) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0;
private: private:
void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, Matrix3x4 *normaltransform, int translation); void RenderFrameModels(const FSpriteModelFrame *smf, const FState *curState, const int curTics, const PClass *ti, int translation);
static double GetTimeFloat();
}; };
struct FModelVertex struct FModelVertex
@ -123,11 +132,7 @@ public:
class FModel class FModel
{ {
public: public:
FModel();
FModel()
{
mVBuf = NULL;
}
virtual ~FModel(); virtual ~FModel();
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0;
@ -135,19 +140,20 @@ public:
virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0; virtual void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0;
virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0;
virtual void AddSkins(uint8_t *hitlist) = 0; virtual void AddSkins(uint8_t *hitlist) = 0;
void DestroyVertexBuffer()
{
delete mVBuf;
mVBuf = NULL;
}
virtual float getAspectFactor() { return 1.f; } virtual float getAspectFactor() { return 1.f; }
void SetVertexBuffer(FModelRenderer *renderer, IModelVertexBuffer *buffer) { mVBuf[renderer->GetType()] = buffer; }
IModelVertexBuffer *GetVertexBuffer(FModelRenderer *renderer) const { return mVBuf[renderer->GetType()]; }
void DestroyVertexBuffer();
const FSpriteModelFrame *curSpriteMDLFrame; const FSpriteModelFrame *curSpriteMDLFrame;
int curMDLIndex; int curMDLIndex;
void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; }; void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; };
IModelVertexBuffer *mVBuf;
FString mFileName; FString mFileName;
private:
IModelVertexBuffer *mVBuf[NumModelRendererTypes];
}; };
class FDMDModel : public FModel class FDMDModel : public FModel
@ -473,9 +479,9 @@ struct FSpriteModelFrame
float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float. float pitchoffset, rolloffset; // I don't want to bother with type transformations, so I made this variables float.
}; };
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped); FSpriteModelFrame * FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped);
bool IsHUDModelForPlayerAvailable(player_t * player);
bool gl_IsHUDModelForPlayerAvailable (player_t * player); void FlushModels();
class DeletingModelArray : public TArray<FModel *> class DeletingModelArray : public TArray<FModel *>
{ {

View file

@ -279,15 +279,17 @@ FDMDModel::~FDMDModel()
void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer) void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer)
{ {
if (mVBuf == NULL) if (!GetVertexBuffer(renderer))
{ {
LoadGeometry(); LoadGeometry();
int VertexBufferSize = info.numFrames * lodInfo[0].numTriangles * 3; int VertexBufferSize = info.numFrames * lodInfo[0].numTriangles * 3;
unsigned int vindex = 0; unsigned int vindex = 0;
mVBuf = renderer->CreateVertexBuffer(false, info.numFrames == 1); auto vbuf = renderer->CreateVertexBuffer(false, info.numFrames == 1);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(VertexBufferSize); SetVertexBuffer(renderer, vbuf);
FModelVertex *vertptr = vbuf->LockVertexBuffer(VertexBufferSize);
for (int i = 0; i < info.numFrames; i++) for (int i = 0; i < info.numFrames; i++)
{ {
@ -313,7 +315,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer)
tri++; tri++;
} }
} }
mVBuf->UnlockVertexBuffer(); vbuf->UnlockVertexBuffer();
UnloadGeometry(); UnloadGeometry();
} }
} }
@ -368,7 +370,7 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
renderer->SetInterpolation(inter); renderer->SetInterpolation(inter);
renderer->SetMaterial(skin, false, translation); renderer->SetMaterial(skin, false, translation);
mVBuf->SetupFrame(renderer, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3); GetVertexBuffer(renderer)->SetupFrame(renderer, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3);
renderer->DrawArrays(0, lodInfo[0].numTriangles * 3); renderer->DrawArrays(0, lodInfo[0].numTriangles * 3);
renderer->SetInterpolation(0.f); renderer->SetInterpolation(0.f);
} }

View file

@ -237,7 +237,7 @@ void FMD3Model::LoadGeometry()
void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer) void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
{ {
if (mVBuf == nullptr) if (!GetVertexBuffer(renderer))
{ {
LoadGeometry(); LoadGeometry();
@ -251,9 +251,11 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
ibufsize += 3 * surf->numTriangles; ibufsize += 3 * surf->numTriangles;
} }
mVBuf = renderer->CreateVertexBuffer(true, numFrames == 1); auto vbuf = renderer->CreateVertexBuffer(true, numFrames == 1);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(vbufsize); SetVertexBuffer(renderer, vbuf);
unsigned int *indxptr = mVBuf->LockIndexBuffer(ibufsize);
FModelVertex *vertptr = vbuf->LockVertexBuffer(vbufsize);
unsigned int *indxptr = vbuf->LockIndexBuffer(ibufsize);
assert(vertptr != nullptr && indxptr != nullptr); assert(vertptr != nullptr && indxptr != nullptr);
@ -285,8 +287,8 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer)
} }
surf->UnloadGeometry(); surf->UnloadGeometry();
} }
mVBuf->UnlockVertexBuffer(); vbuf->UnlockVertexBuffer();
mVBuf->UnlockIndexBuffer(); vbuf->UnlockIndexBuffer();
} }
} }
@ -365,7 +367,7 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame
} }
renderer->SetMaterial(surfaceSkin, false, translation); renderer->SetMaterial(surfaceSkin, false, translation);
mVBuf->SetupFrame(renderer, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices); GetVertexBuffer(renderer)->SetupFrame(renderer, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices);
renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int)); renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int));
} }
renderer->SetInterpolation(0.f); renderer->SetInterpolation(0.f);

View file

@ -198,7 +198,7 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FTexture *skin, int frame
} }
} }
renderer->SetMaterial(sskin,false,translation); renderer->SetMaterial(sskin,false,translation);
mVBuf->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize); GetVertexBuffer(renderer)->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize);
renderer->DrawArrays(0,vsize); renderer->DrawArrays(0,vsize);
vofs += vsize; vofs += vsize;
} }
@ -207,14 +207,15 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FTexture *skin, int frame
void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
{ {
if ( mVBuf != NULL ) if (GetVertexBuffer(renderer))
return; return;
int vsize = 0; int vsize = 0;
for ( int i=0; i<numGroups; i++ ) for ( int i=0; i<numGroups; i++ )
vsize += groups[i].numPolys*3; vsize += groups[i].numPolys*3;
vsize *= numFrames; vsize *= numFrames;
mVBuf = renderer->CreateVertexBuffer(false,numFrames==1); auto vbuf = renderer->CreateVertexBuffer(false,numFrames==1);
FModelVertex *vptr = mVBuf->LockVertexBuffer(vsize); SetVertexBuffer(renderer, vbuf);
FModelVertex *vptr = vbuf->LockVertexBuffer(vsize);
int vidx = 0; int vidx = 0;
for ( int i=0; i<numFrames; i++ ) for ( int i=0; i<numFrames; i++ )
{ {
@ -233,7 +234,7 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
} }
} }
} }
mVBuf->UnlockVertexBuffer(); vbuf->UnlockVertexBuffer();
} }
void FUE1Model::AddSkins( uint8_t *hitlist ) void FUE1Model::AddSkins( uint8_t *hitlist )

View file

@ -321,19 +321,21 @@ void FVoxelModel::Initialize()
void FVoxelModel::BuildVertexBuffer(FModelRenderer *renderer) void FVoxelModel::BuildVertexBuffer(FModelRenderer *renderer)
{ {
if (mVBuf == NULL) if (!GetVertexBuffer(renderer))
{ {
Initialize(); Initialize();
mVBuf = renderer->CreateVertexBuffer(true, true); auto vbuf = renderer->CreateVertexBuffer(true, true);
FModelVertex *vertptr = mVBuf->LockVertexBuffer(mVertices.Size()); SetVertexBuffer(renderer, vbuf);
unsigned int *indxptr = mVBuf->LockIndexBuffer(mIndices.Size());
FModelVertex *vertptr = vbuf->LockVertexBuffer(mVertices.Size());
unsigned int *indxptr = vbuf->LockIndexBuffer(mIndices.Size());
memcpy(vertptr, &mVertices[0], sizeof(FModelVertex)* mVertices.Size()); memcpy(vertptr, &mVertices[0], sizeof(FModelVertex)* mVertices.Size());
memcpy(indxptr, &mIndices[0], sizeof(unsigned int)* mIndices.Size()); memcpy(indxptr, &mIndices[0], sizeof(unsigned int)* mIndices.Size());
mVBuf->UnlockVertexBuffer(); vbuf->UnlockVertexBuffer();
mVBuf->UnlockIndexBuffer(); vbuf->UnlockIndexBuffer();
mNumIndices = mIndices.Size(); mNumIndices = mIndices.Size();
// delete our temporary buffers // delete our temporary buffers
@ -398,7 +400,7 @@ float FVoxelModel::getAspectFactor()
void FVoxelModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation) void FVoxelModel::RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation)
{ {
renderer->SetMaterial(skin, true, translation); renderer->SetMaterial(skin, true, translation);
mVBuf->SetupFrame(renderer, 0, 0, 0); GetVertexBuffer(renderer)->SetupFrame(renderer, 0, 0, 0);
renderer->DrawElements(mNumIndices, 0); renderer->DrawElements(mNumIndices, 0);
} }

View file

@ -34,7 +34,7 @@
#include "r_data/voxels.h" #include "r_data/voxels.h"
#include "vm.h" #include "vm.h"
void gl_InitModels(); void InitModels();
// variables used to look up // variables used to look up
// and range check thing_t sprites patches // and range check thing_t sprites patches
@ -1048,7 +1048,7 @@ void R_InitSprites ()
// [RH] Sort the skins, but leave base as skin 0 // [RH] Sort the skins, but leave base as skin 0
//qsort (&skins[PlayerClasses.Size ()], numskins-PlayerClasses.Size (), sizeof(FPlayerSkin), skinsorter); //qsort (&skins[PlayerClasses.Size ()], numskins-PlayerClasses.Size (), sizeof(FPlayerSkin), skinsorter);
gl_InitModels(); InitModels();
} }

View file

@ -962,7 +962,7 @@ namespace swrenderer
{ {
int spritenum = thing->sprite; int spritenum = thing->sprite;
bool isPicnumOverride = thing->picnum.isValid(); bool isPicnumOverride = thing->picnum.isValid();
FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : gl_FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); FSpriteModelFrame *modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
if (modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull) if (modelframe && (thing->Pos() - Thread->Viewport->viewpoint.Pos).LengthSquared() < model_distance_cull)
{ {
DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac); DVector3 pos = thing->InterpolatedPosition(Thread->Viewport->viewpoint.TicFrac);

View file

@ -34,9 +34,6 @@
#include "swrenderer/viewport/r_viewport.h" #include "swrenderer/viewport/r_viewport.h"
#include "swrenderer/scene/r_light.h" #include "swrenderer/scene/r_light.h"
void gl_FlushModels();
extern bool polymodelsInUse;
namespace swrenderer namespace swrenderer
{ {
void RenderModel::Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor) void RenderModel::Project(RenderThread *thread, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
@ -83,11 +80,6 @@ namespace swrenderer
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor) SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor)
{ {
if (polymodelsInUse)
{
gl_FlushModels();
polymodelsInUse = false;
}
} }
void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) void SWModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix)

View file

@ -54,6 +54,8 @@ namespace swrenderer
public: public:
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor); SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor);
ModelRendererType GetType() const override { return SWModelRendererType; }
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override; void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix) override;
void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override; void EndDrawModel(AActor *actor, FSpriteModelFrame *smf) override;
IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override; IModelVertexBuffer *CreateVertexBuffer(bool needindex, bool singleframe) override;

View file

@ -94,7 +94,7 @@ namespace swrenderer
(r_deathcamera && Thread->Viewport->viewpoint.camera->health <= 0)) (r_deathcamera && Thread->Viewport->viewpoint.camera->health <= 0))
return; return;
renderHUDModel = r_models && gl_IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player); renderHUDModel = r_models && IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
FDynamicColormap *basecolormap; FDynamicColormap *basecolormap;
CameraLight *cameraLight = CameraLight::Instance(); CameraLight *cameraLight = CameraLight::Instance();