mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-15 08:41:46 +00:00
Merge remote-tracking branch 'gzdoom/master' into newmaster
This commit is contained in:
commit
4c8f87627e
42 changed files with 1493 additions and 1277 deletions
|
@ -1003,6 +1003,7 @@ set (PCH_SOURCES
|
|||
maploader/polyobjects.cpp
|
||||
maploader/renderinfo.cpp
|
||||
maploader/compatibility.cpp
|
||||
maploader/postprocessor.cpp
|
||||
menu/joystickmenu.cpp
|
||||
menu/loadsavemenu.cpp
|
||||
menu/menu.cpp
|
||||
|
|
|
@ -128,6 +128,10 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
sc.MustGetString();
|
||||
iwad->MapInfo = sc.String;
|
||||
}
|
||||
else if (sc.Compare("NoKeyboardCheats"))
|
||||
{
|
||||
iwad->nokeyboardcheats = true;
|
||||
}
|
||||
else if (sc.Compare("Compatibility"))
|
||||
{
|
||||
sc.MustGetStringName("=");
|
||||
|
|
|
@ -2480,6 +2480,7 @@ static int D_DoomMain_Internal (void)
|
|||
if (!iwad_info) return 0; // user exited the selection popup via cancel button.
|
||||
gameinfo.gametype = iwad_info->gametype;
|
||||
gameinfo.flags = iwad_info->flags;
|
||||
gameinfo.nokeyboardcheats = iwad_info->nokeyboardcheats;
|
||||
gameinfo.ConfigName = iwad_info->Configname;
|
||||
lastIWAD = iwad;
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ struct FIWADInfo
|
|||
EGameType gametype = GAME_Doom; // which game are we playing?
|
||||
int StartupType = FStartupInfo::DefaultStartup; // alternate startup type
|
||||
FString MapInfo; // Base mapinfo to load
|
||||
bool nokeyboardcheats = false; // disable keyboard cheats
|
||||
TArray<FString> Load; // Wads to be loaded with this one.
|
||||
TArray<FString> Lumps; // Lump names for identification
|
||||
TArray<FString> DeleteLumps; // Lumps which must be deleted from the directory.
|
||||
|
|
|
@ -111,6 +111,7 @@ struct gameinfo_t
|
|||
FString ConfigName;
|
||||
|
||||
FString TitlePage;
|
||||
bool nokeyboardcheats;
|
||||
bool drawreadthis;
|
||||
bool noloopfinalemusic;
|
||||
bool intermissioncounter;
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "w_wad.h"
|
||||
#include "textures.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "actor.h"
|
||||
#include "p_setup.h"
|
||||
#include "maploader/maploader.h"
|
||||
|
@ -340,209 +339,3 @@ FName MapLoader::CheckCompatibility(MapData *map)
|
|||
}
|
||||
return FName(hash, true); // if this returns NAME_None it means there is no scripted compatibility handler.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SetCompatibilityParams
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class DLevelCompatibility : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DLevelCompatibility, DObject)
|
||||
public:
|
||||
MapLoader *loader;
|
||||
FLevelLocals *Level;
|
||||
};
|
||||
IMPLEMENT_CLASS(DLevelCompatibility, true, false);
|
||||
|
||||
|
||||
void MapLoader::SetCompatibilityParams(FName checksum)
|
||||
{
|
||||
auto lc = Create<DLevelCompatibility>();
|
||||
lc->loader = this;
|
||||
lc->Level = Level;
|
||||
for(auto cls : PClass::AllClasses)
|
||||
{
|
||||
if (cls->IsDescendantOf(RUNTIME_CLASS(DLevelCompatibility)))
|
||||
{
|
||||
PFunction *const func = dyn_cast<PFunction>(cls->FindSymbol("Apply", false));
|
||||
if (func == nullptr)
|
||||
{
|
||||
Printf("Missing 'Apply' method in class '%s', level compatibility object ignored\n", cls->TypeName.GetChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto argTypes = func->Variants[0].Proto->ArgumentTypes;
|
||||
if (argTypes.Size() != 3 || argTypes[1] != TypeName || argTypes[2] != TypeString)
|
||||
{
|
||||
Printf("Wrong signature of 'Apply' method in class '%s', level compatibility object ignored\n", cls->TypeName.GetChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
VMValue param[] = { lc, checksum.GetIndex(), &Level->MapName };
|
||||
VMCall(func->Variants[0].Implementation, param, 3, nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, OffsetSectorPlane)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(sector);
|
||||
PARAM_INT(planeval);
|
||||
PARAM_FLOAT(delta);
|
||||
|
||||
if ((unsigned)sector < self->Level->sectors.Size())
|
||||
{
|
||||
sector_t *sec = &self->Level->sectors[sector];
|
||||
secplane_t& plane = sector_t::floor == planeval? sec->floorplane : sec->ceilingplane;
|
||||
plane.ChangeHeight(delta);
|
||||
sec->ChangePlaneTexZ(planeval, delta);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, ClearSectorTags)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(sector);
|
||||
self->Level->tagManager.RemoveSectorTags(sector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, AddSectorTag)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(sector);
|
||||
PARAM_INT(tag);
|
||||
|
||||
if ((unsigned)sector < self->Level->sectors.Size())
|
||||
{
|
||||
self->Level->tagManager.AddSectorTag(sector, tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, ClearLineIDs)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(line);
|
||||
self->Level->tagManager.RemoveLineIDs(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, AddLineID)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(line);
|
||||
PARAM_INT(tag);
|
||||
|
||||
if ((unsigned)line < self->Level->lines.Size())
|
||||
{
|
||||
self->Level->tagManager.AddLineID(line, tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingSkills)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(thing);
|
||||
PARAM_INT(skillmask);
|
||||
|
||||
if ((unsigned)thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].SkillFilter = skillmask;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingXY)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(thing);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
|
||||
if ((unsigned)thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
auto& pos = self->loader->MapThingsConverted[thing].pos;
|
||||
pos.X = x;
|
||||
pos.Y = y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingZ)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(thing);
|
||||
PARAM_FLOAT(z);
|
||||
|
||||
if ((unsigned)thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].pos.Z = z;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingFlags)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_INT(thing);
|
||||
PARAM_INT(flags);
|
||||
|
||||
if ((unsigned)thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].flags = flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetVertex)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_UINT(vertex);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
|
||||
if (vertex < self->Level->vertexes.Size())
|
||||
{
|
||||
self->Level->vertexes[vertex].p = DVector2(x, y);
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_UINT(lineidx);
|
||||
PARAM_UINT(sideidx);
|
||||
PARAM_UINT(sectoridx);
|
||||
|
||||
if ( sideidx < 2
|
||||
&& lineidx < self->Level->lines.Size()
|
||||
&& sectoridx < self->Level->sectors.Size())
|
||||
{
|
||||
line_t *line = &self->Level->lines[lineidx];
|
||||
side_t *side = line->sidedef[sideidx];
|
||||
side->sector = &self->Level->sectors[sectoridx];
|
||||
if (sideidx == 0) line->frontsector = side->sector;
|
||||
else line->backsector = side->sector;
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, GetDefaultActor)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelCompatibility);
|
||||
PARAM_NAME(actorclass);
|
||||
ACTION_RETURN_OBJECT(GetDefaultByName(actorclass));
|
||||
}
|
||||
|
||||
|
||||
DEFINE_FIELD(DLevelCompatibility, Level);
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "swrenderer/r_swrenderer.h"
|
||||
#include "hwrenderer/data/flatvertices.h"
|
||||
#include "xlat/xlat.h"
|
||||
#include "vm.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -3053,7 +3054,8 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
ParseTextMap(map, missingtex);
|
||||
}
|
||||
|
||||
SetCompatibilityParams(checksum);
|
||||
CalcIndices();
|
||||
PostProcessLevel(checksum);
|
||||
|
||||
LoopSidedefs(true);
|
||||
|
||||
|
@ -3269,3 +3271,4 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
|
|||
if (!Level->IsReentering())
|
||||
Level->FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ private:
|
|||
TArray<int32_t> KnownPolySides;
|
||||
|
||||
FName CheckCompatibility(MapData *map);
|
||||
void SetCompatibilityParams(FName checksum);
|
||||
void PostProcessLevel(FName checksum);
|
||||
|
||||
// Slopes
|
||||
void SlopeLineToPoint(int lineid, const DVector3 &pos, bool slopeCeil);
|
||||
|
|
516
src/maploader/postprocessor.cpp
Normal file
516
src/maploader/postprocessor.cpp
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
** postprocessor.cpp
|
||||
** Level postprocessing
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2009 Randy Heit
|
||||
** Copyright 2009-2018 Christoph Oelckers
|
||||
** Copyright 2019 Alexey Lysiuk
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#include "doomstat.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "gi.h"
|
||||
#include "g_level.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "p_tags.h"
|
||||
#include "w_wad.h"
|
||||
#include "textures.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actor.h"
|
||||
#include "p_setup.h"
|
||||
#include "maploader/maploader.h"
|
||||
#include "types.h"
|
||||
#include "vm.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PostProcessLevel
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class DLevelPostProcessor : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(DLevelPostProcessor, DObject)
|
||||
public:
|
||||
MapLoader *loader;
|
||||
FLevelLocals *Level;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DLevelPostProcessor, true, false);
|
||||
|
||||
void MapLoader::PostProcessLevel(FName checksum)
|
||||
{
|
||||
auto lc = Create<DLevelPostProcessor>();
|
||||
lc->loader = this;
|
||||
lc->Level = Level;
|
||||
for(auto cls : PClass::AllClasses)
|
||||
{
|
||||
if (cls->IsDescendantOf(RUNTIME_CLASS(DLevelPostProcessor)))
|
||||
{
|
||||
PFunction *const func = dyn_cast<PFunction>(cls->FindSymbol("Apply", false));
|
||||
if (func == nullptr)
|
||||
{
|
||||
Printf("Missing 'Apply' method in class '%s', level compatibility object ignored\n", cls->TypeName.GetChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto argTypes = func->Variants[0].Proto->ArgumentTypes;
|
||||
if (argTypes.Size() != 3 || argTypes[1] != TypeName || argTypes[2] != TypeString)
|
||||
{
|
||||
Printf("Wrong signature of 'Apply' method in class '%s', level compatibility object ignored\n", cls->TypeName.GetChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
VMValue param[] = { lc, checksum.GetIndex(), &Level->MapName };
|
||||
VMCall(func->Variants[0].Implementation, param, 3, nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, OffsetSectorPlane)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_INT(sector);
|
||||
PARAM_INT(planeval);
|
||||
PARAM_FLOAT(delta);
|
||||
|
||||
if ((unsigned)sector < self->Level->sectors.Size())
|
||||
{
|
||||
sector_t *sec = &self->Level->sectors[sector];
|
||||
secplane_t& plane = sector_t::floor == planeval? sec->floorplane : sec->ceilingplane;
|
||||
plane.ChangeHeight(delta);
|
||||
sec->ChangePlaneTexZ(planeval, delta);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, ClearSectorTags)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_INT(sector);
|
||||
self->Level->tagManager.RemoveSectorTags(sector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, AddSectorTag)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_INT(sector);
|
||||
PARAM_INT(tag);
|
||||
|
||||
if ((unsigned)sector < self->Level->sectors.Size())
|
||||
{
|
||||
self->Level->tagManager.AddSectorTag(sector, tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, ClearLineIDs)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_INT(line);
|
||||
self->Level->tagManager.RemoveLineIDs(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, AddLineID)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_INT(line);
|
||||
PARAM_INT(tag);
|
||||
|
||||
if ((unsigned)line < self->Level->lines.Size())
|
||||
{
|
||||
self->Level->tagManager.AddLineID(line, tag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingCount)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
ACTION_RETURN_INT(self->loader->MapThingsConverted.Size());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, AddThing)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(ednum);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_INT(angle);
|
||||
PARAM_UINT(skills);
|
||||
PARAM_UINT(flags);
|
||||
|
||||
auto &things = self->loader->MapThingsConverted;
|
||||
const unsigned newindex = things.Size();
|
||||
things.Resize(newindex + 1);
|
||||
|
||||
auto &newthing = things.Last();
|
||||
memset(&newthing, 0, sizeof newthing);
|
||||
|
||||
newthing.Gravity = 1;
|
||||
newthing.SkillFilter = skills;
|
||||
newthing.ClassFilter = 0xFFFF;
|
||||
newthing.RenderStyle = STYLE_Count;
|
||||
newthing.Alpha = -1;
|
||||
newthing.Health = 1;
|
||||
newthing.FloatbobPhase = -1;
|
||||
newthing.pos.X = x;
|
||||
newthing.pos.Y = y;
|
||||
newthing.pos.Z = z;
|
||||
newthing.angle = angle;
|
||||
newthing.EdNum = ednum;
|
||||
newthing.info = DoomEdMap.CheckKey(ednum);
|
||||
newthing.flags = flags;
|
||||
|
||||
ACTION_RETURN_INT(newindex);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingEdNum)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const int ednum = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].EdNum : 0;
|
||||
ACTION_RETURN_INT(ednum);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingEdNum)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_UINT(ednum);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
auto &mti = self->loader->MapThingsConverted[thing];
|
||||
mti.EdNum = ednum;
|
||||
mti.info = DoomEdMap.CheckKey(ednum);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingPos)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const DVector3 pos = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].pos
|
||||
: DVector3(0, 0, 0);
|
||||
ACTION_RETURN_VEC3(pos);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingXY)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
auto& pos = self->loader->MapThingsConverted[thing].pos;
|
||||
pos.X = x;
|
||||
pos.Y = y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingZ)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_FLOAT(z);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].pos.Z = z;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingAngle)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const int angle = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].angle : 0;
|
||||
ACTION_RETURN_INT(angle);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingAngle)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_INT(angle);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].angle = angle;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingSkills)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const int skills = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].SkillFilter : 0;
|
||||
ACTION_RETURN_INT(skills);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingSkills)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_UINT(skillmask);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].SkillFilter = skillmask;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingFlags)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const unsigned flags = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].flags : 0;
|
||||
ACTION_RETURN_INT(flags);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingFlags)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_UINT(flags);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].flags = flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingSpecial)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const int special = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].special : 0;
|
||||
ACTION_RETURN_INT(special);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingSpecial)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_INT(special);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].special = special;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingArgument)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_UINT(index);
|
||||
|
||||
const int argument = index < 5 && thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].args[index] : 0;
|
||||
ACTION_RETURN_INT(argument);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingStringArgument)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const FName argument = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].arg0str : NAME_None;
|
||||
ACTION_RETURN_INT(argument);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingArgument)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_UINT(index);
|
||||
PARAM_INT(value);
|
||||
|
||||
if (index < 5 && thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].args[index] = value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingStringArgument)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_INT(value);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].arg0str = ENamedName(value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetThingID)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
|
||||
const int id = thing < self->loader->MapThingsConverted.Size()
|
||||
? self->loader->MapThingsConverted[thing].thingid : 0;
|
||||
ACTION_RETURN_INT(id);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetThingID)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(thing);
|
||||
PARAM_INT(id);
|
||||
|
||||
if (thing < self->loader->MapThingsConverted.Size())
|
||||
{
|
||||
self->loader->MapThingsConverted[thing].thingid = id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetVertex)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(vertex);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
|
||||
if (vertex < self->Level->vertexes.Size())
|
||||
{
|
||||
self->Level->vertexes[vertex].p = DVector2(x, y);
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetLineVertexes)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(lineidx);
|
||||
PARAM_UINT(vertexidx1);
|
||||
PARAM_UINT(vertexidx2);
|
||||
|
||||
if (lineidx < self->Level->lines.Size() &&
|
||||
vertexidx1 < self->Level->vertexes.Size() &&
|
||||
vertexidx2 < self->Level->vertexes.Size())
|
||||
{
|
||||
line_t *line = &self->Level->lines[lineidx];
|
||||
vertex_t *vertex1 = &self->Level->vertexes[vertexidx1];
|
||||
vertex_t *vertex2 = &self->Level->vertexes[vertexidx2];
|
||||
|
||||
line->v1 = vertex1;
|
||||
line->v2 = vertex2;
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, FlipLineSideRefs)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(lineidx);
|
||||
|
||||
if (lineidx < self->Level->lines.Size())
|
||||
{
|
||||
line_t *line = &self->Level->lines[lineidx];
|
||||
side_t *side1 = line->sidedef[1];
|
||||
side_t *side2 = line->sidedef[0];
|
||||
|
||||
if (!!side1 && !!side2) // don't flip single-sided lines
|
||||
{
|
||||
sector_t *frontsector = line->sidedef[1]->sector;
|
||||
sector_t *backsector = line->sidedef[0]->sector;
|
||||
line->sidedef[0] = side1;
|
||||
line->sidedef[1] = side2;
|
||||
line->frontsector = frontsector;
|
||||
line->backsector = backsector;
|
||||
}
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetLineSectorRef)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_UINT(lineidx);
|
||||
PARAM_UINT(sideidx);
|
||||
PARAM_UINT(sectoridx);
|
||||
|
||||
if ( sideidx < 2
|
||||
&& lineidx < self->Level->lines.Size()
|
||||
&& sectoridx < self->Level->sectors.Size())
|
||||
{
|
||||
line_t *line = &self->Level->lines[lineidx];
|
||||
side_t *side = line->sidedef[sideidx];
|
||||
side->sector = &self->Level->sectors[sectoridx];
|
||||
if (sideidx == 0) line->frontsector = side->sector;
|
||||
else line->backsector = side->sector;
|
||||
}
|
||||
self->loader->ForceNodeBuild = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelPostProcessor, GetDefaultActor)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DLevelPostProcessor);
|
||||
PARAM_NAME(actorclass);
|
||||
ACTION_RETURN_OBJECT(GetDefaultByName(actorclass));
|
||||
}
|
||||
|
||||
DEFINE_FIELD(DLevelPostProcessor, Level);
|
||||
|
|
@ -592,12 +592,10 @@ void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool pl
|
|||
{
|
||||
if (printmessage)
|
||||
{
|
||||
if (!showsecretsector || sectornum < 0) C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]);
|
||||
else
|
||||
C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]);
|
||||
if (showsecretsector && sectornum >= 0)
|
||||
{
|
||||
FString s = GStrings["SECRETMESSAGE"];
|
||||
s.AppendFormat(" (Sector %d)", sectornum);
|
||||
C_MidPrint(nullptr, s);
|
||||
Printf(PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum);
|
||||
}
|
||||
}
|
||||
if (playsound) S_Sound (CHAN_AUTO | CHAN_UI, "misc/secret", 1, ATTN_NORM);
|
||||
|
|
|
@ -54,12 +54,15 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, const ProjectedWallLight &wallLight)
|
||||
void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const DrawSegmentClipInfo& clip, const ProjectedWallLight &wallLight)
|
||||
{
|
||||
// This is essentially the same as R_MapVisPlane but with an extra step
|
||||
// to create new horizontal spans whenever the light changes enough that
|
||||
// we need to use a new colormap.
|
||||
|
||||
const short* uclip = clip.sprtopclip;
|
||||
const short* dclip = clip.sprbottomclip;
|
||||
|
||||
int wallshade = LightVisibility::LightLevelToShade(wallLight.GetLightLevel(), wallLight.GetFoggy(), thread->Viewport.get());
|
||||
int x = x2 - 1;
|
||||
int t2 = uclip[x];
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace swrenderer
|
|||
class RenderFogBoundary
|
||||
{
|
||||
public:
|
||||
void Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, const ProjectedWallLight &wallLight);
|
||||
void Render(RenderThread *thread, int x1, int x2, const DrawSegmentClipInfo &clip, const ProjectedWallLight &wallLight);
|
||||
|
||||
private:
|
||||
void RenderSection(RenderThread *thread, int y, int y2, int x1);
|
||||
|
|
|
@ -109,21 +109,7 @@ namespace swrenderer
|
|||
if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos))
|
||||
return;
|
||||
|
||||
vertex_t *v1 = line->linedef->v1;
|
||||
vertex_t *v2 = line->linedef->v2;
|
||||
|
||||
if ((v1 == line->v1 && v2 == line->v2) || (v2 == line->v1 && v1 == line->v2))
|
||||
{ // The seg is the entire wall.
|
||||
WallT.InitFromWallCoords(Thread, &WallC);
|
||||
}
|
||||
else
|
||||
{ // The seg is only part of the wall.
|
||||
if (line->linedef->sidedef[0] != line->sidedef)
|
||||
{
|
||||
swapvalues(v1, v2);
|
||||
}
|
||||
WallT.InitFromLine(Thread, v1->fPos() - Thread->Viewport->viewpoint.Pos, v2->fPos() - Thread->Viewport->viewpoint.Pos);
|
||||
}
|
||||
WallT.InitFromLine(Thread, line);
|
||||
|
||||
mFrontCeilingZ1 = mFrontSector->ceilingplane.ZatPoint(line->v1);
|
||||
mFrontFloorZ1 = mFrontSector->floorplane.ZatPoint(line->v1);
|
||||
|
@ -301,14 +287,6 @@ namespace swrenderer
|
|||
// A wall segment will be drawn between start and stop pixels (inclusive).
|
||||
bool SWRenderLine::RenderWallSegment(int start, int stop)
|
||||
{
|
||||
int i;
|
||||
bool maskedtexture = false;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (start >= viewwidth || start >= stop)
|
||||
I_Error("Bad R_StoreWallRange: %i to %i", start, stop);
|
||||
#endif
|
||||
|
||||
if (!rw_prepped)
|
||||
{
|
||||
rw_prepped = true;
|
||||
|
@ -327,41 +305,39 @@ namespace swrenderer
|
|||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
Thread->DrawSegments->Push(draw_segment);
|
||||
|
||||
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
draw_segment->drawsegclip.CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
draw_segment->WallC = WallC;
|
||||
draw_segment->tmapvals = WallT;
|
||||
draw_segment->x1 = start;
|
||||
draw_segment->x2 = stop;
|
||||
draw_segment->curline = mLineSegment;
|
||||
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||
draw_segment->drawsegclip.SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||
|
||||
bool markportal = ShouldMarkPortal();
|
||||
|
||||
if (markportal)
|
||||
{
|
||||
draw_segment->silhouette = SIL_BOTH;
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, Thread->OpaquePass->floorclip);
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTH;
|
||||
}
|
||||
else if (mBackSector == NULL)
|
||||
else if (!mBackSector)
|
||||
{
|
||||
draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
fillshort(draw_segment->sprtopclip, stop - start, viewheight);
|
||||
memset(draw_segment->sprbottomclip, -1, (stop - start) * sizeof(short));
|
||||
draw_segment->silhouette = SIL_BOTH;
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, viewheight);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, -1);
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// two sided line
|
||||
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 ||
|
||||
mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 || mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
{
|
||||
draw_segment->silhouette = SIL_BOTTOM;
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTTOM;
|
||||
}
|
||||
|
||||
if (mFrontCeilingZ1 < mBackCeilingZ1 || mFrontCeilingZ2 < mBackCeilingZ2 ||
|
||||
mBackSector->ceilingplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
if (mFrontCeilingZ1 < mBackCeilingZ1 || mFrontCeilingZ2 < mBackCeilingZ2 || mBackSector->ceilingplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
{
|
||||
draw_segment->silhouette |= SIL_TOP;
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP;
|
||||
}
|
||||
|
||||
// killough 1/17/98: this test is required if the fix
|
||||
|
@ -372,83 +348,65 @@ namespace swrenderer
|
|||
//
|
||||
// killough 4/7/98: make doorclosed external variable
|
||||
|
||||
if (mDoorClosed || (mBackCeilingZ1 <= mFrontFloorZ1 && mBackCeilingZ2 <= mFrontFloorZ2))
|
||||
{
|
||||
if (mDoorClosed || (mBackCeilingZ1 <= mFrontFloorZ1 && mBackCeilingZ2 <= mFrontFloorZ2))
|
||||
{
|
||||
draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
memset(draw_segment->sprbottomclip, -1, (stop - start) * sizeof(short));
|
||||
draw_segment->silhouette |= SIL_BOTTOM;
|
||||
}
|
||||
if (mDoorClosed || (mBackFloorZ1 >= mFrontCeilingZ1 && mBackFloorZ2 >= mFrontCeilingZ2))
|
||||
{ // killough 1/17/98, 2/8/98
|
||||
draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
fillshort(draw_segment->sprtopclip, stop - start, viewheight);
|
||||
draw_segment->silhouette |= SIL_TOP;
|
||||
}
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, -1);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_BOTTOM;
|
||||
}
|
||||
if (mDoorClosed || (mBackFloorZ1 >= mFrontCeilingZ1 && mBackFloorZ2 >= mFrontCeilingZ2))
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, viewheight);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP;
|
||||
}
|
||||
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
{
|
||||
if (r_3dfloors)
|
||||
{
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allocate space for masked texture tables, if needed
|
||||
// [RH] Don't just allocate the space; fill it in too.
|
||||
if ((sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||
(mCeilingClipped != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) &&
|
||||
if ((mCeilingClipped != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) &&
|
||||
(mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) &&
|
||||
(WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z))
|
||||
{
|
||||
maskedtexture = true;
|
||||
|
||||
// kg3D - backup for mid and fake walls
|
||||
draw_segment->bkup = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start));
|
||||
|
||||
draw_segment->bFogBoundary = IsFogBoundary(mFrontSector, mBackSector);
|
||||
bool is_translucent = sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls();
|
||||
if (is_translucent)
|
||||
if (r_3dfloors)
|
||||
{
|
||||
if (sidedef->GetTexture(side_t::mid).isValid())
|
||||
draw_segment->SetHas3DFloorMidTexture();
|
||||
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
double yscale = (pic ? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
|
||||
fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||
|
||||
if (pic && pic->useWorldPanning(sidedef->GetLevel()))
|
||||
{
|
||||
xoffset = xs_RoundToInt(xoffset * lwallscale);
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (int i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor* rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (int i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor* rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_segment->texcoords.Set(Thread, walltexcoords, start, stop, xoffset, yscale);
|
||||
}
|
||||
|
||||
draw_segment->light = mLight.GetLightPos(start);
|
||||
draw_segment->lightstep = mLight.GetLightStep();
|
||||
if (IsFogBoundary(mFrontSector, mBackSector))
|
||||
draw_segment->SetHasFogBoundary();
|
||||
|
||||
if (draw_segment->bFogBoundary || is_translucent)
|
||||
if (mLineSegment->linedef->alpha > 0.0f && sidedef->GetTexture(side_t::mid).isValid())
|
||||
{
|
||||
FTexture* tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture* pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (pic)
|
||||
{
|
||||
draw_segment->SetHasTranslucentMidTexture();
|
||||
draw_segment->texcoords.ProjectTranslucent(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, pic);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP | SIL_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
if (draw_segment->HasFogBoundary() || draw_segment->HasTranslucentMidTexture() || draw_segment->Has3DFloorWalls())
|
||||
{
|
||||
draw_segment->drawsegclip.SetBackupClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
draw_segment->light = mLight.GetLightPos(start);
|
||||
draw_segment->lightstep = mLight.GetLightStep();
|
||||
Thread->DrawSegments->PushTranslucent(draw_segment);
|
||||
}
|
||||
}
|
||||
|
@ -468,22 +426,16 @@ namespace swrenderer
|
|||
|
||||
MarkOpaquePassClip(start, stop);
|
||||
|
||||
// save sprite clipping info
|
||||
if (((draw_segment->silhouette & SIL_TOP) || maskedtexture) && draw_segment->sprtopclip == nullptr)
|
||||
bool needcliplists = draw_segment->HasFogBoundary() || draw_segment->HasTranslucentMidTexture() || draw_segment->Has3DFloorWalls();
|
||||
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_TOP) || needcliplists) && !draw_segment->drawsegclip.sprtopclip)
|
||||
{
|
||||
draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
memcpy(draw_segment->sprtopclip, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start));
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
}
|
||||
|
||||
if (((draw_segment->silhouette & SIL_BOTTOM) || maskedtexture) && draw_segment->sprbottomclip == nullptr)
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_BOTTOM) || needcliplists) && !draw_segment->drawsegclip.sprbottomclip)
|
||||
{
|
||||
draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(stop - start);
|
||||
memcpy(draw_segment->sprbottomclip, &Thread->OpaquePass->floorclip[start], sizeof(short)*(stop - start));
|
||||
}
|
||||
|
||||
if (maskedtexture && mLineSegment->sidedef->GetTexture(side_t::mid).isValid())
|
||||
{
|
||||
draw_segment->silhouette |= SIL_TOP | SIL_BOTTOM;
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, Thread->OpaquePass->floorclip);
|
||||
}
|
||||
|
||||
RenderMiddleTexture(start, stop);
|
||||
|
@ -499,7 +451,7 @@ namespace swrenderer
|
|||
|
||||
if (markportal)
|
||||
{
|
||||
Thread->Portal->AddLinePortal(mLineSegment->linedef, draw_segment->x1, draw_segment->x2, draw_segment->sprtopclip, draw_segment->sprbottomclip);
|
||||
Thread->Portal->AddLinePortal(mLineSegment->linedef, draw_segment->x1, draw_segment->x2, draw_segment->drawsegclip.sprtopclip, draw_segment->drawsegclip.sprbottomclip);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -685,9 +637,7 @@ namespace swrenderer
|
|||
markfloor = ShouldMarkFloor();
|
||||
markceiling = ShouldMarkCeiling();
|
||||
|
||||
SetTopTexture();
|
||||
SetMiddleTexture();
|
||||
SetBottomTexture();
|
||||
SetTextures();
|
||||
|
||||
if (mBackSector && !(sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)))
|
||||
{
|
||||
|
@ -715,7 +665,7 @@ namespace swrenderer
|
|||
FTexture *ftex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture *midtex = ftex && ftex->isValid() ? ftex->GetSoftwareTexture() : nullptr;
|
||||
|
||||
bool segtextured = ftex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
||||
bool segtextured = ftex != NULL || mTopTexture != NULL || mBottomTexture != NULL;
|
||||
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
{
|
||||
|
@ -725,201 +675,69 @@ namespace swrenderer
|
|||
// calculate light table
|
||||
if (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector)))
|
||||
{
|
||||
lwallscale =
|
||||
ftex ? ((midtex? midtex->GetScale().X : 1.0) * sidedef->GetTextureXScale(side_t::mid)) :
|
||||
mTopPart.Texture ? (mTopPart.Texture->GetScale().X * sidedef->GetTextureXScale(side_t::top)) :
|
||||
mBottomPart.Texture ? (mBottomPart.Texture->GetScale().X * sidedef->GetTextureXScale(side_t::bottom)) :
|
||||
1.;
|
||||
|
||||
walltexcoords.Project(Thread->Viewport.get(), sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT);
|
||||
|
||||
mLight.SetLightLeft(Thread, WallC);
|
||||
}
|
||||
}
|
||||
|
||||
void SWRenderLine::SetTextures()
|
||||
{
|
||||
mTopTexture = nullptr;
|
||||
mMiddleTexture = nullptr;
|
||||
mBottomTexture = nullptr;
|
||||
|
||||
side_t* sidedef = mLineSegment->sidedef;
|
||||
line_t* linedef = mLineSegment->linedef;
|
||||
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||
|
||||
if (!mBackSector)
|
||||
{
|
||||
SetMiddleTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mFrontCeilingZ1 > mBackCeilingZ1 || mFrontCeilingZ2 > mBackCeilingZ2) SetTopTexture();
|
||||
if (mFrontFloorZ1 < mBackFloorZ1 || mFrontFloorZ2 < mBackFloorZ2) SetBottomTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void SWRenderLine::SetTopTexture()
|
||||
{
|
||||
mTopPart.Texture = nullptr;
|
||||
|
||||
if (!(mFrontCeilingZ1 > mBackCeilingZ1 || mFrontCeilingZ2 > mBackCeilingZ2)) return;
|
||||
|
||||
side_t *sidedef = mLineSegment->sidedef;
|
||||
line_t *linedef = mLineSegment->linedef;
|
||||
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||
if (!mBackSector) return;
|
||||
|
||||
// No top texture for skyhack lines
|
||||
if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum && mBackSector->GetTexture(sector_t::ceiling) == skyflatnum) return;
|
||||
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::top), true);
|
||||
mTopPart.Texture = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (mTopPart.Texture == nullptr) return;
|
||||
if (!tex || !tex->isValid()) return;
|
||||
|
||||
mTopPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::top));
|
||||
double rowoffset = sidedef->GetTextureYOffset(side_t::top);
|
||||
mTopPart.TextureScaleU = sidedef->GetTextureXScale(side_t::top);
|
||||
mTopPart.TextureScaleV = sidedef->GetTextureYScale(side_t::top);
|
||||
double yrepeat = mTopPart.Texture->GetScale().Y * mTopPart.TextureScaleV;
|
||||
if (yrepeat >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGTOP)
|
||||
{ // top of texture at top
|
||||
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
if (rowoffset < 0 && mTopPart.Texture != NULL)
|
||||
{
|
||||
rowoffset += mTopPart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at bottom
|
||||
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
rowoffset = -rowoffset;
|
||||
if (linedef->flags & ML_DONTPEGTOP)
|
||||
{ // bottom of texture at top
|
||||
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
||||
}
|
||||
else
|
||||
{ // top of texture at bottom
|
||||
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
}
|
||||
}
|
||||
if (mTopPart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
mTopPart.TextureMid += rowoffset * yrepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTopPart.TextureMid += rowoffset;
|
||||
}
|
||||
mTopTexture = tex->GetSoftwareTexture();
|
||||
}
|
||||
|
||||
void SWRenderLine::SetMiddleTexture()
|
||||
{
|
||||
mMiddlePart.Texture = nullptr;
|
||||
|
||||
side_t *sidedef = mLineSegment->sidedef;
|
||||
line_t *linedef = mLineSegment->linedef;
|
||||
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||
if (mBackSector) return;
|
||||
|
||||
// [RH] Horizon lines do not need to be textured
|
||||
if (linedef->isVisualPortal()) return;
|
||||
if (linedef->special == Line_Horizon) return;
|
||||
|
||||
auto tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
mMiddlePart.Texture = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (mMiddlePart.Texture == nullptr) return;
|
||||
mMiddlePart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||
double rowoffset = sidedef->GetTextureYOffset(side_t::mid);
|
||||
mMiddlePart.TextureScaleU = sidedef->GetTextureXScale(side_t::mid);
|
||||
mMiddlePart.TextureScaleV = sidedef->GetTextureYScale(side_t::mid);
|
||||
double yrepeat = mMiddlePart.Texture->GetScale().Y * mMiddlePart.TextureScaleV;
|
||||
if (yrepeat >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
mMiddlePart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::floor) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + mMiddlePart.Texture->GetHeight();
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
mMiddlePart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
if (rowoffset < 0 && mMiddlePart.Texture != NULL)
|
||||
{
|
||||
rowoffset += mMiddlePart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
rowoffset = -rowoffset;
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
mMiddlePart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::floor) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
mMiddlePart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + mMiddlePart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
if (mMiddlePart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
mMiddlePart.TextureMid += rowoffset * yrepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
mMiddlePart.TextureMid += rowoffset;
|
||||
}
|
||||
if (!tex || !tex->isValid()) return;
|
||||
|
||||
mMiddleTexture = tex->GetSoftwareTexture();
|
||||
}
|
||||
|
||||
void SWRenderLine::SetBottomTexture()
|
||||
{
|
||||
mBottomPart.Texture = nullptr;
|
||||
|
||||
if (!(mFrontFloorZ1 < mBackFloorZ1 || mFrontFloorZ2 < mBackFloorZ2)) return;
|
||||
|
||||
side_t *sidedef = mLineSegment->sidedef;
|
||||
line_t *linedef = mLineSegment->linedef;
|
||||
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||
if (!mBackSector) return;
|
||||
|
||||
double frontlowertop = mFrontSector->GetPlaneTexZ(sector_t::ceiling);
|
||||
if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum && mBackSector->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
{
|
||||
// Putting sky ceilings on the front and back of a line alters the way unpegged
|
||||
// positioning works.
|
||||
frontlowertop = mBackSector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::bottom), true);
|
||||
mBottomPart.Texture = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (!mBottomPart.Texture) return;
|
||||
if (!tex || !tex->isValid()) return;
|
||||
|
||||
mBottomPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::bottom));
|
||||
double rowoffset = sidedef->GetTextureYOffset(side_t::bottom);
|
||||
mBottomPart.TextureScaleU = sidedef->GetTextureXScale(side_t::bottom);
|
||||
mBottomPart.TextureScaleV = sidedef->GetTextureYScale(side_t::bottom);
|
||||
double yrepeat = mBottomPart.Texture->GetScale().Y * mBottomPart.TextureScaleV;
|
||||
if (yrepeat >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
mBottomPart.TextureMid = (frontlowertop - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
mBottomPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::floor) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
if (rowoffset < 0 && mBottomPart.Texture != NULL)
|
||||
{
|
||||
rowoffset += mBottomPart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
rowoffset = -rowoffset;
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
mBottomPart.TextureMid = (frontlowertop - Thread->Viewport->viewpoint.Pos.Z) * yrepeat;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
mBottomPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::floor) - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + mBottomPart.Texture->GetHeight();
|
||||
}
|
||||
}
|
||||
if (mBottomPart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
mBottomPart.TextureMid += rowoffset * yrepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBottomPart.TextureMid += rowoffset;
|
||||
}
|
||||
mBottomTexture = tex->GetSoftwareTexture();
|
||||
}
|
||||
|
||||
bool SWRenderLine::IsFogBoundary(sector_t *front, sector_t *back) const
|
||||
|
@ -1037,14 +855,14 @@ namespace swrenderer
|
|||
auto ceilingclip = Thread->OpaquePass->ceilingclip;
|
||||
auto floorclip = Thread->OpaquePass->floorclip;
|
||||
|
||||
if (mMiddlePart.Texture) // one sided line
|
||||
if (mMiddleTexture) // one sided line
|
||||
{
|
||||
fillshort(ceilingclip + x1, x2 - x1, viewheight);
|
||||
fillshort(floorclip + x1, x2 - x1, 0xffff);
|
||||
}
|
||||
else
|
||||
{ // two sided line
|
||||
if (mTopPart.Texture != nullptr)
|
||||
if (mTopTexture != nullptr)
|
||||
{ // top wall
|
||||
for (int x = x1; x < x2; ++x)
|
||||
{
|
||||
|
@ -1057,7 +875,7 @@ namespace swrenderer
|
|||
memcpy(ceilingclip + x1, walltop.ScreenY + x1, (x2 - x1) * sizeof(short));
|
||||
}
|
||||
|
||||
if (mBottomPart.Texture != nullptr)
|
||||
if (mBottomTexture != nullptr)
|
||||
{ // bottom wall
|
||||
for (int x = x1; x < x2; ++x)
|
||||
{
|
||||
|
@ -1074,97 +892,40 @@ namespace swrenderer
|
|||
|
||||
void SWRenderLine::RenderTopTexture(int x1, int x2)
|
||||
{
|
||||
if (mMiddlePart.Texture) return;
|
||||
if (!mTopPart.Texture) return;
|
||||
if (mMiddleTexture) return;
|
||||
if (!mTopTexture) return;
|
||||
if (!viewactive) return;
|
||||
|
||||
auto rw_pic = mTopPart.Texture;
|
||||
double xscale = rw_pic->GetScale().X * mTopPart.TextureScaleU;
|
||||
double yscale = rw_pic->GetScale().Y * mTopPart.TextureScaleV;
|
||||
if (xscale != lwallscale)
|
||||
{
|
||||
walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
|
||||
lwallscale = xscale;
|
||||
}
|
||||
fixed_t offset;
|
||||
if (mTopPart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
offset = xs_RoundToInt(mTopPart.TextureOffsetU * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = mTopPart.TextureOffsetU;
|
||||
}
|
||||
if (xscale < 0)
|
||||
{
|
||||
offset = -offset;
|
||||
}
|
||||
ProjectedWallTexcoords texcoords;
|
||||
texcoords.ProjectTop(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mTopTexture);
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, mLight, GetLightList());
|
||||
}
|
||||
|
||||
void SWRenderLine::RenderMiddleTexture(int x1, int x2)
|
||||
{
|
||||
if (!mMiddlePart.Texture) return;
|
||||
if (!mMiddleTexture) return;
|
||||
if (!viewactive) return;
|
||||
|
||||
auto rw_pic = mMiddlePart.Texture;
|
||||
double xscale = rw_pic->GetScale().X * mMiddlePart.TextureScaleU;
|
||||
double yscale = rw_pic->GetScale().Y * mMiddlePart.TextureScaleV;
|
||||
if (xscale != lwallscale)
|
||||
{
|
||||
walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
|
||||
lwallscale = xscale;
|
||||
}
|
||||
fixed_t offset;
|
||||
if (mMiddlePart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
offset = xs_RoundToInt(mMiddlePart.TextureOffsetU * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = mMiddlePart.TextureOffsetU;
|
||||
}
|
||||
if (xscale < 0)
|
||||
{
|
||||
offset = -offset;
|
||||
}
|
||||
ProjectedWallTexcoords texcoords;
|
||||
texcoords.ProjectMid(Thread->Viewport.get(), mFrontSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mMiddleTexture);
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList());
|
||||
}
|
||||
|
||||
void SWRenderLine::RenderBottomTexture(int x1, int x2)
|
||||
{
|
||||
if (mMiddlePart.Texture) return;
|
||||
if (!mBottomPart.Texture) return;
|
||||
if (mMiddleTexture) return;
|
||||
if (!mBottomTexture) return;
|
||||
if (!viewactive) return;
|
||||
|
||||
auto rw_pic = mBottomPart.Texture;
|
||||
double xscale = rw_pic->GetScale().X * mBottomPart.TextureScaleU;
|
||||
double yscale = rw_pic->GetScale().Y * mBottomPart.TextureScaleV;
|
||||
if (xscale != lwallscale)
|
||||
{
|
||||
walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
|
||||
lwallscale = xscale;
|
||||
}
|
||||
fixed_t offset;
|
||||
if (mBottomPart.Texture->useWorldPanning(mLineSegment->GetLevel()))
|
||||
{
|
||||
offset = xs_RoundToInt(mBottomPart.TextureOffsetU * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = mBottomPart.TextureOffsetU;
|
||||
}
|
||||
if (xscale < 0)
|
||||
{
|
||||
offset = -offset;
|
||||
}
|
||||
ProjectedWallTexcoords texcoords;
|
||||
texcoords.ProjectBottom(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mBottomTexture);
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList());
|
||||
}
|
||||
|
||||
FLightNode *SWRenderLine::GetLightList()
|
||||
|
@ -1253,48 +1014,4 @@ namespace swrenderer
|
|||
|
||||
return sx2 <= sx1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FWallTmapVals::InitFromWallCoords(RenderThread *thread, const FWallCoords *wallc)
|
||||
{
|
||||
const FVector2 *left = &wallc->tleft;
|
||||
const FVector2 *right = &wallc->tright;
|
||||
|
||||
RenderPortal *renderportal = thread->Portal.get();
|
||||
|
||||
if (renderportal->MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
swapvalues(left, right);
|
||||
}
|
||||
UoverZorg = left->X * thread->Viewport->CenterX;
|
||||
UoverZstep = -left->Y;
|
||||
InvZorg = (left->X - right->X) * thread->Viewport->CenterX;
|
||||
InvZstep = right->Y - left->Y;
|
||||
}
|
||||
|
||||
void FWallTmapVals::InitFromLine(RenderThread *thread, const DVector2 &left, const DVector2 &right)
|
||||
{
|
||||
// Coordinates should have already had viewx,viewy subtracted
|
||||
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
double fullx1 = left.X * viewport->viewpoint.Sin - left.Y * viewport->viewpoint.Cos;
|
||||
double fullx2 = right.X * viewport->viewpoint.Sin - right.Y * viewport->viewpoint.Cos;
|
||||
double fully1 = left.X * viewport->viewpoint.TanCos + left.Y * viewport->viewpoint.TanSin;
|
||||
double fully2 = right.X * viewport->viewpoint.TanCos + right.Y * viewport->viewpoint.TanSin;
|
||||
|
||||
RenderPortal *renderportal = thread->Portal.get();
|
||||
|
||||
if (renderportal->MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
fullx1 = -fullx1;
|
||||
fullx2 = -fullx2;
|
||||
}
|
||||
|
||||
UoverZorg = float(fullx1 * viewport->CenterX);
|
||||
UoverZstep = float(-fully1);
|
||||
InvZorg = float((fullx1 - fullx2) * viewport->CenterX);
|
||||
InvZstep = float(fully2 - fully1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,24 +50,6 @@ namespace swrenderer
|
|||
bool Init(RenderThread *thread, const DVector2 &pt1, const DVector2 &pt2, double too_close);
|
||||
};
|
||||
|
||||
struct FWallTmapVals
|
||||
{
|
||||
float UoverZorg, UoverZstep;
|
||||
float InvZorg, InvZstep;
|
||||
|
||||
void InitFromWallCoords(RenderThread *thread, const FWallCoords *wallc);
|
||||
void InitFromLine(RenderThread *thread, const DVector2 &left, const DVector2 &right);
|
||||
};
|
||||
|
||||
struct WallPartTexture
|
||||
{
|
||||
fixed_t TextureOffsetU;
|
||||
double TextureMid;
|
||||
double TextureScaleU;
|
||||
double TextureScaleV;
|
||||
FSoftwareTexture *Texture;
|
||||
};
|
||||
|
||||
class SWRenderLine : VisibleSegmentRenderer
|
||||
{
|
||||
public:
|
||||
|
@ -79,6 +61,7 @@ namespace swrenderer
|
|||
private:
|
||||
bool RenderWallSegment(int x1, int x2) override;
|
||||
void SetWallVariables();
|
||||
void SetTextures();
|
||||
void SetTopTexture();
|
||||
void SetMiddleTexture();
|
||||
void SetBottomTexture();
|
||||
|
@ -134,14 +117,12 @@ namespace swrenderer
|
|||
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
double lwallscale;
|
||||
|
||||
bool markfloor; // False if the back side is the same plane.
|
||||
bool markceiling;
|
||||
|
||||
WallPartTexture mTopPart;
|
||||
WallPartTexture mMiddlePart;
|
||||
WallPartTexture mBottomPart;
|
||||
FSoftwareTexture* mTopTexture;
|
||||
FSoftwareTexture* mMiddleTexture;
|
||||
FSoftwareTexture* mBottomTexture;
|
||||
|
||||
ProjectedWallCull mCeilingClipped;
|
||||
ProjectedWallCull mFloorClipped;
|
||||
|
@ -150,7 +131,6 @@ namespace swrenderer
|
|||
ProjectedWallLine wallbottom;
|
||||
ProjectedWallLine wallupper;
|
||||
ProjectedWallLine walllower;
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
|
||||
sector_t tempsec; // killough 3/8/98: ceiling/water hack
|
||||
};
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
#include "swrenderer/viewport/r_viewport.h"
|
||||
#include "swrenderer/viewport/r_spritedrawer.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
RenderDrawSegment::RenderDrawSegment(RenderThread *thread)
|
||||
|
@ -92,52 +90,33 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
float alpha = (float)MIN(curline->linedef->alpha, 1.);
|
||||
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
||||
|
||||
SpriteDrawerArgs columndrawerargs;
|
||||
ColormapLight cmlight;
|
||||
cmlight.SetColormap(Thread, MINZ, mLight.GetLightLevel(), mLight.GetFoggy(), mLight.GetBaseColormap(), false, false, false, false, false);
|
||||
bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, cmlight);
|
||||
if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls())
|
||||
if (!ds->HasTranslucentMidTexture() && !ds->HasFogBoundary() && !ds->Has3DFloorWalls())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] Draw fog partition
|
||||
bool renderwall = true;
|
||||
bool notrelevant = false;
|
||||
if (ds->bFogBoundary)
|
||||
if (ds->HasFogBoundary())
|
||||
{
|
||||
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||
|
||||
RenderFogBoundary renderfog;
|
||||
renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, mLight);
|
||||
|
||||
if (!ds->texcoords)
|
||||
renderwall = false;
|
||||
renderfog.Render(Thread, x1, x2, ds->drawsegclip, mLight);
|
||||
}
|
||||
else if ((ds->Has3DFloorWalls() && !ds->Has3DFloorMidTexture()) || !visible)
|
||||
|
||||
bool notrelevant = false;
|
||||
if (ds->HasTranslucentMidTexture())
|
||||
notrelevant = RenderWall(ds, x1, x2);
|
||||
|
||||
if (ds->Has3DFloorWalls())
|
||||
{
|
||||
renderwall = false;
|
||||
Render3DFloorWallRange(ds, x1, x2);
|
||||
}
|
||||
|
||||
if (renderwall)
|
||||
notrelevant = RenderWall(ds, x1, x2, columndrawerargs, visible);
|
||||
|
||||
if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
RenderFakeWallRange(ds, x1, x2);
|
||||
}
|
||||
if (!notrelevant)
|
||||
{
|
||||
ds->sprclipped = true;
|
||||
fillshort(ds->sprtopclip - ds->x1 + x1, x2 - x1, viewheight);
|
||||
ds->drawsegclip.SetRangeDrawn(x1, x2);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, SpriteDrawerArgs &columndrawerargs, bool visible)
|
||||
bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2)
|
||||
{
|
||||
auto renderstyle = DefaultRenderStyle();
|
||||
auto viewport = Thread->Viewport.get();
|
||||
|
@ -153,63 +132,24 @@ namespace swrenderer
|
|||
}
|
||||
FSoftwareTexture *tex = ttex->GetSoftwareTexture();
|
||||
|
||||
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||
|
||||
float MaskedScaleY = ds->texcoords.yscale;
|
||||
|
||||
// find positioning
|
||||
double texheight = tex->GetScaledHeightDouble();
|
||||
double texheightscale = fabs(curline->sidedef->GetTextureYScale(side_t::mid));
|
||||
if (texheightscale != 1)
|
||||
{
|
||||
texheight = texheight / texheightscale;
|
||||
}
|
||||
|
||||
double texturemid;
|
||||
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{
|
||||
texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling));
|
||||
}
|
||||
|
||||
double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid);
|
||||
const short *mfloorclip = ds->drawsegclip.sprbottomclip;
|
||||
const short *mceilingclip = ds->drawsegclip.sprtopclip;
|
||||
|
||||
bool wrap = (curline->linedef->flags & ML_WRAP_MIDTEX) || (curline->sidedef->Flags & WALLF_WRAP_MIDTEX);
|
||||
if (!wrap)
|
||||
{ // Texture does not wrap vertically.
|
||||
double textop;
|
||||
|
||||
bool sprflipvert = false;
|
||||
|
||||
if (MaskedScaleY < 0)
|
||||
{
|
||||
MaskedScaleY = -MaskedScaleY;
|
||||
sprflipvert = true;
|
||||
}
|
||||
if (tex->useWorldPanning(curline->GetLevel()))
|
||||
{
|
||||
// rowoffset is added before the multiply so that the masked texture will
|
||||
// still be positioned in world units rather than texels.
|
||||
texturemid += rowoffset - Thread->Viewport->viewpoint.Pos.Z;
|
||||
textop = texturemid;
|
||||
texturemid *= MaskedScaleY;
|
||||
}
|
||||
// find positioning
|
||||
double texheight = tex->GetScaledHeightDouble() / fabs(curline->sidedef->GetTextureYScale(side_t::mid));
|
||||
double texturemid;
|
||||
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
|
||||
texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight;
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
textop = texturemid + rowoffset / MaskedScaleY - Thread->Viewport->viewpoint.Pos.Z;
|
||||
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z) * MaskedScaleY + rowoffset;
|
||||
}
|
||||
if (sprflipvert)
|
||||
{
|
||||
MaskedScaleY = -MaskedScaleY;
|
||||
texturemid -= tex->GetHeight() << FRACBITS;
|
||||
}
|
||||
texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling));
|
||||
double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid);
|
||||
if (tex->useWorldPanning(curline->GetLevel()))
|
||||
rowoffset /= fabs(tex->GetScale().Y * curline->sidedef->GetTextureYScale(side_t::mid));
|
||||
double textop = texturemid + rowoffset - Thread->Viewport->viewpoint.Pos.Z;
|
||||
|
||||
// [RH] Don't bother drawing segs that are completely offscreen
|
||||
if (viewport->globaldclip * ds->WallC.sz1 < -textop && viewport->globaldclip * ds->WallC.sz2 < -textop)
|
||||
|
@ -231,11 +171,6 @@ namespace swrenderer
|
|||
return true;
|
||||
}
|
||||
|
||||
WallC.sz1 = ds->WallC.sz1;
|
||||
WallC.sz2 = ds->WallC.sz2;
|
||||
WallC.sx1 = ds->WallC.sx1;
|
||||
WallC.sx2 = ds->WallC.sx2;
|
||||
|
||||
// Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range.
|
||||
double ceilZ = textop;
|
||||
double floorZ = textop - texheight;
|
||||
|
@ -267,19 +202,11 @@ namespace swrenderer
|
|||
floorZ = MAX(floorZ, clipZ);
|
||||
}
|
||||
|
||||
wallupper.Project(Thread->Viewport.get(), ceilZ, &WallC);
|
||||
walllower.Project(Thread->Viewport.get(), floorZ, &WallC);
|
||||
wallupper.Project(Thread->Viewport.get(), ceilZ, &ds->WallC);
|
||||
walllower.Project(Thread->Viewport.get(), floorZ, &ds->WallC);
|
||||
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
if (wallupper.ScreenY[i] < mceilingclip[i])
|
||||
wallupper.ScreenY[i] = mceilingclip[i];
|
||||
}
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
if (walllower.ScreenY[i] > mfloorclip[i])
|
||||
walllower.ScreenY[i] = mfloorclip[i];
|
||||
}
|
||||
wallupper.ClipTop(x1, x2, ds->drawsegclip);
|
||||
walllower.ClipBottom(x1, x2, ds->drawsegclip);
|
||||
|
||||
if (clip3d->CurrentSkybox)
|
||||
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
|
||||
|
@ -289,52 +216,15 @@ namespace swrenderer
|
|||
(curline->sidedef->Flags & WALLF_CLIP_MIDTEX) ||
|
||||
(curline->GetLevel()->ib_compatflags & BCOMPATF_CLIPMIDTEX))
|
||||
{
|
||||
ClipMidtex(x1, x2);
|
||||
ClipMidtex(ds, x1, x2);
|
||||
}
|
||||
}
|
||||
|
||||
mfloorclip = walllower.ScreenY;
|
||||
mceilingclip = wallupper.ScreenY;
|
||||
|
||||
auto cameraLight = CameraLight::Instance();
|
||||
bool needslight = (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0);
|
||||
|
||||
// draw the columns one at a time
|
||||
if (visible)
|
||||
{
|
||||
Thread->PrepareTexture(tex, renderstyle);
|
||||
float lightpos = mLight.GetLightPos(x1);
|
||||
for (int x = x1; x < x2; ++x)
|
||||
{
|
||||
if (needslight)
|
||||
{
|
||||
columndrawerargs.SetLight(lightpos, mLight.GetLightLevel(), mLight.GetFoggy(), Thread->Viewport.get());
|
||||
lightpos += mLight.GetLightStep();
|
||||
}
|
||||
|
||||
columndrawerargs.DrawMaskedColumn(Thread, x, tex, ds->texcoords, texturemid, MaskedScaleY, sprflipvert, mfloorclip, mceilingclip, renderstyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Texture does wrap vertically.
|
||||
if (tex->useWorldPanning(curline->GetLevel()))
|
||||
{
|
||||
// rowoffset is added before the multiply so that the masked texture will
|
||||
// still be positioned in world units rather than texels.
|
||||
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z + rowoffset) * MaskedScaleY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z) * MaskedScaleY + rowoffset;
|
||||
}
|
||||
|
||||
WallC.sz1 = ds->WallC.sz1;
|
||||
WallC.sz2 = ds->WallC.sz2;
|
||||
WallC.sx1 = ds->WallC.sx1;
|
||||
WallC.sx2 = ds->WallC.sx2;
|
||||
|
||||
if (clip3d->CurrentSkybox)
|
||||
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
|
||||
|
@ -344,13 +234,13 @@ namespace swrenderer
|
|||
(curline->sidedef->Flags & WALLF_CLIP_MIDTEX) ||
|
||||
(curline->GetLevel()->ib_compatflags & BCOMPATF_CLIPMIDTEX))
|
||||
{
|
||||
ClipMidtex(x1, x2);
|
||||
ClipMidtex(ds, x1, x2);
|
||||
}
|
||||
}
|
||||
|
||||
if (m3DFloor.clipTop)
|
||||
{
|
||||
wallupper.Project(Thread->Viewport.get(), m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
wallupper.Project(Thread->Viewport.get(), m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC);
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
if (wallupper.ScreenY[i] < mceilingclip[i])
|
||||
|
@ -360,7 +250,7 @@ namespace swrenderer
|
|||
}
|
||||
if (m3DFloor.clipBottom)
|
||||
{
|
||||
walllower.Project(Thread->Viewport.get(), m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
walllower.Project(Thread->Viewport.get(), m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC);
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
if (walllower.ScreenY[i] > mfloorclip[i])
|
||||
|
@ -368,115 +258,48 @@ namespace swrenderer
|
|||
}
|
||||
mfloorclip = walllower.ScreenY;
|
||||
}
|
||||
|
||||
rw_offset = 0;
|
||||
FSoftwareTexture *rw_pic = tex;
|
||||
|
||||
double top, bot;
|
||||
GetMaskedWallTopBottom(ds, top, bot);
|
||||
|
||||
float alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.));
|
||||
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, ds->texcoords, ds->texcoords.yscale, top, bot, true, additive, alpha, rw_offset, mLight, nullptr);
|
||||
}
|
||||
|
||||
double top, bot;
|
||||
GetMaskedWallTopBottom(ds, top, bot);
|
||||
|
||||
float alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.));
|
||||
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(frontsector, curline, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, top, bot, true, additive, alpha, mLight, nullptr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// kg3D - render one fake wall
|
||||
void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic)
|
||||
void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic)
|
||||
{
|
||||
int i;
|
||||
double xscale;
|
||||
double yscale;
|
||||
|
||||
fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255);
|
||||
if (Alpha <= 0)
|
||||
return;
|
||||
|
||||
mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1);
|
||||
|
||||
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||
|
||||
// find positioning
|
||||
side_t *scaledside;
|
||||
side_t::ETexpart scaledpart;
|
||||
if (rover->flags & FF_UPPERTEXTURE)
|
||||
{
|
||||
scaledside = curline->sidedef;
|
||||
scaledpart = side_t::top;
|
||||
}
|
||||
else if (rover->flags & FF_LOWERTEXTURE)
|
||||
{
|
||||
scaledside = curline->sidedef;
|
||||
scaledpart = side_t::bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
scaledside = rover->master->sidedef[0];
|
||||
scaledpart = side_t::mid;
|
||||
}
|
||||
xscale = rw_pic->GetScale().X * scaledside->GetTextureXScale(scaledpart);
|
||||
yscale = rw_pic->GetScale().Y * scaledside->GetTextureYScale(scaledpart);
|
||||
|
||||
double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid);
|
||||
double planez = rover->model->GetPlaneTexZ(sector_t::ceiling);
|
||||
rw_offset = FLOAT2FIXED(curline->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid));
|
||||
if (rowoffset < 0)
|
||||
{
|
||||
rowoffset += rw_pic->GetHeight();
|
||||
}
|
||||
double texturemid = (planez - Thread->Viewport->viewpoint.Pos.Z) * yscale;
|
||||
if (rw_pic->useWorldPanning(curline->GetLevel()))
|
||||
{
|
||||
// rowoffset is added before the multiply so that the masked texture will
|
||||
// still be positioned in world units rather than texels.
|
||||
|
||||
texturemid = texturemid + rowoffset * yscale;
|
||||
rw_offset = xs_RoundToInt(rw_offset * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
texturemid += rowoffset;
|
||||
}
|
||||
|
||||
WallC = ds->WallC;
|
||||
WallT = ds->tmapvals;
|
||||
|
||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||
wallupper.Project(Thread->Viewport.get(), clipTop - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
walllower.Project(Thread->Viewport.get(), clipBottom - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
wallupper.Project(Thread->Viewport.get(), clipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC);
|
||||
walllower.Project(Thread->Viewport.get(), clipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC);
|
||||
|
||||
for (i = x1; i < x2; i++)
|
||||
{
|
||||
if (wallupper.ScreenY[i] < mceilingclip[i])
|
||||
wallupper.ScreenY[i] = mceilingclip[i];
|
||||
}
|
||||
for (i = x1; i < x2; i++)
|
||||
{
|
||||
if (walllower.ScreenY[i] > mfloorclip[i])
|
||||
walllower.ScreenY[i] = mfloorclip[i];
|
||||
}
|
||||
wallupper.ClipTop(x1, x2, ds->drawsegclip);
|
||||
walllower.ClipBottom(x1, x2, ds->drawsegclip);
|
||||
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
walltexcoords.Project(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->WallC.sx1, ds->WallC.sx2, WallT);
|
||||
walltexcoords.Project3DFloor(Thread->Viewport.get(), rover, curline, ds->WallC.sx1, ds->WallC.sx2, ds->tmapvals, rw_pic);
|
||||
|
||||
double top, bot;
|
||||
GetMaskedWallTopBottom(ds, top, bot);
|
||||
|
||||
RenderWallPart renderWallpart(Thread);
|
||||
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, walltexcoords, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, rw_offset, mLight, nullptr);
|
||||
renderWallpart.Render(frontsector, curline, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, mLight, nullptr);
|
||||
|
||||
RenderDecal::RenderDecals(Thread, curline->sidedef, ds, curline, mLight, wallupper.ScreenY, walllower.ScreenY, true);
|
||||
}
|
||||
|
||||
// kg3D - walls of fake floors
|
||||
void RenderDrawSegment::RenderFakeWallRange(DrawSegment *ds, int x1, int x2)
|
||||
void RenderDrawSegment::Render3DFloorWallRange(DrawSegment *ds, int x1, int x2)
|
||||
{
|
||||
int i, j;
|
||||
F3DFloor *rover, *fover = nullptr;
|
||||
|
@ -699,7 +522,7 @@ namespace swrenderer
|
|||
//mLight.lightlevel = ds->lightlevel;
|
||||
mLight.SetColormap(frontsector, curline, lit);
|
||||
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
Render3DFloorWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -881,7 +704,7 @@ namespace swrenderer
|
|||
//mLight.lightlevel = ds->lightlevel;
|
||||
mLight.SetColormap(frontsector, curline, lit);
|
||||
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
Render3DFloorWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -889,19 +712,19 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
// Clip a midtexture to the floor and ceiling of the sector in front of it.
|
||||
void RenderDrawSegment::ClipMidtex(int x1, int x2)
|
||||
void RenderDrawSegment::ClipMidtex(DrawSegment* ds, int x1, int x2)
|
||||
{
|
||||
ProjectedWallLine most;
|
||||
|
||||
RenderPortal *renderportal = Thread->Portal.get();
|
||||
|
||||
most.Project(Thread->Viewport.get(), curline->frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP);
|
||||
most.Project(Thread->Viewport.get(), curline->frontsector->ceilingplane, &ds->WallC, curline, renderportal->MirrorFlags & RF_XFLIP);
|
||||
for (int i = x1; i < x2; ++i)
|
||||
{
|
||||
if (wallupper.ScreenY[i] < most.ScreenY[i])
|
||||
wallupper.ScreenY[i] = most.ScreenY[i];
|
||||
}
|
||||
most.Project(Thread->Viewport.get(), curline->frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP);
|
||||
most.Project(Thread->Viewport.get(), curline->frontsector->floorplane, &ds->WallC, curline, renderportal->MirrorFlags & RF_XFLIP);
|
||||
for (int i = x1; i < x2; ++i)
|
||||
{
|
||||
if (walllower.ScreenY[i] > most.ScreenY[i])
|
||||
|
|
|
@ -37,10 +37,10 @@ namespace swrenderer
|
|||
RenderThread *Thread = nullptr;
|
||||
|
||||
private:
|
||||
bool RenderWall(DrawSegment *ds, int x1, int x2, SpriteDrawerArgs &columndrawerargs, bool visible);
|
||||
void ClipMidtex(int x1, int x2);
|
||||
void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic);
|
||||
void RenderFakeWallRange(DrawSegment *ds, int x1, int x2);
|
||||
bool RenderWall(DrawSegment *ds, int x1, int x2);
|
||||
void ClipMidtex(DrawSegment* ds, int x1, int x2);
|
||||
void Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic);
|
||||
void Render3DFloorWallRange(DrawSegment *ds, int x1, int x2);
|
||||
void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot);
|
||||
|
||||
sector_t *frontsector = nullptr;
|
||||
|
@ -49,13 +49,8 @@ namespace swrenderer
|
|||
seg_t *curline = nullptr;
|
||||
Fake3DTranslucent m3DFloor;
|
||||
|
||||
FWallCoords WallC;
|
||||
FWallTmapVals WallT;
|
||||
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
fixed_t rw_offset = 0;
|
||||
|
||||
ProjectedWallLine wallupper;
|
||||
ProjectedWallLine walllower;
|
||||
};
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
|
||||
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords)
|
||||
{
|
||||
if (rw_pic == nullptr)
|
||||
return;
|
||||
|
@ -63,8 +63,6 @@ namespace swrenderer
|
|||
if (fracbits == 32)
|
||||
{ // Hack for one pixel tall textures
|
||||
fracbits = 0;
|
||||
yrepeat = 0;
|
||||
texturemid = 0;
|
||||
}
|
||||
|
||||
WallDrawerArgs drawerargs;
|
||||
|
@ -114,13 +112,13 @@ namespace swrenderer
|
|||
if (!fixed)
|
||||
drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||
|
||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(texcoords.UPos(x + 1)) - FIXED2DBL(texcoords.UPos(x)));
|
||||
|
||||
fixed_t xxoffset = (lwal[x] + xoffset + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||
fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||
|
||||
// Normalize to 0-1 range:
|
||||
double uv_stepd = swal[x] * yrepeat;
|
||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||
double uv_stepd = texcoords.VStep(x) * texcoords.yscale;
|
||||
double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||
v = v - floor(v);
|
||||
double v_step = uv_stepd / rw_pic->GetHeight();
|
||||
|
||||
|
@ -227,19 +225,19 @@ namespace swrenderer
|
|||
if (!fixed)
|
||||
drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||
|
||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(texcoords.UPos(x + 1)) - FIXED2DBL(texcoords.UPos(x)));
|
||||
|
||||
uint32_t uv_pos;
|
||||
uint32_t uv_step;
|
||||
|
||||
fixed_t xxoffset = (lwal[x] + xoffset + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||
fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||
|
||||
if (uv_fracbits != 32)
|
||||
{
|
||||
// Find start uv in [0-base_height[ range.
|
||||
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
|
||||
double uv_stepd = swal[x] * yrepeat;
|
||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||
double uv_stepd = texcoords.VStep(x) * texcoords.yscale;
|
||||
double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||
v = v - floor(v);
|
||||
v *= height;
|
||||
v *= (1 << uv_fracbits);
|
||||
|
@ -410,7 +408,7 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
|
||||
void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords)
|
||||
{
|
||||
ProjectedWallLine most1, most2, most3;
|
||||
const short *up;
|
||||
|
@ -434,7 +432,7 @@ namespace swrenderer
|
|||
{
|
||||
down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]);
|
||||
}
|
||||
ProcessNormalWall(up, down, texturemid, swal, lwal);
|
||||
ProcessNormalWall(up, down, texcoords);
|
||||
up = down;
|
||||
down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
|
||||
}
|
||||
|
@ -442,19 +440,19 @@ namespace swrenderer
|
|||
mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]);
|
||||
}
|
||||
|
||||
ProcessNormalWall(up, dwal, texturemid, swal, lwal);
|
||||
ProcessNormalWall(up, dwal, texcoords);
|
||||
}
|
||||
|
||||
void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
|
||||
void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords)
|
||||
{
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size()))
|
||||
{
|
||||
ProcessNormalWall(uwal, dwal, texturemid, swal, lwal);
|
||||
ProcessNormalWall(uwal, dwal, texcoords);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessStripedWall(uwal, dwal, texturemid, swal, lwal);
|
||||
ProcessStripedWall(uwal, dwal, texcoords);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,23 +467,23 @@ namespace swrenderer
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
void RenderWallPart::ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal, double top, double bot)
|
||||
void RenderWallPart::ProcessWallNP2(const short *uwal, const short *dwal, ProjectedWallTexcoords texcoords, double top, double bot)
|
||||
{
|
||||
ProjectedWallLine most1, most2, most3;
|
||||
double texheight = rw_pic->GetHeight();
|
||||
double partition;
|
||||
double scaledtexheight = texheight / yrepeat;
|
||||
double scaledtexheight = texheight / texcoords.yscale;
|
||||
|
||||
if (yrepeat >= 0)
|
||||
if (texcoords.yscale >= 0)
|
||||
{ // normal orientation: draw strips from top to bottom
|
||||
partition = top - fmod(top - texturemid / yrepeat - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight);
|
||||
partition = top - fmod(top - texcoords.texturemid / texcoords.yscale - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight);
|
||||
if (partition == top)
|
||||
{
|
||||
partition -= scaledtexheight;
|
||||
}
|
||||
const short *up = uwal;
|
||||
short *down = most1.ScreenY;
|
||||
texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + texheight;
|
||||
texcoords.texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * texcoords.yscale + texheight;
|
||||
while (partition > bot)
|
||||
{
|
||||
ProjectedWallCull j = most3.Project(Thread->Viewport.get(), partition - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
|
@ -495,21 +493,21 @@ namespace swrenderer
|
|||
{
|
||||
down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]);
|
||||
}
|
||||
ProcessWall(up, down, texturemid, swal, lwal);
|
||||
ProcessWall(up, down, texcoords);
|
||||
up = down;
|
||||
down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
|
||||
}
|
||||
partition -= scaledtexheight;
|
||||
texturemid -= texheight;
|
||||
texcoords.texturemid -= texheight;
|
||||
}
|
||||
ProcessWall(up, dwal, texturemid, swal, lwal);
|
||||
ProcessWall(up, dwal, texcoords);
|
||||
}
|
||||
else
|
||||
{ // upside down: draw strips from bottom to top
|
||||
partition = bot - fmod(bot - texturemid / yrepeat - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight);
|
||||
partition = bot - fmod(bot - texcoords.texturemid / texcoords.yscale - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight);
|
||||
short *up = most1.ScreenY;
|
||||
const short *down = dwal;
|
||||
texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * yrepeat + texheight;
|
||||
texcoords.texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * texcoords.yscale + texheight;
|
||||
while (partition < top)
|
||||
{
|
||||
ProjectedWallCull j = most3.Project(Thread->Viewport.get(), partition - Thread->Viewport->viewpoint.Pos.Z, &WallC);
|
||||
|
@ -519,27 +517,25 @@ namespace swrenderer
|
|||
{
|
||||
up[j] = clamp(most3.ScreenY[j], uwal[j], down[j]);
|
||||
}
|
||||
ProcessWall(up, down, texturemid, swal, lwal);
|
||||
ProcessWall(up, down, texcoords);
|
||||
down = up;
|
||||
up = (up == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
|
||||
}
|
||||
partition -= scaledtexheight;
|
||||
texturemid -= texheight;
|
||||
texcoords.texturemid -= texheight;
|
||||
}
|
||||
ProcessWall(uwal, down, texturemid, swal, lwal);
|
||||
ProcessWall(uwal, down, texcoords);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, const ProjectedWallTexcoords& texcoords, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight &light, FLightNode *light_list)
|
||||
void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, const ProjectedWallTexcoords& texcoords, double top, double bottom, bool mask, bool additive, fixed_t alpha, const ProjectedWallLight &light, FLightNode *light_list)
|
||||
{
|
||||
this->x1 = x1;
|
||||
this->x2 = x2;
|
||||
this->frontsector = frontsector;
|
||||
this->curline = curline;
|
||||
this->WallC = WallC;
|
||||
this->yrepeat = yscale;
|
||||
this->mLight = light;
|
||||
this->xoffset = xoffset;
|
||||
this->light_list = light_list;
|
||||
this->rw_pic = pic;
|
||||
this->mask = mask;
|
||||
|
@ -548,41 +544,13 @@ namespace swrenderer
|
|||
|
||||
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
|
||||
|
||||
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
|
||||
if (rw_pic->GetHeight() != (1 << rw_pic->GetHeightBits()))
|
||||
{
|
||||
ProcessWallNP2(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos, top, bottom);
|
||||
ProcessWallNP2(walltop, wallbottom, texcoords, top, bottom);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessWall(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::Render(sector_t* frontsector, seg_t* curline, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, double texturemid, const DrawSegmentWallTexcoords& texcoords, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight& light, FLightNode* light_list)
|
||||
{
|
||||
this->x1 = x1;
|
||||
this->x2 = x2;
|
||||
this->frontsector = frontsector;
|
||||
this->curline = curline;
|
||||
this->WallC = WallC;
|
||||
this->yrepeat = yscale;
|
||||
this->mLight = light;
|
||||
this->xoffset = xoffset;
|
||||
this->light_list = light_list;
|
||||
this->rw_pic = pic;
|
||||
this->mask = mask;
|
||||
this->additive = additive;
|
||||
this->alpha = alpha;
|
||||
|
||||
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
|
||||
|
||||
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
|
||||
{
|
||||
ProcessWallNP2(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos, top, bottom);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessWall(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos);
|
||||
ProcessWall(walltop, wallbottom, texcoords);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,46 +54,22 @@ namespace swrenderer
|
|||
int x2,
|
||||
const short *walltop,
|
||||
const short *wallbottom,
|
||||
double texturemid,
|
||||
const ProjectedWallTexcoords &texcoords,
|
||||
double yscale,
|
||||
double top,
|
||||
double bottom,
|
||||
bool mask,
|
||||
bool additive,
|
||||
fixed_t alpha,
|
||||
fixed_t xoffset,
|
||||
const ProjectedWallLight &light,
|
||||
FLightNode *light_list);
|
||||
|
||||
void Render(
|
||||
sector_t* frontsector,
|
||||
seg_t* curline,
|
||||
const FWallCoords& WallC,
|
||||
FSoftwareTexture* rw_pic,
|
||||
int x1,
|
||||
int x2,
|
||||
const short* walltop,
|
||||
const short* wallbottom,
|
||||
double texturemid,
|
||||
const DrawSegmentWallTexcoords& texcoords,
|
||||
double yscale,
|
||||
double top,
|
||||
double bottom,
|
||||
bool mask,
|
||||
bool additive,
|
||||
fixed_t alpha,
|
||||
fixed_t xoffset,
|
||||
const ProjectedWallLight& light,
|
||||
FLightNode* light_list);
|
||||
|
||||
RenderThread *Thread = nullptr;
|
||||
|
||||
private:
|
||||
void ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal, double top, double bot);
|
||||
void ProcessWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
|
||||
void ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
|
||||
void ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
|
||||
void ProcessWallNP2(const short *uwal, const short *dwal, ProjectedWallTexcoords texcoords, double top, double bot);
|
||||
void ProcessWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
|
||||
void ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
|
||||
void ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords);
|
||||
void SetLights(WallDrawerArgs &drawerargs, int x, int y1);
|
||||
|
||||
int x1 = 0;
|
||||
|
@ -105,8 +81,6 @@ namespace swrenderer
|
|||
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
double yrepeat = 0.0;
|
||||
fixed_t xoffset = 0;
|
||||
FLightNode *light_list = nullptr;
|
||||
bool mask = false;
|
||||
bool additive = false;
|
||||
|
|
|
@ -168,84 +168,416 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx)
|
||||
void ProjectedWallLine::ClipTop(int x1, int x2, const DrawSegmentClipInfo& clip)
|
||||
{
|
||||
float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - viewport->CenterX);
|
||||
float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - viewport->CenterX);
|
||||
float uGradient = WallT.UoverZstep;
|
||||
float zGradient = WallT.InvZstep;
|
||||
float xrepeat = (float)fabs(walxrepeat);
|
||||
float depthScale = (float)(WallT.InvZstep * viewport->WallTMapScale2);
|
||||
float depthOrg = (float)(-WallT.UoverZstep * viewport->WallTMapScale2);
|
||||
|
||||
if (walxrepeat < 0.0)
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
float u = uOverZ / invZ;
|
||||
|
||||
UPos[x] = (fixed_t)((xrepeat - u * xrepeat) * FRACUNIT);
|
||||
VStep[x] = depthOrg + u * depthScale;
|
||||
|
||||
uOverZ += uGradient;
|
||||
invZ += zGradient;
|
||||
}
|
||||
ScreenY[i] = std::max(ScreenY[i], clip.sprtopclip[i]);
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
void ProjectedWallLine::ClipBottom(int x1, int x2, const DrawSegmentClipInfo& clip)
|
||||
{
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
float u = uOverZ / invZ;
|
||||
|
||||
UPos[x] = (fixed_t)(u * xrepeat * FRACUNIT);
|
||||
VStep[x] = depthOrg + u * depthScale;
|
||||
|
||||
uOverZ += uGradient;
|
||||
invZ += zGradient;
|
||||
}
|
||||
}
|
||||
|
||||
if (flipx)
|
||||
{
|
||||
int right = (int)walxrepeat - 1;
|
||||
for (int i = x1; i < x2; i++)
|
||||
{
|
||||
UPos[i] = right - UPos[i];
|
||||
}
|
||||
ScreenY[i] = std::min(ScreenY[i], clip.sprbottomclip[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DrawSegmentWallTexcoords::Set(RenderThread* thread, const ProjectedWallTexcoords& texcoords, int x1, int x2, fixed_t xoffset, double yscale)
|
||||
void FWallTmapVals::InitFromWallCoords(RenderThread* thread, const FWallCoords* wallc)
|
||||
{
|
||||
UPos = thread->FrameMemory->AllocMemory<fixed_t>(x2 - x1) - x1;
|
||||
VStep = thread->FrameMemory->AllocMemory<float>(x2 - x1) - x1;
|
||||
const FVector2* left = &wallc->tleft;
|
||||
const FVector2* right = &wallc->tright;
|
||||
|
||||
for (int i = x1; i < x2; i++)
|
||||
if (thread->Portal->MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
UPos[i] = texcoords.UPos[i] + xoffset;
|
||||
VStep[i] = texcoords.VStep[i];
|
||||
swapvalues(left, right);
|
||||
}
|
||||
|
||||
double istart = VStep[x1] * yscale;
|
||||
double iend = VStep[x2 - 1] * yscale;
|
||||
UoverZorg = left->X * thread->Viewport->CenterX;
|
||||
UoverZstep = -left->Y;
|
||||
InvZorg = (left->X - right->X) * thread->Viewport->CenterX;
|
||||
InvZstep = right->Y - left->Y;
|
||||
}
|
||||
|
||||
istart = 1 / istart;
|
||||
iend = 1 / iend;
|
||||
void FWallTmapVals::InitFromLine(RenderThread* thread, seg_t* line)
|
||||
{
|
||||
auto viewport = thread->Viewport.get();
|
||||
auto renderportal = thread->Portal.get();
|
||||
|
||||
this->yscale = (float)yscale;
|
||||
iscale = (float)istart;
|
||||
if (x2 - x1 > 1)
|
||||
vertex_t* v1 = line->linedef->v1;
|
||||
vertex_t* v2 = line->linedef->v2;
|
||||
|
||||
if (line->linedef->sidedef[0] != line->sidedef)
|
||||
{
|
||||
iscalestep = float((iend - istart) / (x2 - x1 - 1));
|
||||
swapvalues(v1, v2);
|
||||
}
|
||||
|
||||
DVector2 left = v1->fPos() - viewport->viewpoint.Pos;
|
||||
DVector2 right = v2->fPos() - viewport->viewpoint.Pos;
|
||||
|
||||
double viewspaceX1 = left.X * viewport->viewpoint.Sin - left.Y * viewport->viewpoint.Cos;
|
||||
double viewspaceX2 = right.X * viewport->viewpoint.Sin - right.Y * viewport->viewpoint.Cos;
|
||||
double viewspaceY1 = left.X * viewport->viewpoint.TanCos + left.Y * viewport->viewpoint.TanSin;
|
||||
double viewspaceY2 = right.X * viewport->viewpoint.TanCos + right.Y * viewport->viewpoint.TanSin;
|
||||
|
||||
if (renderportal->MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
viewspaceX1 = -viewspaceX1;
|
||||
viewspaceX2 = -viewspaceX2;
|
||||
}
|
||||
|
||||
UoverZorg = float(viewspaceX1 * viewport->CenterX);
|
||||
UoverZstep = float(-viewspaceY1);
|
||||
InvZorg = float((viewspaceX1 - viewspaceX2) * viewport->CenterX);
|
||||
InvZstep = float(viewspaceY2 - viewspaceY1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProjectedWallTexcoords::ProjectTop(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
side_t* sidedef = lineseg->sidedef;
|
||||
line_t* linedef = lineseg->linedef;
|
||||
|
||||
yscale = GetYScale(sidedef, pic, side_t::top);
|
||||
double cameraZ = viewport->viewpoint.Pos.Z;
|
||||
|
||||
if (yscale >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGTOP)
|
||||
{ // top of texture at top
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at bottom
|
||||
texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
if (linedef->flags & ML_DONTPEGTOP)
|
||||
{ // bottom of texture at top
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
else
|
||||
{ // top of texture at bottom
|
||||
texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
|
||||
}
|
||||
}
|
||||
|
||||
texturemid += GetRowOffset(lineseg, pic, side_t::top);
|
||||
|
||||
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::top), x1, x2, WallT);
|
||||
xoffset = GetXOffset(lineseg, pic, side_t::top);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::ProjectMid(RenderViewport* viewport, sector_t* frontsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
side_t* sidedef = lineseg->sidedef;
|
||||
line_t* linedef = lineseg->linedef;
|
||||
|
||||
yscale = GetYScale(sidedef, pic, side_t::mid);
|
||||
double cameraZ = viewport->viewpoint.Pos.Z;
|
||||
|
||||
if (yscale >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
}
|
||||
|
||||
texturemid += GetRowOffset(lineseg, pic, side_t::mid);
|
||||
|
||||
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), x1, x2, WallT);
|
||||
xoffset = GetXOffset(lineseg, pic, side_t::mid);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::ProjectBottom(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
side_t* sidedef = lineseg->sidedef;
|
||||
line_t* linedef = lineseg->linedef;
|
||||
|
||||
double frontlowertop = frontsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
if (frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
{
|
||||
// Putting sky ceilings on the front and back of a line alters the way unpegged
|
||||
// positioning works.
|
||||
frontlowertop = backsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
|
||||
yscale = GetYScale(sidedef, pic, side_t::bottom);
|
||||
double cameraZ = viewport->viewpoint.Pos.Z;
|
||||
|
||||
if (yscale >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
texturemid = (frontlowertop - cameraZ) * yscale;
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
texturemid = (frontlowertop - cameraZ) * yscale;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
}
|
||||
|
||||
texturemid += GetRowOffset(lineseg, pic, side_t::bottom);
|
||||
|
||||
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::bottom), x1, x2, WallT);
|
||||
xoffset = GetXOffset(lineseg, pic, side_t::bottom);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::ProjectTranslucent(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
line_t* linedef = lineseg->linedef;
|
||||
side_t* sidedef = lineseg->sidedef;
|
||||
|
||||
yscale = GetYScale(sidedef, pic, side_t::mid);
|
||||
double cameraZ = viewport->viewpoint.Pos.Z;
|
||||
|
||||
double texZFloor = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor));
|
||||
double texZCeiling = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling));
|
||||
|
||||
if (yscale >= 0)
|
||||
{ // normal orientation
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // bottom of texture at bottom
|
||||
texturemid = (texZFloor - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
else
|
||||
{ // top of texture at top
|
||||
texturemid = (texZCeiling - cameraZ) * yscale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // upside down
|
||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||
{ // top of texture at bottom
|
||||
texturemid = (texZFloor - cameraZ) * yscale;
|
||||
}
|
||||
else
|
||||
{ // bottom of texture at top
|
||||
texturemid = (texZCeiling - cameraZ) * yscale + pic->GetHeight();
|
||||
}
|
||||
}
|
||||
|
||||
texturemid += GetRowOffset(lineseg, pic, side_t::mid);
|
||||
|
||||
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), x1, x2, WallT);
|
||||
xoffset = GetXOffset(lineseg, pic, side_t::mid);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::Project3DFloor(RenderViewport* viewport, F3DFloor* rover, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
// find positioning
|
||||
side_t* scaledside;
|
||||
side_t::ETexpart scaledpart;
|
||||
if (rover->flags & FF_UPPERTEXTURE)
|
||||
{
|
||||
scaledside = lineseg->sidedef;
|
||||
scaledpart = side_t::top;
|
||||
}
|
||||
else if (rover->flags & FF_LOWERTEXTURE)
|
||||
{
|
||||
scaledside = lineseg->sidedef;
|
||||
scaledpart = side_t::bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
iscalestep = 0;
|
||||
scaledside = rover->master->sidedef[0];
|
||||
scaledpart = side_t::mid;
|
||||
}
|
||||
|
||||
double xscale = pic->GetScale().X * scaledside->GetTextureXScale(scaledpart);
|
||||
yscale = pic->GetScale().Y * scaledside->GetTextureYScale(scaledpart);
|
||||
|
||||
double rowoffset = lineseg->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid);
|
||||
double planez = rover->model->GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
xoffset = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid));
|
||||
if (rowoffset < 0)
|
||||
{
|
||||
rowoffset += pic->GetHeight();
|
||||
}
|
||||
|
||||
texturemid = (planez - viewport->viewpoint.Pos.Z) * yscale;
|
||||
if (pic->useWorldPanning(lineseg->GetLevel()))
|
||||
{
|
||||
// rowoffset is added before the multiply so that the masked texture will
|
||||
// still be positioned in world units rather than texels.
|
||||
|
||||
texturemid = texturemid + rowoffset * yscale;
|
||||
xoffset = xs_RoundToInt(xoffset * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
texturemid += rowoffset;
|
||||
}
|
||||
|
||||
Project(viewport, lineseg->sidedef->TexelLength * xscale, x1, x2, WallT);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::ProjectSprite(RenderViewport* viewport, double topZ, double scale, bool flipX, bool flipY, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic)
|
||||
{
|
||||
yscale = 1.0 / scale;
|
||||
texturemid = pic->GetTopOffset(0) + (topZ - viewport->viewpoint.Pos.Z) * yscale;
|
||||
if (flipY)
|
||||
{
|
||||
yscale = -yscale;
|
||||
texturemid -= pic->GetHeight();
|
||||
}
|
||||
|
||||
Project(viewport, pic->GetWidth(), x1, x2, WallT, flipX);
|
||||
}
|
||||
|
||||
void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx)
|
||||
{
|
||||
this->walxrepeat = walxrepeat;
|
||||
this->x1 = x1;
|
||||
this->x2 = x2;
|
||||
this->WallT = WallT;
|
||||
this->flipx = flipx;
|
||||
CenterX = viewport->CenterX;
|
||||
WallTMapScale2 = viewport->WallTMapScale2;
|
||||
}
|
||||
|
||||
float ProjectedWallTexcoords::VStep(int x) const
|
||||
{
|
||||
float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - CenterX);
|
||||
float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - CenterX);
|
||||
float uGradient = WallT.UoverZstep;
|
||||
float zGradient = WallT.InvZstep;
|
||||
float depthScale = (float)(WallT.InvZstep * WallTMapScale2);
|
||||
float depthOrg = (float)(-WallT.UoverZstep * WallTMapScale2);
|
||||
float u = (uOverZ + uGradient * (x - x1)) / (invZ + zGradient * (x - x1));
|
||||
|
||||
return depthOrg + u * depthScale;
|
||||
}
|
||||
|
||||
fixed_t ProjectedWallTexcoords::UPos(int x) const
|
||||
{
|
||||
float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - CenterX);
|
||||
float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - CenterX);
|
||||
float uGradient = WallT.UoverZstep;
|
||||
float zGradient = WallT.InvZstep;
|
||||
float u = (uOverZ + uGradient * (x - x1)) / (invZ + zGradient * (x - x1));
|
||||
|
||||
fixed_t value;
|
||||
if (walxrepeat < 0.0)
|
||||
{
|
||||
float xrepeat = -walxrepeat;
|
||||
value = (fixed_t)((xrepeat - u * xrepeat) * FRACUNIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (fixed_t)(u * walxrepeat * FRACUNIT);
|
||||
}
|
||||
|
||||
if (flipx)
|
||||
{
|
||||
value = (int)walxrepeat - 1 - value;
|
||||
}
|
||||
|
||||
return value + xoffset;
|
||||
}
|
||||
|
||||
double ProjectedWallTexcoords::GetRowOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart)
|
||||
{
|
||||
double yrepeat = GetYScale(lineseg->sidedef, tex, texpart);
|
||||
double rowoffset = lineseg->sidedef->GetTextureYOffset(texpart);
|
||||
if (yrepeat >= 0)
|
||||
{
|
||||
// check if top of texture at top:
|
||||
bool top_at_top =
|
||||
(texpart == side_t::top && (lineseg->linedef->flags & ML_DONTPEGTOP)) ||
|
||||
(texpart != side_t::top && !(lineseg->linedef->flags & ML_DONTPEGBOTTOM));
|
||||
|
||||
if (rowoffset < 0 && top_at_top)
|
||||
{
|
||||
rowoffset += tex->GetHeight();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rowoffset = -rowoffset;
|
||||
}
|
||||
|
||||
if (tex->useWorldPanning(lineseg->GetLevel()))
|
||||
{
|
||||
return rowoffset * yrepeat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rowoffset is added outside the multiply so that it positions the texture
|
||||
// by texels instead of world units.
|
||||
return rowoffset;
|
||||
}
|
||||
}
|
||||
|
||||
fixed_t ProjectedWallTexcoords::GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart)
|
||||
{
|
||||
fixed_t TextureOffsetU = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(texpart));
|
||||
double xscale = GetXScale(lineseg->sidedef, tex, texpart);
|
||||
|
||||
fixed_t xoffset;
|
||||
if (tex->useWorldPanning(lineseg->GetLevel()))
|
||||
{
|
||||
xoffset = xs_RoundToInt(TextureOffsetU * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
xoffset = TextureOffsetU;
|
||||
}
|
||||
|
||||
if (xscale < 0)
|
||||
{
|
||||
xoffset = -xoffset;
|
||||
}
|
||||
|
||||
return xoffset;
|
||||
}
|
||||
|
||||
double ProjectedWallTexcoords::GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart)
|
||||
{
|
||||
double TextureScaleU = sidedef->GetTextureXScale(texpart);
|
||||
return tex->GetScale().X * TextureScaleU;
|
||||
}
|
||||
|
||||
double ProjectedWallTexcoords::GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart)
|
||||
{
|
||||
double TextureScaleV = sidedef->GetTextureYScale(texpart);
|
||||
return tex->GetScale().Y * TextureScaleV;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
namespace swrenderer
|
||||
{
|
||||
struct FWallCoords;
|
||||
struct FWallTmapVals;
|
||||
struct DrawSegmentClipInfo;
|
||||
|
||||
enum class ProjectedWallCull
|
||||
{
|
||||
|
@ -45,35 +45,55 @@ namespace swrenderer
|
|||
ProjectedWallCull Project(RenderViewport *viewport, double z1, double z2, const FWallCoords *wallc);
|
||||
ProjectedWallCull Project(RenderViewport *viewport, const secplane_t &plane, const FWallCoords *wallc, seg_t *line, bool xflip);
|
||||
ProjectedWallCull Project(RenderViewport *viewport, double z, const FWallCoords *wallc);
|
||||
|
||||
void ClipTop(int x1, int x2, const DrawSegmentClipInfo& clip);
|
||||
void ClipBottom(int x1, int x2, const DrawSegmentClipInfo& clip);
|
||||
};
|
||||
|
||||
struct FWallTmapVals
|
||||
{
|
||||
void InitFromWallCoords(RenderThread* thread, const FWallCoords* wallc);
|
||||
void InitFromLine(RenderThread* thread, seg_t* line);
|
||||
|
||||
private:
|
||||
float UoverZorg, UoverZstep;
|
||||
float InvZorg, InvZstep;
|
||||
|
||||
friend class ProjectedWallTexcoords;
|
||||
};
|
||||
|
||||
class ProjectedWallTexcoords
|
||||
{
|
||||
public:
|
||||
void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx = false);
|
||||
void ProjectTop(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
void ProjectMid(RenderViewport* viewport, sector_t* frontsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
void ProjectBottom(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
void ProjectTranslucent(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
void Project3DFloor(RenderViewport* viewport, F3DFloor* rover, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
void ProjectSprite(RenderViewport* viewport, double topZ, double scale, bool flipX, bool flipY, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic);
|
||||
|
||||
float VStep(int x) const;
|
||||
fixed_t UPos(int x) const;
|
||||
|
||||
private:
|
||||
float VStep[MAXWIDTH]; // swall
|
||||
fixed_t UPos[MAXWIDTH]; // lwall
|
||||
void Project(RenderViewport* viewport, double walxrepeat, int x1, int x2, const FWallTmapVals& WallT, bool flipx = false);
|
||||
|
||||
friend class DrawSegmentWallTexcoords;
|
||||
friend class RenderWallPart;
|
||||
friend class SpriteDrawerArgs;
|
||||
};
|
||||
static fixed_t GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
static double GetRowOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
static double GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
static double GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
|
||||
class DrawSegmentWallTexcoords
|
||||
{
|
||||
public:
|
||||
void Set(RenderThread *thread, const ProjectedWallTexcoords& texcoords, int x1, int x2, fixed_t xoffset, double yscale);
|
||||
double CenterX;
|
||||
double WallTMapScale2;
|
||||
double walxrepeat;
|
||||
int x1;
|
||||
int x2;
|
||||
FWallTmapVals WallT;
|
||||
bool flipx;
|
||||
|
||||
float yscale;
|
||||
float iscale, iscalestep;
|
||||
|
||||
explicit operator bool() const { return UPos; }
|
||||
|
||||
private:
|
||||
float* VStep = nullptr; // swall
|
||||
fixed_t* UPos = nullptr; // maskedtexturecol
|
||||
float yscale = 1.0f;
|
||||
fixed_t xoffset = 0;
|
||||
double texturemid = 0.0f;
|
||||
|
||||
friend class RenderWallPart;
|
||||
friend class SpriteDrawerArgs;
|
||||
|
|
|
@ -206,18 +206,15 @@ namespace swrenderer
|
|||
|
||||
// Create a drawseg to clip sprites to the sky plane
|
||||
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
|
||||
draw_segment->CurrentPortalUniq = CurrentPortalUniq;
|
||||
draw_segment->drawsegclip.CurrentPortalUniq = CurrentPortalUniq;
|
||||
draw_segment->WallC.sz1 = 0;
|
||||
draw_segment->WallC.sz2 = 0;
|
||||
draw_segment->x1 = pl->left;
|
||||
draw_segment->x2 = pl->right;
|
||||
draw_segment->silhouette = SIL_BOTH;
|
||||
draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
|
||||
draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
|
||||
draw_segment->bFogBoundary = false;
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTH;
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, pl->left, pl->right, ceilingclip);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, pl->left, pl->right, floorclip);
|
||||
draw_segment->curline = nullptr;
|
||||
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
drawseglist->Push(draw_segment);
|
||||
|
||||
Thread->OpaquePass->RenderScene(Thread->Viewport->Level());
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace swrenderer
|
|||
for (DrawSegment *seg : portaldrawsegs)
|
||||
{
|
||||
// ignore segs from other portals
|
||||
if (seg->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
if (seg->drawsegclip.CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue;
|
||||
|
||||
// (all checks that are already done in R_CollectPortals have been removed for performance reasons.)
|
||||
|
@ -154,19 +154,17 @@ namespace swrenderer
|
|||
DrawSegment *ds = drawseglist->Segment(index);
|
||||
|
||||
// [ZZ] the same as above
|
||||
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
if (ds->drawsegclip.CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue;
|
||||
if (ds->texcoords || ds->bFogBoundary)
|
||||
|
||||
if (ds->HasTranslucentMidTexture() || ds->Has3DFloorWalls() || ds->HasFogBoundary())
|
||||
{
|
||||
RenderDrawSegment renderer(Thread);
|
||||
renderer.Render(ds, ds->x1, ds->x2, clip3DFloor);
|
||||
if (renew && ds->bFogBoundary) // don't draw fogboundary again
|
||||
ds->bFogBoundary = false;
|
||||
|
||||
if (renew && ds->sprclipped)
|
||||
if (renew)
|
||||
{
|
||||
memcpy(ds->sprtopclip, ds->bkup, (ds->x2 - ds->x1) * sizeof(short));
|
||||
ds->sprclipped = false;
|
||||
ds->ClearFogBoundary(); // don't draw fogboundary again
|
||||
ds->drawsegclip.SetRangeUndrawn(ds->x1, ds->x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,10 +131,10 @@ namespace swrenderer
|
|||
{
|
||||
ds = Segment(groupIndex);
|
||||
|
||||
if (ds->silhouette & SIL_BOTTOM)
|
||||
if (ds->drawsegclip.silhouette & SIL_BOTTOM)
|
||||
{
|
||||
short *clip1 = clipbottom + ds->x1;
|
||||
const short *clip2 = ds->sprbottomclip;
|
||||
const short *clip2 = ds->drawsegclip.sprbottomclip + ds->x1;
|
||||
int i = ds->x2 - ds->x1;
|
||||
do
|
||||
{
|
||||
|
@ -145,10 +145,10 @@ namespace swrenderer
|
|||
} while (--i);
|
||||
}
|
||||
|
||||
if (ds->silhouette & SIL_TOP)
|
||||
if (ds->drawsegclip.silhouette & SIL_TOP)
|
||||
{
|
||||
short *clip1 = cliptop + ds->x1;
|
||||
const short *clip2 = ds->sprtopclip;
|
||||
const short *clip2 = ds->drawsegclip.sprtopclip + ds->x1;
|
||||
int i = ds->x2 - ds->x1;
|
||||
do
|
||||
{
|
||||
|
@ -168,4 +168,58 @@ namespace swrenderer
|
|||
SegmentGroups.Push(group);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DrawSegmentClipInfo::SetTopClip(RenderThread* thread, int x1, int x2, const short* ceilingclip)
|
||||
{
|
||||
short* clip = thread->FrameMemory->AllocMemory<short>(x2 - x1);
|
||||
memcpy(clip, ceilingclip + x1, (x2 - x1) * sizeof(short));
|
||||
sprtopclip = clip - x1;
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetTopClip(RenderThread* thread, int x1, int x2, short value)
|
||||
{
|
||||
short* clip = thread->FrameMemory->AllocMemory<short>(x2 - x1);
|
||||
for (int i = 0; i < x2 - x1; i++)
|
||||
clip[i] = value;
|
||||
sprtopclip = clip - x1;
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetBottomClip(RenderThread* thread, int x1, int x2, const short* floorclip)
|
||||
{
|
||||
short* clip = thread->FrameMemory->AllocMemory<short>(x2 - x1);
|
||||
memcpy(clip, floorclip + x1, (x2 - x1) * sizeof(short));
|
||||
sprbottomclip = clip - x1;
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetBottomClip(RenderThread* thread, int x1, int x2, short value)
|
||||
{
|
||||
short* clip = thread->FrameMemory->AllocMemory<short>(x2 - x1);
|
||||
for (int i = 0; i < x2 - x1; i++)
|
||||
clip[i] = value;
|
||||
sprbottomclip = clip - x1;
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetBackupClip(RenderThread* thread, int x1, int x2, const short* ceilingclip)
|
||||
{
|
||||
short* clip = thread->FrameMemory->AllocMemory<short>(x2 - x1);
|
||||
memcpy(clip, ceilingclip + x1, (x2 - x1) * sizeof(short));
|
||||
bkup = clip - x1;
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetRangeDrawn(int x1, int x2)
|
||||
{
|
||||
sprclipped = true;
|
||||
fillshort(const_cast<short*>(sprtopclip) + x1, x2 - x1, viewheight);
|
||||
}
|
||||
|
||||
void DrawSegmentClipInfo::SetRangeUndrawn(int x1, int x2)
|
||||
{
|
||||
if (sprclipped)
|
||||
{
|
||||
sprclipped = false;
|
||||
memcpy(const_cast<short*>(sprtopclip) + x1, bkup + x1, (x2 - x1) * sizeof(short));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,40 +25,56 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
struct DrawSegmentClipInfo
|
||||
{
|
||||
void SetTopClip(RenderThread* thread, int x1, int x2, const short* ceilingclip);
|
||||
void SetTopClip(RenderThread* thread, int x1, int x2, short value);
|
||||
void SetBottomClip(RenderThread* thread, int x1, int x2, const short* floorclip);
|
||||
void SetBottomClip(RenderThread* thread, int x1, int x2, short value);
|
||||
void SetBackupClip(RenderThread* thread, int x1, int x2, const short* ceilingclip);
|
||||
void SetRangeDrawn(int x1, int x2);
|
||||
void SetRangeUndrawn(int x1, int x2);
|
||||
|
||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||
int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
|
||||
int SubsectorDepth;
|
||||
|
||||
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
||||
const short* sprtopclip = nullptr;
|
||||
const short* sprbottomclip = nullptr;
|
||||
|
||||
private:
|
||||
bool sprclipped = false; // True if draw segment was used for clipping sprites
|
||||
const short* bkup = nullptr;
|
||||
};
|
||||
|
||||
struct DrawSegment
|
||||
{
|
||||
seg_t *curline;
|
||||
float light, lightstep;
|
||||
short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg
|
||||
|
||||
FWallCoords WallC;
|
||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||
bool bFogBoundary = false;
|
||||
|
||||
DrawSegmentWallTexcoords texcoords;
|
||||
|
||||
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
||||
short *sprtopclip = nullptr;
|
||||
short *sprbottomclip = nullptr;
|
||||
short *bkup = nullptr; // sprtopclip backup, for mid and fake textures
|
||||
bool sprclipped = false; // True if draw segment was used for clipping sprites
|
||||
|
||||
FWallTmapVals tmapvals;
|
||||
|
||||
int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
|
||||
ProjectedWallTexcoords texcoords;
|
||||
|
||||
int SubsectorDepth;
|
||||
DrawSegmentClipInfo drawsegclip;
|
||||
|
||||
bool Has3DFloorWalls() const { return b3DFloorBoundary != 0; }
|
||||
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
|
||||
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }
|
||||
bool Has3DFloorMidTexture() const { return (b3DFloorBoundary & 4) == 4; }
|
||||
bool HasFogBoundary() const { return (flags & 8) != 0; }
|
||||
bool Has3DFloorWalls() const { return (flags & 3) != 0; }
|
||||
bool Has3DFloorFrontSectorWalls() const { return (flags & 2) != 0; }
|
||||
bool Has3DFloorBackSectorWalls() const { return (flags & 1) != 0; }
|
||||
bool HasTranslucentMidTexture() const { return (flags & 4) != 0; }
|
||||
|
||||
void SetHas3DFloorFrontSectorWalls() { b3DFloorBoundary |= 2; }
|
||||
void SetHas3DFloorBackSectorWalls() { b3DFloorBoundary |= 1; }
|
||||
void SetHas3DFloorMidTexture() { b3DFloorBoundary |= 4; }
|
||||
void SetHasFogBoundary() { flags |= 8; }
|
||||
void SetHas3DFloorFrontSectorWalls() { flags |= 2; }
|
||||
void SetHas3DFloorBackSectorWalls() { flags |= 1; }
|
||||
void SetHasTranslucentMidTexture() { flags |= 4; }
|
||||
|
||||
void ClearFogBoundary() { flags &= ~8; } // Note: this shouldn't be needed as fog boundaries should be able to clip same way as 3dfloor walls
|
||||
|
||||
private:
|
||||
uint8_t b3DFloorBoundary = 0; // 1=backsector, 2=frontsector, 4=midtexture
|
||||
int flags = 0; // 1=backsector, 2=frontsector, 4=midtexture, 8=fogboundary
|
||||
};
|
||||
|
||||
struct DrawSegmentGroup
|
||||
|
|
|
@ -52,8 +52,8 @@ namespace swrenderer
|
|||
|
||||
ceilingclip = thread->FrameMemory->AllocMemory<short>(len);
|
||||
floorclip = thread->FrameMemory->AllocMemory<short>(len);
|
||||
memcpy(ceilingclip, topclip, len * sizeof(short));
|
||||
memcpy(floorclip, bottomclip, len * sizeof(short));
|
||||
memcpy(ceilingclip, topclip + x1, len * sizeof(short));
|
||||
memcpy(floorclip, bottomclip + x1, len * sizeof(short));
|
||||
|
||||
for (int i = 0; i < x2 - x1; i++)
|
||||
{
|
||||
|
|
|
@ -69,8 +69,6 @@ namespace swrenderer
|
|||
{
|
||||
DVector2 decal_left, decal_right, decal_pos;
|
||||
int x1, x2;
|
||||
double yscale;
|
||||
uint8_t flipx;
|
||||
double zpos;
|
||||
int needrepeat = 0;
|
||||
sector_t *back;
|
||||
|
@ -127,7 +125,6 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
FTexture *tex = TexMan.GetPalettedTexture(decal->PicNum, true);
|
||||
flipx = (uint8_t)(decal->RenderFlags & RF_XFLIP);
|
||||
|
||||
if (tex == NULL || !tex->isValid())
|
||||
{
|
||||
|
@ -149,13 +146,11 @@ namespace swrenderer
|
|||
decal_pos = { dcx, dcy };
|
||||
|
||||
DVector2 angvec = (curline->v2->fPos() - curline->v1->fPos()).Unit();
|
||||
float maskedScaleY;
|
||||
|
||||
decal_left = decal_pos - edge_left * angvec - thread->Viewport->viewpoint.Pos;
|
||||
decal_right = decal_pos + edge_right * angvec - thread->Viewport->viewpoint.Pos;
|
||||
|
||||
CameraLight *cameraLight;
|
||||
double texturemid;
|
||||
|
||||
FWallCoords WallC;
|
||||
if (WallC.Init(thread, decal_left, decal_right, TOO_CLOSE_Z))
|
||||
|
@ -167,9 +162,6 @@ namespace swrenderer
|
|||
if (x1 >= clipper->x2 || x2 <= clipper->x1)
|
||||
return;
|
||||
|
||||
FWallTmapVals WallT;
|
||||
WallT.InitFromWallCoords(thread, &WallC);
|
||||
|
||||
if (drawsegPass)
|
||||
{
|
||||
uint32_t clipMode = decal->RenderFlags & RF_CLIPMASK;
|
||||
|
@ -230,9 +222,6 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
yscale = decal->ScaleY;
|
||||
texturemid = WallSpriteTile->GetTopOffset(0) + (zpos - thread->Viewport->viewpoint.Pos.Z) / yscale;
|
||||
|
||||
// Clip sprite to drawseg
|
||||
x1 = MAX<int>(clipper->x1, x1);
|
||||
x2 = MIN<int>(clipper->x2, x2);
|
||||
|
@ -241,9 +230,6 @@ namespace swrenderer
|
|||
return;
|
||||
}
|
||||
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
walltexcoords.Project(thread->Viewport.get(), WallSpriteTile->GetWidth(), x1, x2, WallT, flipx);
|
||||
|
||||
// Prepare lighting
|
||||
usecolormap = light.GetBaseColormap();
|
||||
|
||||
|
@ -258,19 +244,13 @@ namespace swrenderer
|
|||
cameraLight = CameraLight::Instance();
|
||||
|
||||
// Draw it
|
||||
bool sprflipvert;
|
||||
if (decal->RenderFlags & RF_YFLIP)
|
||||
{
|
||||
sprflipvert = true;
|
||||
yscale = -yscale;
|
||||
texturemid -= WallSpriteTile->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
sprflipvert = false;
|
||||
}
|
||||
|
||||
maskedScaleY = float(1 / yscale);
|
||||
FWallTmapVals WallT;
|
||||
WallT.InitFromWallCoords(thread, &WallC);
|
||||
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
walltexcoords.ProjectSprite(thread->Viewport.get(), zpos, decal->ScaleY, decal->RenderFlags & RF_XFLIP, decal->RenderFlags & RF_YFLIP, x1, x2, WallT, WallSpriteTile);
|
||||
|
||||
do
|
||||
{
|
||||
int x = x1;
|
||||
|
@ -285,13 +265,14 @@ namespace swrenderer
|
|||
if (visible)
|
||||
{
|
||||
thread->PrepareTexture(WallSpriteTile, decal->RenderStyle);
|
||||
bool sprflipvert = (decal->RenderFlags & RF_YFLIP);
|
||||
while (x < x2)
|
||||
{
|
||||
if (calclighting)
|
||||
{ // calculate lighting
|
||||
drawerargs.SetLight(lightpos, light.GetLightLevel(), light.GetFoggy(), thread->Viewport.get());
|
||||
}
|
||||
drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
|
||||
drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
|
||||
lightpos += light.GetLightStep();
|
||||
x++;
|
||||
}
|
||||
|
|
|
@ -298,7 +298,7 @@ namespace swrenderer
|
|||
if ((siz2 - siz1) * ((x2 + x1) / 2 - ds->WallC.sx1) / (ds->WallC.sx2 - ds->WallC.sx1) + siz1 < idepth)
|
||||
{
|
||||
// [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves
|
||||
if (ds->CurrentPortalUniq == CurrentPortalUniq)
|
||||
if (ds->drawsegclip.CurrentPortalUniq == CurrentPortalUniq)
|
||||
{
|
||||
RenderDrawSegment renderer(thread);
|
||||
renderer.Render(ds, MAX<int>(ds->x1, x1), MIN<int>(ds->x2, x2), clip3DFloor);
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace swrenderer
|
|||
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
|
||||
{
|
||||
DrawSegment *ds = segmentlist->TranslucentSegment(index);
|
||||
if (ds->SubsectorDepth >= SubsectorDepth && ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
if (ds->drawsegclip.SubsectorDepth >= SubsectorDepth && ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
{
|
||||
int r1 = MAX<int>(ds->x1, 0);
|
||||
int r2 = MIN<int>(ds->x2, viewwidth - 1);
|
||||
|
@ -321,7 +321,7 @@ namespace swrenderer
|
|||
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
|
||||
{
|
||||
DrawSegment *ds = segmentlist->TranslucentSegment(index);
|
||||
if (ds->SubsectorDepth >= subsectordepth && ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
if (ds->drawsegclip.SubsectorDepth >= subsectordepth && ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
{
|
||||
int r1 = MAX<int>(ds->x1, 0);
|
||||
int r2 = MIN<int>(ds->x2, viewwidth - 1);
|
||||
|
@ -350,7 +350,7 @@ namespace swrenderer
|
|||
(spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) -
|
||||
(spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0))
|
||||
{
|
||||
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
if (ds->drawsegclip.CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||
{
|
||||
int r1 = MAX<int>(ds->x1, x1);
|
||||
int r2 = MIN<int>(ds->x2, x2);
|
||||
|
@ -405,7 +405,7 @@ namespace swrenderer
|
|||
DrawSegment *ds = segmentlist->Segment(index);
|
||||
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1 || (!(ds->silhouette & SIL_BOTH) && !ds->texcoords && !ds->bFogBoundary))
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1 || (!(ds->drawsegclip.silhouette & SIL_BOTH) && !ds->Has3DFloorWalls() && !ds->HasTranslucentMidTexture() && !ds->HasFogBoundary()))
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
|
@ -431,10 +431,10 @@ namespace swrenderer
|
|||
// [RH] Optimized further (at least for VC++;
|
||||
// other compilers should be at least as good as before)
|
||||
|
||||
if (ds->silhouette & SIL_BOTTOM) //bottom sil
|
||||
if (ds->drawsegclip.silhouette & SIL_BOTTOM) //bottom sil
|
||||
{
|
||||
short *clip1 = clipbot + r1;
|
||||
const short *clip2 = ds->sprbottomclip + r1 - ds->x1;
|
||||
const short *clip2 = ds->drawsegclip.sprbottomclip + r1;
|
||||
int i = r2 - r1;
|
||||
do
|
||||
{
|
||||
|
@ -445,10 +445,10 @@ namespace swrenderer
|
|||
} while (--i);
|
||||
}
|
||||
|
||||
if (ds->silhouette & SIL_TOP) // top sil
|
||||
if (ds->drawsegclip.silhouette & SIL_TOP) // top sil
|
||||
{
|
||||
short *clip1 = cliptop + r1;
|
||||
const short *clip2 = ds->sprtopclip + r1 - ds->x1;
|
||||
const short *clip2 = ds->drawsegclip.sprtopclip + r1;
|
||||
int i = r2 - r1;
|
||||
do
|
||||
{
|
||||
|
|
|
@ -67,8 +67,6 @@
|
|||
#include "swrenderer/r_memory.h"
|
||||
#include "swrenderer/r_renderthread.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
void RenderWallSprite::Project(RenderThread *thread, AActor *thing, const DVector3 &pos, FTexture *ppic, const DVector2 &scale, int renderflags, int lightlevel, bool foggy, FDynamicColormap *basecolormap)
|
||||
|
@ -162,24 +160,11 @@ namespace swrenderer
|
|||
{
|
||||
auto spr = this;
|
||||
|
||||
int x1, x2;
|
||||
double iyscale;
|
||||
bool sprflipvert;
|
||||
|
||||
x1 = MAX<int>(spr->x1, spr->wallc.sx1);
|
||||
x2 = MIN<int>(spr->x2, spr->wallc.sx2);
|
||||
int x1 = MAX<int>(spr->x1, spr->wallc.sx1);
|
||||
int x2 = MIN<int>(spr->x2, spr->wallc.sx2);
|
||||
if (x1 >= x2)
|
||||
return;
|
||||
|
||||
FWallTmapVals WallT;
|
||||
WallT.InitFromWallCoords(thread, &spr->wallc);
|
||||
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
walltexcoords.Project(thread->Viewport.get(), spr->pic->GetWidth(), x1, x2, WallT, spr->renderflags & RF_XFLIP);
|
||||
|
||||
iyscale = 1 / spr->yscale;
|
||||
double texturemid = (spr->gzt - thread->Viewport->viewpoint.Pos.Z) * iyscale;
|
||||
|
||||
// Prepare lighting
|
||||
|
||||
// Decals that are added to the scene must fade to black.
|
||||
|
@ -203,25 +188,18 @@ namespace swrenderer
|
|||
|
||||
// Draw it
|
||||
auto WallSpriteTile = spr->pic;
|
||||
if (spr->renderflags & RF_YFLIP)
|
||||
{
|
||||
sprflipvert = true;
|
||||
iyscale = -iyscale;
|
||||
texturemid -= spr->pic->GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
sprflipvert = false;
|
||||
}
|
||||
|
||||
float maskedScaleY = (float)iyscale;
|
||||
FWallTmapVals WallT;
|
||||
WallT.InitFromWallCoords(thread, &spr->wallc);
|
||||
|
||||
int x = x1;
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
walltexcoords.ProjectSprite(thread->Viewport.get(), spr->gzt, spr->yscale, spr->renderflags & RF_XFLIP, spr->renderflags & RF_YFLIP, x1, x2, WallT, WallSpriteTile);
|
||||
|
||||
RenderTranslucentPass *translucentPass = thread->TranslucentPass.get();
|
||||
|
||||
thread->PrepareTexture(WallSpriteTile, spr->RenderStyle);
|
||||
while (x < x2)
|
||||
bool sprflipvert = (spr->renderflags & RF_YFLIP);
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
if (calclighting)
|
||||
{
|
||||
|
@ -229,9 +207,8 @@ namespace swrenderer
|
|||
drawerargs.SetLight(light, spr->sector->lightlevel, spr->foggy, thread->Viewport.get());
|
||||
}
|
||||
if (!translucentPass->ClipSpriteColumnWithPortals(x, spr))
|
||||
drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle);
|
||||
drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle);
|
||||
light += lightstep;
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,34 +43,19 @@ namespace swrenderer
|
|||
colfunc = &SWPixelFormatDrawers::DrawColumn;
|
||||
}
|
||||
|
||||
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
|
||||
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
|
||||
{
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
float iscale = walltexcoords.VStep[x] * maskedScaleY;
|
||||
float iscale = walltexcoords.VStep(x) * walltexcoords.yscale;
|
||||
double spryscale = 1 / iscale;
|
||||
double sprtopscreen;
|
||||
if (sprflipvert)
|
||||
sprtopscreen = viewport->CenterY + texturemid * spryscale;
|
||||
sprtopscreen = viewport->CenterY + walltexcoords.texturemid * spryscale;
|
||||
else
|
||||
sprtopscreen = viewport->CenterY - texturemid * spryscale;
|
||||
sprtopscreen = viewport->CenterY - walltexcoords.texturemid * spryscale;
|
||||
|
||||
DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
|
||||
}
|
||||
|
||||
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const DrawSegmentWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
|
||||
{
|
||||
auto viewport = thread->Viewport.get();
|
||||
|
||||
float iscale = walltexcoords.VStep[x] * maskedScaleY;
|
||||
double spryscale = 1 / iscale;
|
||||
double sprtopscreen;
|
||||
if (sprflipvert)
|
||||
sprtopscreen = viewport->CenterY + texturemid * spryscale;
|
||||
else
|
||||
sprtopscreen = viewport->CenterY - texturemid * spryscale;
|
||||
|
||||
DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
|
||||
DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos(x), spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
|
||||
}
|
||||
|
||||
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked)
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace swrenderer
|
|||
{
|
||||
class RenderThread;
|
||||
class ProjectedWallTexcoords;
|
||||
class DrawSegmentWallTexcoords;
|
||||
|
||||
class VoxelBlock
|
||||
{
|
||||
|
@ -35,8 +34,7 @@ namespace swrenderer
|
|||
void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; }
|
||||
void SetDynamicLight(uint32_t color) { dynlightcolor = color; }
|
||||
|
||||
void DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
|
||||
void DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const DrawSegmentWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
|
||||
void DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
|
||||
void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked = false);
|
||||
void FillColumn(RenderThread *thread);
|
||||
void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount);
|
||||
|
|
|
@ -86,6 +86,7 @@ static const FLOP FxFlops[] =
|
|||
{ NAME_Round, FLOP_ROUND, [](double v) { return round(v); } },
|
||||
};
|
||||
|
||||
static bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -143,9 +144,12 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
// A prototype that defines fewer return types can be compatible with
|
||||
// one that defines more if the shorter one matches the initial types
|
||||
// for the longer one.
|
||||
bool swapped = false;
|
||||
|
||||
if (ReturnProto->ReturnTypes.Size() < proto->ReturnTypes.Size())
|
||||
{ // Make proto the shorter one to avoid code duplication below.
|
||||
swapvalues(proto, ReturnProto);
|
||||
swapped = true;
|
||||
}
|
||||
// If one prototype returns nothing, they both must.
|
||||
if (proto->ReturnTypes.Size() == 0)
|
||||
|
@ -159,9 +163,13 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
{
|
||||
for (unsigned i = 0; i < proto->ReturnTypes.Size(); i++)
|
||||
{
|
||||
if (ReturnProto->ReturnTypes[i] != proto->ReturnTypes[i])
|
||||
PType* expected = ReturnProto->ReturnTypes[i];
|
||||
PType* actual = proto->ReturnTypes[i];
|
||||
if (swapped) swapvalues(expected, actual);
|
||||
|
||||
if (expected != actual && !AreCompatiblePointerTypes(expected, actual))
|
||||
{ // Incompatible
|
||||
Printf("Return type %s mismatch with %s\n", ReturnProto->ReturnTypes[i]->DescriptiveName(), proto->ReturnTypes[i]->DescriptiveName());
|
||||
Printf("Return type %s mismatch with %s\n", expected->DescriptiveName(), actual->DescriptiveName());
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
@ -274,7 +282,7 @@ static PFunction *FindBuiltinFunction(FName funcname)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare = false)
|
||||
static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare)
|
||||
{
|
||||
if (dest->isPointer() && source->isPointer())
|
||||
{
|
||||
|
@ -10708,27 +10716,44 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
|||
|
||||
PPrototype *retproto;
|
||||
|
||||
if (ctx.ReturnProto != nullptr && ctx.ReturnProto->ReturnTypes.Size() == 0 && ctx.ReturnProto->ReturnTypes.Size() != Args.Size())
|
||||
const bool hasProto = ctx.ReturnProto != nullptr;
|
||||
const unsigned protoRetCount = hasProto ? ctx.ReturnProto->ReturnTypes.Size() : 0;
|
||||
const unsigned retCount = Args.Size();
|
||||
int mismatchSeverity = -1;
|
||||
|
||||
if (hasProto)
|
||||
{
|
||||
int severity = ctx.Version >= MakeVersion(3, 7) ? MSG_ERROR : MSG_WARNING;
|
||||
ScriptPosition.Message(severity, "Incorrect number of return values. Got %u, but expected %u", Args.Size(), ctx.ReturnProto->ReturnTypes.Size());
|
||||
if (severity == MSG_ERROR)
|
||||
if (protoRetCount == 0 && retCount == 1)
|
||||
{
|
||||
// Handle the case with void function returning something, but only for one value
|
||||
// It was accepted in previous versions, do not abort with fatal error when compiling old scripts
|
||||
mismatchSeverity = ctx.Version >= MakeVersion(3, 7) ? MSG_ERROR : MSG_WARNING;
|
||||
}
|
||||
else if (protoRetCount < retCount)
|
||||
{
|
||||
mismatchSeverity = MSG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (mismatchSeverity != -1)
|
||||
{
|
||||
ScriptPosition.Message(mismatchSeverity, "Incorrect number of return values. Got %u, but expected %u", Args.Size(), ctx.ReturnProto->ReturnTypes.Size());
|
||||
if (mismatchSeverity == MSG_ERROR)
|
||||
{
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
// For older script versions this must fall through.
|
||||
}
|
||||
|
||||
if (Args.Size() == 0)
|
||||
|
||||
if (retCount == 0)
|
||||
{
|
||||
TArray<PType *> none(0);
|
||||
retproto = NewPrototype(none, none);
|
||||
}
|
||||
else if (Args.Size() == 1)
|
||||
else if (retCount == 1)
|
||||
{
|
||||
// If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.)
|
||||
if (ctx.ReturnProto != nullptr && ctx.ReturnProto->ReturnTypes.Size() > 0 && ctx.Function->SymbolName != NAME_None)
|
||||
if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None)
|
||||
{
|
||||
Args[0] = new FxTypeCast(Args[0], ctx.ReturnProto->ReturnTypes[0], false, false);
|
||||
Args[0] = Args[0]->Resolve(ctx);
|
||||
|
@ -10738,7 +10763,7 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
for (unsigned i = 0; i < Args.Size(); i++)
|
||||
for (unsigned i = 0; i < retCount; i++)
|
||||
{
|
||||
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
||||
Args[i] = Args[i]->Resolve(ctx);
|
||||
|
@ -11898,4 +11923,4 @@ ExpEmit FxOutVarDereference::Emit(VMFunctionBuilder *build)
|
|||
selfEmit.Free(build);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
EXTERN_CVAR (Bool, ticker);
|
||||
EXTERN_CVAR (Bool, noisedebug);
|
||||
EXTERN_CVAR (Int, am_cheat);
|
||||
EXTERN_CVAR (Int, cl_blockcheats);
|
||||
|
||||
struct cheatseq_t
|
||||
{
|
||||
|
@ -300,6 +301,7 @@ static cheatseq_t SpecialCheats[] =
|
|||
|
||||
|
||||
CVAR(Bool, allcheats, false, CVAR_ARCHIVE)
|
||||
CVAR(Bool, nocheats, false, CVAR_ARCHIVE)
|
||||
|
||||
// Respond to keyboard input events, intercept cheats.
|
||||
// [RH] Cheats eat the last keypress used to trigger them
|
||||
|
@ -307,7 +309,11 @@ bool ST_Responder (event_t *ev)
|
|||
{
|
||||
bool eat = false;
|
||||
|
||||
if (!allcheats)
|
||||
if (nocheats || !!cl_blockcheats || (gameinfo.nokeyboardcheats && !allcheats))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!allcheats)
|
||||
{
|
||||
cheatseq_t *cheats;
|
||||
int numcheats;
|
||||
|
|
|
@ -1187,6 +1187,7 @@ OptionMenu "MiscOptions" protected
|
|||
}
|
||||
Option "$MISCMNU_QUERYIWAD", "queryiwad", "OnOff"
|
||||
StaticText " "
|
||||
Option "$MISCMNU_NOCHEATS", "nocheats", "OnOff"
|
||||
Option "$MISCMNU_ALLCHEATS", "allcheats", "OnOff"
|
||||
Option "$MISCMNU_ENABLEAUTOSAVES", "disableautosave", "Autosave"
|
||||
Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff"
|
||||
|
|
|
@ -6,6 +6,7 @@ version "4.2"
|
|||
#include "zscript/constants.zs"
|
||||
#include "zscript/events.zs"
|
||||
#include "zscript/destructible.zs"
|
||||
#include "zscript/level_postprocessor.zs"
|
||||
#include "zscript/level_compatibility.zs"
|
||||
|
||||
#include "zscript/actors/actor.zs"
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
class LevelCompatibility native play
|
||||
class LevelCompatibility : LevelPostProcessor
|
||||
{
|
||||
native LevelLocals level;
|
||||
|
||||
protected void Apply(Name checksum, String mapname)
|
||||
{
|
||||
switch (checksum)
|
||||
|
@ -1461,77 +1459,4 @@ class LevelCompatibility native play
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected native void ClearSectorTags(int sector);
|
||||
protected native void AddSectorTag(int sector, int tag);
|
||||
protected native void ClearLineIDs(int line);
|
||||
protected native void AddLineID(int line, int tag);
|
||||
protected native void OffsetSectorPlane(int sector, int plane, double offset);
|
||||
protected native void SetThingSkills(int thing, int skills);
|
||||
protected native void SetThingXY(int thing, double x, double y);
|
||||
protected native void SetThingZ(int thing, double z);
|
||||
protected native void SetThingFlags(int thing, int flags);
|
||||
protected native void SetVertex(uint vertex, double x, double y);
|
||||
protected native void SetLineSectorRef(uint line, uint side, uint sector);
|
||||
protected native Actor GetDefaultActor(Name actorclass);
|
||||
|
||||
protected void SetWallTexture(int line, int side, int texpart, String texture)
|
||||
{
|
||||
SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall));
|
||||
}
|
||||
|
||||
protected void SetWallTextureID(int line, int side, int texpart, TextureID texture)
|
||||
{
|
||||
level.Lines[line].sidedef[side].SetTexture(texpart, texture);
|
||||
}
|
||||
|
||||
protected void SetLineFlags(int line, int setflags, int clearflags = 0)
|
||||
{
|
||||
level.Lines[line].flags = (level.Lines[line].flags & ~clearflags) | setflags;
|
||||
}
|
||||
|
||||
protected void SetLineActivation(int line, int acttype)
|
||||
{
|
||||
level.Lines[line].activation = acttype;
|
||||
}
|
||||
|
||||
protected void ClearLineSpecial(int line)
|
||||
{
|
||||
level.Lines[line].special = 0;
|
||||
}
|
||||
|
||||
protected void SetLineSpecial(int line, int special, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0)
|
||||
{
|
||||
level.Lines[line].special = special;
|
||||
level.Lines[line].args[0] = arg1;
|
||||
level.Lines[line].args[1] = arg2;
|
||||
level.Lines[line].args[2] = arg3;
|
||||
level.Lines[line].args[3] = arg4;
|
||||
level.Lines[line].args[4] = arg5;
|
||||
}
|
||||
|
||||
protected void SetSectorSpecial(int sectornum, int special)
|
||||
{
|
||||
level.sectors[sectornum].special = special;
|
||||
}
|
||||
|
||||
protected void SetSectorTextureID(int sectornum, int plane, TextureID texture)
|
||||
{
|
||||
level.sectors[sectornum].SetTexture(plane, texture);
|
||||
}
|
||||
|
||||
protected void SetSectorTexture(int sectornum, int plane, String texture)
|
||||
{
|
||||
SetSectorTextureID(sectornum, plane, TexMan.CheckForTexture(texture, TexMan.Type_Flat));
|
||||
}
|
||||
|
||||
protected void SetSectorLight(int sectornum, int newval)
|
||||
{
|
||||
level.sectors[sectornum].SetLightLevel(newval);
|
||||
}
|
||||
|
||||
protected void SetWallYScale(int line, int side, int texpart, double scale)
|
||||
{
|
||||
level.lines[line].sidedef[side].SetTextureYScale(texpart, scale);
|
||||
}
|
||||
}
|
||||
|
|
121
wadsrc/static/zscript/level_postprocessor.zs
Normal file
121
wadsrc/static/zscript/level_postprocessor.zs
Normal file
|
@ -0,0 +1,121 @@
|
|||
|
||||
class LevelPostProcessor native play
|
||||
{
|
||||
protected native LevelLocals level;
|
||||
|
||||
protected void Apply(Name checksum, String mapname)
|
||||
{
|
||||
}
|
||||
|
||||
protected native void ClearSectorTags(int sector);
|
||||
protected native void AddSectorTag(int sector, int tag);
|
||||
protected native void ClearLineIDs(int line);
|
||||
protected native void AddLineID(int line, int tag);
|
||||
protected native void OffsetSectorPlane(int sector, int plane, double offset);
|
||||
|
||||
const SKILLS_ALL = 31;
|
||||
const MODES_ALL = MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH;
|
||||
|
||||
protected native uint GetThingCount();
|
||||
protected native uint AddThing(int ednum, Vector3 pos, int angle = 0, uint skills = SKILLS_ALL, uint flags = MODES_ALL);
|
||||
|
||||
protected native int GetThingEdNum(uint thing);
|
||||
protected native void SetThingEdNum(uint thing, int ednum);
|
||||
|
||||
protected native vector3 GetThingPos(uint thing);
|
||||
protected native void SetThingXY(uint thing, double x, double y);
|
||||
protected native void SetThingZ(uint thing, double z);
|
||||
|
||||
protected native int GetThingAngle(uint thing);
|
||||
protected native void SetThingAngle(uint thing, int angle);
|
||||
|
||||
protected native uint GetThingSkills(uint thing);
|
||||
protected native void SetThingSkills(uint thing, uint skills);
|
||||
|
||||
protected native uint GetThingFlags(uint thing);
|
||||
protected native void SetThingFlags(uint thing, uint flags);
|
||||
|
||||
protected native int GetThingID(uint thing);
|
||||
protected native void SetThingID(uint thing, int id);
|
||||
|
||||
protected native int GetThingSpecial(uint thing);
|
||||
protected native void SetThingSpecial(uint thing, int special);
|
||||
|
||||
protected native int GetThingArgument(uint thing, uint index);
|
||||
protected native Name GetThingStringArgument(uint thing);
|
||||
protected native void SetThingArgument(uint thing, uint index, int value);
|
||||
protected native void SetThingStringArgument(uint thing, Name value);
|
||||
|
||||
protected native void SetVertex(uint vertex, double x, double y);
|
||||
protected native void SetLineVertexes(uint Line, uint v1, uint v2);
|
||||
protected native void FlipLineSideRefs(uint Line);
|
||||
protected native void SetLineSectorRef(uint line, uint side, uint sector);
|
||||
protected native Actor GetDefaultActor(Name actorclass);
|
||||
|
||||
protected void FlipLine(uint Line)
|
||||
{
|
||||
uint v1 = level.lines[Line].v1.Index();
|
||||
uint v2 = level.lines[Line].v2.Index();
|
||||
SetLineVertexes(Line, v2, v1);
|
||||
}
|
||||
|
||||
protected void SetWallTexture(int line, int side, int texpart, String texture)
|
||||
{
|
||||
SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall));
|
||||
}
|
||||
|
||||
protected void SetWallTextureID(int line, int side, int texpart, TextureID texture)
|
||||
{
|
||||
level.Lines[line].sidedef[side].SetTexture(texpart, texture);
|
||||
}
|
||||
|
||||
protected void SetLineFlags(int line, int setflags, int clearflags = 0)
|
||||
{
|
||||
level.Lines[line].flags = (level.Lines[line].flags & ~clearflags) | setflags;
|
||||
}
|
||||
|
||||
protected void SetLineActivation(int line, int acttype)
|
||||
{
|
||||
level.Lines[line].activation = acttype;
|
||||
}
|
||||
|
||||
protected void ClearLineSpecial(int line)
|
||||
{
|
||||
level.Lines[line].special = 0;
|
||||
}
|
||||
|
||||
protected void SetLineSpecial(int line, int special, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0)
|
||||
{
|
||||
level.Lines[line].special = special;
|
||||
level.Lines[line].args[0] = arg1;
|
||||
level.Lines[line].args[1] = arg2;
|
||||
level.Lines[line].args[2] = arg3;
|
||||
level.Lines[line].args[3] = arg4;
|
||||
level.Lines[line].args[4] = arg5;
|
||||
}
|
||||
|
||||
protected void SetSectorSpecial(int sectornum, int special)
|
||||
{
|
||||
level.sectors[sectornum].special = special;
|
||||
}
|
||||
|
||||
protected void SetSectorTextureID(int sectornum, int plane, TextureID texture)
|
||||
{
|
||||
level.sectors[sectornum].SetTexture(plane, texture);
|
||||
}
|
||||
|
||||
protected void SetSectorTexture(int sectornum, int plane, String texture)
|
||||
{
|
||||
SetSectorTextureID(sectornum, plane, TexMan.CheckForTexture(texture, TexMan.Type_Flat));
|
||||
}
|
||||
|
||||
protected void SetSectorLight(int sectornum, int newval)
|
||||
{
|
||||
level.sectors[sectornum].SetLightLevel(newval);
|
||||
}
|
||||
|
||||
protected void SetWallYScale(int line, int side, int texpart, double scale)
|
||||
{
|
||||
level.lines[line].sidedef[side].SetTextureYScale(texpart, scale);
|
||||
}
|
||||
}
|
|
@ -862,10 +862,10 @@ class StatusScreen abstract play version("2.5")
|
|||
enteringPatch = TexMan.CheckForTexture("WIENTER", TexMan.Type_MiscPatch); // "entering"
|
||||
finishedPatch = TexMan.CheckForTexture("WIF", TexMan.Type_MiscPatch); // "finished"
|
||||
|
||||
lnametexts[0] = wbstartstruct.thisname;
|
||||
lnametexts[1] = wbstartstruct.nextname;
|
||||
authortexts[0] = wbstartstruct.thisauthor;
|
||||
authortexts[1] = wbstartstruct.nextauthor;
|
||||
lnametexts[0] = StringTable.Localize(wbstartstruct.thisname);
|
||||
lnametexts[1] = StringTable.Localize(wbstartstruct.nextname);
|
||||
authortexts[0] = StringTable.Localize(wbstartstruct.thisauthor);
|
||||
authortexts[1] = StringTable.Localize(wbstartstruct.nextauthor);
|
||||
|
||||
bg = InterBackground.Create(wbs);
|
||||
noautostartmap = bg.LoadBackground(false);
|
||||
|
|
|
@ -320,6 +320,7 @@ class BaseStatusBar native ui
|
|||
|
||||
virtual void Init()
|
||||
{
|
||||
SetSize(0, 320, 200);
|
||||
}
|
||||
|
||||
native virtual void Tick ();
|
||||
|
|
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2012.lmp
Normal file
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2012.lmp
Normal file
Binary file not shown.
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2013.lmp
Normal file
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2013.lmp
Normal file
Binary file not shown.
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2026.lmp
Normal file
BIN
wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/2026.lmp
Normal file
Binary file not shown.
Loading…
Reference in a new issue