mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
Merge remote-tracking branch 'zdoom/master'
This commit is contained in:
commit
8334189d66
92 changed files with 1196 additions and 1047 deletions
|
@ -193,7 +193,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
|
|||
option(FORCE_INTERNAL_ZLIB "Use internal zlib")
|
||||
option(FORCE_INTERNAL_JPEG "Use internal jpeg")
|
||||
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
|
||||
option(FORCE_INTERNAL_GME "Use internal gme" ON)
|
||||
option(FORCE_INTERNAL_GME "Use internal gme")
|
||||
|
||||
# Fast math flags, required by some subprojects
|
||||
set( ZD_FASTMATH_FLAG "" )
|
||||
|
|
|
@ -1091,7 +1091,6 @@ set (PCH_SOURCES
|
|||
statistics.cpp
|
||||
stats.cpp
|
||||
stringtable.cpp
|
||||
tables.cpp
|
||||
teaminfo.cpp
|
||||
tempfiles.cpp
|
||||
v_blend.cpp
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define __P_MOBJ_H__
|
||||
|
||||
// Basics.
|
||||
#include "tables.h"
|
||||
#include "templates.h"
|
||||
|
||||
// We need the thinker_t stuff.
|
||||
|
@ -380,6 +379,7 @@ enum ActorFlag7
|
|||
MF7_FORCEDECAL = 0x00080000, // [ZK] Forces puff's decal to override the weapon's.
|
||||
MF7_LAXTELEFRAGDMG = 0x00100000, // [MC] Telefrag damage can be reduced.
|
||||
MF7_ICESHATTER = 0x00200000, // [MC] Shatters ice corpses regardless of damagetype.
|
||||
MF7_ALLOWTHRUFLAGS = 0x00400000, // [MC] Allow THRUACTORS and the likes on puffs to prevent mod breakage.
|
||||
};
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define __B_BOT_H__
|
||||
|
||||
#include "c_cvars.h"
|
||||
#include "tables.h"
|
||||
#include "info.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_ticcmd.h"
|
||||
|
|
|
@ -72,6 +72,14 @@ typedef DWORD dsfixed_t; // fixedpt used by span drawer
|
|||
#define DWORD_MIN ((uint32)0)
|
||||
#define DWORD_MAX ((uint32)0xffffffff)
|
||||
|
||||
// the last remnants of tables.h
|
||||
#define ANGLE_90 (0x40000000)
|
||||
#define ANGLE_180 (0x80000000)
|
||||
#define ANGLE_270 (0xc0000000)
|
||||
#define ANGLE_MAX (0xffffffff)
|
||||
|
||||
typedef uint32 angle_t;
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GCCPRINTF(stri,firstargi) __attribute__((format(printf,stri,firstargi)))
|
||||
|
|
|
@ -438,7 +438,7 @@ void PType::SkipValue(FArchive &ar, int tag)
|
|||
ar.Read(buff, 2);
|
||||
break;
|
||||
|
||||
case VAL_Int32: case VAL_UInt32: case VAL_Float32: case VAL_Fixed: case VAL_BAM:
|
||||
case VAL_Int32: case VAL_UInt32: case VAL_Float32:
|
||||
ar.Read(buff, 4);
|
||||
break;
|
||||
|
||||
|
@ -936,10 +936,8 @@ bool PInt::ReadValue(FArchive &ar, void *addr) const
|
|||
BYTE val8;
|
||||
WORD val16;
|
||||
DWORD val32;
|
||||
fixed_t fix;
|
||||
float single;
|
||||
double dbl;
|
||||
angle_t ang;
|
||||
};
|
||||
|
||||
ar << tag;
|
||||
|
@ -955,8 +953,6 @@ bool PInt::ReadValue(FArchive &ar, void *addr) const
|
|||
case VAL_UInt32: ar << val32; uval = val32; break;
|
||||
case VAL_Int64: ar << sval; break;
|
||||
case VAL_UInt64: ar << uval; break;
|
||||
case VAL_Fixed: ar << fix; sval = fix >> FRACBITS; break; // fixed -> int
|
||||
case VAL_BAM: ar << ang; uval = ang / ANGLE_1; break; // BAM -> degrees
|
||||
case VAL_Float32: ar << single; sval = (SQWORD)single; break;
|
||||
case VAL_Float64: ar << dbl; sval = (SQWORD)dbl; break;
|
||||
default: SkipValue(ar, tag); return false; // Incompatible type
|
||||
|
@ -1317,8 +1313,6 @@ static bool ReadValueDbl(FArchive &ar, double *addr, unsigned tag)
|
|||
case VAL_UInt32: ar << val32; val = val32; break;
|
||||
case VAL_Int64: ar << val64; val = (double)(SQWORD)val64; break;
|
||||
case VAL_UInt64: ar << val64; val = (double)val64; break;
|
||||
case VAL_Fixed: ar << fix; val = FIXED2DBL(fix); break;
|
||||
case VAL_BAM: ar << ang; val = ang * (90.0 / ANGLE_90); break; // BAM -> degrees
|
||||
case VAL_Float32: ar << single; val = single; break;
|
||||
case VAL_Float64: ar << val; break;
|
||||
default: PType::SkipValue(ar, tag); return false; // Incompatible type
|
||||
|
|
|
@ -904,8 +904,6 @@ enum ETypeVal : BYTE
|
|||
VAL_One,
|
||||
VAL_Float32,
|
||||
VAL_Float64,
|
||||
VAL_Fixed,
|
||||
VAL_BAM,
|
||||
VAL_String,
|
||||
VAL_Name,
|
||||
VAL_Struct,
|
||||
|
|
|
@ -121,7 +121,6 @@ extern int viewwindowx;
|
|||
extern int viewwindowy;
|
||||
extern "C" int viewheight;
|
||||
extern "C" int viewwidth;
|
||||
extern "C" int halfviewwidth; // [RH] Half view width, for plane drawing
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1054,6 +1054,12 @@ FArchive &FArchive::SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize)
|
|||
|
||||
FArchive &FArchive::SerializeObject (DObject *&object, PClass *type)
|
||||
{
|
||||
if (!m_ThinkersAllowed && type->IsDescendantOf(RUNTIME_CLASS(DThinker)))
|
||||
{
|
||||
assert(true);
|
||||
I_Error("Tried to serialize a thinker before P_SerializeThinkers");
|
||||
}
|
||||
|
||||
if (!type->IsDescendantOf(RUNTIME_CLASS(PClass)))
|
||||
{ // a regular object
|
||||
if (IsStoring())
|
||||
|
|
|
@ -216,6 +216,16 @@ inline FArchive& operator<< (signed char *&str) { return operator<< ((char *&)st
|
|||
inline FArchive& operator<< (bool &b) { return operator<< ((BYTE &)b); }
|
||||
inline FArchive& operator<< (DObject* &object) { return ReadObject (object, RUNTIME_CLASS(DObject)); }
|
||||
|
||||
void EnableThinkers()
|
||||
{
|
||||
m_ThinkersAllowed = true;
|
||||
}
|
||||
|
||||
bool ThinkersAllowed()
|
||||
{
|
||||
return m_ThinkersAllowed;
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { EObjectHashSize = 137 };
|
||||
|
||||
|
@ -253,6 +263,7 @@ protected:
|
|||
|
||||
int *m_SpriteMap;
|
||||
size_t m_NumSprites;
|
||||
bool m_ThinkersAllowed = false;
|
||||
|
||||
FArchive ();
|
||||
void AttachToFile (FFile &file);
|
||||
|
|
|
@ -338,6 +338,7 @@ struct level_info_t
|
|||
|
||||
TArray<FSoundID> PrecacheSounds;
|
||||
TArray<FString> PrecacheTextures;
|
||||
TArray<FName> PrecacheClasses;
|
||||
|
||||
level_info_t()
|
||||
{
|
||||
|
|
|
@ -1083,6 +1083,18 @@ DEFINE_MAP_OPTION(PrecacheTextures, true)
|
|||
} while (parse.sc.CheckString(","));
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(PrecacheClasses, true)
|
||||
{
|
||||
parse.ParseAssign();
|
||||
|
||||
do
|
||||
{
|
||||
parse.sc.MustGetString();
|
||||
//the class list is not initialized here so all we can do is store the class's name.
|
||||
info->PrecacheClasses.Push(parse.sc.String);
|
||||
} while (parse.sc.CheckString(","));
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(redirect, true)
|
||||
{
|
||||
parse.ParseAssign();
|
||||
|
|
|
@ -22,7 +22,7 @@ struct OneKey
|
|||
if (owner->IsKindOf(RUNTIME_CLASS(AKey)))
|
||||
{
|
||||
// P_GetMapColorForKey() checks the key directly
|
||||
return owner->IsA(key);
|
||||
return owner->IsA(key) || owner->GetSpecies() == key->TypeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -37,7 +37,8 @@ DEarthquake::DEarthquake()
|
|||
|
||||
DEarthquake::DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration,
|
||||
int damrad, int tremrad, FSoundID quakesound, int flags,
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint)
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint,
|
||||
double rollIntensity, double rollWave)
|
||||
: DThinker(STAT_EARTHQUAKE)
|
||||
{
|
||||
m_QuakeSFX = quakesound;
|
||||
|
@ -53,6 +54,8 @@ DEarthquake::DEarthquake(AActor *center, int intensityX, int intensityY, int int
|
|||
m_Falloff = falloff;
|
||||
m_Highpoint = highpoint;
|
||||
m_MiniCount = highpoint;
|
||||
m_RollIntensity = rollIntensity;
|
||||
m_RollWave = rollWave;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -68,7 +71,8 @@ void DEarthquake::Serialize (FArchive &arc)
|
|||
<< m_TremorRadius << m_DamageRadius
|
||||
<< m_QuakeSFX << m_Flags << m_CountdownStart
|
||||
<< m_WaveSpeed
|
||||
<< m_Falloff << m_Highpoint << m_MiniCount;
|
||||
<< m_Falloff << m_Highpoint << m_MiniCount
|
||||
<< m_RollIntensity << m_RollWave;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -276,16 +280,19 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
|
|||
double dist = quake->m_Spot->Distance2D (victim, true);
|
||||
if (dist < quake->m_TremorRadius)
|
||||
{
|
||||
double falloff = quake->GetFalloff(dist);
|
||||
const double falloff = quake->GetFalloff(dist);
|
||||
const double rfalloff = (quake->m_RollIntensity != 0) ? falloff : 0.;
|
||||
++count;
|
||||
double x = quake->GetModIntensity(quake->m_Intensity.X);
|
||||
double y = quake->GetModIntensity(quake->m_Intensity.Y);
|
||||
double z = quake->GetModIntensity(quake->m_Intensity.Z);
|
||||
|
||||
double r = quake->GetModIntensity(quake->m_RollIntensity);
|
||||
|
||||
if (!(quake->m_Flags & QF_WAVE))
|
||||
{
|
||||
jiggers.Falloff = MAX(falloff, jiggers.Falloff);
|
||||
jiggers.RFalloff = MAX(rfalloff, jiggers.RFalloff);
|
||||
jiggers.RollIntensity = MAX(r, jiggers.RollIntensity);
|
||||
if (quake->m_Flags & QF_RELATIVE)
|
||||
{
|
||||
jiggers.RelIntensity.X = MAX(x, jiggers.RelIntensity.X);
|
||||
|
@ -302,6 +309,8 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
|
|||
else
|
||||
{
|
||||
jiggers.WFalloff = MAX(falloff, jiggers.WFalloff);
|
||||
jiggers.RWFalloff = MAX(rfalloff, jiggers.RWFalloff);
|
||||
jiggers.RollWave = r * quake->GetModWave(quake->m_RollWave);
|
||||
double mx = x * quake->GetModWave(quake->m_WaveSpeed.X);
|
||||
double my = y * quake->GetModWave(quake->m_WaveSpeed.Y);
|
||||
double mz = z * quake->GetModWave(quake->m_WaveSpeed.Z);
|
||||
|
@ -338,7 +347,8 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger
|
|||
|
||||
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration,
|
||||
int damrad, int tremrad, FSoundID quakesfx, int flags,
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint)
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint,
|
||||
double rollIntensity, double rollWave)
|
||||
{
|
||||
AActor *center;
|
||||
bool res = false;
|
||||
|
@ -352,7 +362,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY,
|
|||
if (activator != NULL)
|
||||
{
|
||||
new DEarthquake(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad,
|
||||
quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint);
|
||||
quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +373,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY,
|
|||
{
|
||||
res = true;
|
||||
new DEarthquake(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad,
|
||||
quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint);
|
||||
quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,5 +382,5 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY,
|
|||
|
||||
bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx)
|
||||
{ //Maintains original behavior by passing 0 to intensityZ, flags, and everything else after QSFX.
|
||||
return P_StartQuakeXYZ(activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0);
|
||||
return P_StartQuakeXYZ(activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
|
|
@ -153,8 +153,8 @@ struct FQuakeJiggers
|
|||
DVector3 RelIntensity;
|
||||
DVector3 Offset;
|
||||
DVector3 RelOffset;
|
||||
double Falloff;
|
||||
double WFalloff;
|
||||
double Falloff, WFalloff, RFalloff, RWFalloff;
|
||||
double RollIntensity, RollWave;
|
||||
};
|
||||
|
||||
class DEarthquake : public DThinker
|
||||
|
@ -164,7 +164,7 @@ class DEarthquake : public DThinker
|
|||
public:
|
||||
DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration,
|
||||
int damrad, int tremrad, FSoundID quakesfx, int flags,
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint);
|
||||
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave);
|
||||
|
||||
void Serialize (FArchive &arc);
|
||||
void Tick ();
|
||||
|
@ -178,6 +178,8 @@ public:
|
|||
DVector3 m_WaveSpeed;
|
||||
double m_Falloff;
|
||||
int m_Highpoint, m_MiniCount;
|
||||
double m_RollIntensity, m_RollWave;
|
||||
|
||||
|
||||
double GetModIntensity(double intensity) const;
|
||||
double GetModWave(double waveMultiplier) const;
|
||||
|
|
|
@ -126,13 +126,16 @@ void ASkyPicker::PostBeginPlay ()
|
|||
else
|
||||
{
|
||||
int boxindex = P_GetSkyboxPortal(box);
|
||||
// Do not override special portal types, only regular skies.
|
||||
if (0 == (args[1] & 2))
|
||||
{
|
||||
Sector->Portals[sector_t::ceiling] = boxindex;
|
||||
if (Sector->GetPortalType(sector_t::ceiling) == PORTS_SKYVIEWPOINT)
|
||||
Sector->Portals[sector_t::ceiling] = boxindex;
|
||||
}
|
||||
if (0 == (args[1] & 1))
|
||||
{
|
||||
Sector->Portals[sector_t::floor] = boxindex;
|
||||
if (Sector->GetPortalType(sector_t::floor) == PORTS_SKYVIEWPOINT)
|
||||
Sector->Portals[sector_t::floor] = boxindex;
|
||||
}
|
||||
}
|
||||
Destroy ();
|
||||
|
|
|
@ -264,6 +264,7 @@ class FMugShot
|
|||
DISABLEOUCH = 0x8,
|
||||
DISABLEPAIN = 0x10,
|
||||
DISABLERAMPAGE = 0x20,
|
||||
CUSTOM = 0x40,
|
||||
};
|
||||
|
||||
FMugShot();
|
||||
|
|
|
@ -489,7 +489,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
|
|||
if (CurrentState != NULL)
|
||||
{
|
||||
int skin = player->userinfo.GetSkin();
|
||||
const char *skin_face = player->morphTics ? player->MorphedPlayerClass->Face.GetChars() : skins[skin].face;
|
||||
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? player->MorphedPlayerClass->Face.GetChars() : skins[skin].face);
|
||||
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -1578,23 +1578,25 @@ class CommandDrawMugShot : public SBarInfoCommand
|
|||
sc.ScriptError("Expected a number between 1 and 9, got %d instead.", sc.Number);
|
||||
accuracy = sc.Number;
|
||||
sc.MustGetToken(',');
|
||||
while(sc.CheckToken(TK_Identifier))
|
||||
while (sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
if(sc.Compare("xdeathface"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::XDEATHFACE);
|
||||
else if(sc.Compare("animatedgodmode"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::ANIMATEDGODMODE);
|
||||
else if(sc.Compare("disablegrin"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::DISABLEGRIN);
|
||||
else if(sc.Compare("disableouch"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::DISABLEOUCH);
|
||||
else if(sc.Compare("disablepain"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::DISABLEPAIN);
|
||||
else if(sc.Compare("disablerampage"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags|FMugShot::DISABLERAMPAGE);
|
||||
if (sc.Compare("xdeathface"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::XDEATHFACE);
|
||||
else if (sc.Compare("animatedgodmode"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::ANIMATEDGODMODE);
|
||||
else if (sc.Compare("disablegrin"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::DISABLEGRIN);
|
||||
else if (sc.Compare("disableouch"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::DISABLEOUCH);
|
||||
else if (sc.Compare("disablepain"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::DISABLEPAIN);
|
||||
else if (sc.Compare("disablerampage"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::DISABLERAMPAGE);
|
||||
else if (sc.Compare("custom"))
|
||||
stateFlags = static_cast<FMugShot::StateFlags> (stateFlags | FMugShot::CUSTOM);
|
||||
else
|
||||
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
||||
if(!sc.CheckToken('|'))
|
||||
if (!sc.CheckToken('|'))
|
||||
sc.MustGetToken(',');
|
||||
}
|
||||
|
||||
|
|
|
@ -839,18 +839,26 @@ static void DrawCoordinates(player_t * CPlayer)
|
|||
int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6;
|
||||
int ypos = 18;
|
||||
|
||||
screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.MapName), ypos, level.MapName,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
|
||||
|
||||
screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.LevelName), ypos + h, level.LevelName,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
|
||||
|
||||
mysnprintf(coordstr, countof(coordstr), "X: %d", int(pos.X));
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos, coordstr,
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
|
||||
|
||||
mysnprintf(coordstr, countof(coordstr), "Y: %d", int(pos.Y));
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+h, coordstr,
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+3*h, coordstr,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
|
||||
|
||||
mysnprintf(coordstr, countof(coordstr), "Z: %d", int(pos.Z));
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr,
|
||||
screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+4*h, coordstr,
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE);
|
||||
}
|
||||
|
|
|
@ -198,6 +198,13 @@ FString M_GetConfigPath(bool for_reading)
|
|||
FString path;
|
||||
HRESULT hr;
|
||||
|
||||
path.Format("%s" GAMENAME "_portable.ini", progdir.GetChars());
|
||||
if (FileExists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
path = "";
|
||||
|
||||
// Construct a user-specific config name
|
||||
if (UseKnownFolders() && GetKnownFolder(CSIDL_APPDATA, FOLDERID_RoamingAppData, true, path))
|
||||
{
|
||||
|
|
|
@ -156,12 +156,12 @@ int FNodeBuilder::CreateNode (DWORD set, unsigned int count, fixed_t bbox[4])
|
|||
D(PrintSet (1, set1));
|
||||
D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg));
|
||||
D(PrintSet (2, set2));
|
||||
node.intchildren[0] = CreateNode (set1, count1, node.bbox[0]);
|
||||
node.intchildren[1] = CreateNode (set2, count2, node.bbox[1]);
|
||||
bbox[BOXTOP] = MAX (node.bbox[0][BOXTOP], node.bbox[1][BOXTOP]);
|
||||
bbox[BOXBOTTOM] = MIN (node.bbox[0][BOXBOTTOM], node.bbox[1][BOXBOTTOM]);
|
||||
bbox[BOXLEFT] = MIN (node.bbox[0][BOXLEFT], node.bbox[1][BOXLEFT]);
|
||||
bbox[BOXRIGHT] = MAX (node.bbox[0][BOXRIGHT], node.bbox[1][BOXRIGHT]);
|
||||
node.intchildren[0] = CreateNode (set1, count1, node.nb_bbox[0]);
|
||||
node.intchildren[1] = CreateNode (set2, count2, node.nb_bbox[1]);
|
||||
bbox[BOXTOP] = MAX (node.nb_bbox[0][BOXTOP], node.nb_bbox[1][BOXTOP]);
|
||||
bbox[BOXBOTTOM] = MIN (node.nb_bbox[0][BOXBOTTOM], node.nb_bbox[1][BOXBOTTOM]);
|
||||
bbox[BOXLEFT] = MIN (node.nb_bbox[0][BOXLEFT], node.nb_bbox[1][BOXLEFT]);
|
||||
bbox[BOXRIGHT] = MAX (node.nb_bbox[0][BOXRIGHT], node.nb_bbox[1][BOXRIGHT]);
|
||||
return (int)Nodes.Push (node);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -94,6 +94,13 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount,
|
|||
outNodes[i].children[j] = outNodes + outNodes[i].intchildren[j];
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
outNodes[i].bbox[j][k] = FIXED2FLOAT(outNodes[i].nb_bbox[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GLNodes)
|
||||
|
@ -194,6 +201,13 @@ void FNodeBuilder::ExtractMini (FMiniBSP *bsp)
|
|||
bsp->Nodes[i].children[j] = &bsp->Nodes[bsp->Nodes[i].intchildren[j]];
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
bsp->Nodes[i].bbox[j][k] = FIXED2FLOAT(bsp->Nodes[i].nb_bbox[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GLNodes)
|
||||
|
|
|
@ -609,25 +609,25 @@ void FNodeBuilder::AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg)
|
|||
if (v2->y > bbox[BOXTOP]) bbox[BOXTOP] = v2->y;
|
||||
}
|
||||
|
||||
void FNodeBuilder::FLevel::FindMapBounds ()
|
||||
void FNodeBuilder::FLevel::FindMapBounds()
|
||||
{
|
||||
fixed_t minx, maxx, miny, maxy;
|
||||
double minx, maxx, miny, maxy;
|
||||
|
||||
minx = maxx = Vertices[0].fixX();
|
||||
miny = maxy = Vertices[0].fixY();
|
||||
minx = maxx = Vertices[0].fX();
|
||||
miny = maxy = Vertices[0].fY();
|
||||
|
||||
for (int i = 1; i < NumVertices; ++i)
|
||||
{
|
||||
if (Vertices[i].fixX() < minx) minx = Vertices[i].fixX();
|
||||
else if (Vertices[i].fixX() > maxx) maxx = Vertices[i].fixX();
|
||||
if (Vertices[i].fixY() < miny) miny = Vertices[i].fixY();
|
||||
else if (Vertices[i].fixY() > maxy) maxy = Vertices[i].fixY();
|
||||
if (Vertices[i].fX() < minx) minx = Vertices[i].fX();
|
||||
else if (Vertices[i].fX() > maxx) maxx = Vertices[i].fX();
|
||||
if (Vertices[i].fY() < miny) miny = Vertices[i].fY();
|
||||
else if (Vertices[i].fY() > maxy) maxy = Vertices[i].fY();
|
||||
}
|
||||
|
||||
MinX = minx;
|
||||
MinY = miny;
|
||||
MaxX = maxx;
|
||||
MaxY = maxy;
|
||||
MinX = FLOAT2FIXED(minx);
|
||||
MinY = FLOAT2FIXED(miny);
|
||||
MaxX = FLOAT2FIXED(maxx);
|
||||
MaxY = FLOAT2FIXED(maxy);
|
||||
}
|
||||
|
||||
FNodeBuilder::IVertexMap::~IVertexMap()
|
||||
|
|
|
@ -790,7 +790,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
lowestceilingsec = j == 0 ? linedef->frontsector : linedef->backsector;
|
||||
}
|
||||
|
||||
if(ff_top > highestfloor && delta1 < delta2 && (!restrict || thing->Z() >= ff_top))
|
||||
if(ff_top > highestfloor && delta1 <= delta2 && (!restrict || thing->Z() >= ff_top))
|
||||
{
|
||||
highestfloor = ff_top;
|
||||
highestfloorpic = *rover->top.texture;
|
||||
|
|
|
@ -5567,6 +5567,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
if (argCount >= 2)
|
||||
{
|
||||
const char *a, *b;
|
||||
// If the string indicies are the same, then they are the same string.
|
||||
if (args[0] == args[1])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
a = FBehavior::StaticLookupString(args[0]);
|
||||
b = FBehavior::StaticLookupString(args[1]);
|
||||
|
||||
|
@ -5768,7 +5773,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
argCount > 10 ? ACSToDouble(args[10]) : 1.0,
|
||||
argCount > 11 ? ACSToDouble(args[11]) : 1.0,
|
||||
argCount > 12 ? args[12] : 0,
|
||||
argCount > 13 ? args[13] : 0);
|
||||
argCount > 13 ? args[13] : 0,
|
||||
argCount > 14 ? args[14] : 0,
|
||||
argCount > 15 ? args[15] : 0);
|
||||
}
|
||||
|
||||
case ACSF_SetLineActivation:
|
||||
|
@ -8748,23 +8755,24 @@ scriptwait:
|
|||
{
|
||||
int tag = STACK(3);
|
||||
int secnum;
|
||||
DVector2 pos(ACSToDouble(STACK(2)), ACSToDouble(STACK(1)));
|
||||
double x = double(STACK(2));
|
||||
double y = double(STACK(1));
|
||||
double z = 0;
|
||||
|
||||
if (tag != 0)
|
||||
secnum = P_FindFirstSectorFromTag (tag);
|
||||
else
|
||||
secnum = int(P_PointInSector (pos) - sectors);
|
||||
secnum = int(P_PointInSector (x, y) - sectors);
|
||||
|
||||
if (secnum >= 0)
|
||||
{
|
||||
if (pcd == PCD_GETSECTORFLOORZ)
|
||||
{
|
||||
z = sectors[secnum].floorplane.ZatPoint (pos);
|
||||
z = sectors[secnum].floorplane.ZatPoint (x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
z = sectors[secnum].ceilingplane.ZatPoint (pos);
|
||||
z = sectors[secnum].ceilingplane.ZatPoint (x, y);
|
||||
}
|
||||
}
|
||||
sp -= 2;
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
*/
|
||||
|
||||
#include "vectors.h"
|
||||
#include "tables.h"
|
||||
|
||||
#define FX_ROCKET 0x00000001
|
||||
#define FX_GRENADE 0x00000002
|
||||
|
|
|
@ -3158,7 +3158,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c
|
|||
int style = sv_dropstyle;
|
||||
if (style == 0)
|
||||
{
|
||||
style = (gameinfo.gametype == GAME_Strife) ? 2 : 1;
|
||||
style = gameinfo.defaultdropstyle;
|
||||
}
|
||||
if (style == 2)
|
||||
{
|
||||
|
@ -3206,7 +3206,7 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c
|
|||
void P_TossItem (AActor *item)
|
||||
{
|
||||
int style = sv_dropstyle;
|
||||
if (style==0) style= gameinfo.defaultdropstyle;
|
||||
if (style==0) style = gameinfo.defaultdropstyle;
|
||||
|
||||
if (style==2)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define __P_ENEMY_H__
|
||||
|
||||
#include "thingdef/thingdef.h"
|
||||
#include "tables.h"
|
||||
|
||||
struct sector_t;
|
||||
class AActor;
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "s_sndseq.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
#include "tables.h"
|
||||
#include "farchive.h"
|
||||
#include "p_3dmidtex.h"
|
||||
#include "p_spec.h"
|
||||
|
|
|
@ -589,7 +589,7 @@ static bool LoadNodes (FileReader * lump)
|
|||
}
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
no->bbox[j][k] = LittleShort(mn->bbox[j][k])<<FRACBITS;
|
||||
no->bbox[j][k] = (float)LittleShort(mn->bbox[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ static bool LoadNodes (FileReader * lump)
|
|||
}
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
no->bbox[j][k] = LittleShort(mn->bbox[j][k])<<FRACBITS;
|
||||
no->bbox[j][k] = (float)LittleShort(mn->bbox[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ static void CreateCachedNodes(MapData *map)
|
|||
{
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
WriteWord(ZNodes, nodes[i].bbox[j][k] >> FRACBITS);
|
||||
WriteWord(ZNodes, (short)nodes[i].bbox[j][k]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -301,9 +301,9 @@ void DFlicker::Tick ()
|
|||
DFlicker::DFlicker (sector_t *sector, int upper, int lower)
|
||||
: DLighting (sector)
|
||||
{
|
||||
m_MaxLight = upper;
|
||||
m_MinLight = lower;
|
||||
sector->lightlevel = upper;
|
||||
m_MaxLight = sector_t::ClampLight(upper);
|
||||
m_MinLight = sector_t::ClampLight(lower);
|
||||
sector->lightlevel = m_MaxLight;
|
||||
m_Count = (pr_flicker()&64)+1;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "p_enemy.h"
|
||||
#include "g_level.h"
|
||||
#include "v_palette.h"
|
||||
#include "tables.h"
|
||||
#include "i_system.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "a_lightning.h"
|
||||
|
@ -76,6 +75,7 @@
|
|||
*/
|
||||
static const BYTE ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 };
|
||||
|
||||
|
||||
#define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \
|
||||
int arg0, int arg1, int arg2, int arg3, int arg4)
|
||||
|
||||
|
@ -1129,7 +1129,7 @@ FUNC(LS_Teleport_Line)
|
|||
|
||||
static void ThrustThingHelper(AActor *it, DAngle angle, double force, INTBOOL nolimit)
|
||||
{
|
||||
it->VelFromAngle(angle, force);
|
||||
it->Thrust(angle, force);
|
||||
if (!nolimit)
|
||||
{
|
||||
it->Vel.X = clamp(it->Vel.X, -MAXMOVE, MAXMOVE);
|
||||
|
@ -3441,9 +3441,9 @@ static lnSpecFunc LineSpecials[] =
|
|||
/* 154 */ LS_Teleport_NoStop,
|
||||
/* 155 */ LS_NOP,
|
||||
/* 156 */ LS_NOP,
|
||||
/* 157 */ LS_NOP, // SetGlobalFogParameter // in GZDoom
|
||||
/* 157 */ LS_NOP, // SetGlobalFogParameter
|
||||
/* 158 */ LS_FS_Execute,
|
||||
/* 159 */ LS_NOP, // Sector_SetPlaneReflection in GZDoom
|
||||
/* 159 */ LS_NOP, // Sector_SetPlaneReflection
|
||||
/* 160 */ LS_NOP, // Sector_Set3DFloor
|
||||
/* 161 */ LS_NOP, // Sector_SetContents
|
||||
/* 162 */ LS_NOP, // Reserved Doom64 branch
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include <float.h>
|
||||
#include "doomtype.h"
|
||||
#include "tables.h"
|
||||
#include "vectors.h"
|
||||
|
||||
const double NO_VALUE = FLT_MAX;
|
||||
|
|
152
src/p_map.cpp
152
src/p_map.cpp
|
@ -45,6 +45,7 @@
|
|||
#include "p_checkposition.h"
|
||||
#include "r_utility.h"
|
||||
#include "p_blockmap.h"
|
||||
#include "p_3dmidtex.h"
|
||||
|
||||
#include "s_sound.h"
|
||||
#include "decallib.h"
|
||||
|
@ -1514,7 +1515,47 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
|
|||
// Any contacted lines the step closer together will adjust them.
|
||||
if (!thing->IsNoClip2())
|
||||
{
|
||||
P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR);
|
||||
if (!newsec->PortalBlocksMovement(sector_t::ceiling) || !newsec->PortalBlocksMovement(sector_t::floor))
|
||||
{
|
||||
// Use P_GetFloorCeilingZ only if there's portals to consider. Its logic is subtly different than what is needed here for 3D floors.
|
||||
P_GetFloorCeilingZ(tm, FFCF_SAMESECTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(pos);
|
||||
tm.floorpic = newsec->GetTexture(sector_t::floor);
|
||||
tm.ceilingz = newsec->ceilingplane.ZatPoint(pos);
|
||||
tm.ceilingpic = newsec->GetTexture(sector_t::ceiling);
|
||||
tm.floorsector = tm.ceilingsector = newsec;
|
||||
tm.floorterrain = newsec->GetTerrain(sector_t::floor);
|
||||
}
|
||||
|
||||
F3DFloor* rover;
|
||||
double thingtop = thing->Height > 0 ? thing->Top() : thing->Z() + 1;
|
||||
|
||||
for (unsigned i = 0; i<newsec->e->XFloor.ffloors.Size(); i++)
|
||||
{
|
||||
rover = newsec->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
double ff_bottom = rover->bottom.plane->ZatPoint(pos);
|
||||
double ff_top = rover->top.plane->ZatPoint(pos);
|
||||
|
||||
double delta1 = thing->Z() - (ff_bottom + ((ff_top - ff_bottom) / 2));
|
||||
double delta2 = thingtop - (ff_bottom + ((ff_top - ff_bottom) / 2));
|
||||
|
||||
if (ff_top > tm.floorz && fabs(delta1) < fabs(delta2))
|
||||
{
|
||||
tm.floorz = tm.dropoffz = ff_top;
|
||||
tm.floorpic = *rover->top.texture;
|
||||
tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling);
|
||||
}
|
||||
if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2))
|
||||
{
|
||||
tm.ceilingz = ff_bottom;
|
||||
tm.ceilingpic = *rover->bottom.texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1865,6 +1906,15 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 *
|
|||
if (fzt >= mobj->Top() && bzt >= mobj->Top() &&
|
||||
fzb <= mobj->Z() && bzb <= mobj->Z())
|
||||
{
|
||||
if (line->flags & ML_3DMIDTEX)
|
||||
{
|
||||
double top, bot;
|
||||
P_GetMidTexturePosition(line, side, &top, &bot);
|
||||
if (bot < mobj->Top() && top > mobj->Z())
|
||||
{
|
||||
goto isblocking;
|
||||
}
|
||||
}
|
||||
// we must also check if some 3D floor in the backsector may be blocking
|
||||
for (auto rover : line->backsector->e->XFloor.ffloors)
|
||||
{
|
||||
|
@ -3973,8 +4023,11 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin
|
|||
struct Origin
|
||||
{
|
||||
AActor *Caller;
|
||||
FNameNoInit PuffSpecies;
|
||||
bool hitGhosts;
|
||||
bool hitSameSpecies;
|
||||
bool MThruSpecies;
|
||||
bool ThruSpecies;
|
||||
bool ThruActors;
|
||||
};
|
||||
|
||||
static ETraceStatus CheckForActor(FTraceResults &res, void *userdata)
|
||||
|
@ -3986,17 +4039,16 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata)
|
|||
|
||||
Origin *data = (Origin *)userdata;
|
||||
|
||||
// check for physical attacks on spectrals
|
||||
if (res.Actor->flags4 & MF4_SPECTRAL)
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
// Skip actors if the puff has:
|
||||
// 1. THRUACTORS or SPECTRAL
|
||||
// 2. MTHRUSPECIES on puff and the shooter has same species as the hit actor
|
||||
// 3. THRUSPECIES on puff and the puff has same species as the hit actor
|
||||
// 4. THRUGHOST on puff and the GHOST flag on the hit actor
|
||||
|
||||
if (data->hitSameSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies())
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
if (data->hitGhosts && res.Actor->flags3 & MF3_GHOST)
|
||||
if ((data->ThruActors) || (res.Actor->flags4 & MF4_SPECTRAL) ||
|
||||
(data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) ||
|
||||
(data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) ||
|
||||
(data->hitGhosts && res.Actor->flags3 & MF3_GHOST))
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
|
@ -4058,14 +4110,41 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
|
|||
|
||||
// We need to check the defaults of the replacement here
|
||||
AActor *puffDefaults = GetDefaultByType(pufftype->GetReplacement());
|
||||
|
||||
|
||||
TData.hitGhosts = (t1->player != NULL &&
|
||||
t1->player->ReadyWeapon != NULL &&
|
||||
(t1->player->ReadyWeapon->flags2 & MF2_THRUGHOST)) ||
|
||||
(puffDefaults && (puffDefaults->flags2 & MF2_THRUGHOST));
|
||||
|
||||
TData.hitSameSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES));
|
||||
TData.MThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_MTHRUSPECIES));
|
||||
TData.PuffSpecies = NAME_None;
|
||||
|
||||
// [MC] To prevent possible mod breakage, this flag is pretty much necessary.
|
||||
// Somewhere, someone is relying on these to spawn on actors and move through them.
|
||||
|
||||
if ((puffDefaults->flags7 & MF7_ALLOWTHRUFLAGS))
|
||||
{
|
||||
TData.ThruSpecies = (puffDefaults && (puffDefaults->flags6 & MF6_THRUSPECIES));
|
||||
TData.ThruActors = (puffDefaults && (puffDefaults->flags2 & MF2_THRUACTORS));
|
||||
|
||||
// [MC] Because this is a one-hit trace event, we need to spawn the puff, get the species
|
||||
// and destroy it. Assume there is no species unless tempuff isn't NULL. We cannot get
|
||||
// a proper species the same way as puffDefaults flags it appears...
|
||||
|
||||
AActor *tempuff = NULL;
|
||||
if (pufftype != NULL)
|
||||
tempuff = Spawn(pufftype, t1->Pos(), ALLOW_REPLACE);
|
||||
if (tempuff != NULL)
|
||||
{
|
||||
TData.PuffSpecies = tempuff->GetSpecies();
|
||||
tempuff->Destroy();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TData.ThruSpecies = false;
|
||||
TData.ThruActors = false;
|
||||
}
|
||||
// if the puff uses a non-standard damage type, this will override default, hitscan and melee damage type.
|
||||
// All other explicitly passed damage types (currenty only MDK) will be preserved.
|
||||
if ((damageType == NAME_None || damageType == NAME_Melee || damageType == NAME_Hitscan) &&
|
||||
|
@ -4493,9 +4572,13 @@ struct RailData
|
|||
AActor *Caller;
|
||||
TArray<SRailHit> RailHits;
|
||||
TArray<SPortalHit> PortalHits;
|
||||
FNameNoInit PuffSpecies;
|
||||
bool StopAtOne;
|
||||
bool StopAtInvul;
|
||||
bool ThruGhosts;
|
||||
bool ThruSpecies;
|
||||
bool MThruSpecies;
|
||||
bool ThruActors;
|
||||
};
|
||||
|
||||
static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata)
|
||||
|
@ -4522,8 +4605,16 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata)
|
|||
return TRACE_Stop;
|
||||
}
|
||||
|
||||
// Skip actors with the same species if the puff has MTHRUSPECIES.
|
||||
if (data->ThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies())
|
||||
// Skip actors if the puff has:
|
||||
// 1. THRUACTORS (This one did NOT include a check for spectral)
|
||||
// 2. MTHRUSPECIES on puff and the shooter has same species as the hit actor
|
||||
// 3. THRUSPECIES on puff and the puff has same species as the hit actor
|
||||
// 4. THRUGHOST on puff and the GHOST flag on the hit actor
|
||||
|
||||
if ((data->ThruActors) ||
|
||||
(data->MThruSpecies && res.Actor->GetSpecies() == data->Caller->GetSpecies()) ||
|
||||
(data->ThruSpecies && res.Actor->GetSpecies() == data->PuffSpecies) ||
|
||||
(data->ThruGhosts && res.Actor->flags3 & MF3_GHOST))
|
||||
{
|
||||
return TRACE_Skip;
|
||||
}
|
||||
|
@ -4598,7 +4689,27 @@ void P_RailAttack(FRailParams *p)
|
|||
// disabled because not complete yet.
|
||||
flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? TRACE_ReportPortals : TRACE_PCross | TRACE_Impact | TRACE_ReportPortals;
|
||||
rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true;
|
||||
rail_data.ThruSpecies = (puffDefaults->flags6 & MF6_MTHRUSPECIES) ? true : false;
|
||||
rail_data.MThruSpecies = ((puffDefaults->flags6 & MF6_MTHRUSPECIES)) ? true : false;
|
||||
|
||||
// Prevent mod breakage as somewhere, someone is relying on these to spawn on an actor
|
||||
// and move through them...
|
||||
if ((puffDefaults->flags7 & MF7_ALLOWTHRUFLAGS))
|
||||
{
|
||||
rail_data.ThruGhosts = !!(puffDefaults->flags2 & MF2_THRUGHOST);
|
||||
rail_data.ThruSpecies = !!(puffDefaults->flags6 & MF6_THRUSPECIES);
|
||||
rail_data.ThruActors = !!(puffDefaults->flags2 & MF2_THRUACTORS);
|
||||
}
|
||||
else
|
||||
{
|
||||
rail_data.ThruGhosts = false;
|
||||
rail_data.MThruSpecies = false;
|
||||
rail_data.ThruActors = false;
|
||||
}
|
||||
// used as damage inflictor
|
||||
AActor *thepuff = NULL;
|
||||
|
||||
if (puffclass != NULL) thepuff = Spawn(puffclass, source->Pos(), ALLOW_REPLACE);
|
||||
rail_data.PuffSpecies = (thepuff != NULL) ? thepuff->GetSpecies() : NAME_None;
|
||||
|
||||
Trace(start, source->Sector, vec, p->distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace, flags, ProcessRailHit, &rail_data);
|
||||
|
||||
|
@ -4606,11 +4717,6 @@ void P_RailAttack(FRailParams *p)
|
|||
unsigned int i;
|
||||
FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType;
|
||||
|
||||
// used as damage inflictor
|
||||
AActor *thepuff = NULL;
|
||||
|
||||
if (puffclass != NULL) thepuff = Spawn(puffclass, source->Pos(), ALLOW_REPLACE);
|
||||
|
||||
for (i = 0; i < rail_data.RailHits.Size(); i++)
|
||||
{
|
||||
bool spawnpuff;
|
||||
|
@ -6340,7 +6446,7 @@ void AActor::UpdateRenderSectorList()
|
|||
if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY())
|
||||
{
|
||||
int bx = GetBlockX(X());
|
||||
int by = GetBlockX(Y());
|
||||
int by = GetBlockY(Y());
|
||||
FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors
|
||||
// Are there any portals near the actor's position?
|
||||
if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines)
|
||||
|
|
|
@ -638,20 +638,23 @@ bool AActor::GiveInventory(PClassInventory *type, int amount, bool givecheat)
|
|||
|
||||
// This shouldn't count for the item statistics!
|
||||
item->ClearCounters();
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
|
||||
if (!givecheat || amount > 0)
|
||||
{
|
||||
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
|
||||
}
|
||||
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
|
||||
{
|
||||
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!givecheat)
|
||||
item->Amount = amount;
|
||||
if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorPickup)))
|
||||
{
|
||||
static_cast<ABasicArmorPickup*>(item)->SaveAmount *= amount;
|
||||
}
|
||||
else if (type->IsDescendantOf (RUNTIME_CLASS(ABasicArmorBonus)))
|
||||
{
|
||||
static_cast<ABasicArmorBonus*>(item)->SaveAmount *= amount;
|
||||
}
|
||||
else
|
||||
item->Amount = MIN (amount, item->MaxAmount);
|
||||
{
|
||||
if (!givecheat)
|
||||
item->Amount = amount;
|
||||
else
|
||||
item->Amount = MIN (amount, item->MaxAmount);
|
||||
}
|
||||
}
|
||||
if (!item->CallTryPickup (this))
|
||||
{
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
// Basic data types.
|
||||
// Needs fixed point, and BAM angles.
|
||||
#include "tables.h"
|
||||
#include "thingdef/thingdef.h"
|
||||
|
||||
#define WEAPONBOTTOM 128.
|
||||
|
|
|
@ -423,7 +423,6 @@ void P_SerializeWorld (FArchive &arc)
|
|||
<< si->LeftSide
|
||||
<< si->RightSide
|
||||
<< si->Index;
|
||||
DBaseDecal::SerializeChain (arc, &si->AttachedDecals);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,6 +451,7 @@ void P_SerializeWorldActors(FArchive &arc)
|
|||
{
|
||||
int i;
|
||||
sector_t *sec;
|
||||
line_t *line;
|
||||
|
||||
for (i = 0, sec = sectors; i < numsectors; i++, sec++)
|
||||
{
|
||||
|
@ -465,6 +465,16 @@ void P_SerializeWorldActors(FArchive &arc)
|
|||
{
|
||||
arc << s.mSkybox;
|
||||
}
|
||||
for (i = 0, line = lines; i < numlines; i++, line++)
|
||||
{
|
||||
for (int s = 0; s < 2; s++)
|
||||
{
|
||||
if (line->sidedef[s] != NULL)
|
||||
{
|
||||
DBaseDecal::SerializeChain(arc, &line->sidedef[s]->AttachedDecals);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void extsector_t::Serialize(FArchive &arc)
|
||||
|
@ -504,6 +514,7 @@ FArchive &operator<< (FArchive &arc, sector_t::splane &p)
|
|||
|
||||
void P_SerializeThinkers (FArchive &arc, bool hubLoad)
|
||||
{
|
||||
arc.EnableThinkers();
|
||||
DImpactDecal::SerializeTime (arc);
|
||||
DThinker::SerializeAll (arc, hubLoad);
|
||||
}
|
||||
|
|
|
@ -1096,7 +1096,7 @@ void LoadZNodes(FileReaderBase &data, int glnodes)
|
|||
{
|
||||
SWORD coord;
|
||||
data >> coord;
|
||||
nodes[i].bbox[j][k] = coord << FRACBITS;
|
||||
nodes[i].bbox[j][k] = coord;
|
||||
}
|
||||
}
|
||||
for (int m = 0; m < 2; ++m)
|
||||
|
@ -1640,7 +1640,7 @@ void P_LoadNodes (MapData * map)
|
|||
}
|
||||
for (k = 0; k < 4; k++)
|
||||
{
|
||||
no->bbox[j][k] = LittleShort(mn->bbox[j][k])<<FRACBITS;
|
||||
no->bbox[j][k] = (float)LittleShort(mn->bbox[j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3366,6 +3366,83 @@ void P_GetPolySpots (MapData * map, TArray<FNodeBuilder::FPolyStart> &spots, TAr
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_PrecacheLevel
|
||||
//
|
||||
// Preloads all relevant graphics for the level.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static void P_PrecacheLevel()
|
||||
{
|
||||
int i;
|
||||
BYTE *hitlist;
|
||||
TMap<PClassActor *, bool> actorhitlist;
|
||||
int cnt = TexMan.NumTextures();
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
hitlist = new BYTE[cnt];
|
||||
memset(hitlist, 0, cnt);
|
||||
|
||||
AActor *actor;
|
||||
TThinkerIterator<AActor> iterator;
|
||||
|
||||
while ((actor = iterator.Next()))
|
||||
{
|
||||
actorhitlist[actor->GetClass()] = true;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < level.info->PrecacheClasses.Size(); i++)
|
||||
{
|
||||
// level.info can only store names, no class pointers.
|
||||
PClassActor *cls = PClass::FindActor(level.info->PrecacheClasses[i]);
|
||||
if (cls != NULL) actorhitlist[cls] = true;
|
||||
}
|
||||
|
||||
for (i = numsectors - 1; i >= 0; i--)
|
||||
{
|
||||
hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] |= FTextureManager::HIT_Flat;
|
||||
hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat;
|
||||
}
|
||||
|
||||
for (i = numsides - 1; i >= 0; i--)
|
||||
{
|
||||
hitlist[sides[i].GetTexture(side_t::top).GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
}
|
||||
|
||||
// Sky texture is always present.
|
||||
// Note that F_SKY1 is the name used to
|
||||
// indicate a sky floor/ceiling as a flat,
|
||||
// while the sky texture is stored like
|
||||
// a wall texture, with an episode dependant
|
||||
// name.
|
||||
|
||||
if (sky1texture.isValid())
|
||||
{
|
||||
hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky;
|
||||
}
|
||||
if (sky2texture.isValid())
|
||||
{
|
||||
hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
|
||||
{
|
||||
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst);
|
||||
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
}
|
||||
|
||||
Renderer->Precache(hitlist, actorhitlist);
|
||||
|
||||
delete[] hitlist;
|
||||
}
|
||||
|
||||
extern polyblock_t **PolyBlockMap;
|
||||
|
||||
void P_FreeLevelData ()
|
||||
|
@ -4094,7 +4171,7 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
// preload graphics and sounds
|
||||
if (precache)
|
||||
{
|
||||
TexMan.PrecacheLevel ();
|
||||
P_PrecacheLevel ();
|
||||
S_PrecacheLevel ();
|
||||
}
|
||||
times[17].Unclock();
|
||||
|
|
|
@ -698,7 +698,7 @@ void P_DoDeferedScripts (void);
|
|||
//
|
||||
// [RH] p_quake.c
|
||||
//
|
||||
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint);
|
||||
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave);
|
||||
bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "p_local.h"
|
||||
#include "info.h"
|
||||
#include "s_sound.h"
|
||||
#include "tables.h"
|
||||
#include "doomstat.h"
|
||||
#include "m_random.h"
|
||||
#include "c_console.h"
|
||||
|
|
|
@ -494,6 +494,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
|||
// clip to the part of the sector we are in
|
||||
if (hit.Z > ff_top)
|
||||
{
|
||||
// 3D floor height is the same as the floor height. We need to test a second spot to see if it is above or below
|
||||
if (fabs(bf - ff_top) < EQUAL_EPSILON)
|
||||
{
|
||||
double cf = entersector->floorplane.ZatPoint(entersector->centerspot);
|
||||
double ffc = rover->top.plane->ZatPoint(entersector->centerspot);
|
||||
if (ffc > cf)
|
||||
{
|
||||
bf = ff_top - EQUAL_EPSILON;
|
||||
}
|
||||
}
|
||||
|
||||
// above
|
||||
if (bf < ff_top)
|
||||
{
|
||||
|
@ -505,6 +516,17 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
|||
}
|
||||
else if (hit.Z < ff_bottom)
|
||||
{
|
||||
// 3D floor height is the same as the ceiling height. We need to test a second spot to see if it is above or below
|
||||
if (fabs(bc - ff_bottom) < EQUAL_EPSILON)
|
||||
{
|
||||
double cc = entersector->ceilingplane.ZatPoint(entersector->centerspot);
|
||||
double fcc = rover->bottom.plane->ZatPoint(entersector->centerspot);
|
||||
if (fcc < cc)
|
||||
{
|
||||
bc = ff_bottom + EQUAL_EPSILON;
|
||||
}
|
||||
}
|
||||
|
||||
//below
|
||||
if (bc > ff_bottom)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "sc_man.h"
|
||||
#include "m_fixed.h"
|
||||
#include "tables.h"
|
||||
|
||||
class UDMFParserBase
|
||||
{
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "w_wad.h"
|
||||
#include "m_swap.h"
|
||||
#include "m_bbox.h"
|
||||
#include "tables.h"
|
||||
#include "s_sndseq.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "p_3dmidtex.h"
|
||||
|
@ -1920,7 +1919,7 @@ static double PartitionDistance(FPolyVertex *vt, node_t *node)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void AddToBBox(fixed_t child[4], fixed_t parent[4])
|
||||
static void AddToBBox(float child[4], float parent[4])
|
||||
{
|
||||
if (child[BOXTOP] > parent[BOXTOP])
|
||||
{
|
||||
|
@ -1946,10 +1945,10 @@ static void AddToBBox(fixed_t child[4], fixed_t parent[4])
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void AddToBBox(FPolyVertex *v, fixed_t bbox[4])
|
||||
static void AddToBBox(FPolyVertex *v, float bbox[4])
|
||||
{
|
||||
fixed_t x = FLOAT2FIXED(v->pos.X);
|
||||
fixed_t y = FLOAT2FIXED(v->pos.Y);
|
||||
float x = float(v->pos.X);
|
||||
float y = float(v->pos.Y);
|
||||
if (x < bbox[BOXLEFT])
|
||||
{
|
||||
bbox[BOXLEFT] = x;
|
||||
|
@ -1974,7 +1973,7 @@ static void AddToBBox(FPolyVertex *v, fixed_t bbox[4])
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void SplitPoly(FPolyNode *pnode, void *node, fixed_t bbox[4])
|
||||
static void SplitPoly(FPolyNode *pnode, void *node, float bbox[4])
|
||||
{
|
||||
static TArray<FPolySeg> lists[2];
|
||||
static const double POLY_EPSILON = 0.3125;
|
||||
|
@ -2111,7 +2110,7 @@ static void SplitPoly(FPolyNode *pnode, void *node, fixed_t bbox[4])
|
|||
|
||||
// calculate bounding box for this polynode
|
||||
assert(pnode->segs.Size() != 0);
|
||||
fixed_t subbbox[4] = { FIXED_MIN, FIXED_MAX, FIXED_MAX, FIXED_MIN };
|
||||
float subbbox[4] = { FLT_MIN, FLT_MAX, FLT_MAX, FLT_MIN };
|
||||
|
||||
for (unsigned i = 0; i < pnode->segs.Size(); ++i)
|
||||
{
|
||||
|
@ -2135,7 +2134,7 @@ void FPolyObj::CreateSubsectorLinks()
|
|||
// Even though we don't care about it, we need to initialize this
|
||||
// bounding box to something so that Valgrind won't complain about it
|
||||
// when SplitPoly modifies it.
|
||||
fixed_t dummybbox[4] = { 0 };
|
||||
float dummybbox[4] = { 0 };
|
||||
|
||||
node->poly = this;
|
||||
node->segs.Resize(Sidedefs.Size());
|
||||
|
|
|
@ -53,11 +53,10 @@ void R_3D_AddHeight(secplane_t *add, sector_t *sec)
|
|||
HeightLevel *near;
|
||||
HeightLevel *curr;
|
||||
|
||||
double fheight = add->ZatPoint(ViewPos);
|
||||
if(fheight >= sec->CenterCeiling()) return;
|
||||
if(fheight <= sec->CenterFloor()) return;
|
||||
double height = add->ZatPoint(ViewPos);
|
||||
if(height >= sec->CenterCeiling()) return;
|
||||
if(height <= sec->CenterFloor()) return;
|
||||
|
||||
fixed_t height = FLOAT2FIXED(fheight);
|
||||
fakeActive = 1;
|
||||
|
||||
if(height_max >= 0) {
|
||||
|
|
|
@ -575,7 +575,6 @@ void R_AddLine (seg_t *line)
|
|||
return;
|
||||
|
||||
vertex_t *v1, *v2;
|
||||
|
||||
v1 = line->linedef->v1;
|
||||
v2 = line->linedef->v2;
|
||||
|
||||
|
@ -605,7 +604,7 @@ void R_AddLine (seg_t *line)
|
|||
rw_havehigh = rw_havelow = false;
|
||||
|
||||
// Single sided line?
|
||||
if (backsector == NULL || (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0]))
|
||||
if (backsector == NULL)
|
||||
{
|
||||
solid = true;
|
||||
}
|
||||
|
@ -636,9 +635,14 @@ void R_AddLine (seg_t *line)
|
|||
WallMost (walllower, backsector->floorplane, &WallC);
|
||||
}
|
||||
|
||||
// Portal
|
||||
if (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0])
|
||||
{
|
||||
solid = true;
|
||||
}
|
||||
// Closed door.
|
||||
if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
|
||||
(rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2))
|
||||
else if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
|
||||
(rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2))
|
||||
{
|
||||
solid = true;
|
||||
}
|
||||
|
@ -873,7 +877,7 @@ extern "C" const int checkcoord[12][4] =
|
|||
};
|
||||
|
||||
|
||||
static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static
|
||||
static bool R_CheckBBox (float *bspcoord) // killough 1/28/98: static
|
||||
{
|
||||
int boxx;
|
||||
int boxy;
|
||||
|
@ -887,16 +891,16 @@ static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static
|
|||
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
if (ViewPos.X <= FIXED2DBL(bspcoord[BOXLEFT]))
|
||||
if (ViewPos.X <= bspcoord[BOXLEFT])
|
||||
boxx = 0;
|
||||
else if (ViewPos.X < FIXED2DBL(bspcoord[BOXRIGHT]))
|
||||
else if (ViewPos.X < bspcoord[BOXRIGHT])
|
||||
boxx = 1;
|
||||
else
|
||||
boxx = 2;
|
||||
|
||||
if (ViewPos.Y >= FIXED2DBL(bspcoord[BOXTOP]))
|
||||
if (ViewPos.Y >= bspcoord[BOXTOP])
|
||||
boxy = 0;
|
||||
else if (ViewPos.Y > FIXED2DBL(bspcoord[BOXBOTTOM]))
|
||||
else if (ViewPos.Y > bspcoord[BOXBOTTOM])
|
||||
boxy = 1;
|
||||
else
|
||||
boxy = 2;
|
||||
|
@ -905,10 +909,10 @@ static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static
|
|||
if (boxpos == 5)
|
||||
return true;
|
||||
|
||||
x1 = FIXED2DBL(bspcoord[checkcoord[boxpos][0]]) - ViewPos.X;
|
||||
y1 = FIXED2DBL(bspcoord[checkcoord[boxpos][1]]) - ViewPos.Y;
|
||||
x2 = FIXED2DBL(bspcoord[checkcoord[boxpos][2]]) - ViewPos.X;
|
||||
y2 = FIXED2DBL(bspcoord[checkcoord[boxpos][3]]) - ViewPos.Y;
|
||||
x1 = bspcoord[checkcoord[boxpos][0]] - ViewPos.X;
|
||||
y1 = bspcoord[checkcoord[boxpos][1]] - ViewPos.Y;
|
||||
x2 = bspcoord[checkcoord[boxpos][2]] - ViewPos.X;
|
||||
y2 = bspcoord[checkcoord[boxpos][3]] - ViewPos.Y;
|
||||
|
||||
// check clip list for an open space
|
||||
|
||||
|
|
|
@ -501,25 +501,33 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts)
|
|||
}
|
||||
else if (sc.Compare("spin"))
|
||||
{
|
||||
int mul = 1;
|
||||
sc.MustGetToken('=');
|
||||
if (sc.CheckToken('-')) mul = -1;
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
opts.DroppedSpin = opts.PlacedSpin = sc.Number;
|
||||
opts.DroppedSpin = opts.PlacedSpin = sc.Number*mul;
|
||||
}
|
||||
else if (sc.Compare("placedspin"))
|
||||
{
|
||||
int mul = 1;
|
||||
sc.MustGetToken('=');
|
||||
if (sc.CheckToken('-')) mul = -1;
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
opts.PlacedSpin = sc.Number;
|
||||
opts.PlacedSpin = sc.Number*mul;
|
||||
}
|
||||
else if (sc.Compare("droppedspin"))
|
||||
{
|
||||
int mul = 1;
|
||||
sc.MustGetToken('=');
|
||||
if (sc.CheckToken('-')) mul = -1;
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
opts.DroppedSpin = sc.Number;
|
||||
opts.DroppedSpin = sc.Number*mul;
|
||||
}
|
||||
else if (sc.Compare("angleoffset"))
|
||||
{
|
||||
int mul = 1;
|
||||
sc.MustGetToken('=');
|
||||
if (sc.CheckToken('-')) mul = -1;
|
||||
sc.MustGetAnyToken();
|
||||
if (sc.TokenType == TK_IntConst)
|
||||
{
|
||||
|
@ -529,7 +537,7 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts)
|
|||
{
|
||||
sc.TokenMustBe(TK_FloatConst);
|
||||
}
|
||||
opts.AngleOffset = sc.Float + 90.;
|
||||
opts.AngleOffset = mul * sc.Float + 90.;
|
||||
}
|
||||
else if (sc.Compare("overridepalette"))
|
||||
{
|
||||
|
|
|
@ -1364,7 +1364,11 @@ struct node_t
|
|||
fixed_t y;
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
fixed_t bbox[2][4]; // Bounding box for each child.
|
||||
union
|
||||
{
|
||||
float bbox[2][4]; // Bounding box for each child.
|
||||
fixed_t nb_bbox[2][4]; // Used by nodebuilder.
|
||||
};
|
||||
float len;
|
||||
union
|
||||
{
|
||||
|
|
|
@ -60,7 +60,6 @@ extern int ST_Y;
|
|||
|
||||
BYTE* viewimage;
|
||||
extern "C" {
|
||||
int halfviewwidth;
|
||||
int ylookup[MAXHEIGHT];
|
||||
BYTE *dc_destorg;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define __R_LOCAL_H__
|
||||
|
||||
// Binary Angles, sine/cosine/atan lookups.
|
||||
#include "tables.h"
|
||||
|
||||
// Screen size related parameters.
|
||||
#include "doomdef.h"
|
||||
|
|
155
src/r_main.cpp
155
src/r_main.cpp
|
@ -165,31 +165,6 @@ static int lastcenteryfrac;
|
|||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// viewangletox
|
||||
//
|
||||
// Used solely for construction the xtoviewangle table.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static inline int viewangletox(int i)
|
||||
{
|
||||
if (finetangent[i] > FRACUNIT*2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (finetangent[i] < -FRACUNIT*2)
|
||||
{
|
||||
return viewwidth+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
double t = FIXED2DBL(finetangent[i]) * FocalLengthX;
|
||||
return clamp(xs_CeilToInt(CenterX - t), -1, viewwidth+1);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_InitTextureMapping
|
||||
|
@ -198,46 +173,29 @@ static inline int viewangletox(int i)
|
|||
|
||||
void R_InitTextureMapping ()
|
||||
{
|
||||
int i, x;
|
||||
int i;
|
||||
|
||||
// Calc focallength so FieldOfView fineangles covers viewwidth.
|
||||
// Calc focallength so FieldOfView angles cover viewwidth.
|
||||
FocalLengthX = CenterX / FocalTangent;
|
||||
FocalLengthY = FocalLengthX * YaspectMul;
|
||||
|
||||
// This is 1/FocalTangent before the widescreen extension of FOV.
|
||||
viewingrangerecip = DivScale32(1, finetangent[FINEANGLES/4+(FieldOfView/2)]);
|
||||
viewingrangerecip = FLOAT2FIXED(1. / tan(FieldOfView.Radians() / 2));
|
||||
|
||||
// [RH] Do not generate viewangletox, because texture mapping is no
|
||||
// longer done with trig, so it's not needed.
|
||||
|
||||
// Now generate xtoviewangle for sky texture mapping.
|
||||
// We do this with a hybrid approach: The center 90 degree span is
|
||||
// constructed as per the original code:
|
||||
// Scan xtoviewangle to find the smallest view angle that maps to x.
|
||||
// (viewangletox is sorted in non-increasing order.)
|
||||
// This reduces the chances of "doubling-up" of texture columns in
|
||||
// the drawn sky texture.
|
||||
// The remaining arcs are done with tantoangle instead.
|
||||
// [RH] Do not generate viewangletox, because texture mapping is no
|
||||
// longer done with trig, so it's not needed.
|
||||
const double slopestep = FocalTangent / centerx;
|
||||
double slope;
|
||||
|
||||
const int t1 = MAX(int(CenterX - FocalLengthX), 0);
|
||||
const int t2 = MIN(int(CenterX + FocalLengthX), viewwidth);
|
||||
const fixed_t dfocus = FLOAT2FIXED(FocalLengthX) >> DBITS;
|
||||
|
||||
for (i = 0, x = t2; x >= t1; --x)
|
||||
for (i = centerx, slope = 0; i <= viewwidth; i++, slope += slopestep)
|
||||
{
|
||||
while (viewangletox(i) > x)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANGLE_90;
|
||||
xtoviewangle[i] = angle_t((2 * M_PI - atan(slope)) * (ANGLE_180 / M_PI));
|
||||
}
|
||||
for (x = t2 + 1; x <= viewwidth; ++x)
|
||||
for (i = 0; i < centerx; i++)
|
||||
{
|
||||
xtoviewangle[x] = ANGLE_270 + tantoangle[dfocus / (x - centerx)];
|
||||
}
|
||||
for (x = 0; x < t1; ++x)
|
||||
{
|
||||
xtoviewangle[x] = (angle_t)(-(signed)xtoviewangle[viewwidth - x]);
|
||||
xtoviewangle[i] = 0 - xtoviewangle[viewwidth - i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,7 +309,6 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight,
|
|||
}
|
||||
|
||||
fuzzviewheight = viewheight - 2; // Maximum row the fuzzer can draw to
|
||||
halfviewwidth = (viewwidth >> 1) - 1;
|
||||
|
||||
lastcenteryfrac = 1<<30;
|
||||
CenterX = centerx;
|
||||
|
@ -544,63 +501,61 @@ void R_SetupColormap(player_t *player)
|
|||
|
||||
void R_SetupFreelook()
|
||||
{
|
||||
{
|
||||
double dy;
|
||||
double dy;
|
||||
|
||||
if (camera != NULL)
|
||||
if (camera != NULL)
|
||||
{
|
||||
dy = FocalLengthY * (-ViewPitch).Tan();
|
||||
}
|
||||
else
|
||||
{
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
CenterY = (viewheight / 2.0) + dy;
|
||||
centery = xs_ToInt(CenterY);
|
||||
globaluclip = -CenterY / InvZtoScale;
|
||||
globaldclip = (viewheight - CenterY) / InvZtoScale;
|
||||
|
||||
//centeryfrac &= 0xffff0000;
|
||||
int e, i;
|
||||
|
||||
i = 0;
|
||||
e = viewheight;
|
||||
float focus = float(FocalLengthY);
|
||||
float den;
|
||||
float cy = float(CenterY);
|
||||
if (i < centery)
|
||||
{
|
||||
den = cy - i - 0.5f;
|
||||
if (e <= centery)
|
||||
{
|
||||
dy = FocalLengthY * (-ViewPitch).Tan();
|
||||
}
|
||||
else
|
||||
{
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
CenterY = (viewheight / 2.0) + dy;
|
||||
centery = xs_ToInt(CenterY);
|
||||
globaluclip = -CenterY / InvZtoScale;
|
||||
globaldclip = (viewheight - CenterY) / InvZtoScale;
|
||||
|
||||
//centeryfrac &= 0xffff0000;
|
||||
int e, i;
|
||||
|
||||
i = 0;
|
||||
e = viewheight;
|
||||
float focus = float(FocalLengthY);
|
||||
float den;
|
||||
float cy = float(CenterY);
|
||||
if (i < centery)
|
||||
{
|
||||
den = cy - i - 0.5f;
|
||||
if (e <= centery)
|
||||
{
|
||||
do {
|
||||
yslope[i] = FLOAT2FIXED(focus / den);
|
||||
den -= 1;
|
||||
} while (++i < e);
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
yslope[i] = FLOAT2FIXED(focus / den);
|
||||
den -= 1;
|
||||
} while (++i < centery);
|
||||
den = i - cy + 0.5f;
|
||||
do {
|
||||
yslope[i] = FLOAT2FIXED(focus / den);
|
||||
den += 1;
|
||||
} while (++i < e);
|
||||
}
|
||||
do {
|
||||
yslope[i] = focus / den;
|
||||
den -= 1;
|
||||
} while (++i < e);
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
yslope[i] = focus / den;
|
||||
den -= 1;
|
||||
} while (++i < centery);
|
||||
den = i - cy + 0.5f;
|
||||
do {
|
||||
yslope[i] = FLOAT2FIXED(focus / den);
|
||||
yslope[i] = focus / den;
|
||||
den += 1;
|
||||
} while (++i < e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
den = i - cy + 0.5f;
|
||||
do {
|
||||
yslope[i] = focus / den;
|
||||
den += 1;
|
||||
} while (++i < e);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
178
src/r_plane.cpp
178
src/r_plane.cpp
|
@ -141,10 +141,10 @@ fixed_t pviewx, pviewy;
|
|||
void R_DrawTiltedPlane_ASM (int y, int x1);
|
||||
}
|
||||
|
||||
fixed_t yslope[MAXHEIGHT];
|
||||
float yslope[MAXHEIGHT];
|
||||
static fixed_t xscale, yscale;
|
||||
static DWORD xstepscale, ystepscale;
|
||||
static DWORD basexfrac, baseyfrac;
|
||||
static double xstepscale, ystepscale;
|
||||
static double basexfrac, baseyfrac;
|
||||
|
||||
#ifdef X86_ASM
|
||||
extern "C" void R_SetSpanSource_ASM (const BYTE *flat);
|
||||
|
@ -205,7 +205,7 @@ void R_DeinitPlanes ()
|
|||
void R_MapPlane (int y, int x1)
|
||||
{
|
||||
int x2 = spanend[y];
|
||||
fixed_t distance;
|
||||
double distance;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (x2 < x1 || x1<0 || x2>=viewwidth || (unsigned)y>=(unsigned)viewheight)
|
||||
|
@ -217,12 +217,12 @@ void R_MapPlane (int y, int x1)
|
|||
// [RH] Notice that I dumped the caching scheme used by Doom.
|
||||
// It did not offer any appreciable speedup.
|
||||
|
||||
distance = xs_ToInt(planeheight * yslope[y]);
|
||||
distance = planeheight * yslope[y];
|
||||
|
||||
ds_xstep = FixedMul (distance, xstepscale);
|
||||
ds_ystep = FixedMul (distance, ystepscale);
|
||||
ds_xfrac = FixedMul (distance, basexfrac) + pviewx;
|
||||
ds_yfrac = FixedMul (distance, baseyfrac) + pviewy;
|
||||
ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale);
|
||||
ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale);
|
||||
ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx;
|
||||
ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy;
|
||||
|
||||
if (plane_shade)
|
||||
{
|
||||
|
@ -287,21 +287,21 @@ void R_CalcTiltedLighting (double lval, double lend, int width)
|
|||
}
|
||||
if (width > 0)
|
||||
{
|
||||
lval = planeshade - lval;
|
||||
lend = planeshade - lend;
|
||||
lval = FIXED2DBL(planeshade) - lval;
|
||||
lend = FIXED2DBL(planeshade) - lend;
|
||||
lstep = (lend - lval) / width;
|
||||
if (lstep < 0)
|
||||
{ // Going from dark to light
|
||||
if (lval < FRACUNIT)
|
||||
if (lval < 1.)
|
||||
{ // All bright
|
||||
lightfiller = basecolormapdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lval >= NUMCOLORMAPS*FRACUNIT)
|
||||
if (lval >= NUMCOLORMAPS)
|
||||
{ // Starts beyond the dark end
|
||||
BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
|
||||
while (lval >= NUMCOLORMAPS*FRACUNIT && i <= width)
|
||||
while (lval >= NUMCOLORMAPS && i <= width)
|
||||
{
|
||||
tiltlighting[i++] = clight;
|
||||
lval += lstep;
|
||||
|
@ -319,7 +319,7 @@ void R_CalcTiltedLighting (double lval, double lend, int width)
|
|||
}
|
||||
else
|
||||
{ // Going from light to dark
|
||||
if (lval >= (NUMCOLORMAPS-1)*FRACUNIT)
|
||||
if (lval >= (NUMCOLORMAPS-1))
|
||||
{ // All dark
|
||||
lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT);
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ void R_CalcTiltedLighting (double lval, double lend, int width)
|
|||
}
|
||||
if (i > width)
|
||||
return;
|
||||
while (i <= width && lval < (NUMCOLORMAPS-1)*FRACUNIT)
|
||||
while (i <= width && lval < (NUMCOLORMAPS-1))
|
||||
{
|
||||
tiltlighting[i++] = basecolormapdata + (xs_ToInt(lval) << COLORMAPSHIFT);
|
||||
lval += lstep;
|
||||
|
@ -582,29 +582,25 @@ static visplane_t *new_visplane (unsigned hash)
|
|||
//==========================================================================
|
||||
|
||||
visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightlevel, double Alpha, bool additive,
|
||||
const FTransform &xform,
|
||||
const FTransform &xxform,
|
||||
int sky, FSectorPortal *portal)
|
||||
{
|
||||
secplane_t plane;
|
||||
visplane_t *check;
|
||||
unsigned hash; // killough
|
||||
bool isskybox;
|
||||
fixed_t xoffs = FLOAT2FIXED(xform.xOffs);
|
||||
fixed_t yoffs = FLOAT2FIXED(xform.yOffs + xform.baseyOffs);
|
||||
fixed_t xscale = FLOAT2FIXED(xform.xScale);
|
||||
fixed_t yscale = FLOAT2FIXED(xform.yScale);
|
||||
const FTransform *xform = &xxform;
|
||||
fixed_t alpha = FLOAT2FIXED(Alpha);
|
||||
angle_t angle = (xform.Angle + xform.baseAngle).BAMs();
|
||||
//angle_t angle = (xform.Angle + xform.baseAngle).BAMs();
|
||||
|
||||
if (picnum == skyflatnum) // killough 10/98
|
||||
{ // most skies map together
|
||||
FTransform nulltransform;
|
||||
lightlevel = 0;
|
||||
xoffs = 0;
|
||||
yoffs = 0;
|
||||
xscale = 0;
|
||||
yscale = 0;
|
||||
angle = 0;
|
||||
alpha = 0;
|
||||
xform = &nulltransform;
|
||||
nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0;
|
||||
nulltransform.xScale = nulltransform.yScale = 1;
|
||||
nulltransform.Angle = nulltransform.baseAngle = 0.0;
|
||||
additive = false;
|
||||
// [RH] Map floor skies and ceiling skies to separate visplanes. This isn't
|
||||
// always necessary, but it is needed if a floor and ceiling sky are in the
|
||||
|
@ -656,13 +652,8 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
(plane == check->height &&
|
||||
picnum == check->picnum &&
|
||||
lightlevel == check->lightlevel &&
|
||||
|
||||
xoffs == check->xoffs && // killough 2/28/98: Add offset checks
|
||||
yoffs == check->yoffs &&
|
||||
basecolormap == check->colormap && // [RH] Add more checks
|
||||
xscale == check->xscale &&
|
||||
yscale == check->yscale &&
|
||||
angle == check->angle
|
||||
*xform == check->xform
|
||||
)
|
||||
) &&
|
||||
check->viewangle == stacked_angle
|
||||
|
@ -683,12 +674,8 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
if (plane == check->height &&
|
||||
picnum == check->picnum &&
|
||||
lightlevel == check->lightlevel &&
|
||||
xoffs == check->xoffs && // killough 2/28/98: Add offset checks
|
||||
yoffs == check->yoffs &&
|
||||
basecolormap == check->colormap && // [RH] Add more checks
|
||||
xscale == check->xscale &&
|
||||
yscale == check->yscale &&
|
||||
angle == check->angle &&
|
||||
*xform == check->xform &&
|
||||
sky == check->sky &&
|
||||
CurrentPortalUniq == check->CurrentPortalUniq &&
|
||||
MirrorFlags == check->MirrorFlags &&
|
||||
|
@ -705,11 +692,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
check->height = plane;
|
||||
check->picnum = picnum;
|
||||
check->lightlevel = lightlevel;
|
||||
check->xoffs = xoffs; // killough 2/28/98: Save offsets
|
||||
check->yoffs = yoffs;
|
||||
check->xscale = xscale;
|
||||
check->yscale = yscale;
|
||||
check->angle = angle;
|
||||
check->xform = *xform;
|
||||
check->colormap = basecolormap; // [RH] Save colormap
|
||||
check->sky = sky;
|
||||
check->portal = portal;
|
||||
|
@ -794,11 +777,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
|||
new_pl->height = pl->height;
|
||||
new_pl->picnum = pl->picnum;
|
||||
new_pl->lightlevel = pl->lightlevel;
|
||||
new_pl->xoffs = pl->xoffs; // killough 2/28/98
|
||||
new_pl->yoffs = pl->yoffs;
|
||||
new_pl->xscale = pl->xscale; // [RH] copy these, too
|
||||
new_pl->yscale = pl->yscale;
|
||||
new_pl->angle = pl->angle;
|
||||
new_pl->xform = pl->xform;
|
||||
new_pl->colormap = pl->colormap;
|
||||
new_pl->portal = pl->portal;
|
||||
new_pl->extralight = pl->extralight;
|
||||
|
@ -1117,8 +1096,8 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
masked = false;
|
||||
}
|
||||
R_SetupSpanBits(tex);
|
||||
pl->xscale = fixed_t(pl->xscale * tex->Scale.X);
|
||||
pl->yscale = fixed_t(pl->yscale * tex->Scale.Y);
|
||||
double xscale = pl->xform.xScale * tex->Scale.X;
|
||||
double yscale = pl->xform.yScale * tex->Scale.Y;
|
||||
ds_source = tex->GetPixels ();
|
||||
|
||||
basecolormap = pl->colormap;
|
||||
|
@ -1126,11 +1105,11 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
|
||||
if (r_drawflat || (!pl->height.isSlope() && !tilt))
|
||||
{
|
||||
R_DrawNormalPlane (pl, alpha, additive, masked);
|
||||
R_DrawNormalPlane(pl, xscale, yscale, alpha, additive, masked);
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawTiltedPlane (pl, alpha, additive, masked);
|
||||
R_DrawTiltedPlane(pl, xscale, yscale, alpha, additive, masked);
|
||||
}
|
||||
}
|
||||
NetUpdate ();
|
||||
|
@ -1502,7 +1481,7 @@ void R_DrawSkyPlane (visplane_t *pl)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked)
|
||||
void R_DrawNormalPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked)
|
||||
{
|
||||
#ifdef X86_ASM
|
||||
if (ds_source != ds_cursource)
|
||||
|
@ -1516,43 +1495,54 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
return;
|
||||
}
|
||||
|
||||
angle_t planeang = pl->angle;
|
||||
xscale = pl->xscale << (16 - ds_xbits);
|
||||
yscale = pl->yscale << (16 - ds_ybits);
|
||||
double planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
|
||||
double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac;
|
||||
double x;
|
||||
|
||||
xscale = xs_ToFixed(32 - ds_xbits, _xscale);
|
||||
yscale = xs_ToFixed(32 - ds_ybits, _yscale);
|
||||
if (planeang != 0)
|
||||
{
|
||||
double rad = planeang * (M_PI / ANGLE_180);
|
||||
double cosine = cos(rad), sine = sin(rad);
|
||||
|
||||
pviewx = xs_RoundToInt(pl->xoffs + FLOAT2FIXED(ViewPos.X * cosine - ViewPos.Y * sine));
|
||||
pviewy = xs_RoundToInt(pl->yoffs - FLOAT2FIXED(ViewPos.X * sine - ViewPos.Y * cosine));
|
||||
double cosine = cos(planeang), sine = sin(planeang);
|
||||
pviewx = FLOAT2FIXED(pl->xform.xOffs + ViewPos.X * cosine - ViewPos.Y * sine);
|
||||
pviewy = FLOAT2FIXED(pl->xform.yOffs - ViewPos.X * sine - ViewPos.Y * cosine);
|
||||
}
|
||||
else
|
||||
{
|
||||
pviewx = pl->xoffs + FLOAT2FIXED(ViewPos.X);
|
||||
pviewy = pl->yoffs - FLOAT2FIXED(ViewPos.Y);
|
||||
pviewx = FLOAT2FIXED(pl->xform.xOffs + ViewPos.X);
|
||||
pviewy = FLOAT2FIXED(pl->xform.yOffs - ViewPos.Y);
|
||||
}
|
||||
|
||||
pviewx = FixedMul (xscale, pviewx);
|
||||
pviewy = FixedMul (yscale, pviewy);
|
||||
|
||||
// left to right mapping
|
||||
planeang = (ViewAngle.BAMs() - ANG90 + planeang) >> ANGLETOFINESHIFT;
|
||||
planeang += (ViewAngle - 90).Radians();
|
||||
|
||||
// Scale will be unit scale at FocalLengthX (normally SCREENWIDTH/2) distance
|
||||
xstepscale = fixed_t(FixedMul(xscale, finecosine[planeang]) / FocalLengthX);
|
||||
ystepscale = fixed_t(FixedMul(yscale, -finesine[planeang]) / FocalLengthX);
|
||||
xstep = cos(planeang) / FocalLengthX;
|
||||
ystep = -sin(planeang) / FocalLengthX;
|
||||
|
||||
// [RH] flip for mirrors
|
||||
if (MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
xstepscale = (DWORD)(-(SDWORD)xstepscale);
|
||||
ystepscale = (DWORD)(-(SDWORD)ystepscale);
|
||||
xstep = -xstep;
|
||||
ystep = -ystep;
|
||||
}
|
||||
|
||||
int x = pl->right - halfviewwidth - 1;
|
||||
planeang = (planeang + (ANG90 >> ANGLETOFINESHIFT)) & FINEMASK;
|
||||
basexfrac = FixedMul (xscale, finecosine[planeang]) + x*xstepscale;
|
||||
baseyfrac = FixedMul (yscale, -finesine[planeang]) + x*ystepscale;
|
||||
planeang += M_PI/2;
|
||||
double cosine = cos(planeang), sine = -sin(planeang);
|
||||
x = pl->right - centerx - 0.5;
|
||||
rightxfrac = _xscale * (cosine + x * xstep);
|
||||
rightyfrac = _yscale * (sine + x * ystep);
|
||||
x = pl->left - centerx - 0.5;
|
||||
leftxfrac = _xscale * (cosine + x * xstep);
|
||||
leftyfrac = _yscale * (sine + x * ystep);
|
||||
|
||||
basexfrac = rightxfrac;
|
||||
baseyfrac = rightyfrac;
|
||||
xstepscale = (rightxfrac - leftxfrac) / (pl->right - pl->left);
|
||||
ystepscale = (rightyfrac - leftyfrac) / (pl->right - pl->left);
|
||||
|
||||
planeheight = fabs(pl->height.Zat0() - ViewPos.Z);
|
||||
|
||||
|
@ -1620,7 +1610,7 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked)
|
||||
void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t alpha, bool additive, bool masked)
|
||||
{
|
||||
static const float ifloatpow2[16] =
|
||||
{
|
||||
|
@ -1634,7 +1624,7 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
double lxscale, lyscale;
|
||||
double xscale, yscale;
|
||||
FVector3 p, m, n;
|
||||
double ang;
|
||||
double ang, planeang, cosine, sine;
|
||||
double zeroheight;
|
||||
|
||||
if (alpha <= 0)
|
||||
|
@ -1642,44 +1632,52 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
return;
|
||||
}
|
||||
|
||||
lxscale = FIXED2DBL(pl->xscale) * ifloatpow2[ds_xbits];
|
||||
lyscale = FIXED2DBL(pl->yscale) * ifloatpow2[ds_ybits];
|
||||
lxscale = _xscale * ifloatpow2[ds_xbits];
|
||||
lyscale = _yscale * ifloatpow2[ds_ybits];
|
||||
xscale = 64.f / lxscale;
|
||||
yscale = 64.f / lyscale;
|
||||
zeroheight = pl->height.ZatPoint(ViewPos);
|
||||
|
||||
pviewx = MulScale (pl->xoffs, pl->xscale, ds_xbits);
|
||||
pviewy = MulScale (pl->yoffs, pl->yscale, ds_ybits);
|
||||
pviewx = xs_ToFixed(32 - ds_xbits, pl->xform.xOffs * pl->xform.xScale);
|
||||
pviewy = xs_ToFixed(32 - ds_ybits, pl->xform.yOffs * pl->xform.yScale);
|
||||
planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
|
||||
|
||||
// p is the texture origin in view space
|
||||
// Don't add in the offsets at this stage, because doing so can result in
|
||||
// errors if the flat is rotated.
|
||||
ang = (DAngle(270.) - ViewAngle).Radians();
|
||||
p[0] = ViewPos.X * cos(ang) - ViewPos.Y * sin(ang);
|
||||
p[2] = ViewPos.X * sin(ang) + ViewPos.Y * cos(ang);
|
||||
ang = M_PI*3/2 - ViewAngle.Radians();
|
||||
cosine = cos(ang), sine = sin(ang);
|
||||
p[0] = ViewPos.X * cosine - ViewPos.Y * sine;
|
||||
p[2] = ViewPos.X * sine + ViewPos.Y * cosine;
|
||||
p[1] = pl->height.ZatPoint(0.0, 0.0) - ViewPos.Z;
|
||||
|
||||
// m is the v direction vector in view space
|
||||
ang = (DAngle(180.) - ViewAngle).Radians();
|
||||
m[0] = yscale * cos(ang);
|
||||
m[2] = yscale * sin(ang);
|
||||
ang = ang - M_PI / 2 - planeang;
|
||||
cosine = cos(ang), sine = sin(ang);
|
||||
m[0] = yscale * cosine;
|
||||
m[2] = yscale * sine;
|
||||
// m[1] = pl->height.ZatPointF (0, iyscale) - pl->height.ZatPointF (0,0));
|
||||
// VectorScale2 (m, 64.f/VectorLength(m));
|
||||
|
||||
// n is the u direction vector in view space
|
||||
ang += PI/2;
|
||||
#if 0
|
||||
//let's use the sin/cosine we already know instead of computing new ones
|
||||
ang += M_PI/2
|
||||
n[0] = -xscale * cos(ang);
|
||||
n[2] = -xscale * sin(ang);
|
||||
#else
|
||||
n[0] = xscale * sine;
|
||||
n[2] = -xscale * cosine;
|
||||
#endif
|
||||
// n[1] = pl->height.ZatPointF (ixscale, 0) - pl->height.ZatPointF (0,0));
|
||||
// VectorScale2 (n, 64.f/VectorLength(n));
|
||||
|
||||
// This code keeps the texture coordinates constant across the x,y plane no matter
|
||||
// how much you slope the surface. Use the commented-out code above instead to keep
|
||||
// the textures a constant size across the surface's plane instead.
|
||||
ang = pl->angle * (M_PI / ANGLE_180);
|
||||
m[1] = pl->height.ZatPoint(ViewPos.X + yscale * sin(ang), ViewPos.Y + yscale * cos(ang)) - zeroheight;
|
||||
ang += PI/2;
|
||||
n[1] = pl->height.ZatPoint(ViewPos.X + xscale * sin(ang), ViewPos.Y + xscale * cos(ang)) - zeroheight;
|
||||
cosine = cos(planeang), sine = sin(planeang);
|
||||
m[1] = pl->height.ZatPoint(ViewPos.X + yscale * sine, ViewPos.Y + yscale * cosine) - zeroheight;
|
||||
n[1] = pl->height.ZatPoint(ViewPos.X - xscale * cosine, ViewPos.Y + xscale * sine) - zeroheight;
|
||||
|
||||
plane_su = p ^ m;
|
||||
plane_sv = p ^ n;
|
||||
|
|
|
@ -34,16 +34,15 @@ struct visplane_s
|
|||
{
|
||||
struct visplane_s *next; // Next visplane in hash chain -- killough
|
||||
|
||||
FDynamicColormap *colormap; // [RH] Support multiple colormaps
|
||||
FSectorPortal *portal; // [RH] Support sky boxes
|
||||
|
||||
FTransform xform;
|
||||
secplane_t height;
|
||||
FTextureID picnum;
|
||||
int lightlevel;
|
||||
fixed_t xoffs, yoffs; // killough 2/28/98: Support scrolling flats
|
||||
int left, right;
|
||||
FDynamicColormap *colormap; // [RH] Support multiple colormaps
|
||||
fixed_t xscale, yscale; // [RH] Support flat scaling
|
||||
angle_t angle; // [RH] Support flat rotation
|
||||
int sky;
|
||||
FSectorPortal *portal; // [RH] Support sky boxes
|
||||
|
||||
// [RH] This set of variables copies information from the time when the
|
||||
// visplane is created. They are only used by stacks so that you can
|
||||
|
@ -81,7 +80,7 @@ extern planefunction_t ceilingfunc_t;
|
|||
extern short floorclip[MAXWIDTH];
|
||||
extern short ceilingclip[MAXWIDTH];
|
||||
|
||||
extern fixed_t yslope[MAXHEIGHT];
|
||||
extern float yslope[MAXHEIGHT];
|
||||
|
||||
void R_InitPlanes ();
|
||||
void R_DeinitPlanes ();
|
||||
|
@ -90,8 +89,8 @@ void R_ClearPlanes (bool fullclear);
|
|||
int R_DrawPlanes ();
|
||||
void R_DrawPortals ();
|
||||
void R_DrawSkyPlane (visplane_t *pl);
|
||||
void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
||||
void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
||||
void R_DrawNormalPlane (visplane_t *pl, double xscale, double yscale, fixed_t alpha, bool additive, bool masked);
|
||||
void R_DrawTiltedPlane (visplane_t *pl, double xscale, double yscale, fixed_t alpha, bool additive, bool masked);
|
||||
void R_MapVisPlane (visplane_t *pl, void (*mapfunc)(int y, int x1));
|
||||
|
||||
visplane_t *R_FindPlane
|
||||
|
|
|
@ -28,7 +28,7 @@ struct FRenderer
|
|||
virtual bool UsesColormap() const = 0;
|
||||
|
||||
// precache one texture
|
||||
virtual void PrecacheTexture(FTexture *tex, int cache) = 0;
|
||||
virtual void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist) = 0;
|
||||
|
||||
// render 3D view
|
||||
virtual void RenderView(player_t *player) = 0;
|
||||
|
|
157
src/r_segs.cpp
157
src/r_segs.cpp
|
@ -231,6 +231,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
double texheight, texheightscale;
|
||||
bool notrelevant = false;
|
||||
double rowoffset;
|
||||
bool wrap = false;
|
||||
|
||||
const sector_t *sec;
|
||||
|
||||
|
@ -334,8 +335,8 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
|
||||
rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid);
|
||||
|
||||
if (!(curline->linedef->flags & ML_WRAP_MIDTEX) &&
|
||||
!(curline->sidedef->Flags & WALLF_WRAP_MIDTEX))
|
||||
wrap = (curline->linedef->flags & ML_WRAP_MIDTEX) || (curline->sidedef->Flags & WALLF_WRAP_MIDTEX);
|
||||
if (!wrap)
|
||||
{ // Texture does not wrap vertically.
|
||||
double textop;
|
||||
|
||||
|
@ -482,7 +483,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
{
|
||||
// rowoffset is added before the multiply so that the masked texture will
|
||||
// still be positioned in world units rather than texels.
|
||||
dc_texturemid = (dc_texturemid + rowoffset - ViewPos.Z) * MaskedScaleY;
|
||||
dc_texturemid = (dc_texturemid - ViewPos.Z + rowoffset) * MaskedScaleY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -543,8 +544,11 @@ clearfog:
|
|||
{
|
||||
if (fake3D & FAKE3D_REFRESHCLIP)
|
||||
{
|
||||
assert(ds->bkup >= 0);
|
||||
memcpy(openings + ds->sprtopclip, openings + ds->bkup, (ds->x2 - ds->x1) * 2);
|
||||
if (!wrap)
|
||||
{
|
||||
assert(ds->bkup >= 0);
|
||||
memcpy(openings + ds->sprtopclip, openings + ds->bkup, (ds->x2 - ds->x1) * 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -558,7 +562,7 @@ clearfog:
|
|||
void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
|
||||
{
|
||||
int i;
|
||||
fixed_t xscale;
|
||||
double xscale;
|
||||
double yscale;
|
||||
|
||||
fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255);
|
||||
|
@ -599,7 +603,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
|
|||
scaledside = rover->master->sidedef[0];
|
||||
scaledpart = side_t::mid;
|
||||
}
|
||||
xscale = FLOAT2FIXED(rw_pic->Scale.X * scaledside->GetTextureXScale(scaledpart));
|
||||
xscale = rw_pic->Scale.X * scaledside->GetTextureXScale(scaledpart);
|
||||
yscale = rw_pic->Scale.Y * scaledside->GetTextureYScale(scaledpart);
|
||||
|
||||
double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid);
|
||||
|
@ -616,7 +620,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
|
|||
// still be positioned in world units rather than texels.
|
||||
|
||||
dc_texturemid = dc_texturemid + rowoffset * yscale;
|
||||
rw_offset = MulScale16 (rw_offset, xscale);
|
||||
rw_offset = xs_RoundToInt(rw_offset * xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -666,8 +670,8 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
|
|||
int i,j;
|
||||
F3DFloor *rover, *fover = NULL;
|
||||
int passed, last;
|
||||
fixed_t floorheight;
|
||||
fixed_t ceilingheight;
|
||||
double floorHeight;
|
||||
double ceilingHeight;
|
||||
|
||||
sprflipvert = false;
|
||||
curline = ds->curline;
|
||||
|
@ -686,16 +690,16 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
|
|||
frontsector = sec;
|
||||
}
|
||||
|
||||
floorheight = FLOAT2FIXED(backsector->CenterFloor());
|
||||
ceilingheight = FLOAT2FIXED(backsector->CenterCeiling());
|
||||
floorHeight = backsector->CenterFloor();
|
||||
ceilingHeight = backsector->CenterCeiling();
|
||||
|
||||
// maybe fix clipheights
|
||||
if (!(fake3D & FAKE3D_CLIPBOTTOM)) sclipBottom = floorheight;
|
||||
if (!(fake3D & FAKE3D_CLIPTOP)) sclipTop = ceilingheight;
|
||||
if (!(fake3D & FAKE3D_CLIPBOTTOM)) sclipBottom = floorHeight;
|
||||
if (!(fake3D & FAKE3D_CLIPTOP)) sclipTop = ceilingHeight;
|
||||
|
||||
// maybe not visible
|
||||
if (sclipBottom >= FLOAT2FIXED(frontsector->CenterCeiling())) return;
|
||||
if (sclipTop <= FLOAT2FIXED(frontsector->CenterFloor())) return;
|
||||
if (sclipBottom >= frontsector->CenterCeiling()) return;
|
||||
if (sclipTop <= frontsector->CenterFloor()) return;
|
||||
|
||||
if (fake3D & FAKE3D_DOWN2UP)
|
||||
{ // bottom to viewz
|
||||
|
@ -709,8 +713,8 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
|
|||
passed = 0;
|
||||
if (!(rover->flags & FF_RENDERSIDES) || rover->top.plane->isSlope() || rover->bottom.plane->isSlope() ||
|
||||
rover->top.plane->Zat0() <= sclipBottom ||
|
||||
rover->bottom.plane->Zat0() >= ceilingheight ||
|
||||
rover->top.plane->Zat0() <= floorheight)
|
||||
rover->bottom.plane->Zat0() >= ceilingHeight ||
|
||||
rover->top.plane->Zat0() <= floorHeight)
|
||||
{
|
||||
if (!i)
|
||||
{
|
||||
|
@ -892,8 +896,8 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
|
|||
if (!(rover->flags & FF_RENDERSIDES) ||
|
||||
rover->top.plane->isSlope() || rover->bottom.plane->isSlope() ||
|
||||
rover->bottom.plane->Zat0() >= sclipTop ||
|
||||
rover->top.plane->Zat0() <= floorheight ||
|
||||
rover->bottom.plane->Zat0() >= ceilingheight)
|
||||
rover->top.plane->Zat0() <= floorHeight ||
|
||||
rover->bottom.plane->Zat0() >= ceilingHeight)
|
||||
{
|
||||
if ((unsigned)i == backsector->e->XFloor.ffloors.Size() - 1)
|
||||
{
|
||||
|
@ -1134,7 +1138,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *l
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
dovline1();
|
||||
}
|
||||
|
@ -1153,7 +1157,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *l
|
|||
bufplce[z] = getcol (rw_pic, (lwal[x+z] + xoffset) >> FRACBITS);
|
||||
iscale = swal[x + z] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 1));
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
{
|
||||
|
@ -1229,7 +1233,7 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *l
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
dovline1();
|
||||
}
|
||||
|
@ -1484,7 +1488,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
domvline1();
|
||||
}
|
||||
|
@ -1501,7 +1505,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_
|
|||
bufplce[z] = getcol (rw_pic, (lwal[dax] + xoffset) >> FRACBITS);
|
||||
iscale = swal[dax] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 1));
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
{
|
||||
|
@ -1575,7 +1579,7 @@ void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
domvline1();
|
||||
}
|
||||
|
@ -1660,7 +1664,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, f
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
tmvline1();
|
||||
}
|
||||
|
@ -1677,7 +1681,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, f
|
|||
bufplce[z] = getcol (rw_pic, (lwal[dax] + xoffset) >> FRACBITS);
|
||||
iscale = swal[dax] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + vince[z] * (y1ve[z] - CenterY + 1));
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + vince[z] * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
{
|
||||
|
@ -1754,7 +1758,7 @@ void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, f
|
|||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 1));
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
tmvline1();
|
||||
}
|
||||
|
@ -2012,9 +2016,9 @@ void R_NewWall (bool needlights)
|
|||
midtexture = toptexture = bottomtexture = 0;
|
||||
|
||||
if (sidedef == linedef->sidedef[0] &&
|
||||
(linedef->isVisualPortal() || (linedef->special == Line_Mirror && r_drawmirrors))) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals
|
||||
(linedef->special == Line_Mirror && r_drawmirrors)) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals
|
||||
{
|
||||
markfloor = markceiling = true; // act like an one-sided wall here (todo: check how does this work with transparency)
|
||||
markfloor = markceiling = true; // act like a one-sided wall here (todo: check how does this work with transparency)
|
||||
rw_markportal = true;
|
||||
}
|
||||
else if (backsector == NULL)
|
||||
|
@ -2023,7 +2027,11 @@ void R_NewWall (bool needlights)
|
|||
// a single sided line is terminal, so it must mark ends
|
||||
markfloor = markceiling = true;
|
||||
// [RH] Horizon lines do not need to be textured
|
||||
if (linedef->special != Line_Horizon)
|
||||
if (linedef->isVisualPortal())
|
||||
{
|
||||
rw_markportal = true;
|
||||
}
|
||||
else if (linedef->special != Line_Horizon)
|
||||
{
|
||||
midtexture = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||
rw_offset_mid = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||
|
@ -2098,8 +2106,12 @@ void R_NewWall (bool needlights)
|
|||
rw_frontlowertop = backsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
|
||||
if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
|
||||
(rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2))
|
||||
if (linedef->isVisualPortal())
|
||||
{
|
||||
markceiling = markfloor = true;
|
||||
}
|
||||
else if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) ||
|
||||
(rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2))
|
||||
{
|
||||
// closed door
|
||||
markceiling = markfloor = true;
|
||||
|
@ -2256,6 +2268,7 @@ void R_NewWall (bool needlights)
|
|||
rw_bottomtexturemid += rowoffset;
|
||||
}
|
||||
}
|
||||
rw_markportal = linedef->isVisualPortal();
|
||||
}
|
||||
|
||||
// if a floor / ceiling plane is on the wrong side of the view plane,
|
||||
|
@ -2670,53 +2683,50 @@ int OWallMost (short *mostbuf, double z, const FWallCoords *wallc)
|
|||
s3 = globaldclip * wallc->sz1; s4 = globaldclip * wallc->sz2;
|
||||
bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
|
||||
|
||||
#if 1
|
||||
if ((bad&3) == 3)
|
||||
{
|
||||
{ // entire line is above the screen
|
||||
memset (&mostbuf[wallc->sx1], 0, (wallc->sx2 - wallc->sx1)*sizeof(mostbuf[0]));
|
||||
return bad;
|
||||
}
|
||||
|
||||
if ((bad&12) == 12)
|
||||
{
|
||||
{ // entire line is below the screen
|
||||
clearbufshort (&mostbuf[wallc->sx1], wallc->sx2 - wallc->sx1, viewheight);
|
||||
return bad;
|
||||
}
|
||||
#endif
|
||||
ix1 = wallc->sx1; iy1 = wallc->sz1;
|
||||
ix2 = wallc->sx2; iy2 = wallc->sz2;
|
||||
#if 1
|
||||
if (bad & 3)
|
||||
{
|
||||
{ // the line intersects the top of the screen
|
||||
double t = (z-s1) / (s2-s1);
|
||||
double inty = wallc->sz1 + t * (wallc->sz2 - wallc->sz1);
|
||||
int xcross = xs_RoundToInt(wallc->sx1 + (t * wallc->sz2 * (wallc->sx2 - wallc->sx1)) / inty);
|
||||
|
||||
if ((bad & 3) == 2)
|
||||
{
|
||||
{ // the right side is above the screen
|
||||
if (wallc->sx1 <= xcross) { iy2 = inty; ix2 = xcross; }
|
||||
if (wallc->sx2 > xcross) memset (&mostbuf[xcross], 0, (wallc->sx2-xcross)*sizeof(mostbuf[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
{ // the left side is above the screen
|
||||
if (xcross <= wallc->sx2) { iy1 = inty; ix1 = xcross; }
|
||||
if (xcross > wallc->sx1) memset (&mostbuf[wallc->sx1], 0, (xcross-wallc->sx1)*sizeof(mostbuf[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if (bad & 12)
|
||||
{
|
||||
{ // the line intersects the bottom of the screen
|
||||
double t = (z-s3) / (s4-s3);
|
||||
double inty = wallc->sz1 + t * (wallc->sz2 - wallc->sz1);
|
||||
int xcross = xs_RoundToInt(wallc->sx1 + (t * wallc->sz2 * (wallc->sx2 - wallc->sx1)) / inty);
|
||||
|
||||
if ((bad & 12) == 8)
|
||||
{
|
||||
{ // the right side is below the screen
|
||||
if (wallc->sx1 <= xcross) { iy2 = inty; ix2 = xcross; }
|
||||
if (wallc->sx2 > xcross) clearbufshort (&mostbuf[xcross], wallc->sx2 - xcross, viewheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
{ // the left side is below the screen
|
||||
if (xcross <= wallc->sx2) { iy1 = inty; ix1 = xcross; }
|
||||
if (xcross > wallc->sx1) clearbufshort (&mostbuf[wallc->sx1], xcross - wallc->sx1, viewheight);
|
||||
}
|
||||
|
@ -2730,40 +2740,8 @@ int OWallMost (short *mostbuf, double z, const FWallCoords *wallc)
|
|||
else
|
||||
{
|
||||
fixed_t yinc = FLOAT2FIXED(((z * InvZtoScale / iy2) - y) / (ix2 - ix1));
|
||||
qinterpolatedown16short (&mostbuf[ix1], ix2-ix1, FLOAT2FIXED(y + CenterY), yinc);
|
||||
qinterpolatedown16short (&mostbuf[ix1], ix2-ix1, FLOAT2FIXED(y + CenterY) + FRACUNIT/2, yinc);
|
||||
}
|
||||
#else
|
||||
double max = viewheight;
|
||||
double zz = z / 65536.0;
|
||||
#if 0
|
||||
double z1 = zz * InvZtoScale / wallc->sz1;
|
||||
double z2 = zz * InvZtoScale / wallc->sz2 - z1;
|
||||
z2 /= (wallc->sx2 - wallc->sx1);
|
||||
z1 += centeryfrac / 65536.0;
|
||||
|
||||
for (int x = wallc->sx1; x < wallc->sx2; ++x)
|
||||
{
|
||||
mostbuf[x] = xs_RoundToInt(clamp(z1, 0.0, max));
|
||||
z1 += z2;
|
||||
}
|
||||
#else
|
||||
double top, bot, i;
|
||||
|
||||
i = wallc->sx1 - centerx;
|
||||
top = WallT.UoverZorg + WallT.UoverZstep * i;
|
||||
bot = WallT.InvZorg + WallT.InvZstep * i;
|
||||
double cy = centeryfrac / 65536.0;
|
||||
|
||||
for (int x = wallc->sx1; x < wallc->sx2; x++)
|
||||
{
|
||||
double frac = top / bot;
|
||||
double scale = frac * WallT.DepthScale + WallT.DepthOrg;
|
||||
mostbuf[x] = xs_RoundToInt(clamp(zz / scale + cy, 0.0, max));
|
||||
top += WallT.UoverZstep;
|
||||
bot += WallT.InvZstep;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return bad;
|
||||
}
|
||||
|
||||
|
@ -2779,6 +2757,7 @@ int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc)
|
|||
int bad, ix1, ix2;
|
||||
double iy1, iy2;
|
||||
|
||||
// Get Z coordinates at both ends of the line
|
||||
if (MirrorFlags & RF_XFLIP)
|
||||
{
|
||||
x = curline->v2->fX();
|
||||
|
@ -2847,20 +2826,20 @@ int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc)
|
|||
oz1 = z1; oz2 = z2;
|
||||
|
||||
if ((bad&3) == 3)
|
||||
{
|
||||
memset (&mostbuf[ix1], -1, (ix2-ix1)*sizeof(mostbuf[0]));
|
||||
{ // The entire line is above the screen
|
||||
memset (&mostbuf[ix1], 0, (ix2-ix1)*sizeof(mostbuf[0]));
|
||||
return bad;
|
||||
}
|
||||
|
||||
if ((bad&12) == 12)
|
||||
{
|
||||
{ // The entire line is below the screen
|
||||
clearbufshort (&mostbuf[ix1], ix2-ix1, viewheight);
|
||||
return bad;
|
||||
|
||||
}
|
||||
|
||||
if (bad&3)
|
||||
{
|
||||
{ // The line intersects the top of the screen
|
||||
//inty = intz / (globaluclip>>16)
|
||||
double t = (oz1-s1) / (s2-s1+oz1-oz2);
|
||||
double inty = wallc->sz1 + t * (wallc->sz2-wallc->sz1);
|
||||
|
@ -2872,19 +2851,19 @@ int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc)
|
|||
//intz = z1 + mulscale30(z2-z1,t);
|
||||
|
||||
if ((bad&3) == 2)
|
||||
{
|
||||
{ // The right side of the line is above the screen
|
||||
if (wallc->sx1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
|
||||
memset (&mostbuf[xcross], 0, (wallc->sx2-xcross)*sizeof(mostbuf[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
{ // The left side of the line is above the screen
|
||||
if (xcross <= wallc->sx2) { z1 = intz; iy1 = inty; ix1 = xcross; }
|
||||
memset (&mostbuf[wallc->sx1], 0, (xcross-wallc->sx1)*sizeof(mostbuf[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if (bad&12)
|
||||
{
|
||||
{ // The line intersects the bottom of the screen
|
||||
//inty = intz / (globaldclip>>16)
|
||||
double t = (oz1-s3) / (s4-s3+oz1-oz2);
|
||||
double inty = wallc->sz1 + t * (wallc->sz2-wallc->sz1);
|
||||
|
@ -2896,12 +2875,12 @@ int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc)
|
|||
//intz = z1 + mulscale30(z2-z1,t);
|
||||
|
||||
if ((bad&12) == 8)
|
||||
{
|
||||
{ // The right side of the line is below the screen
|
||||
if (wallc->sx1 <= xcross) { z2 = intz; iy2 = inty; ix2 = xcross; }
|
||||
if (wallc->sx2 > xcross) clearbufshort (&mostbuf[xcross], wallc->sx2-xcross, viewheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
{ // The left side of the line is below the screen
|
||||
if (xcross <= wallc->sx2) { z1 = intz; iy1 = inty; ix1 = xcross; }
|
||||
if (xcross > wallc->sx1) clearbufshort (&mostbuf[wallc->sx1], xcross-wallc->sx1, viewheight);
|
||||
}
|
||||
|
@ -2910,12 +2889,12 @@ int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc)
|
|||
y = z1 * InvZtoScale / iy1;
|
||||
if (ix2 == ix1)
|
||||
{
|
||||
mostbuf[ix1] = (short)xs_RoundToInt(y/65536.0 + CenterY);
|
||||
mostbuf[ix1] = (short)xs_RoundToInt(y + CenterY);
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_t yinc = FLOAT2FIXED(((z2 * InvZtoScale / iy2) - y) / (ix2-ix1));
|
||||
qinterpolatedown16short (&mostbuf[ix1], ix2-ix1, FLOAT2FIXED(y/65536.0 + CenterY), yinc);
|
||||
qinterpolatedown16short (&mostbuf[ix1], ix2-ix1, FLOAT2FIXED(y + CenterY) + FRACUNIT/2, yinc);
|
||||
}
|
||||
|
||||
return bad;
|
||||
|
|
|
@ -115,8 +115,8 @@ void R_InitSkyMap ()
|
|||
skyiscale = float(r_Yaspect / freelookviewheight);
|
||||
skyscale = freelookviewheight / r_Yaspect;
|
||||
|
||||
skyiscale *= FieldOfView / 2048.f;
|
||||
skyscale *= 2048.0 / FieldOfView;
|
||||
skyiscale *= float(FieldOfView.Degrees / 90.);
|
||||
skyscale *= float(90. / FieldOfView.Degrees);
|
||||
}
|
||||
|
||||
if (skystretch)
|
||||
|
|
|
@ -82,7 +82,7 @@ extern AActor* camera; // [RH] camera instead of viewplayer
|
|||
extern sector_t* viewsector; // [RH] keep track of sector viewing from
|
||||
|
||||
extern angle_t xtoviewangle[MAXWIDTH+1];
|
||||
extern int FieldOfView;
|
||||
extern DAngle FieldOfView;
|
||||
|
||||
int R_FindSkin (const char *name, int pclass); // [RH] Find a skin
|
||||
|
||||
|
|
|
@ -50,8 +50,6 @@ void R_SetupColormap(player_t *);
|
|||
void R_SetupFreelook();
|
||||
void R_InitRenderer();
|
||||
|
||||
extern float LastFOV;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DCanvas :: Init
|
||||
|
@ -100,6 +98,55 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache)
|
|||
}
|
||||
}
|
||||
|
||||
void FSoftwareRenderer::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist)
|
||||
{
|
||||
BYTE *spritelist = new BYTE[sprites.Size()];
|
||||
TMap<PClassActor*, bool>::Iterator it(actorhitlist);
|
||||
TMap<PClassActor*, bool>::Pair *pair;
|
||||
|
||||
memset(spritelist, 0, sprites.Size());
|
||||
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
PClassActor *cls = pair->Key;
|
||||
|
||||
for (int i = 0; i < cls->NumOwnedStates; i++)
|
||||
{
|
||||
spritelist[cls->OwnedStates[i].sprite] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Precache textures (and sprites).
|
||||
|
||||
for (int i = (int)(sprites.Size() - 1); i >= 0; i--)
|
||||
{
|
||||
if (spritelist[i])
|
||||
{
|
||||
int j, k;
|
||||
for (j = 0; j < sprites[i].numframes; j++)
|
||||
{
|
||||
const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j];
|
||||
|
||||
for (k = 0; k < 16; k++)
|
||||
{
|
||||
FTextureID pic = frame->Texture[k];
|
||||
if (pic.isValid())
|
||||
{
|
||||
texhitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] spritelist;
|
||||
|
||||
int cnt = TexMan.NumTextures();
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Render the view
|
||||
|
@ -272,8 +319,8 @@ void FSoftwareRenderer::RenderTextureView (FCanvasTexture *tex, AActor *viewpoin
|
|||
unsigned char *savecolormap = fixedcolormap;
|
||||
FSpecialColormap *savecm = realfixedcolormap;
|
||||
|
||||
float savedfov = LastFOV;
|
||||
R_SetFOV ((float)fov);
|
||||
DAngle savedfov = FieldOfView;
|
||||
R_SetFOV ((double)fov);
|
||||
R_RenderViewToCanvas (viewpoint, Canvas, 0, 0, tex->GetWidth(), tex->GetHeight(), tex->bFirstUpdate);
|
||||
R_SetFOV (savedfov);
|
||||
if (Pixels == Canvas->GetBuffer())
|
||||
|
|
|
@ -9,7 +9,8 @@ struct FSoftwareRenderer : public FRenderer
|
|||
virtual bool UsesColormap() const;
|
||||
|
||||
// precache one texture
|
||||
virtual void PrecacheTexture(FTexture *tex, int cache);
|
||||
void PrecacheTexture(FTexture *tex, int cache);
|
||||
virtual void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist);
|
||||
|
||||
// render 3D view
|
||||
virtual void RenderView(player_t *player);
|
||||
|
|
|
@ -678,7 +678,7 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop
|
|||
}
|
||||
|
||||
// Render the voxel, either directly to the screen or offscreen.
|
||||
R_DrawVoxel(spr->pa.vpos, spr->pa.vang, spr->gpos, spr->angle,
|
||||
R_DrawVoxel(spr->pa.vpos, spr->pa.vang, spr->gpos, spr->Angle,
|
||||
spr->xscale, FLOAT2FIXED(spr->yscale), spr->voxel, spr->Style.colormap, cliptop, clipbot,
|
||||
minslabz, maxslabz, flags);
|
||||
|
||||
|
@ -994,7 +994,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
vis->texturemid = tex->TopOffset - (ViewPos.Z - pos.Z + thing->Floorclip) / yscale;
|
||||
vis->x1 = x1 < WindowLeft ? WindowLeft : x1;
|
||||
vis->x2 = x2 > WindowRight ? WindowRight : x2;
|
||||
vis->angle = thing->Angles.Yaw.BAMs();
|
||||
vis->Angle = thing->Angles.Yaw;
|
||||
|
||||
if (renderflags & RF_XFLIP)
|
||||
{
|
||||
|
@ -1024,13 +1024,13 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
|
||||
pos.Z -= thing->Floorclip;
|
||||
|
||||
vis->angle = thing->Angles.Yaw.BAMs() + voxel->AngleOffset.BAMs();
|
||||
vis->Angle = thing->Angles.Yaw + voxel->AngleOffset;
|
||||
|
||||
int voxelspin = (thing->flags & MF_DROPPED) ? voxel->DroppedSpin : voxel->PlacedSpin;
|
||||
if (voxelspin != 0)
|
||||
{
|
||||
DAngle ang = double(I_FPSTime()) * voxelspin / 1000;
|
||||
vis->angle -= ang.BAMs();
|
||||
vis->Angle -= ang;
|
||||
}
|
||||
|
||||
vis->pa.vpos = { (float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z };
|
||||
|
@ -2664,7 +2664,7 @@ void R_DrawParticle (vissprite_t *vis)
|
|||
extern double BaseYaspectMul;;
|
||||
|
||||
void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle,
|
||||
const FVector3 &dasprpos, angle_t dasprang,
|
||||
const FVector3 &dasprpos, DAngle dasprang,
|
||||
fixed_t daxscale, fixed_t dayscale, FVoxel *voxobj,
|
||||
lighttable_t *colormap, short *daumost, short *dadmost, int minslabz, int maxslabz, int flags)
|
||||
{
|
||||
|
@ -2698,10 +2698,10 @@ void R_DrawVoxel(const FVector3 &globalpos, FAngle viewangle,
|
|||
dayscale = dayscale / (0xC000 >> 6);
|
||||
|
||||
angle_t viewang = viewangle.BAMs();
|
||||
cosang = finecosine[viewang >> ANGLETOFINESHIFT] >> 2;
|
||||
sinang = -finesine[viewang >> ANGLETOFINESHIFT] >> 2;
|
||||
sprcosang = finecosine[dasprang >> ANGLETOFINESHIFT] >> 2;
|
||||
sprsinang = -finesine[dasprang >> ANGLETOFINESHIFT] >> 2;
|
||||
cosang = FLOAT2FIXED(viewangle.Cos()) >> 2;
|
||||
sinang = FLOAT2FIXED(-viewangle.Sin()) >> 2;
|
||||
sprcosang = FLOAT2FIXED(dasprang.Cos()) >> 2;
|
||||
sprsinang = FLOAT2FIXED(-dasprang.Sin()) >> 2;
|
||||
|
||||
R_SetupDrawSlab(colormap);
|
||||
|
||||
|
|
|
@ -41,10 +41,16 @@ struct vissprite_t
|
|||
FVector3 gpos; // origin in world coordinates
|
||||
union
|
||||
{
|
||||
float gzb, gzt; // global bottom / top for silhouette clipping
|
||||
int y1, y2; // top / bottom of particle on screen
|
||||
struct
|
||||
{
|
||||
float gzb, gzt; // global bottom / top for silhouette clipping
|
||||
};
|
||||
struct
|
||||
{
|
||||
int y1, y2; // top / bottom of particle on screen
|
||||
};
|
||||
};
|
||||
angle_t angle;
|
||||
DAngle Angle;
|
||||
fixed_t xscale;
|
||||
float yscale;
|
||||
float depth;
|
||||
|
@ -135,7 +141,7 @@ void R_CheckOffscreenBuffer(int width, int height, bool spansonly);
|
|||
enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2, DVF_MIRRORED = 4 };
|
||||
|
||||
void R_DrawVoxel(const FVector3 &viewpos, FAngle viewangle,
|
||||
const FVector3 &sprpos, angle_t dasprang,
|
||||
const FVector3 &sprpos, DAngle dasprang,
|
||||
fixed_t daxscale, fixed_t dayscale, struct FVoxel *voxobj,
|
||||
lighttable_t *colormap, short *daumost, short *dadmost, int minslabz, int maxslabz, int flags);
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ int viewwindowy;
|
|||
DVector3 ViewPos;
|
||||
DAngle ViewAngle;
|
||||
DAngle ViewPitch;
|
||||
DAngle ViewRoll;
|
||||
DVector3 ViewPath[2];
|
||||
|
||||
extern "C"
|
||||
|
@ -137,7 +138,6 @@ angle_t LocalViewAngle;
|
|||
int LocalViewPitch;
|
||||
bool LocalKeyboardTurner;
|
||||
|
||||
float LastFOV;
|
||||
int WidescreenRatio;
|
||||
int setblocks;
|
||||
int extralight;
|
||||
|
@ -146,7 +146,7 @@ double FocalTangent;
|
|||
|
||||
unsigned int R_OldBlend = ~0;
|
||||
int validcount = 1; // increment every time a check is made
|
||||
int FieldOfView = 2048; // Fineangles in the SCREENWIDTH wide window
|
||||
DAngle FieldOfView = 90.; // Angles in the SCREENWIDTH wide window
|
||||
|
||||
FCanvasTextureInfo *FCanvasTextureInfo::List;
|
||||
|
||||
|
@ -157,63 +157,6 @@ DAngle viewpitch;
|
|||
// CODE --------------------------------------------------------------------
|
||||
static void R_Shutdown ();
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_InitPointToAngle
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_InitPointToAngle (void)
|
||||
{
|
||||
double f;
|
||||
int i;
|
||||
//
|
||||
// slope (tangent) to angle lookup
|
||||
//
|
||||
for (i = 0; i <= SLOPERANGE; i++)
|
||||
{
|
||||
f = g_atan2 ((double)i, (double)SLOPERANGE) / (6.28318530718 /* 2*pi */);
|
||||
tantoangle[i] = (angle_t)(0xffffffff*f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_InitTables
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_InitTables (void)
|
||||
{
|
||||
int i;
|
||||
const double pimul = PI*2/FINEANGLES;
|
||||
|
||||
// viewangle tangent table
|
||||
finetangent[0] = (fixed_t)(FRACUNIT*g_tan ((0.5-FINEANGLES/4)*pimul)+0.5);
|
||||
for (i = 1; i < FINEANGLES/2; i++)
|
||||
{
|
||||
finetangent[i] = (fixed_t)(FRACUNIT*g_tan ((i-FINEANGLES/4)*pimul)+0.5);
|
||||
}
|
||||
|
||||
// finesine table
|
||||
for (i = 0; i < FINEANGLES/4; i++)
|
||||
{
|
||||
finesine[i] = (fixed_t)(FRACUNIT * g_sin (i*pimul));
|
||||
}
|
||||
for (i = 0; i < FINEANGLES/4; i++)
|
||||
{
|
||||
finesine[i+FINEANGLES/4] = finesine[FINEANGLES/4-1-i];
|
||||
}
|
||||
for (i = 0; i < FINEANGLES/2; i++)
|
||||
{
|
||||
finesine[i+FINEANGLES/2] = -finesine[i];
|
||||
}
|
||||
finesine[FINEANGLES/4] = FRACUNIT;
|
||||
finesine[FINEANGLES*3/4] = -FRACUNIT;
|
||||
memcpy (&finesine[FINEANGLES], &finesine[0], sizeof(angle_t)*FINEANGLES/4);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_SetFOV
|
||||
|
@ -222,33 +165,18 @@ void R_InitTables (void)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_SetFOV (float fov)
|
||||
void R_SetFOV (DAngle fov)
|
||||
{
|
||||
if (fov < 5.f)
|
||||
fov = 5.f;
|
||||
else if (fov > 170.f)
|
||||
fov = 170.f;
|
||||
if (fov != LastFOV)
|
||||
|
||||
if (fov < 5.) fov = 5.;
|
||||
else if (fov > 170.) fov = 170.;
|
||||
if (fov != FieldOfView)
|
||||
{
|
||||
LastFOV = fov;
|
||||
FieldOfView = (int)(fov * (float)FINEANGLES / 360.f);
|
||||
FieldOfView = fov;
|
||||
setsizeneeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_GetFOV
|
||||
//
|
||||
// Returns the current field of view in degrees
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
float R_GetFOV ()
|
||||
{
|
||||
return LastFOV;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_SetViewSize
|
||||
|
@ -312,18 +240,16 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight)
|
|||
}
|
||||
|
||||
|
||||
int fov = FieldOfView;
|
||||
DAngle fov = FieldOfView;
|
||||
|
||||
// For widescreen displays, increase the FOV so that the middle part of the
|
||||
// screen that would be visible on a 4:3 display has the requested FOV.
|
||||
if (centerxwide != centerx)
|
||||
{ // centerxwide is what centerx would be if the display was not widescreen
|
||||
fov = int(atan(double(centerx)*tan(double(fov)*M_PI/(FINEANGLES))/double(centerxwide))*(FINEANGLES)/M_PI);
|
||||
if (fov > 170*FINEANGLES/360)
|
||||
fov = 170*FINEANGLES/360;
|
||||
fov = DAngle::ToDegrees(2 * atan(centerx * tan(fov.Radians()/2) / double(centerxwide)));
|
||||
if (fov > 170.) fov = 170.;
|
||||
}
|
||||
|
||||
FocalTangent = FIXED2FLOAT(finetangent[FINEANGLES/4+fov/2]);
|
||||
FocalTangent = tan(fov.Radians() / 2);
|
||||
Renderer->SetWindow(windowSize, fullWidth, fullHeight, stHeight, trueratio);
|
||||
}
|
||||
|
||||
|
@ -409,8 +335,6 @@ void R_Init ()
|
|||
//R_InitColormaps ();
|
||||
//StartScreen->Progress();
|
||||
|
||||
R_InitPointToAngle ();
|
||||
R_InitTables ();
|
||||
R_InitTranslationTables ();
|
||||
R_SetViewSize (screenblocks);
|
||||
Renderer->Init();
|
||||
|
@ -542,11 +466,13 @@ void R_InterpolateView (player_t *player, double Frac, InterpolationViewer *ivie
|
|||
ViewAngle = (nviewangle + AngleToFloat(LocalViewAngle & 0xFFFF0000)).Normalized180();
|
||||
DAngle delta = player->centering ? DAngle(0.) : AngleToFloat(int(LocalViewPitch & 0xFFFF0000));
|
||||
ViewPitch = clamp<DAngle>((iview->New.Angles.Pitch - delta).Normalized180(), player->MinPitch, player->MaxPitch);
|
||||
ViewRoll = iview->New.Angles.Roll.Normalized180();
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewPitch = (iview->Old.Angles.Pitch + deltaangle(iview->Old.Angles.Pitch, iview->New.Angles.Pitch) * Frac).Normalized180();
|
||||
ViewAngle = (oviewangle + deltaangle(oviewangle, nviewangle) * Frac).Normalized180();
|
||||
ViewRoll = (iview->Old.Angles.Roll + deltaangle(iview->Old.Angles.Roll, iview->New.Angles.Roll) * Frac).Normalized180();
|
||||
}
|
||||
|
||||
// Due to interpolation this is not necessarily the same as the sector the camera is in.
|
||||
|
@ -799,6 +725,7 @@ void R_SetupFrame (AActor *actor)
|
|||
P_AimCamera (camera, campos, camangle, viewsector, unlinked); // fixme: This needs to translate the angle, too.
|
||||
iview->New.Pos = campos;
|
||||
iview->New.Angles.Yaw = camangle;
|
||||
|
||||
r_showviewer = true;
|
||||
// Interpolating this is a very complicated thing because nothing keeps track of the aim camera's movement, so whenever we detect a portal transition
|
||||
// it's probably best to just reset the interpolation for this move.
|
||||
|
@ -868,6 +795,10 @@ void R_SetupFrame (AActor *actor)
|
|||
double quakefactor = r_quakeintensity;
|
||||
DAngle an;
|
||||
|
||||
if (jiggers.RollIntensity != 0 || jiggers.RollWave != 0)
|
||||
{
|
||||
ViewRoll += QuakePower(quakefactor, jiggers.RollIntensity, jiggers.RollWave, jiggers.RFalloff, jiggers.RWFalloff);
|
||||
}
|
||||
if (jiggers.RelIntensity.X != 0 || jiggers.RelOffset.X != 0)
|
||||
{
|
||||
an = camera->Angles.Yaw;
|
||||
|
|
|
@ -15,6 +15,7 @@ extern DCanvas *RenderTarget;
|
|||
extern DVector3 ViewPos;
|
||||
extern DAngle ViewAngle;
|
||||
extern DAngle ViewPitch;
|
||||
extern DAngle ViewRoll;
|
||||
extern DVector3 ViewPath[2];
|
||||
|
||||
extern "C" int centerx, centerxwide;
|
||||
|
@ -84,8 +85,7 @@ bool R_GetViewInterpolationStatus();
|
|||
void R_ClearInterpolationPath();
|
||||
void R_AddInterpolationPoint(const DVector3a &vec);
|
||||
void R_SetViewSize (int blocks);
|
||||
void R_SetFOV (float fov);
|
||||
float R_GetFOV ();
|
||||
void R_SetFOV (DAngle fov);
|
||||
void R_SetupFrame (AActor * camera);
|
||||
void R_SetViewAngle ();
|
||||
|
||||
|
|
|
@ -500,6 +500,7 @@ int S_AddSoundLump (const char *logicalname, int lump)
|
|||
sfxinfo_t newsfx;
|
||||
|
||||
newsfx.data.Clear();
|
||||
newsfx.data3d.Clear();
|
||||
newsfx.name = logicalname;
|
||||
newsfx.lumpnum = lump;
|
||||
newsfx.next = 0;
|
||||
|
|
|
@ -98,6 +98,7 @@ extern float S_GetMusicVolume (const char *music);
|
|||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static void S_LoadSound3D(sfxinfo_t *sfx);
|
||||
static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, float limit_range, AActor *actor, int channel);
|
||||
static bool S_IsChannelUsed(AActor *actor, int channel, int *seen);
|
||||
static void S_ActivatePlayList(bool goBack);
|
||||
|
@ -546,8 +547,11 @@ void S_UnloadSound (sfxinfo_t *sfx)
|
|||
{
|
||||
if (sfx->data.isValid())
|
||||
{
|
||||
if(sfx->data3d.isValid() && sfx->data != sfx->data3d)
|
||||
GSnd->UnloadSound(sfx->data3d);
|
||||
GSnd->UnloadSound(sfx->data);
|
||||
sfx->data.Clear();
|
||||
sfx->data3d.Clear();
|
||||
DPrintf("Unloaded sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]);
|
||||
}
|
||||
}
|
||||
|
@ -1098,9 +1102,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
|
|||
|
||||
if (attenuation > 0)
|
||||
{
|
||||
S_LoadSound3D(sfx);
|
||||
SoundListener listener;
|
||||
S_SetListener(listener, players[consoleplayer].camera);
|
||||
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL);
|
||||
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1194,12 +1199,13 @@ void S_RestartSound(FSoundChan *chan)
|
|||
return;
|
||||
}
|
||||
|
||||
S_LoadSound3D(sfx);
|
||||
SoundListener listener;
|
||||
S_SetListener(listener, players[consoleplayer].camera);
|
||||
|
||||
chan->ChanFlags &= ~(CHAN_EVICTED|CHAN_ABSTIME);
|
||||
ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch,
|
||||
chan->Priority, pos, vel, chan->EntChannel, startflags, chan);
|
||||
ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data3d, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch,
|
||||
chan->Priority, pos, vel, chan->EntChannel, startflags, chan);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1339,31 +1345,35 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
|
|||
BYTE *sfxdata = new BYTE[size];
|
||||
wlump.Read(sfxdata, size);
|
||||
SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]);
|
||||
std::pair<SoundHandle,bool> snd;
|
||||
|
||||
// If the sound is voc, use the custom loader.
|
||||
if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0)
|
||||
{
|
||||
sfx->data = GSnd->LoadSoundVoc(sfxdata, size);
|
||||
snd = GSnd->LoadSoundVoc(sfxdata, size);
|
||||
}
|
||||
// If the sound is raw, just load it as such.
|
||||
else if (sfx->bLoadRAW)
|
||||
{
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart);
|
||||
snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart);
|
||||
}
|
||||
// Otherwise, try the sound as DMX format.
|
||||
else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8)
|
||||
{
|
||||
int frequency = LittleShort(((WORD *)sfxdata)[1]);
|
||||
if (frequency == 0) frequency = 11025;
|
||||
sfx->data = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
|
||||
snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart);
|
||||
}
|
||||
// If that fails, let the sound system try and figure it out.
|
||||
else
|
||||
{
|
||||
sfx->data = GSnd->LoadSound(sfxdata, size);
|
||||
snd = GSnd->LoadSound(sfxdata, size);
|
||||
}
|
||||
|
||||
delete[] sfxdata;
|
||||
|
||||
sfx->data = snd.first;
|
||||
if(snd.second)
|
||||
sfx->data3d = sfx->data;
|
||||
}
|
||||
|
||||
if (!sfx->data.isValid())
|
||||
|
@ -1379,6 +1389,53 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
|
|||
return sfx;
|
||||
}
|
||||
|
||||
static void S_LoadSound3D(sfxinfo_t *sfx)
|
||||
{
|
||||
if (GSnd->IsNull()) return;
|
||||
|
||||
if(sfx->data3d.isValid())
|
||||
return;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
DPrintf("Loading monoized sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]);
|
||||
|
||||
int size = Wads.LumpLength(sfx->lumpnum);
|
||||
if(size <= 0) return;
|
||||
|
||||
FWadLump wlump = Wads.OpenLumpNum(sfx->lumpnum);
|
||||
BYTE *sfxdata = new BYTE[size];
|
||||
wlump.Read(sfxdata, size);
|
||||
SDWORD dmxlen = LittleLong(((SDWORD *)sfxdata)[1]);
|
||||
std::pair<SoundHandle,bool> snd;
|
||||
|
||||
// If the sound is voc, use the custom loader.
|
||||
if (strncmp ((const char *)sfxdata, "Creative Voice File", 19) == 0)
|
||||
{
|
||||
snd = GSnd->LoadSoundVoc(sfxdata, size, true);
|
||||
}
|
||||
// If the sound is raw, just load it as such.
|
||||
else if (sfx->bLoadRAW)
|
||||
{
|
||||
snd = GSnd->LoadSoundRaw(sfxdata, size, sfx->RawRate, 1, 8, sfx->LoopStart, true);
|
||||
}
|
||||
// Otherwise, try the sound as DMX format.
|
||||
else if (((BYTE *)sfxdata)[0] == 3 && ((BYTE *)sfxdata)[1] == 0 && dmxlen <= size - 8)
|
||||
{
|
||||
int frequency = LittleShort(((WORD *)sfxdata)[1]);
|
||||
if (frequency == 0) frequency = 11025;
|
||||
snd = GSnd->LoadSoundRaw(sfxdata+8, dmxlen, frequency, 1, 8, sfx->LoopStart, -1, true);
|
||||
}
|
||||
// If that fails, let the sound system try and figure it out.
|
||||
else
|
||||
{
|
||||
snd = GSnd->LoadSound(sfxdata, size, true);
|
||||
}
|
||||
delete[] sfxdata;
|
||||
|
||||
sfx->data3d = snd.first;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_CheckSingular
|
||||
|
|
|
@ -36,6 +36,9 @@ struct sfxinfo_t
|
|||
// Next field is for use by the system sound interface.
|
||||
// A non-null data means the sound has been loaded.
|
||||
SoundHandle data;
|
||||
// Also for the sound interface. Used for 3D positional
|
||||
// sounds, may be the same as data.
|
||||
SoundHandle data3d;
|
||||
|
||||
FString name; // [RH] Sound name defined in SNDINFO
|
||||
int lumpnum; // lump number of sfx
|
||||
|
|
|
@ -2510,7 +2510,7 @@ void FMODSoundRenderer::UpdateSounds()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend)
|
||||
std::pair<SoundHandle,bool> FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
SoundHandle retval = { NULL };
|
||||
|
@ -2518,7 +2518,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
|
||||
if (length <= 0)
|
||||
{
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
|
@ -2550,7 +2550,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
break;
|
||||
|
||||
default:
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
const FMOD_MODE samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_OPENRAW;
|
||||
|
@ -2561,7 +2561,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
if (result != FMOD_OK)
|
||||
{
|
||||
DPrintf("Failed to allocate sample: Error %d\n", result);
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
if (loopstart >= 0)
|
||||
|
@ -2572,7 +2572,7 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
}
|
||||
|
||||
retval.data = sample;
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2581,12 +2581,12 @@ SoundHandle FMODSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequ
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
||||
std::pair<SoundHandle,bool> FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize)
|
||||
{
|
||||
FMOD_CREATESOUNDEXINFO exinfo;
|
||||
SoundHandle retval = { NULL };
|
||||
|
||||
if (length == 0) return retval;
|
||||
if (length == 0) return std::make_pair(retval, true);
|
||||
|
||||
InitCreateSoundExInfo(&exinfo);
|
||||
exinfo.length = length;
|
||||
|
@ -2599,11 +2599,11 @@ SoundHandle FMODSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
|||
if (result != FMOD_OK)
|
||||
{
|
||||
DPrintf("Failed to allocate sample: Error %d\n", result);
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
SetCustomLoopPts(sample);
|
||||
retval.data = sample;
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -15,8 +15,8 @@ public:
|
|||
|
||||
void SetSfxVolume (float volume);
|
||||
void SetMusicVolume (float volume);
|
||||
SoundHandle LoadSound(BYTE *sfxdata, int length);
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1);
|
||||
std::pair<SoundHandle,bool> LoadSound(BYTE *sfxdata, int length, bool monoize);
|
||||
std::pair<SoundHandle,bool> LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false);
|
||||
void UnloadSound (SoundHandle sfx);
|
||||
unsigned int GetMSLength(SoundHandle sfx);
|
||||
unsigned int GetSampleLength(SoundHandle sfx);
|
||||
|
|
|
@ -135,15 +135,15 @@ public:
|
|||
void SetMusicVolume (float volume)
|
||||
{
|
||||
}
|
||||
SoundHandle LoadSound(BYTE *sfxdata, int length)
|
||||
std::pair<SoundHandle,bool> LoadSound(BYTE *sfxdata, int length, bool monoize)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend)
|
||||
std::pair<SoundHandle,bool> LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
void UnloadSound (SoundHandle sfx)
|
||||
{
|
||||
|
@ -456,7 +456,7 @@ FString SoundStream::GetStats()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length)
|
||||
std::pair<SoundHandle,bool> SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length, bool monoize)
|
||||
{
|
||||
BYTE * data = NULL;
|
||||
int len, frequency, channels, bits, loopstart, loopend;
|
||||
|
@ -600,7 +600,7 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length)
|
|||
}
|
||||
|
||||
} while (false);
|
||||
SoundHandle retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend);
|
||||
std::pair<SoundHandle,bool> retval = LoadSoundRaw(data, len, frequency, channels, bits, loopstart, loopend, monoize);
|
||||
if (data) delete[] data;
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -95,9 +95,10 @@ public:
|
|||
virtual bool IsNull() { return false; }
|
||||
virtual void SetSfxVolume (float volume) = 0;
|
||||
virtual void SetMusicVolume (float volume) = 0;
|
||||
virtual SoundHandle LoadSound(BYTE *sfxdata, int length) = 0;
|
||||
SoundHandle LoadSoundVoc(BYTE *sfxdata, int length);
|
||||
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1) = 0;
|
||||
// Returns a pair containing a sound handle and a boolean indicating the sound can be used in 3D.
|
||||
virtual std::pair<SoundHandle,bool> LoadSound(BYTE *sfxdata, int length, bool monoize=false) = 0;
|
||||
std::pair<SoundHandle,bool> LoadSoundVoc(BYTE *sfxdata, int length, bool monoize=false);
|
||||
virtual std::pair<SoundHandle,bool> LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false) = 0;
|
||||
virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory
|
||||
virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency
|
||||
virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency
|
||||
|
|
|
@ -91,6 +91,11 @@ struct SoundHandle
|
|||
|
||||
bool isValid() const { return data != NULL; }
|
||||
void Clear() { data = NULL; }
|
||||
|
||||
bool operator==(const SoundHandle &rhs) const
|
||||
{ return data == rhs.data; }
|
||||
bool operator!=(const SoundHandle &rhs) const
|
||||
{ return !(*this == rhs); }
|
||||
};
|
||||
|
||||
struct FISoundChannel
|
||||
|
|
|
@ -22,7 +22,7 @@ static oalloadentry oalfuncs[] = {
|
|||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
#ifndef IN_IDE_PARSER
|
||||
#define alEnable p_alEnable
|
||||
#define alDisable p_alDisable
|
||||
#define alIsEnabled p_alIsEnabled
|
||||
|
@ -116,6 +116,7 @@ static oalloadentry oalfuncs[] = {
|
|||
#define alcCaptureStart p_alcCaptureStart
|
||||
#define alcCaptureStop p_alcCaptureStop
|
||||
#define alcCaptureSamples p_alcCaptureSamples
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
#include "except.h"
|
||||
#include "doomstat.h"
|
||||
#include "templates.h"
|
||||
|
@ -69,7 +72,7 @@ static void* hmodOpenAL;
|
|||
#ifdef __APPLE__
|
||||
#define OPENALLIB "OpenAL.framework/OpenAL"
|
||||
#else
|
||||
#define OPENALLIB "libopenal.so"
|
||||
#define OPENALLIB "libopenal.so.1"
|
||||
#endif
|
||||
#define LoadLibrary(x) dlopen((x), RTLD_LAZY)
|
||||
#define GetProcAddress(a,b) dlsym((a),(b))
|
||||
|
@ -273,6 +276,8 @@ class OpenALSoundStream : public SoundStream
|
|||
alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL);
|
||||
alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);
|
||||
}
|
||||
if(Renderer->AL.EXT_SOURCE_RADIUS)
|
||||
alSourcef(Source, AL_SOURCE_RADIUS, 0.f);
|
||||
|
||||
alGenBuffers(BufferCount, Buffers);
|
||||
return (getALError() == AL_NO_ERROR);
|
||||
|
@ -645,12 +650,21 @@ public:
|
|||
|
||||
extern ReverbContainer *ForcedEnvironment;
|
||||
|
||||
#define AREA_SOUND_RADIUS (128.f)
|
||||
#define AREA_SOUND_RADIUS (32.f)
|
||||
|
||||
#define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */
|
||||
|
||||
#define PITCH(pitch) (snd_pitched ? (pitch)/128.f : 1.f)
|
||||
|
||||
static size_t GetChannelCount(ChannelConfig chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
case ChannelConfig_Mono: return 1;
|
||||
case ChannelConfig_Stereo: return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float GetRolloff(const FRolloffInfo *rolloff, float distance)
|
||||
{
|
||||
|
@ -705,7 +719,12 @@ template<typename T>
|
|||
static void LoadALFunc(const char *name, T *x)
|
||||
{ *x = reinterpret_cast<T>(alGetProcAddress(name)); }
|
||||
|
||||
template<typename T>
|
||||
static void LoadALCFunc(ALCdevice *device, const char *name, T *x)
|
||||
{ *x = reinterpret_cast<T>(alcGetProcAddress(device, name)); }
|
||||
|
||||
#define LOAD_FUNC(x) (LoadALFunc(#x, &x))
|
||||
#define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x))
|
||||
OpenALSoundRenderer::OpenALSoundRenderer()
|
||||
: QuitThread(false), Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0)
|
||||
{
|
||||
|
@ -763,8 +782,10 @@ OpenALSoundRenderer::OpenALSoundRenderer()
|
|||
DPrintf(" Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS));
|
||||
|
||||
ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX");
|
||||
ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");;
|
||||
ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");
|
||||
ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device");
|
||||
AL.EXT_source_distance_model = !!alIsExtensionPresent("AL_EXT_source_distance_model");
|
||||
AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS");
|
||||
AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates");
|
||||
AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points");
|
||||
|
||||
|
@ -785,6 +806,12 @@ OpenALSoundRenderer::OpenALSoundRenderer()
|
|||
alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT;
|
||||
}
|
||||
|
||||
if(ALC.SOFT_pause_device)
|
||||
{
|
||||
LOAD_DEV_FUNC(Device, alcDevicePauseSOFT);
|
||||
LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT);
|
||||
}
|
||||
|
||||
ALenum err = getALError();
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
|
@ -924,6 +951,7 @@ OpenALSoundRenderer::OpenALSoundRenderer()
|
|||
if(EnvSlot)
|
||||
Printf(" EFX enabled\n");
|
||||
}
|
||||
#undef LOAD_DEV_FUNC
|
||||
#undef LOAD_FUNC
|
||||
|
||||
OpenALSoundRenderer::~OpenALSoundRenderer()
|
||||
|
@ -1084,11 +1112,11 @@ float OpenALSoundRenderer::GetOutputRate()
|
|||
}
|
||||
|
||||
|
||||
SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend)
|
||||
std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend, bool monoize)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
|
||||
if(length == 0) return retval;
|
||||
if(length == 0) return std::make_pair(retval, true);
|
||||
|
||||
if(bits == -8)
|
||||
{
|
||||
|
@ -1098,6 +1126,33 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre
|
|||
bits = -bits;
|
||||
}
|
||||
|
||||
if(channels > 1 && monoize)
|
||||
{
|
||||
size_t frames = length / channels * 8 / bits;
|
||||
if(bits == 16)
|
||||
{
|
||||
for(size_t i = 0;i < frames;i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for(int c = 0;c < channels;c++)
|
||||
sum += ((short*)sfxdata)[i*channels + c];
|
||||
((short*)sfxdata)[i] = sum / channels;
|
||||
}
|
||||
}
|
||||
else if(bits == 8)
|
||||
{
|
||||
for(size_t i = 0;i < frames;i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for(int c = 0;c < channels;c++)
|
||||
sum += sfxdata[i*channels + c] - 128;
|
||||
sfxdata[i] = (sum / channels) + 128;
|
||||
}
|
||||
}
|
||||
length /= channels;
|
||||
channels = 1;
|
||||
}
|
||||
|
||||
ALenum format = AL_NONE;
|
||||
if(bits == 16)
|
||||
{
|
||||
|
@ -1113,7 +1168,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre
|
|||
if(format == AL_NONE || frequency <= 0)
|
||||
{
|
||||
Printf("Unhandled format: %d bit, %d channel, %d hz\n", bits, channels, frequency);
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
length -= length%(channels*bits/8);
|
||||
|
||||
|
@ -1126,7 +1181,7 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre
|
|||
Printf("Failed to buffer data: %s\n", alGetString(err));
|
||||
alDeleteBuffers(1, &buffer);
|
||||
getALError();
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
if((loopstart > 0 || loopend > 0) && AL.SOFT_loop_points)
|
||||
|
@ -1150,10 +1205,10 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre
|
|||
}
|
||||
|
||||
retval.data = MAKE_PTRID(buffer);
|
||||
return retval;
|
||||
return std::make_pair(retval, channels==1);
|
||||
}
|
||||
|
||||
SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
||||
std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length, bool monoize)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
MemoryReader reader((const char*)sfxdata, length);
|
||||
|
@ -1162,16 +1217,16 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
|||
SampleType type;
|
||||
int srate;
|
||||
|
||||
SoundDecoder *decoder = CreateDecoder(&reader);
|
||||
if(!decoder) return retval;
|
||||
std::unique_ptr<SoundDecoder> decoder(CreateDecoder(&reader));
|
||||
if(!decoder) return std::make_pair(retval, true);
|
||||
|
||||
decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans == ChannelConfig_Mono)
|
||||
if(chans == ChannelConfig_Mono || monoize)
|
||||
{
|
||||
if(type == SampleType_UInt8) format = AL_FORMAT_MONO8;
|
||||
if(type == SampleType_Int16) format = AL_FORMAT_MONO16;
|
||||
}
|
||||
if(chans == ChannelConfig_Stereo)
|
||||
else if(chans == ChannelConfig_Stereo)
|
||||
{
|
||||
if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8;
|
||||
if(type == SampleType_Int16) format = AL_FORMAT_STEREO16;
|
||||
|
@ -1181,29 +1236,54 @@ SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
|||
{
|
||||
Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans),
|
||||
GetSampleTypeName(type));
|
||||
delete decoder;
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
TArray<char> data = decoder->readAll();
|
||||
if(chans != ChannelConfig_Mono && monoize)
|
||||
{
|
||||
size_t chancount = GetChannelCount(chans);
|
||||
size_t frames = data.Size() / chancount /
|
||||
(type == SampleType_Int16 ? 2 : 1);
|
||||
if(type == SampleType_Int16)
|
||||
{
|
||||
short *sfxdata = (short*)&data[0];
|
||||
for(size_t i = 0;i < frames;i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for(size_t c = 0;c < chancount;c++)
|
||||
sum += sfxdata[i*chancount + c];
|
||||
sfxdata[i] = sum / chancount;
|
||||
}
|
||||
}
|
||||
else if(type == SampleType_UInt8)
|
||||
{
|
||||
BYTE *sfxdata = (BYTE*)&data[0];
|
||||
for(size_t i = 0;i < frames;i++)
|
||||
{
|
||||
int sum = 0;
|
||||
for(size_t c = 0;c < chancount;c++)
|
||||
sum += sfxdata[i*chancount + c] - 128;
|
||||
sfxdata[i] = (sum / chancount) + 128;
|
||||
}
|
||||
}
|
||||
data.Resize(data.Size()/chancount);
|
||||
}
|
||||
|
||||
ALenum err;
|
||||
ALuint buffer = 0;
|
||||
alGenBuffers(1, &buffer);
|
||||
alBufferData(buffer, format, &data[0], data.Size(), srate);
|
||||
|
||||
ALenum err;
|
||||
if((err=getALError()) != AL_NO_ERROR)
|
||||
{
|
||||
Printf("Failed to buffer data: %s\n", alGetString(err));
|
||||
alDeleteBuffers(1, &buffer);
|
||||
getALError();
|
||||
delete decoder;
|
||||
return retval;
|
||||
return std::make_pair(retval, true);
|
||||
}
|
||||
|
||||
retval.data = MAKE_PTRID(buffer);
|
||||
delete decoder;
|
||||
return retval;
|
||||
return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize));
|
||||
}
|
||||
|
||||
void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
|
||||
|
@ -1286,6 +1366,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
|
|||
alSourcef(source, AL_ROLLOFF_FACTOR, 0.f);
|
||||
alSourcef(source, AL_MAX_GAIN, SfxVolume);
|
||||
alSourcef(source, AL_GAIN, SfxVolume*vol);
|
||||
if(AL.EXT_SOURCE_RADIUS)
|
||||
alSourcef(source, AL_SOURCE_RADIUS, 0.f);
|
||||
|
||||
if(EnvSlot)
|
||||
{
|
||||
|
@ -1306,7 +1388,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
|
|||
else
|
||||
alSourcef(source, AL_PITCH, PITCH(pitch));
|
||||
|
||||
if(!reuse_chan)
|
||||
if(!reuse_chan || reuse_chan->StartTime.AsOne == 0)
|
||||
alSourcef(source, AL_SEC_OFFSET, 0.f);
|
||||
else
|
||||
{
|
||||
|
@ -1314,8 +1396,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
|
|||
alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f);
|
||||
else
|
||||
{
|
||||
// FIXME: set offset based on the current time and the StartTime
|
||||
alSourcef(source, AL_SEC_OFFSET, 0.f);
|
||||
float offset = std::chrono::duration_cast<std::chrono::duration<float>>(
|
||||
std::chrono::steady_clock::now().time_since_epoch() -
|
||||
std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne)
|
||||
).count();
|
||||
if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset);
|
||||
}
|
||||
}
|
||||
if(getALError() != AL_NO_ERROR)
|
||||
|
@ -1345,7 +1430,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
|
|||
chan->Rolloff.RolloffType = ROLLOFF_Log;
|
||||
chan->Rolloff.RolloffFactor = 0.f;
|
||||
chan->Rolloff.MinDistance = 1.f;
|
||||
chan->DistanceScale = 1.f;
|
||||
chan->DistanceSqr = 0.f;
|
||||
chan->ManualRolloff = false;
|
||||
|
||||
|
@ -1428,7 +1512,16 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
|
|||
float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale);
|
||||
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
|
||||
}
|
||||
if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
if(AL.EXT_SOURCE_RADIUS)
|
||||
{
|
||||
/* Since the OpenAL distance is decoupled from the sound's distance, get the OpenAL
|
||||
* distance that corresponds to the area radius. */
|
||||
alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ?
|
||||
// Clamp in case the max distance is <= the area radius
|
||||
1.f/MAX<float>(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f
|
||||
);
|
||||
}
|
||||
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
{
|
||||
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
|
||||
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
|
||||
|
@ -1438,20 +1531,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
|
|||
|
||||
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
|
||||
}
|
||||
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
else
|
||||
{
|
||||
FVector3 dir = pos - listener->position;
|
||||
FVector3 dir = pos;
|
||||
if(AL.EXT_SOURCE_RADIUS)
|
||||
alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f);
|
||||
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
{
|
||||
dir -= listener->position;
|
||||
|
||||
float mindist = rolloff->MinDistance/distscale;
|
||||
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
|
||||
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
|
||||
dir = amb + (dir-amb)*a;
|
||||
float mindist = rolloff->MinDistance/distscale;
|
||||
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
|
||||
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
|
||||
dir = amb + (dir-amb)*a;
|
||||
|
||||
dir += listener->position;
|
||||
dir += listener->position;
|
||||
}
|
||||
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
|
||||
}
|
||||
else
|
||||
alSource3f(source, AL_POSITION, pos[0], pos[1], -pos[2]);
|
||||
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
|
||||
alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f);
|
||||
|
||||
|
@ -1480,7 +1577,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
|
|||
else
|
||||
alSourcef(source, AL_PITCH, PITCH(pitch));
|
||||
|
||||
if(!reuse_chan)
|
||||
if(!reuse_chan || reuse_chan->StartTime.AsOne == 0)
|
||||
alSourcef(source, AL_SEC_OFFSET, 0.f);
|
||||
else
|
||||
{
|
||||
|
@ -1488,8 +1585,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
|
|||
alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f);
|
||||
else
|
||||
{
|
||||
// FIXME: set offset based on the current time and the StartTime
|
||||
alSourcef(source, AL_SAMPLE_OFFSET, 0.f);
|
||||
float offset = std::chrono::duration_cast<std::chrono::duration<float>>(
|
||||
std::chrono::steady_clock::now().time_since_epoch() -
|
||||
std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne)
|
||||
).count();
|
||||
if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset);
|
||||
}
|
||||
}
|
||||
if(getALError() != AL_NO_ERROR)
|
||||
|
@ -1517,7 +1617,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
|
|||
else chan->SysChannel = MAKE_PTRID(source);
|
||||
|
||||
chan->Rolloff = *rolloff;
|
||||
chan->DistanceScale = distscale;
|
||||
chan->DistanceSqr = dist_sqr;
|
||||
chan->ManualRolloff = manualRolloff;
|
||||
|
||||
|
@ -1603,10 +1702,20 @@ void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state)
|
|||
{
|
||||
case SoundRenderer::INACTIVE_Active:
|
||||
alListenerf(AL_GAIN, 1.0f);
|
||||
if(ALC.SOFT_pause_device)
|
||||
{
|
||||
alcDeviceResumeSOFT(Device);
|
||||
getALCError(Device);
|
||||
}
|
||||
break;
|
||||
|
||||
/* FIXME: This doesn't stop anything. */
|
||||
case SoundRenderer::INACTIVE_Complete:
|
||||
if(ALC.SOFT_pause_device)
|
||||
{
|
||||
alcDevicePauseSOFT(Device);
|
||||
getALCError(Device);
|
||||
}
|
||||
/* fall-through */
|
||||
case SoundRenderer::INACTIVE_Mute:
|
||||
alListenerf(AL_GAIN, 0.0f);
|
||||
break;
|
||||
|
@ -1655,26 +1764,26 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
|
|||
if(chan == NULL || chan->SysChannel == NULL)
|
||||
return;
|
||||
|
||||
alDeferUpdatesSOFT();
|
||||
|
||||
FVector3 dir = pos - listener->position;
|
||||
chan->DistanceSqr = (float)dir.LengthSquared();
|
||||
|
||||
if(chan->ManualRolloff)
|
||||
{
|
||||
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
|
||||
{
|
||||
float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale);
|
||||
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
|
||||
}
|
||||
if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
if(!AL.EXT_SOURCE_RADIUS && areasound &&
|
||||
chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
{
|
||||
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
|
||||
float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS;
|
||||
dir = amb + (dir-amb)*a;
|
||||
}
|
||||
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
|
||||
{
|
||||
float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale);
|
||||
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
|
||||
}
|
||||
}
|
||||
else if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
else if(!AL.EXT_SOURCE_RADIUS && areasound &&
|
||||
chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
|
||||
{
|
||||
float mindist = chan->Rolloff.MinDistance / chan->DistanceScale;
|
||||
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
|
||||
|
@ -1683,6 +1792,8 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
|
|||
}
|
||||
dir += listener->position;
|
||||
|
||||
alDeferUpdatesSOFT();
|
||||
|
||||
ALuint source = GET_PTRID(chan->SysChannel);
|
||||
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
|
||||
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
|
||||
|
@ -1819,7 +1930,7 @@ void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan)
|
|||
{
|
||||
// FIXME: Get current time (preferably from the audio clock, but the system
|
||||
// time will have to do)
|
||||
chan->StartTime.AsOne = 0;
|
||||
chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count();
|
||||
}
|
||||
|
||||
float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan)
|
||||
|
|
|
@ -63,6 +63,11 @@
|
|||
#define AL_FORMAT_71CHN32 0x1212
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_SOURCE_RADIUS
|
||||
#define AL_EXT_SOURCE_RADIUS 1
|
||||
#define AL_SOURCE_RADIUS 0x1031
|
||||
#endif
|
||||
|
||||
#include "efx.h"
|
||||
|
||||
|
||||
|
@ -76,8 +81,8 @@ public:
|
|||
|
||||
virtual void SetSfxVolume(float volume);
|
||||
virtual void SetMusicVolume(float volume);
|
||||
virtual SoundHandle LoadSound(BYTE *sfxdata, int length);
|
||||
virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1);
|
||||
virtual std::pair<SoundHandle,bool> LoadSound(BYTE *sfxdata, int length, bool monoize);
|
||||
virtual std::pair<SoundHandle,bool> LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1, bool monoize = false);
|
||||
virtual void UnloadSound(SoundHandle sfx);
|
||||
virtual unsigned int GetMSLength(SoundHandle sfx);
|
||||
virtual unsigned int GetSampleLength(SoundHandle sfx);
|
||||
|
@ -128,9 +133,11 @@ private:
|
|||
struct {
|
||||
bool EXT_EFX;
|
||||
bool EXT_disconnect;
|
||||
bool SOFT_pause_device;
|
||||
} ALC;
|
||||
struct {
|
||||
bool EXT_source_distance_model;
|
||||
bool EXT_SOURCE_RADIUS;
|
||||
bool SOFT_deferred_updates;
|
||||
bool SOFT_loop_points;
|
||||
} AL;
|
||||
|
@ -178,9 +185,13 @@ private:
|
|||
ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void);
|
||||
ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void);
|
||||
|
||||
void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device);
|
||||
void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device);
|
||||
|
||||
void BackgroundProc();
|
||||
void AddStream(OpenALSoundStream *stream);
|
||||
void RemoveStream(OpenALSoundStream *stream);
|
||||
|
||||
void LoadReverb(const ReverbContainer *env);
|
||||
void PurgeStoppedSources();
|
||||
static FSoundChan *FindLowestChannel();
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Lookup tables.
|
||||
// Do not try to look them up :-).
|
||||
// In the order of appearance:
|
||||
//
|
||||
// int finetangent[4096] - Tangens LUT.
|
||||
// Should work with BAM fairly well (12 of 16bit,
|
||||
// effectively, by shifting).
|
||||
//
|
||||
// int finesine[10240] - Sine lookup.
|
||||
// Guess what, serves as cosine, too.
|
||||
// Remarkable thing is, how to use BAMs with this?
|
||||
//
|
||||
// int tantoangle[2049] - ArcTan LUT,
|
||||
// maps tan(angle) to angle fast. Gotta search.
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "tables.h"
|
||||
|
||||
fixed_t finetangent[4096];
|
||||
fixed_t finesine[10240];
|
||||
angle_t tantoangle[2049];
|
||||
|
||||
cosine_inline finecosine; // in case this is actually needed
|
111
src/tables.h
111
src/tables.h
|
@ -1,111 +0,0 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Lookup tables.
|
||||
// Do not try to look them up :-).
|
||||
// In the order of appearance:
|
||||
//
|
||||
// int finetangent[4096] - Tangens LUT.
|
||||
// Should work with BAM fairly well (12 of 16bit,
|
||||
// effectively, by shifting).
|
||||
//
|
||||
// int finesine[10240] - Sine lookup.
|
||||
// Guess what, serves as cosine, too.
|
||||
// Remarkable thing is, how to use BAMs with this?
|
||||
//
|
||||
// int tantoangle[2049] - ArcTan LUT,
|
||||
// maps tan(angle) to angle fast. Gotta search.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __TABLES_H__
|
||||
#define __TABLES_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "basictypes.h"
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
#endif
|
||||
|
||||
|
||||
#define FINEANGLEBITS 13
|
||||
#define FINEANGLES 8192
|
||||
#define FINEMASK (FINEANGLES-1)
|
||||
|
||||
// 0x100000000 to 0x2000
|
||||
#define ANGLETOFINESHIFT 19
|
||||
|
||||
#define BOBTOFINESHIFT (FINEANGLEBITS - 6)
|
||||
|
||||
// Effective size is 10240.
|
||||
extern fixed_t finesine[5*FINEANGLES/4];
|
||||
|
||||
// Re-use data, is just PI/2 phase shift.
|
||||
// [RH] Instead of using a pointer, use some inline code
|
||||
// (encapsulated in a struct so that we can still use array accesses).
|
||||
struct cosine_inline
|
||||
{
|
||||
fixed_t operator[] (unsigned int x) const
|
||||
{
|
||||
return finesine[x+FINEANGLES/4];
|
||||
}
|
||||
};
|
||||
extern cosine_inline finecosine;
|
||||
|
||||
// Effective size is 4096.
|
||||
extern fixed_t finetangent[FINEANGLES/2];
|
||||
|
||||
// Binary Angle Measument, BAM.
|
||||
#define ANG45 (0x20000000)
|
||||
#define ANG90 (0x40000000)
|
||||
#define ANG180 (0x80000000)
|
||||
#define ANG270 (0xc0000000)
|
||||
|
||||
#define ANGLE_45 (0x20000000)
|
||||
#define ANGLE_90 (0x40000000)
|
||||
#define ANGLE_180 (0x80000000)
|
||||
#define ANGLE_270 (0xc0000000)
|
||||
#define ANGLE_MAX (0xffffffff)
|
||||
#define ANGLE_1 (ANGLE_45/45)
|
||||
#define ANGLE_60 (ANGLE_180/3)
|
||||
|
||||
|
||||
#define SLOPERANGE 2048
|
||||
#define SLOPEBITS 11
|
||||
#define DBITS (FRACBITS-SLOPEBITS)
|
||||
|
||||
typedef uint32 angle_t;
|
||||
|
||||
// Previously seen all over the place, code like this: abs(ang1 - ang2)
|
||||
// Clang warns (and is absolutely correct) that technically, this
|
||||
// could be optimized away and do nothing:
|
||||
// warning: taking the absolute value of unsigned type 'unsigned int' has no effect
|
||||
// note: remove the call to 'abs' since unsigned values cannot be negative
|
||||
inline angle_t absangle(angle_t a)
|
||||
{
|
||||
return (angle_t)abs((int32_t)a);
|
||||
}
|
||||
|
||||
// Effective size is 2049;
|
||||
// The +1 size is to handle the case when x==y
|
||||
// without additional checking.
|
||||
extern angle_t tantoangle[SLOPERANGE+1];
|
||||
|
||||
#endif // __TABLES_H__
|
|
@ -219,7 +219,7 @@ void FTextureManager::InitAnimated (void)
|
|||
// SMMU-style swirly hack? Don't apply on already-warping texture
|
||||
if (animspeed > 65535 && tex1 != NULL && !tex1->bWarped)
|
||||
{
|
||||
FTexture *warper = new FWarp2Texture (tex1);
|
||||
FTexture *warper = new FWarpTexture (tex1, 2);
|
||||
ReplaceTexture (pic1, warper, false);
|
||||
}
|
||||
// These tests were not really relevant for swirling textures, or even potentially
|
||||
|
@ -617,9 +617,7 @@ void FTextureManager::ParseWarp(FScanner &sc)
|
|||
// don't warp a texture more than once
|
||||
if (!warper->bWarped)
|
||||
{
|
||||
if (type2) warper = new FWarp2Texture (warper);
|
||||
else warper = new FWarpTexture (warper);
|
||||
|
||||
warper = new FWarpTexture (warper, type2? 2:1);
|
||||
ReplaceTexture (picnum, warper, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,10 @@ FTextureManager::FTextureManager ()
|
|||
{
|
||||
memset (HashFirst, -1, sizeof(HashFirst));
|
||||
|
||||
for (int i = 0; i < 2048; ++i)
|
||||
{
|
||||
sintable[i] = short(sin(i*(M_PI / 1024)) * 16384);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1222,44 +1226,6 @@ int FTextureManager::CountLumpTextures (int lumpnum)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// R_PrecacheLevel
|
||||
//
|
||||
|
||||
// Preloads all relevant graphics for the level.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FTextureManager::PrecacheLevel (void)
|
||||
{
|
||||
BYTE *hitlist;
|
||||
int cnt = NumTextures();
|
||||
|
||||
if (demoplayback)
|
||||
return;
|
||||
|
||||
hitlist = new BYTE[cnt];
|
||||
memset (hitlist, 0, cnt);
|
||||
|
||||
screen->GetHitlist(hitlist);
|
||||
|
||||
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
|
||||
{
|
||||
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
|
||||
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
}
|
||||
|
||||
for (int i = cnt - 1; i >= 0; i--)
|
||||
{
|
||||
Renderer->PrecacheTexture(ByIndex(i), hitlist[i]);
|
||||
}
|
||||
|
||||
delete[] hitlist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -379,7 +379,6 @@ public:
|
|||
void UnloadAll ();
|
||||
|
||||
int NumTextures () const { return (int)Textures.Size(); }
|
||||
void PrecacheLevel (void);
|
||||
|
||||
void WriteTexture (FArchive &arc, int picnum);
|
||||
int ReadTexture (FArchive &arc);
|
||||
|
@ -446,6 +445,12 @@ private:
|
|||
TArray<FSwitchDef *> mSwitchDefs;
|
||||
TArray<FDoorAnimation> mAnimatedDoors;
|
||||
TArray<BYTE *> BuildTileFiles;
|
||||
public:
|
||||
short sintable[2048]; // for texture warping
|
||||
enum
|
||||
{
|
||||
SINMASK = 2047
|
||||
};
|
||||
};
|
||||
|
||||
// A texture that doesn't really exist
|
||||
|
@ -463,7 +468,7 @@ public:
|
|||
class FWarpTexture : public FTexture
|
||||
{
|
||||
public:
|
||||
FWarpTexture (FTexture *source);
|
||||
FWarpTexture (FTexture *source, int warptype);
|
||||
~FWarpTexture ();
|
||||
|
||||
virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL);
|
||||
|
@ -483,23 +488,13 @@ protected:
|
|||
BYTE *Pixels;
|
||||
Span **Spans;
|
||||
float Speed;
|
||||
int WidthOffsetMultipiler, HeightOffsetMultipiler; // [mxd]
|
||||
int WidthOffsetMultiplier, HeightOffsetMultiplier; // [mxd]
|
||||
|
||||
virtual void MakeTexture (DWORD time);
|
||||
int NextPo2 (int v); // [mxd]
|
||||
void SetupMultipliers (int width, int height); // [mxd]
|
||||
};
|
||||
|
||||
// [GRB] Eternity-like warping
|
||||
class FWarp2Texture : public FWarpTexture
|
||||
{
|
||||
public:
|
||||
FWarp2Texture (FTexture *source);
|
||||
|
||||
protected:
|
||||
void MakeTexture (DWORD time);
|
||||
};
|
||||
|
||||
// A texture that can be drawn to.
|
||||
class DSimpleCanvas;
|
||||
class AActor;
|
||||
|
|
63
src/textures/warpbuffer.h
Normal file
63
src/textures/warpbuffer.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
|
||||
template<class TYPE>
|
||||
void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed, int warptype)
|
||||
{
|
||||
int ymask = height - 1;
|
||||
int x, y;
|
||||
|
||||
if (warptype == 1)
|
||||
{
|
||||
TYPE *buffer = (TYPE *)alloca(sizeof(TYPE) * MAX(width, height));
|
||||
// [mxd] Rewrote to fix animation for NPo2 textures
|
||||
unsigned timebase = unsigned(time * Speed * 32 / 28);
|
||||
for (y = height - 1; y >= 0; y--)
|
||||
{
|
||||
int xf = (TexMan.sintable[((timebase + y*ymul) >> 2)&TexMan.SINMASK] >> 11) % width;
|
||||
if (xf < 0) xf += width;
|
||||
int xt = xf;
|
||||
const TYPE *sourcep = source + y;
|
||||
TYPE *dest = Pixels + y;
|
||||
for (xt = width; xt; xt--, xf = (xf + 1) % width, dest += height)
|
||||
*dest = sourcep[xf + ymask * xf];
|
||||
}
|
||||
timebase = unsigned(time * Speed * 23 / 28);
|
||||
for (x = width - 1; x >= 0; x--)
|
||||
{
|
||||
int yf = (TexMan.sintable[((time + (x + 17)*xmul) >> 2)&TexMan.SINMASK] >> 11) % height;
|
||||
if (yf < 0) yf += height;
|
||||
int yt = yf;
|
||||
const TYPE *sourcep = Pixels + (x + ymask * x);
|
||||
TYPE *dest = buffer;
|
||||
for (yt = height; yt; yt--, yf = (yf + 1) % height)
|
||||
*dest++ = sourcep[yf];
|
||||
memcpy(Pixels + (x + ymask*x), buffer, height * sizeof(TYPE));
|
||||
}
|
||||
}
|
||||
else if (warptype == 2)
|
||||
{
|
||||
unsigned timebase = unsigned(time * Speed * 40 / 28);
|
||||
// [mxd] Rewrote to fix animation for NPo2 textures
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
TYPE *dest = Pixels + (x + ymask * x);
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
int xt = (x + 128
|
||||
+ ((TexMan.sintable[((y*ymul + timebase * 5 + 900) >> 2) & TexMan.SINMASK]) >> 13)
|
||||
+ ((TexMan.sintable[((x*xmul + timebase * 4 + 300) >> 2) & TexMan.SINMASK]) >> 13)) % width;
|
||||
|
||||
int yt = (y + 128
|
||||
+ ((TexMan.sintable[((y*ymul + timebase * 3 + 700) >> 2) & TexMan.SINMASK]) >> 13)
|
||||
+ ((TexMan.sintable[((x*xmul + timebase * 4 + 1200) >> 2) & TexMan.SINMASK]) >> 13)) % height;
|
||||
|
||||
*dest++ = source[(xt + ymask * xt) + yt];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// should never happen, just in case...
|
||||
memcpy(Pixels, source, width*height * sizeof(TYPE));
|
||||
}
|
||||
}
|
||||
|
|
@ -38,14 +38,16 @@
|
|||
#include "templates.h"
|
||||
#include "r_utility.h"
|
||||
#include "textures/textures.h"
|
||||
#include "warpbuffer.h"
|
||||
|
||||
|
||||
FWarpTexture::FWarpTexture (FTexture *source)
|
||||
FWarpTexture::FWarpTexture (FTexture *source, int warptype)
|
||||
: GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f)
|
||||
{
|
||||
CopyInfo(source);
|
||||
if (warptype == 2) SetupMultipliers(256, 128);
|
||||
SetupMultipliers(128, 128); // [mxd]
|
||||
bWarped = 1;
|
||||
bWarped = warptype;
|
||||
}
|
||||
|
||||
FWarpTexture::~FWarpTexture ()
|
||||
|
@ -120,9 +122,10 @@ const BYTE *FWarpTexture::GetColumn (unsigned int column, const Span **spans_out
|
|||
return Pixels + column*Height;
|
||||
}
|
||||
|
||||
void FWarpTexture::MakeTexture (DWORD time)
|
||||
|
||||
void FWarpTexture::MakeTexture(DWORD time)
|
||||
{
|
||||
const BYTE *otherpix = SourcePic->GetPixels ();
|
||||
const BYTE *otherpix = SourcePic->GetPixels();
|
||||
|
||||
if (Pixels == NULL)
|
||||
{
|
||||
|
@ -130,62 +133,23 @@ void FWarpTexture::MakeTexture (DWORD time)
|
|||
}
|
||||
if (Spans != NULL)
|
||||
{
|
||||
FreeSpans (Spans);
|
||||
FreeSpans(Spans);
|
||||
Spans = NULL;
|
||||
}
|
||||
|
||||
GenTime = time;
|
||||
|
||||
BYTE *buffer = (BYTE *)alloca (MAX (Width, Height));
|
||||
int xsize = Width;
|
||||
int ysize = Height;
|
||||
int xmul = WidthOffsetMultipiler; // [mxd]
|
||||
int ymul = HeightOffsetMultipiler; // [mxd]
|
||||
int xmask = WidthMask;
|
||||
int ymask = Height - 1;
|
||||
int ybits = HeightBits;
|
||||
int x, y;
|
||||
|
||||
if ((1 << ybits) > Height)
|
||||
{
|
||||
ybits--;
|
||||
}
|
||||
|
||||
DWORD timebase = DWORD(time * Speed * 32 / 28);
|
||||
// [mxd] Rewrote to fix animation for NPo2 textures
|
||||
for (y = ysize-1; y >= 0; y--)
|
||||
{
|
||||
int xf = (finesine[(timebase+y*ymul)&FINEMASK]>>13) % xsize;
|
||||
if(xf < 0) xf += xsize;
|
||||
int xt = xf;
|
||||
const BYTE *source = otherpix + y;
|
||||
BYTE *dest = Pixels + y;
|
||||
for (xt = xsize; xt; xt--, xf = (xf+1)%xsize, dest += ysize)
|
||||
*dest = source[xf + ymask * xf];
|
||||
}
|
||||
timebase = DWORD(time * Speed * 23 / 28);
|
||||
for (x = xsize-1; x >= 0; x--)
|
||||
{
|
||||
int yf = (finesine[(time+(x+17)*xmul)&FINEMASK]>>13) % ysize;
|
||||
if(yf < 0) yf += ysize;
|
||||
int yt = yf;
|
||||
const BYTE *source = Pixels + (x + ymask * x);
|
||||
BYTE *dest = buffer;
|
||||
for (yt = ysize; yt; yt--, yf = (yf+1)%ysize)
|
||||
*dest++ = source[yf];
|
||||
memcpy (Pixels+(x+ymask*x), buffer, ysize);
|
||||
}
|
||||
WarpBuffer(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed, bWarped);
|
||||
}
|
||||
|
||||
// [mxd] Non power of 2 textures need different offset multipliers, otherwise warp animation won't sync across texture
|
||||
void FWarpTexture::SetupMultipliers (int width, int height)
|
||||
{
|
||||
WidthOffsetMultipiler = width;
|
||||
HeightOffsetMultipiler = height;
|
||||
WidthOffsetMultiplier = width;
|
||||
HeightOffsetMultiplier = height;
|
||||
int widthpo2 = NextPo2(Width);
|
||||
int heightpo2 = NextPo2(Height);
|
||||
if(widthpo2 != Width) WidthOffsetMultipiler = (int)(WidthOffsetMultipiler * ((float)widthpo2 / Width));
|
||||
if(heightpo2 != Height) HeightOffsetMultipiler = (int)(HeightOffsetMultipiler * ((float)heightpo2 / Height));
|
||||
if(widthpo2 != Width) WidthOffsetMultiplier = (int)(WidthOffsetMultiplier * ((float)widthpo2 / Width));
|
||||
if(heightpo2 != Height) HeightOffsetMultiplier = (int)(HeightOffsetMultiplier * ((float)heightpo2 / Height));
|
||||
}
|
||||
|
||||
int FWarpTexture::NextPo2 (int v)
|
||||
|
@ -199,64 +163,6 @@ int FWarpTexture::NextPo2 (int v)
|
|||
return ++v;
|
||||
}
|
||||
|
||||
// [GRB] Eternity-like warping
|
||||
FWarp2Texture::FWarp2Texture (FTexture *source)
|
||||
: FWarpTexture (source)
|
||||
{
|
||||
SetupMultipliers(256, 128); // [mxd]
|
||||
bWarped = 2;
|
||||
}
|
||||
|
||||
void FWarp2Texture::MakeTexture (DWORD time)
|
||||
{
|
||||
const BYTE *otherpix = SourcePic->GetPixels ();
|
||||
|
||||
if (Pixels == NULL)
|
||||
{
|
||||
Pixels = new BYTE[Width * Height];
|
||||
}
|
||||
if (Spans != NULL)
|
||||
{
|
||||
FreeSpans (Spans);
|
||||
Spans = NULL;
|
||||
}
|
||||
|
||||
GenTime = time;
|
||||
|
||||
int xsize = Width;
|
||||
int ysize = Height;
|
||||
int xmul = WidthOffsetMultipiler; // [mxd]
|
||||
int ymul = HeightOffsetMultipiler; // [mxd]
|
||||
int xmask = WidthMask;
|
||||
int ymask = Height - 1;
|
||||
int ybits = HeightBits;
|
||||
int x, y;
|
||||
|
||||
if ((1 << ybits) > Height)
|
||||
{
|
||||
ybits--;
|
||||
}
|
||||
|
||||
DWORD timebase = DWORD(time * Speed * 40 / 28);
|
||||
// [mxd] Rewrote to fix animation for NPo2 textures
|
||||
for (x = 0; x < xsize; x++)
|
||||
{
|
||||
BYTE *dest = Pixels + (x + ymask * x);
|
||||
for (y = 0; y < ysize; y++)
|
||||
{
|
||||
int xt = (x + 128
|
||||
+ ((finesine[(y*ymul + timebase*5 + 900) & FINEMASK]*2)>>FRACBITS)
|
||||
+ ((finesine[(x*xmul + timebase*4 + 300) & FINEMASK]*2)>>FRACBITS)) % xsize;
|
||||
|
||||
int yt = (y + 128
|
||||
+ ((finesine[(y*ymul + timebase*3 + 700) & FINEMASK]*2)>>FRACBITS)
|
||||
+ ((finesine[(x*xmul + timebase*4 + 1200) & FINEMASK]*2)>>FRACBITS)) % ysize;
|
||||
|
||||
*dest++ = otherpix[(xt + ymask * xt) + yt];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMultiPatchTexture :: TexPart :: TexPart
|
||||
|
|
|
@ -320,6 +320,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetDistance)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetAngle
|
||||
//
|
||||
// NON-ACTION function to get the angle in degrees (normalized to -180..180)
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetAngle)
|
||||
{
|
||||
if (numret > 0)
|
||||
{
|
||||
assert(ret != NULL);
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_BOOL(relative);
|
||||
PARAM_INT_OPT(ptr) { ptr = AAPTR_TARGET; }
|
||||
|
||||
AActor *target = COPY_AAPTR(self, ptr);
|
||||
|
||||
if (!target || target == self)
|
||||
{
|
||||
ret->SetFloat(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DVector3 diff = self->Vec3To(target);
|
||||
DAngle angto = diff.Angle();
|
||||
if (relative) angto = deltaangle(self->Angles.Yaw, angto);
|
||||
ret->SetFloat(angto.Degrees);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetSpawnHealth
|
||||
|
@ -2399,12 +2433,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem)
|
|||
ACTION_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
if (distance == 0)
|
||||
{
|
||||
// use the minimum distance that does not result in an overlap
|
||||
distance = (self->radius + GetDefaultByType(missile)->radius);
|
||||
}
|
||||
|
||||
if (ACTION_CALL_FROM_WEAPON())
|
||||
{
|
||||
// Used from a weapon, so use some ammo
|
||||
|
@ -4951,7 +4979,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx)
|
|||
PARAM_FLOAT_OPT(mulWaveZ) { mulWaveZ = 1.; }
|
||||
PARAM_INT_OPT(falloff) { falloff = 0; }
|
||||
PARAM_INT_OPT(highpoint) { highpoint = 0; }
|
||||
P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint);
|
||||
PARAM_FLOAT_OPT(rollIntensity) { rollIntensity = 0.; }
|
||||
PARAM_FLOAT_OPT(rollWave) { rollWave = 0.; }
|
||||
P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint,
|
||||
rollIntensity, rollWave);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF7, FORCEDECAL, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, LAXTELEFRAGDMG, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, ICESHATTER, AActor, flags7),
|
||||
DEFINE_FLAG(MF7, ALLOWTHRUFLAGS, AActor, flags7),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
|
@ -1207,83 +1207,6 @@ void DFrameBuffer::WipeCleanup()
|
|||
wipe_Cleanup();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Create texture hitlist
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void DFrameBuffer::GetHitlist(BYTE *hitlist)
|
||||
{
|
||||
BYTE *spritelist;
|
||||
int i;
|
||||
|
||||
spritelist = new BYTE[sprites.Size()];
|
||||
|
||||
// Precache textures (and sprites).
|
||||
memset (spritelist, 0, sprites.Size());
|
||||
|
||||
{
|
||||
AActor *actor;
|
||||
TThinkerIterator<AActor> iterator;
|
||||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
spritelist[actor->sprite] = 1;
|
||||
}
|
||||
|
||||
for (i = (int)(sprites.Size () - 1); i >= 0; i--)
|
||||
{
|
||||
if (spritelist[i])
|
||||
{
|
||||
int j, k;
|
||||
for (j = 0; j < sprites[i].numframes; j++)
|
||||
{
|
||||
const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j];
|
||||
|
||||
for (k = 0; k < 16; k++)
|
||||
{
|
||||
FTextureID pic = frame->Texture[k];
|
||||
if (pic.isValid())
|
||||
{
|
||||
hitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] spritelist;
|
||||
|
||||
for (i = numsectors - 1; i >= 0; i--)
|
||||
{
|
||||
hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] =
|
||||
hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat;
|
||||
}
|
||||
|
||||
for (i = numsides - 1; i >= 0; i--)
|
||||
{
|
||||
hitlist[sides[i].GetTexture(side_t::top).GetIndex()] =
|
||||
hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] =
|
||||
hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall;
|
||||
}
|
||||
|
||||
// Sky texture is always present.
|
||||
// Note that F_SKY1 is the name used to
|
||||
// indicate a sky floor/ceiling as a flat,
|
||||
// while the sky texture is stored like
|
||||
// a wall texture, with an episode dependant
|
||||
// name.
|
||||
|
||||
if (sky1texture.isValid())
|
||||
{
|
||||
hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky;
|
||||
}
|
||||
if (sky2texture.isValid())
|
||||
{
|
||||
hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DFrameBuffer :: GameRestart
|
||||
|
|
|
@ -395,8 +395,7 @@ public:
|
|||
virtual FNativePalette *CreatePalette(FRemapTable *remap);
|
||||
|
||||
// Precaches or unloads a texture
|
||||
virtual void GetHitlist(BYTE *hitlist);
|
||||
|
||||
|
||||
// Report a game restart
|
||||
virtual void GameRestart();
|
||||
|
||||
|
|
|
@ -1135,7 +1135,8 @@ struct TRotator
|
|||
|
||||
Angle Pitch; // up/down
|
||||
Angle Yaw; // left/right
|
||||
Angle Roll; // rotation about the forward axis
|
||||
Angle Roll; // rotation about the forward axis.
|
||||
Angle CamRoll; // Roll specific to actor cameras. Used by quakes.
|
||||
|
||||
TRotator ()
|
||||
{
|
||||
|
|
|
@ -72,11 +72,11 @@ const char *GetVersionString();
|
|||
// SAVESIG should match SAVEVER.
|
||||
|
||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||
#define MINSAVEVER 4543
|
||||
#define MINSAVEVER 4545
|
||||
|
||||
// Use 4500 as the base git save version, since it's higher than the
|
||||
// SVN revision ever got.
|
||||
#define SAVEVER 4543
|
||||
#define SAVEVER 4545
|
||||
|
||||
#define SAVEVERSTRINGIFY2(x) #x
|
||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||
|
|
|
@ -42,6 +42,7 @@ ACTOR Actor native //: Thinker
|
|||
native bool IsPointerEqual(int ptr_select1, int ptr_select2);
|
||||
native int CountInv(class<Inventory> itemtype, int ptr_select = AAPTR_DEFAULT);
|
||||
native float GetDistance(bool checkz, int ptr = AAPTR_DEFAULT);
|
||||
native float GetAngle(bool relative, int ptr = AAPTR_DEFAULT);
|
||||
native int GetSpawnHealth();
|
||||
native int GetGibHealth();
|
||||
|
||||
|
@ -280,7 +281,7 @@ ACTOR Actor native //: Thinker
|
|||
native void A_SetUserArrayFloat(name varname, int index, float value);
|
||||
native void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0);
|
||||
native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake");
|
||||
native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1, int falloff = 0, int highpoint = 0);
|
||||
native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1, int falloff = 0, int highpoint = 0, float rollIntensity = 0, float rollWave = 0);
|
||||
action native A_SetTics(int tics);
|
||||
native void A_SetDamageType(name damagetype);
|
||||
native void A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
|
||||
|
|
|
@ -15,6 +15,7 @@ ACTOR SecurityCamera native
|
|||
+NOGRAVITY
|
||||
+DONTSPLASH
|
||||
RenderStyle None
|
||||
CameraHeight 0
|
||||
}
|
||||
|
||||
ACTOR AimingCamera : SecurityCamera native
|
||||
|
|
|
@ -28,6 +28,7 @@ ACTOR ActorMover : PathFollower native
|
|||
|
||||
ACTOR MovingCamera : PathFollower native
|
||||
{
|
||||
CameraHeight 0
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ ACTOR MapSpot
|
|||
+NOGRAVITY
|
||||
+DONTSPLASH
|
||||
RenderStyle None
|
||||
CameraHeight 0
|
||||
}
|
||||
|
||||
// same with different editor number for Legacy maps -----------------------
|
||||
|
|
|
@ -231,3 +231,6 @@ enum
|
|||
444 = 0, Teleport(0)
|
||||
445 = 0, Teleport_NoFog(0)
|
||||
446 = 0, Teleport_Line(0)
|
||||
447 = 0, Exit_Normal(0)
|
||||
448 = 0, Exit_Secret(0)
|
||||
449 = 0, Teleport_NewMap(0)
|
||||
|
|
Loading…
Reference in a new issue