- backend update from GZDoom.

mainly TAngle overhaul and needed code adjustments.
This commit is contained in:
Christoph Oelckers 2022-08-26 18:28:22 +02:00
parent ca1171187f
commit 111dbd7a7d
26 changed files with 322 additions and 240 deletions

View file

@ -739,7 +739,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
poly.mColor1.g = uint8_t(colormap.FadeColor.g * fadelevel); poly.mColor1.g = uint8_t(colormap.FadeColor.g * fadelevel);
poly.mColor1.b = uint8_t(colormap.FadeColor.b * fadelevel); poly.mColor1.b = uint8_t(colormap.FadeColor.b * fadelevel);
bool dorotate = rotation != 0; bool dorotate = rotation != nullAngle;
float cosrot = (float)cos(rotation.Radians()); float cosrot = (float)cos(rotation.Radians());
float sinrot = (float)sin(rotation.Radians()); float sinrot = (float)sin(rotation.Radians());

View file

@ -52,6 +52,8 @@
#include "version.h" #include "version.h"
#include "findfile.h" #include "findfile.h"
#include "md5.h" #include "md5.h"
#include "i_specialpaths.h"
#include "i_system.h"
extern FILE* Logfile; extern FILE* Logfile;
@ -177,12 +179,12 @@ UNSAFE_CCMD (crashout)
UNSAFE_CCMD (dir) UNSAFE_CCMD (dir)
{ {
FString dir, path; FString dir, path;
char curdir[256];
const char *match; const char *match;
findstate_t c_file; findstate_t c_file;
void *file; void *file;
if (!getcwd (curdir, countof(curdir))) FString curdir = I_GetCWD();
if (curdir.IsEmpty())
{ {
Printf ("Current path too long\n"); Printf ("Current path too long\n");
return; return;
@ -191,7 +193,7 @@ UNSAFE_CCMD (dir)
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
path = NicePath(argv[1]); path = NicePath(argv[1]);
if (chdir(path)) if (!I_ChDir(path))
{ {
match = path; match = path;
dir = ExtractFilePath(path); dir = ExtractFilePath(path);
@ -207,7 +209,7 @@ UNSAFE_CCMD (dir)
{ {
match = "*"; match = "*";
} }
if (chdir (dir)) if (!I_ChDir(dir))
{ {
Printf ("%s not found\n", dir.GetChars()); Printf ("%s not found\n", dir.GetChars());
return; return;
@ -244,7 +246,7 @@ UNSAFE_CCMD (dir)
I_FindClose (file); I_FindClose (file);
} }
chdir (curdir); I_ChDir(curdir);
} }
//========================================================================== //==========================================================================
@ -336,3 +338,4 @@ CCMD(printlocalized)
} }
} }

View file

@ -15,7 +15,9 @@ enum
struct FRemapTable struct FRemapTable
{ {
FRemapTable(int count = 256) { NumEntries = count; } FRemapTable(int count = 256) { NumEntries = count; }
FRemapTable(const FRemapTable& o) = default; FRemapTable(const FRemapTable& o) = default;
FRemapTable& operator=(const FRemapTable& o) = default;
bool operator==(const FRemapTable& o); bool operator==(const FRemapTable& o);
void MakeIdentity(); void MakeIdentity();

View file

@ -339,7 +339,7 @@ inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector2& p, FV
template<class T> template<class T>
inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle<T> &p, TAngle<T> *def) inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle<T> &p, TAngle<T> *def)
{ {
return Serialize(arc, key, p.Degrees, def? &def->Degrees : nullptr); return Serialize(arc, key, p.Degrees__(), def ? &def->Degrees__() : nullptr);
} }
inline FSerializer &Serialize(FSerializer &arc, const char *key, PalEntry &pe, PalEntry *def) inline FSerializer &Serialize(FSerializer &arc, const char *key, PalEntry &pe, PalEntry *def)

View file

@ -1608,17 +1608,17 @@ FileData::~FileData ()
{ {
} }
FString::FString (ELumpNum lumpnum) FString::FString(ELumpNum lumpnum)
{ {
auto lumpr = fileSystem.OpenFileReader ((int)lumpnum); auto lumpr = fileSystem.OpenFileReader((int)lumpnum);
auto size = lumpr.GetLength (); auto size = lumpr.GetLength();
AllocBuffer (1 + size); AllocBuffer(size);
auto numread = lumpr.Read (&Chars[0], size); auto numread = lumpr.Read(&Chars[0], size);
Chars[size] = '\0'; Chars[size] = '\0';
if (numread != size) if (numread != size)
{ {
I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n", I_Error("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum)); numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum));
} }
} }

View file

@ -232,7 +232,7 @@ int FUE1Model::FindFrame( const char *name, bool nodefault )
void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids)
{ {
// the moment of magic // the moment of magic
if ( (frame >= numFrames) || (frame2 >= numFrames) ) return; if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return;
renderer->SetInterpolation(inter); renderer->SetInterpolation(inter);
int vsize, fsize = 0, vofs = 0; int vsize, fsize = 0, vofs = 0;
for ( int i=0; i<numGroups; i++ ) fsize += groups[i].numPolys*3; for ( int i=0; i<numGroups; i++ ) fsize += groups[i].numPolys*3;

View file

@ -317,7 +317,7 @@ FVoxelDef *R_LoadVoxelDef(int lumpnum, int spin)
voxdef->Voxel = vox; voxdef->Voxel = vox;
voxdef->Scale = 1.; voxdef->Scale = 1.;
voxdef->DroppedSpin = voxdef->PlacedSpin = spin; voxdef->DroppedSpin = voxdef->PlacedSpin = spin;
voxdef->AngleOffset = 90.; voxdef->AngleOffset = DAngle::fromDeg(90.);
Voxels.Push(vox); Voxels.Push(vox);
VoxelDefs.Push(voxdef); VoxelDefs.Push(voxdef);

View file

@ -170,3 +170,26 @@ unsigned int I_MakeRNGSeed()
{ {
return static_cast<unsigned int>(arc4random()); return static_cast<unsigned int>(arc4random());
} }
FString I_GetCWD()
{
NSString *currentpath = [[NSFileManager defaultManager] currentDirectoryPath];
return currentpath.UTF8String;
}
bool I_ChDir(const char* path)
{
return [[NSFileManager defaultManager] changeCurrentDirectoryPath:[NSString stringWithUTF8String:path]];
}
void I_OpenShellFolder(const char* folder)
{
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *currentpath = [filemgr currentDirectoryPath];
[filemgr changeCurrentDirectoryPath:[NSString stringWithUTF8String:folder]];
Printf("Opening folder: %s\n", folder);
std::system("open .");
[filemgr changeCurrentDirectoryPath:currentpath];
}

View file

@ -69,4 +69,8 @@ inline int I_GetNumaNodeCount() { return 1; }
inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max<int>(std::thread::hardware_concurrency(), 1); } inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max<int>(std::thread::hardware_concurrency(), 1); }
inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { } inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { }
FString I_GetCWD();
bool I_ChDir(const char* path);
void I_OpenShellFolder(const char*);
#endif #endif

View file

@ -410,6 +410,23 @@ FString I_GetFromClipboard (bool use_primary_selection)
return ""; return "";
} }
FString I_GetCWD()
{
char* curdir = get_current_dir_name();
if (!curdir)
{
return "";
}
FString ret(curdir);
free(curdir);
return ret;
}
bool I_ChDir(const char* path)
{
return chdir(path) == 0;
}
// Return a random seed, preferably one with lots of entropy. // Return a random seed, preferably one with lots of entropy.
unsigned int I_MakeRNGSeed() unsigned int I_MakeRNGSeed()
{ {
@ -431,3 +448,21 @@ unsigned int I_MakeRNGSeed()
} }
return seed; return seed;
} }
void I_OpenShellFolder(const char* infolder)
{
char* curdir = get_current_dir_name();
if (!chdir(infolder))
{
Printf("Opening folder: %s\n", infolder);
std::system("xdg-open .");
chdir(curdir);
}
else
{
Printf("Unable to open directory '%s\n", infolder);
}
free(curdir);
}

View file

@ -283,7 +283,7 @@ FString M_GetScreenshotsPath()
if (!UseKnownFolders()) if (!UseKnownFolders())
{ {
path << progdir << "/Screenshots/"; path << progdir << "Screenshots/";
} }
else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path)) else if (GetKnownFolder(-1, MyFOLDERID_Screenshots, true, path))
{ {

View file

@ -6,6 +6,7 @@
** Copyright 1998-2009 Randy Heit ** Copyright 1998-2009 Randy Heit
** Copyright (C) 2007-2012 Skulltag Development Team ** Copyright (C) 2007-2012 Skulltag Development Team
** Copyright (C) 2007-2016 Zandronum Development Team ** Copyright (C) 2007-2016 Zandronum Development Team
** Copyright (C) 2017-2022 GZDoom Development Team
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -49,9 +50,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdexcept>
#include <process.h> #include <process.h>
#include <time.h> #include <time.h>
#include <map> #include <map>
#include <codecvt>
#include <stdarg.h> #include <stdarg.h>
@ -62,6 +65,8 @@
#include <wincrypt.h> #include <wincrypt.h>
#include <shlwapi.h> #include <shlwapi.h>
#include <shellapi.h>
#include "hardware.h" #include "hardware.h"
#include "printf.h" #include "printf.h"
@ -955,3 +960,43 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode)
SetThreadAffinityMask(handle, (DWORD_PTR)numaNodes[numaNode].affinityMask); SetThreadAffinityMask(handle, (DWORD_PTR)numaNodes[numaNode].affinityMask);
} }
} }
FString I_GetCWD()
{
auto len = GetCurrentDirectoryW(0, nullptr);
TArray<wchar_t> curdir(len + 1, true);
if (!GetCurrentDirectoryW(len + 1, curdir.Data()))
{
return "";
}
FString returnv(curdir.Data());
FixPathSeperator(returnv);
return returnv;
}
bool I_ChDir(const char* path)
{
return SetCurrentDirectoryW(WideString(path).c_str());
}
void I_OpenShellFolder(const char* infolder)
{
auto len = GetCurrentDirectoryW(0, nullptr);
TArray<wchar_t> curdir(len + 1, true);
if (!GetCurrentDirectoryW(len + 1, curdir.Data()))
{
Printf("Unable to retrieve current directory\n");
}
else if (SetCurrentDirectoryW(WideString(infolder).c_str()))
{
Printf("Opening folder: %s\n", infolder);
ShellExecuteW(NULL, L"open", L"explorer.exe", L".", NULL, SW_SHOWNORMAL);
SetCurrentDirectoryW(curdir.Data());
}
else
{
Printf("Unable to open directory '%s\n", infolder);
}
}

View file

@ -79,4 +79,8 @@ int I_GetNumaNodeCount();
int I_GetNumaNodeThreadCount(int numaNode); int I_GetNumaNodeThreadCount(int numaNode);
void I_SetThreadNumaNode(std::thread &thread, int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode);
void I_OpenShellFolder(const char*);
FString I_GetCWD();
bool I_ChDir(const char* path);
#endif #endif

View file

@ -147,10 +147,10 @@ FSkyVertexBuffer::~FSkyVertexBuffer()
void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip) void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip)
{ {
static const FAngle maxSideAngle = 60.f; static const FAngle maxSideAngle = FAngle::fromDeg(60.f);
static const float scale = 10000.; static const float scale = 10000.;
FAngle topAngle = (c / (float)mColumns * 360.f); FAngle topAngle = FAngle::fromDeg((c / (float)mColumns * 360.f));
FAngle sideAngle = maxSideAngle * float(mRows - r) / float(mRows); FAngle sideAngle = maxSideAngle * float(mRows - r) / float(mRows);
float height = sideAngle.Sin(); float height = sideAngle.Sin();
float realRadius = scale * sideAngle.Cos(); float realRadius = scale * sideAngle.Cos();
@ -190,10 +190,10 @@ void FSkyVertexBuffer::SkyVertexDoom(int r, int c, bool zflip)
void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip) void FSkyVertexBuffer::SkyVertexBuild(int r, int c, bool zflip)
{ {
static const FAngle maxSideAngle = 60.f; static const FAngle maxSideAngle = FAngle::fromDeg(60.f);
static const float scale = 10000.; static const float scale = 10000.;
FAngle topAngle = (c / (float)mColumns * 360.f); FAngle topAngle = FAngle::fromDeg((c / (float)mColumns * 360.f));
FVector2 pos = topAngle.ToVector(scale); FVector2 pos = topAngle.ToVector(scale);
float z = (!zflip) ? (mRows - r) * 4000.f : -(mRows - r) * 4000.f; float z = (!zflip) ? (mRows - r) * 4000.f : -(mRows - r) * 4000.f;

View file

@ -2596,7 +2596,7 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx)
auto rets = VMRight->GetReturnTypes(); auto rets = VMRight->GetReturnTypes();
if (Base.Size() == 1) if (Base.Size() == 1)
{ {
Right->ScriptPosition.Message(MSG_ERROR, "Multi-assignment with only one element", VMRight->Function->SymbolName.GetChars()); Right->ScriptPosition.Message(MSG_ERROR, "Multi-assignment with only one element in function %s", VMRight->Function->SymbolName.GetChars());
delete this; delete this;
return nullptr; return nullptr;
} }

View file

@ -315,6 +315,10 @@ struct VMValue
{ {
i = v; i = v;
} }
VMValue(unsigned int v)
{
i = v;
}
VMValue(double v) VMValue(double v)
{ {
f = v; f = v;
@ -511,7 +515,8 @@ bool AssertObject(void * ob);
#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FSoundID x = param[p].i; #define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); FSoundID x = param[p].i;
#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); PalEntry x; x.d = param[p].i; #define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); PalEntry x; x.d = param[p].i;
#define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); double x = param[p].f; #define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); double x = param[p].f;
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); DAngle x = param[p].f; #define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); DAngle x = DAngle::fromDeg(param[p].f);
#define PARAM_FANGLE_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_FLOAT); FAngle x = FAngle::fromDeg(param[p].f);
#define PARAM_STRING_VAL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); FString x = param[p].s(); #define PARAM_STRING_VAL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); FString x = param[p].s();
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); const FString &x = param[p].s(); #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_STRING); const FString &x = param[p].s();
#define PARAM_STATELABEL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); int x = param[p].i; #define PARAM_STATELABEL_AT(p,x) assert((p) < numparam); assert(reginfo[p] == REGT_INT); int x = param[p].i;
@ -538,6 +543,7 @@ bool AssertObject(void * ob);
#define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x) #define PARAM_COLOR(x) ++paramnum; PARAM_COLOR_AT(paramnum,x)
#define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x) #define PARAM_FLOAT(x) ++paramnum; PARAM_FLOAT_AT(paramnum,x)
#define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x) #define PARAM_ANGLE(x) ++paramnum; PARAM_ANGLE_AT(paramnum,x)
#define PARAM_FANGLE(x) ++paramnum; PARAM_FANGLE_AT(paramnum,x)
#define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x) #define PARAM_STRING(x) ++paramnum; PARAM_STRING_AT(paramnum,x)
#define PARAM_STRING_VAL(x) ++paramnum; PARAM_STRING_VAL_AT(paramnum,x) #define PARAM_STRING_VAL(x) ++paramnum; PARAM_STRING_VAL_AT(paramnum,x)
#define PARAM_STATELABEL(x) ++paramnum; PARAM_STATELABEL_AT(paramnum,x) #define PARAM_STATELABEL(x) ++paramnum; PARAM_STATELABEL_AT(paramnum,x)

View file

@ -54,14 +54,14 @@ extern FFastTrig fasttrig;
#define RAD2BAM(f) ((unsigned)xs_CRoundToInt((f) * (0x80000000/3.14159265358979323846))) #define RAD2BAM(f) ((unsigned)xs_CRoundToInt((f) * (0x80000000/3.14159265358979323846)))
inline double fastcosbam(double v) inline double fastcosbam(unsigned int v)
{ {
return fasttrig.cos(xs_CRoundToUInt(v)); return fasttrig.cos(v);
} }
inline double fastsinbam(double v) inline double fastsinbam(unsigned int v)
{ {
return fasttrig.sin(xs_CRoundToUInt(v)); return fasttrig.sin(v);
} }
inline double fastcosdeg(double v) inline double fastcosdeg(double v)

View file

@ -100,7 +100,7 @@ inline void fillshort(void* buff, size_t count, uint16_t clear)
} }
} }
template<typename T> inline constexpr T Sgn(const T& val) { return (val > 0) - (val < 0); } template<typename T> inline constexpr int Sgn(const T& val) { return (val > 0) - (val < 0); }
inline int sizeToBits(int w) inline int sizeToBits(int w)

View file

@ -37,6 +37,7 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "printf.h" #include "printf.h"
#include "configfile.h" #include "configfile.h"
#include "i_system.h"
#ifndef _WIN32 #ifndef _WIN32
@ -369,9 +370,8 @@ void D_AddConfigFiles(TArray<FString>& wadfiles, const char* section, const char
void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *filespec, FConfigFile* config) void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *filespec, FConfigFile* config)
{ {
char curdir[ZPATH_MAX]; FString curdir = I_GetCWD();
if (curdir.IsNotEmpty())
if (getcwd(curdir, ZPATH_MAX))
{ {
char skindir[ZPATH_MAX]; char skindir[ZPATH_MAX];
findstate_t findstate; findstate_t findstate;
@ -387,7 +387,7 @@ void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *file
skindir[--stuffstart] = 0; skindir[--stuffstart] = 0;
} }
if (!chdir(skindir)) if (I_ChDir(skindir))
{ {
skindir[stuffstart++] = '/'; skindir[stuffstart++] = '/';
if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1)
@ -403,7 +403,7 @@ void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *file
I_FindClose(handle); I_FindClose(handle);
} }
} }
chdir(curdir); I_ChDir(curdir);
} }
} }
@ -417,27 +417,27 @@ void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *file
// //
//========================================================================== //==========================================================================
static FString BFSwad; // outside the function to evade C++'s insane rules for constructing static variables inside functions.
const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config) const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config)
{ {
static char wad[ZPATH_MAX];
if (file == nullptr || *file == '\0') if (file == nullptr || *file == '\0')
{ {
return nullptr; return nullptr;
} }
if (lookfirstinprogdir) if (lookfirstinprogdir)
{ {
mysnprintf(wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); BFSwad.Format("%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file);
if (DirEntryExists(wad)) if (DirEntryExists(BFSwad))
{ {
return wad; return BFSwad.GetChars();
} }
} }
if (DirEntryExists(file)) if (DirEntryExists(file))
{ {
mysnprintf(wad, countof(wad), "%s", file); BFSwad.Format("%s", file);
return wad; return BFSwad.GetChars();
} }
if (config != nullptr && config->SetSection("FileSearch.Directories")) if (config != nullptr && config->SetSection("FileSearch.Directories"))
@ -454,10 +454,10 @@ const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinpr
dir = NicePath(value); dir = NicePath(value);
if (dir.IsNotEmpty()) if (dir.IsNotEmpty())
{ {
mysnprintf(wad, countof(wad), "%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); BFSwad.Format("%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file);
if (DirEntryExists(wad)) if (DirEntryExists(BFSwad))
{ {
return wad; return BFSwad.GetChars();
} }
} }
} }

View file

@ -40,20 +40,9 @@ inline unsigned FloatToAngle(double f)
return xs_CRoundToInt((f)* (0x40000000 / 90.)); return xs_CRoundToInt((f)* (0x40000000 / 90.));
} }
inline constexpr double AngleToFloat(unsigned f)
{
return f * (90. / 0x40000000);
}
inline constexpr double AngleToFloat(int f)
{
return f * (90. / 0x40000000);
}
#define FLOAT2FIXED(f) FloatToFixed(f) #define FLOAT2FIXED(f) FloatToFixed(f)
#define FIXED2FLOAT(f) float(FixedToFloat(f)) #define FIXED2FLOAT(f) float(FixedToFloat(f))
#define FIXED2DBL(f) FixedToFloat(f) #define FIXED2DBL(f) FixedToFloat(f)
#define ANGLE2DBL(f) AngleToFloat(f)
#endif #endif

View file

@ -343,6 +343,11 @@ struct TVector3
return X == 0 && Y == 0 && Z == 0; return X == 0 && Y == 0 && Z == 0;
} }
TVector3 plusZ(double z)
{
return { X, Y, Z + z };
}
TVector3 &operator= (const TVector3 &other) = default; TVector3 &operator= (const TVector3 &other) = default;
// Access X and Y and Z as an array // Access X and Y and Z as an array
@ -1139,7 +1144,7 @@ Outside comments: A faster version with only 10 (not 24) multiplies.
template<class vec_t> template<class vec_t>
struct TAngle struct TAngle
{ {
vec_t Degrees; vec_t Degrees_;
// This is to catch any accidental attempt to assign an angle_t to this type. Any explicit exception will require a type cast. // This is to catch any accidental attempt to assign an angle_t to this type. Any explicit exception will require a type cast.
TAngle(int) = delete; TAngle(int) = delete;
@ -1153,180 +1158,146 @@ struct TAngle
TAngle() = default; TAngle() = default;
TAngle (vec_t amt) private:
: Degrees(amt) // Both constructors are needed to avoid unnecessary conversions when assigning to FAngle.
constexpr TAngle (float amt)
: Degrees_((vec_t)amt)
{ {
} }
constexpr TAngle (double amt)
: Degrees_((vec_t)amt)
{
}
public:
vec_t& Degrees__() { return Degrees_; }
static constexpr TAngle fromDeg(float deg)
{
return TAngle(deg);
}
static constexpr TAngle fromDeg(double deg)
{
return TAngle(deg);
}
static constexpr TAngle fromDeg(int deg)
{
return TAngle((vec_t)deg);
}
static constexpr TAngle fromDeg(unsigned deg)
{
return TAngle((vec_t)deg);
}
static constexpr TAngle fromRad(float rad)
{
return TAngle(float(rad * (180.0f / pi::pif())));
}
static constexpr TAngle fromRad(double rad)
{
return TAngle(double(rad * (180.0 / pi::pi())));
}
static constexpr TAngle fromBam(int f)
{
return TAngle(f * (90. / 0x40000000));
}
static constexpr TAngle fromBam(unsigned f)
{
return TAngle(f * (90. / 0x40000000));
}
static constexpr TAngle fromBuild(int bang)
{
return TAngle(bang * (90. / 512));
}
static constexpr TAngle fromQ16(int bang)
{
return TAngle(bang * (90. / 16384));
}
TAngle(const TAngle &other) = default; TAngle(const TAngle &other) = default;
TAngle &operator= (const TAngle &other) = default; TAngle &operator= (const TAngle &other) = default;
TAngle &operator= (double other) constexpr TAngle operator- () const
{ {
Degrees = (decltype(Degrees))other; return TAngle(-Degrees_);
}
constexpr TAngle &operator+= (TAngle other)
{
Degrees_ += other.Degrees_;
return *this; return *this;
} }
// intentionally disabled so that common math functions cannot be accidentally called with a TAngle. constexpr TAngle &operator-= (TAngle other)
//operator vec_t() const { return Degrees; }
TAngle operator- () const
{ {
return TAngle(-Degrees); Degrees_ -= other.Degrees_;
}
TAngle &operator+= (TAngle other)
{
Degrees += other.Degrees;
return *this; return *this;
} }
TAngle &operator-= (TAngle other) constexpr TAngle operator+ (TAngle other) const
{ {
Degrees -= other.Degrees; return Degrees_ + other.Degrees_;
}
constexpr TAngle operator- (TAngle other) const
{
return Degrees_ - other.Degrees_;
}
constexpr TAngle &operator*= (vec_t other)
{
Degrees_ = Degrees_ * other;
return *this; return *this;
} }
TAngle &operator*= (TAngle other) constexpr TAngle &operator/= (vec_t other)
{ {
Degrees *= other.Degrees; Degrees_ = Degrees_ / other;
return *this; return *this;
} }
TAngle &operator/= (TAngle other) constexpr TAngle operator* (vec_t other) const
{ {
Degrees /= other.Degrees; return Degrees_ * other;
return *this;
} }
TAngle operator+ (TAngle other) const constexpr TAngle operator/ (vec_t other) const
{ {
return Degrees + other.Degrees; return Degrees_ / other;
}
TAngle operator- (TAngle other) const
{
return Degrees - other.Degrees;
}
TAngle operator* (TAngle other) const
{
return Degrees * other.Degrees;
}
TAngle operator/ (TAngle other) const
{
return Degrees / other.Degrees;
}
TAngle &operator+= (vec_t other)
{
Degrees = Degrees + other;
return *this;
}
TAngle &operator-= (vec_t other)
{
Degrees = Degrees - other;
return *this;
}
TAngle &operator*= (vec_t other)
{
Degrees = Degrees * other;
return *this;
}
TAngle &operator/= (vec_t other)
{
Degrees = Degrees / other;
return *this;
}
TAngle operator+ (vec_t other) const
{
return Degrees + other;
}
TAngle operator- (vec_t other) const
{
return Degrees - other;
}
friend TAngle operator- (vec_t o1, TAngle o2)
{
return TAngle(o1 - o2.Degrees);
}
TAngle operator* (vec_t other) const
{
return Degrees * other;
}
TAngle operator/ (vec_t other) const
{
return Degrees / other;
} }
// Should the comparisons consider an epsilon value? // Should the comparisons consider an epsilon value?
bool operator< (TAngle other) const constexpr bool operator< (TAngle other) const
{ {
return Degrees < other.Degrees; return Degrees_ < other.Degrees_;
} }
bool operator> (TAngle other) const constexpr bool operator> (TAngle other) const
{ {
return Degrees > other.Degrees; return Degrees_ > other.Degrees_;
} }
bool operator<= (TAngle other) const constexpr bool operator<= (TAngle other) const
{ {
return Degrees <= other.Degrees; return Degrees_ <= other.Degrees_;
} }
bool operator>= (TAngle other) const constexpr bool operator>= (TAngle other) const
{ {
return Degrees >= other.Degrees; return Degrees_ >= other.Degrees_;
} }
bool operator== (TAngle other) const constexpr bool operator== (TAngle other) const
{ {
return Degrees == other.Degrees; return Degrees_ == other.Degrees_;
} }
bool operator!= (TAngle other) const constexpr bool operator!= (TAngle other) const
{ {
return Degrees != other.Degrees; return Degrees_ != other.Degrees_;
}
bool operator< (vec_t other) const
{
return Degrees < other;
}
bool operator> (vec_t other) const
{
return Degrees > other;
}
bool operator<= (vec_t other) const
{
return Degrees <= other;
}
bool operator>= (vec_t other) const
{
return Degrees >= other;
}
bool operator== (vec_t other) const
{
return Degrees == other;
}
bool operator!= (vec_t other) const
{
return Degrees != other;
} }
// Ensure the angle is between [0.0,360.0) degrees // Ensure the angle is between [0.0,360.0) degrees
@ -1343,14 +1314,29 @@ struct TAngle
return (vec_t)(BAM_FACTOR * (signed int)BAMs()); return (vec_t)(BAM_FACTOR * (signed int)BAMs());
} }
vec_t Radians() const constexpr vec_t Radians() const
{ {
return vec_t(Degrees * (pi::pi() / 180.0)); return vec_t(Degrees_ * (pi::pi() / 180.0));
} }
unsigned BAMs() const unsigned BAMs() const
{ {
return xs_CRoundToInt(Degrees * (0x40000000 / 90.)); return xs_CRoundToInt(Degrees_ * (0x40000000 / 90.));
}
constexpr vec_t Degrees() const
{
return Degrees_;
}
constexpr int Buildang() const
{
return int(Degrees_ * (512 / 90.0));
}
constexpr int Q16() const
{
return int(Degrees_ * (16384 / 90.0));
} }
TVector2<vec_t> ToVector(vec_t length = 1) const TVector2<vec_t> ToVector(vec_t length = 1) const
@ -1360,12 +1346,12 @@ struct TAngle
vec_t Cos() const vec_t Cos() const
{ {
return vec_t(g_cosdeg(Degrees)); return vec_t(g_cosdeg(Degrees_));
} }
vec_t Sin() const vec_t Sin() const
{ {
return vec_t(g_sindeg(Degrees)); return vec_t(g_sindeg(Degrees_));
} }
double Tan() const double Tan() const
@ -1378,24 +1364,24 @@ struct TAngle
{ {
return clamp(Tan(), -max, max); return clamp(Tan(), -max, max);
} }
static inline TAngle ToDegrees(double rad)
{
return TAngle(double(rad * (180.0 / pi::pi())));
}
}; };
// Emulates the old floatbob offset table with direct calls to trig functions. // Emulates the old floatbob offset table with direct calls to trig functions.
inline double BobSin(double fb) inline double BobSin(double fb)
{ {
return TAngle<double>(double(fb * (180.0 / 32))).Sin() * 8; return g_sindeg(double(fb * (180.0 / 32))) * 8;
} }
template<class T> template<class T>
inline TAngle<T> fabs (const TAngle<T> &deg) inline TAngle<T> fabs (const TAngle<T> &deg)
{ {
return TAngle<T>(fabs(deg.Degrees)); return TAngle<T>::fromDeg(fabs(deg.Degrees()));
}
template<class T>
inline TAngle<T> abs (const TAngle<T> &deg)
{
return TAngle<T>::fromDeg(fabs(deg.Degrees()));
} }
template<class T> template<class T>
@ -1404,45 +1390,27 @@ inline TAngle<T> deltaangle(const TAngle<T> &a1, const TAngle<T> &a2)
return (a2 - a1).Normalized180(); return (a2 - a1).Normalized180();
} }
template<class T>
inline TAngle<T> deltaangle(const TAngle<T> &a1, double a2)
{
return (a2 - a1).Normalized180();
}
template<class T>
inline TAngle<T> deltaangle(double a1, const TAngle<T> &a2)
{
return (a2 - a1).Normalized180();
}
template<class T> template<class T>
inline TAngle<T> absangle(const TAngle<T> &a1, const TAngle<T> &a2) inline TAngle<T> absangle(const TAngle<T> &a1, const TAngle<T> &a2)
{ {
return fabs((a1 - a2).Normalized180()); return fabs((a1 - a2).Normalized180());
} }
template<class T>
inline TAngle<T> absangle(const TAngle<T> &a1, double a2)
{
return fabs((a1 - a2).Normalized180());
}
inline TAngle<double> VecToAngle(double x, double y) inline TAngle<double> VecToAngle(double x, double y)
{ {
return g_atan2(y, x) * (180.0 / pi::pi()); return TAngle<double>::fromRad(g_atan2(y, x));
} }
template<class T> template<class T>
inline TAngle<T> VecToAngle (const TVector2<T> &vec) inline TAngle<T> VecToAngle (const TVector2<T> &vec)
{ {
return (T)g_atan2(vec.Y, vec.X) * (180.0 / pi::pi()); return TAngle<T>::fromRad(g_atan2(vec.Y, vec.X));
} }
template<class T> template<class T>
inline TAngle<T> VecToAngle (const TVector3<T> &vec) inline TAngle<T> VecToAngle (const TVector3<T> &vec)
{ {
return (T)g_atan2(vec.Y, vec.X) * (180.0 / pi::pi()); return TAngle<T>::fromRad(g_atan2(vec.Y, vec.X));
} }
template<class T> template<class T>
@ -1562,14 +1530,14 @@ struct TRotator
// Scalar division // Scalar division
TRotator &operator/= (const Angle &scalar) TRotator &operator/= (const Angle &scalar)
{ {
Angle mul(1 / scalar.Degrees); Angle mul(1 / scalar.Degrees_);
Pitch *= scalar, Yaw *= scalar, Roll *= scalar; Pitch *= scalar, Yaw *= scalar, Roll *= scalar;
return *this; return *this;
} }
TRotator operator/ (const Angle &scalar) const TRotator operator/ (const Angle &scalar) const
{ {
Angle mul(1 / scalar.Degrees); Angle mul(1 / scalar.Degrees_);
return TRotator(Pitch * mul, Yaw * mul, Roll * mul); return TRotator(Pitch * mul, Yaw * mul, Roll * mul);
} }
@ -1646,6 +1614,8 @@ typedef TRotator<double> DRotator;
typedef TMatrix3x3<double> DMatrix3x3; typedef TMatrix3x3<double> DMatrix3x3;
typedef TAngle<double> DAngle; typedef TAngle<double> DAngle;
constexpr DAngle nullAngle = DAngle::fromDeg(0.);
constexpr FAngle nullFAngle = FAngle::fromDeg(0.);
class Plane class Plane
{ {

View file

@ -39,6 +39,7 @@
#include <math.h> #include <math.h>
#include "basics.h" #include "basics.h"
#include "m_fixed.h" #include "m_fixed.h"
#include "vectors.h"
#include "xs_Float.h" // needed for reliably overflowing float->int conversions. #include "xs_Float.h" // needed for reliably overflowing float->int conversions.
#include "serializer.h" #include "serializer.h"
#include "math/cmath.h" #include "math/cmath.h"
@ -136,13 +137,13 @@ public:
constexpr fixed_t asq16() const { return value >> 5; } constexpr fixed_t asq16() const { return value >> 5; }
constexpr uint32_t asbam() const { return value; } constexpr uint32_t asbam() const { return value; }
constexpr double asrad() const { return value * (pi::pi() / 0x80000000u); } constexpr double asrad() const { return value * (pi::pi() / 0x80000000u); }
constexpr double asdeg() const { return AngleToFloat(value); } constexpr double asdeg() const { return DAngle::fromBam(value).Degrees(); }
constexpr short signedbuild() const { return tosigned() >> BAMBITS; } constexpr short signedbuild() const { return tosigned() >> BAMBITS; }
constexpr double signedbuildf() const { return tosigned() * (1. / +BAMUNIT); } constexpr double signedbuildf() const { return tosigned() * (1. / +BAMUNIT); }
constexpr fixed_t signedq16() const { return tosigned() >> 5; } constexpr fixed_t signedq16() const { return tosigned() >> 5; }
constexpr int32_t signedbam() const { return tosigned(); } constexpr int32_t signedbam() const { return tosigned(); }
constexpr double signedrad() const { return tosigned() * (pi::pi() / 0x80000000u); } constexpr double signedrad() const { return tosigned() * (pi::pi() / 0x80000000u); }
constexpr double signeddeg() const { return AngleToFloat(tosigned()); } constexpr double signeddeg() const { return DAngle::fromBam(tosigned()).Degrees(); }
double fsin() const { return g_sinbam(asbam()); } double fsin() const { return g_sinbam(asbam()); }
double fcos() const { return g_cosbam(asbam()); } double fcos() const { return g_cosbam(asbam()); }

View file

@ -150,12 +150,12 @@ void RenderViewpoint(FRenderViewpoint& mainvp, IntRect* bounds, float fov, float
di->Set3DViewport(RenderState); di->Set3DViewport(RenderState);
float flash = 8.f / (r_scenebrightness + 8.f); float flash = 8.f / (r_scenebrightness + 8.f);
di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) di->Viewpoint.FieldOfView = FAngle::fromDeg(fov); // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
// Stereo mode specific perspective projection // Stereo mode specific perspective projection
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio); di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio);
// Stereo mode specific viewpoint adjustment // Stereo mode specific viewpoint adjustment
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees); vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees());
di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
di->ProcessScene(toscreen); di->ProcessScene(toscreen);
@ -199,13 +199,13 @@ FRenderViewpoint SetupViewpoint(DCoreActor* cam, const vec3_t& position, int sec
r_viewpoint.SectNums = nullptr; r_viewpoint.SectNums = nullptr;
r_viewpoint.SectCount = sectnum; r_viewpoint.SectCount = sectnum;
r_viewpoint.Pos = { position.X / 16.f, position.Y / -16.f, position.Z / -256.f }; r_viewpoint.Pos = { position.X / 16.f, position.Y / -16.f, position.Z / -256.f };
r_viewpoint.HWAngles.Yaw = -90.f + angle.asdeg(); r_viewpoint.HWAngles.Yaw = FAngle::fromDeg(- 90.f + angle.asdeg());
r_viewpoint.HWAngles.Pitch = -horizon.aspitch(); r_viewpoint.HWAngles.Pitch = FAngle::fromDeg(-horizon.aspitch());
r_viewpoint.HWAngles.Roll = -rollang.asdeg(); r_viewpoint.HWAngles.Roll = FAngle::fromDeg(-rollang.asdeg());
r_viewpoint.FieldOfView = fov > 0? fov : (float)r_fov; r_viewpoint.FieldOfView = FAngle::fromDeg(fov > 0? fov : (float)r_fov);
r_viewpoint.RotAngle = angle.asbam(); r_viewpoint.RotAngle = angle.asbam();
double FocalTangent = tan(r_viewpoint.FieldOfView.Radians() / 2); double FocalTangent = tan(r_viewpoint.FieldOfView.Radians() / 2);
DAngle an = 270. - r_viewpoint.HWAngles.Yaw.Degrees; DAngle an = DAngle::fromDeg(270. - r_viewpoint.HWAngles.Yaw.Degrees());
r_viewpoint.TanSin = FocalTangent * an.Sin(); r_viewpoint.TanSin = FocalTangent * an.Sin();
r_viewpoint.TanCos = FocalTangent * an.Cos(); r_viewpoint.TanCos = FocalTangent * an.Cos();
r_viewpoint.ViewVector = an.ToVector(); r_viewpoint.ViewVector = an.ToVector();
@ -272,7 +272,7 @@ void RenderToSavePic(FRenderViewpoint& vp, FileWriter* file, int width, int heig
twodpsp.Clear(); twodpsp.Clear();
RenderViewpoint(vp, &bounds, vp.FieldOfView.Degrees, 1.333f, 1.333f, true, false); RenderViewpoint(vp, &bounds, vp.FieldOfView.Degrees(), 1.333f, 1.333f, true, false);
int numpixels = width * height; int numpixels = width * height;
@ -356,7 +356,7 @@ void render_drawrooms(DCoreActor* playersprite, const vec3_t& position, int sect
screen->ImageTransitionScene(true); // Only relevant for Vulkan. screen->ImageTransitionScene(true); // Only relevant for Vulkan.
RenderViewpoint(r_viewpoint, nullptr, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); RenderViewpoint(r_viewpoint, nullptr, r_viewpoint.FieldOfView.Degrees(), ratio, fovratio, true, true);
All.Unclock(); All.Unclock();
} }
@ -373,7 +373,7 @@ void render_camtex(DCoreActor* playersprite, const vec3_t& position, sectortype*
FRenderViewpoint r_viewpoint = SetupViewpoint(playersprite, position, sectnum(sect), angle, horizon, rollang); FRenderViewpoint r_viewpoint = SetupViewpoint(playersprite, position, sectnum(sect), angle, horizon, rollang);
if (cl_capfps) r_viewpoint.TicFrac = smoothratio; if (cl_capfps) r_viewpoint.TicFrac = smoothratio;
RenderViewpoint(r_viewpoint, &rect, r_viewpoint.FieldOfView.Degrees, ratio, ratio, false, false); RenderViewpoint(r_viewpoint, &rect, r_viewpoint.FieldOfView.Degrees(), ratio, ratio, false, false);
All.Unclock(); All.Unclock();
} }

View file

@ -202,15 +202,15 @@ void HWDrawInfo::ClearBuffers()
angle_t HWDrawInfo::FrustumAngle() angle_t HWDrawInfo::FrustumAngle()
{ {
float WidescreenRatio = (float)screen->GetWidth() / screen->GetHeight(); float WidescreenRatio = (float)screen->GetWidth() / screen->GetHeight();
float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees); float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees());
// If the pitch is larger than this you can look all around at a FOV of 90° // If the pitch is larger than this you can look all around at a FOV of 90°
if (tilt > 46.0f) return 0xffffffff; if (tilt > 46.0f) return 0xffffffff;
// ok, this is a gross hack that barely works... // ok, this is a gross hack that barely works...
// but at least it doesn't overestimate too much... // but at least it doesn't overestimate too much...
double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(WidescreenRatio) / 90.0; double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees() * 48.0 / AspectMultiplier(WidescreenRatio) / 90.0;
angle_t a1 = DAngle(floatangle).BAMs(); angle_t a1 = DAngle::fromDeg(floatangle).BAMs();
if (a1 >= ANGLE_90) return 0xffffffff; // it's either below 90 or bust. if (a1 >= ANGLE_90) return 0xffffffff; // it's either below 90 or bust.
return a1; return a1;
} }
@ -227,9 +227,9 @@ void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float
float planemult = planemirror ? -1 : 1;// Level->info->pixelstretch : Level->info->pixelstretch; float planemult = planemirror ? -1 : 1;// Level->info->pixelstretch : Level->info->pixelstretch;
VPUniforms.mViewMatrix.loadIdentity(); VPUniforms.mViewMatrix.loadIdentity();
VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees, 0.0f, 0.0f, 1.0f); VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees(), 0.0f, 0.0f, 1.0f);
VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees, 1.0f, 0.0f, 0.0f); VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees(), 1.0f, 0.0f, 0.0f);
VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees, 0.0f, mult, 0.0f); VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees(), 0.0f, mult, 0.0f);
VPUniforms.mViewMatrix.translate(vx * mult, -vz * planemult, -vy); VPUniforms.mViewMatrix.translate(vx * mult, -vz * planemult, -vy);
VPUniforms.mViewMatrix.scale(-mult, planemult, 1); VPUniforms.mViewMatrix.scale(-mult, planemult, 1);
} }

View file

@ -549,10 +549,10 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
vp.Pos.X = newx; vp.Pos.X = newx;
vp.Pos.Y = -newy; vp.Pos.Y = -newy;
vp.HWAngles.Yaw = -90.f + newan.asdeg(); vp.HWAngles.Yaw = FAngle::fromDeg( - 90.f + newan.asdeg());
double FocalTangent = tan(vp.FieldOfView.Radians() / 2); double FocalTangent = tan(vp.FieldOfView.Radians() / 2);
DAngle an = 270. - vp.HWAngles.Yaw.Degrees; DAngle an = DAngle::fromDeg(270. - vp.HWAngles.Yaw.Degrees());
vp.TanSin = FocalTangent * an.Sin(); vp.TanSin = FocalTangent * an.Sin();
vp.TanCos = FocalTangent * an.Cos(); vp.TanCos = FocalTangent * an.Cos();
vp.ViewVector = an.ToVector(); vp.ViewVector = an.ToVector();

View file

@ -139,7 +139,7 @@ public:
} }
DVector2 dv = { (ix2 - ix1), -(iy2 - iy1) }; DVector2 dv = { (ix2 - ix1), -(iy2 - iy1) };
auto vang = dv.Angle() - 90.; auto vang = dv.Angle() - DAngle::fromDeg(90.);
cosalign = float(vang.Cos()); cosalign = float(vang.Cos());
sinalign = float(vang.Sin()); sinalign = float(vang.Sin());