mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-17 23:39:18 +02:00
Merge remote-tracking branch 'upstream/master' into utilities-simplification
This commit is contained in:
@@ -1754,6 +1754,8 @@ class TMoverParameters
|
||||
bool HasCamshaft{false};
|
||||
int DynamicBrakeType = 0; /*patrz dbrake_**/
|
||||
int DynamicBrakeAmpmeters = 2; /*liczba amperomierzy przy hamowaniu ED*/
|
||||
bool SplitEDPneumaticBrake = false; /*czy hamulec ED i pneumatyczny pomocniczy są rozdzielone na osobne nastawniki*/
|
||||
int DynamicBrakeCtrlPosNo = 10; /*ilosc pozycji nastawnika hamulca ED (DBPN, domyslnie 10)*/
|
||||
double DynamicBrakeRes = 5.8; /*rezystancja oporników przy hamowaniu ED*/
|
||||
double DynamicBrakeRes1 = 5.8; /*rezystancja oporników przy hamowaniu ED - 1 tryb*/
|
||||
double DynamicBrakeRes2 = 5.8; /*rezystancja oporników przy hamowaniu ED - 2 tryb*/
|
||||
@@ -2030,6 +2032,7 @@ class TMoverParameters
|
||||
int ManualBrakePos = 0; /*nastawa hamulca recznego*/
|
||||
double LocalBrakePosA = 0.0; /*nastawa hamulca pomocniczego*/
|
||||
double LocalBrakePosAEIM = 0.0; /*pozycja hamulca pomocniczego ep dla asynchronicznych ezt*/
|
||||
double DynamicBrakeCtrlPos = 0.0; /*nastawa nastawnika hamulca elektrodynamicznego (0..1) - aktywne tylko gdy SplitEDPneumaticBrake*/
|
||||
bool UniversalBrakeButtonActive[3] = {false, false, false}; /* brake button pressed */
|
||||
/*
|
||||
int BrakeStatus = b_off; //0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R
|
||||
@@ -2380,6 +2383,12 @@ class TMoverParameters
|
||||
/*! ABu 010205: - skrajne polozenia ham. pomocniczego*/
|
||||
bool IncManualBrakeLevel(int CtrlSpeed);
|
||||
bool DecManualBrakeLevel(int CtrlSpeed);
|
||||
/*! oddzielny nastawnik hamulca elektrodynamicznego (gdy SplitEDPneumaticBrake)*/
|
||||
bool IncDynamicBrakeLevel(float const CtrlSpeed);
|
||||
bool DecDynamicBrakeLevel(float const CtrlSpeed);
|
||||
bool DynamicBrakeLevelSet(double Position);
|
||||
double DynamicBrakeRatio(void) const;
|
||||
bool DynamicBrakeAvailable(void) const; /*czy ED dostepny w aktualnym oknie predkosci Vh0..Vh1*/
|
||||
bool DynamicBrakeSwitch(bool Switch);
|
||||
bool RadiostopSwitch(bool Switch);
|
||||
bool AlarmChainSwitch(bool const State);
|
||||
|
||||
@@ -3882,6 +3882,79 @@ bool TMoverParameters::DecLocalBrakeLevel(float const CtrlSpeed)
|
||||
return DBL;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// zwiększenie nastawy nastawnika hamulca elektrodynamicznego (DynamicBrakeCtrl)
|
||||
// uzywane gdy SplitEDPneumaticBrake = true
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::IncDynamicBrakeLevel(float const CtrlSpeed)
|
||||
{
|
||||
if (false == SplitEDPneumaticBrake)
|
||||
return false;
|
||||
if (DynamicBrakeCtrlPosNo < 1)
|
||||
return false;
|
||||
if (DynamicBrakeCtrlPos < 1.0)
|
||||
{
|
||||
DynamicBrakeCtrlPos = std::min(1.0, DynamicBrakeCtrlPos + (double)CtrlSpeed / (double)DynamicBrakeCtrlPosNo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// zmniejszenie nastawy nastawnika hamulca elektrodynamicznego (DynamicBrakeCtrl)
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::DecDynamicBrakeLevel(float const CtrlSpeed)
|
||||
{
|
||||
if (false == SplitEDPneumaticBrake)
|
||||
return false;
|
||||
if (DynamicBrakeCtrlPosNo < 1)
|
||||
return false;
|
||||
if (DynamicBrakeCtrlPos > 0.0)
|
||||
{
|
||||
DynamicBrakeCtrlPos = std::max(0.0, DynamicBrakeCtrlPos - (double)CtrlSpeed / (double)DynamicBrakeCtrlPosNo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// bezposrednie ustawienie nastawnika hamulca elektrodynamicznego (DynamicBrakeCtrl)
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::DynamicBrakeLevelSet(double Position)
|
||||
{
|
||||
if (false == SplitEDPneumaticBrake)
|
||||
return false;
|
||||
DynamicBrakeCtrlPos = clamp(Position, 0.0, 1.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// odczyt nastawy nastawnika hamulca elektrodynamicznego (DynamicBrakeCtrl)
|
||||
// zwraca 0 jezeli SplitEDPneumaticBrake nie jest aktywne (dla zachowania starej logiki)
|
||||
// *************************************************************************************************
|
||||
double TMoverParameters::DynamicBrakeRatio(void) const
|
||||
{
|
||||
if (false == SplitEDPneumaticBrake)
|
||||
return 0.0;
|
||||
return clamp(DynamicBrakeCtrlPos, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// czy hamulec ED jest aktualnie dostepny w oknie predkosci Vh0..Vh1
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::DynamicBrakeAvailable(void) const
|
||||
{
|
||||
double const vh0{eimc[eimc_p_Vh0]};
|
||||
double const vh1{eimc[eimc_p_Vh1]};
|
||||
if (vh1 <= 0.001)
|
||||
{
|
||||
// brak zdefiniowanej strefy - ED dziala zawsze
|
||||
return true;
|
||||
}
|
||||
// strefa wylaczenia jest definiowana przez Vh0 (minimum); powyzej Vh0 ED dziala
|
||||
return (Vel >= vh0);
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160711
|
||||
// zwiększenie nastawy hamulca ręcznego
|
||||
@@ -4438,7 +4511,13 @@ void TMoverParameters::UpdatePipePressure(double dt)
|
||||
dpLocalValve = LocHandle->GetPF(std::max(lbpa, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0);
|
||||
}
|
||||
else
|
||||
dpLocalValve = LocHandle->GetPF(LocalBrakePosAEIM, Hamulec->GetBCP(), ScndPipePress, dt, 0);
|
||||
{
|
||||
// in EIM stock the pneumatic local brake is normally driven only by the MED algorithm
|
||||
// (LocalBrakePosAEIM). When SplitEDPneumaticBrake is active the dedicated LocalBrake
|
||||
// lever should apply pneumatic pressure on the locomotive directly, bypassing MED.
|
||||
double lbpa = SplitEDPneumaticBrake ? LocalBrakePosA : 0.0;
|
||||
dpLocalValve = LocHandle->GetPF(std::max(lbpa, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0);
|
||||
}
|
||||
|
||||
LockPipe = PipePress < (LockPipe ? LockPipeOff : LockPipeOn);
|
||||
bool lock_new = (LockPipe && !UnlockPipe && (BrakeCtrlPosR > HandleUnlock)) || ((EmergencyCutsOffHandle) && (EmergencyValveFlow > 0)); // new simple codition based on .fiz
|
||||
@@ -6232,14 +6311,19 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
double edBCP = Hamulec->GetEDBCP();
|
||||
auto const localbrakeactive{(CabOccupied != 0) && (LocHandle->GetCP() > 0.25)};
|
||||
// gdy SplitEDPneumaticBrake jest aktywne, hamulec pomocniczy (LocalBrake) NIE wymusza
|
||||
// zalaczenia hamulca elektrodynamicznego - ED jest sterowany wlasnym nastawnikiem
|
||||
auto const dynbrakectrlactive{SplitEDPneumaticBrake && (DynamicBrakeRatio() > 0.01) && DynamicBrakeAvailable()};
|
||||
auto const localbrakeforED{SplitEDPneumaticBrake ? false : localbrakeactive};
|
||||
if ((false == Doors.instances[side::left].is_closed) || (false == Doors.instances[side::right].is_closed) ||
|
||||
(Doors.permit_needed && (Doors.instances[side::left].open_permit || Doors.instances[side::right].open_permit)))
|
||||
{
|
||||
DynamicBrakeFlag = true;
|
||||
}
|
||||
else if (((edBCP < 0.25) && (false == localbrakeactive) && (AnPos < 0.01)) || ((edBCP < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01)))
|
||||
else if (((edBCP < 0.25) && (false == localbrakeforED) && (false == dynbrakectrlactive) && (AnPos < 0.01)) ||
|
||||
((edBCP < 0.25) && (ShuntModeAllow) && (false == dynbrakectrlactive) && (LocalBrakePosA < 0.01)))
|
||||
DynamicBrakeFlag = false;
|
||||
else if ((((BrakePress > 0.25) && (edBCP > 0.25) || localbrakeactive)) || (AnPos > 0.02))
|
||||
else if ((((BrakePress > 0.25) && (edBCP > 0.25) || localbrakeforED)) || (AnPos > 0.02) || dynbrakectrlactive)
|
||||
DynamicBrakeFlag = true;
|
||||
edBCP = Hamulec->GetEDBCP() * eimc[eimc_p_abed]; // stala napedu
|
||||
if ((DynamicBrakeFlag))
|
||||
@@ -6266,8 +6350,21 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
else
|
||||
{
|
||||
PosRatio = -std::max(std::min(edBCP * 1.0 / MaxBrakePress[0], 1.0), AnPos) * std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0])));
|
||||
eimv[eimv_Fzad] = -std::min(1.0, std::max(LocalBrakeRatio(), edBCP / MaxBrakePress[0]));
|
||||
// strefa wylaczenia ED (Vh0..Vh1) - mnoznik 0..1 zaleznie od predkosci
|
||||
double const vhRamp = std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0])));
|
||||
if (SplitEDPneumaticBrake)
|
||||
{
|
||||
// w trybie split LocalBrake nie zaleca ED; uzywany jest DynamicBrakeCtrl
|
||||
// oraz zwykle zapotrzebowanie z hamulca zespolonego (edBCP)
|
||||
double const edLeverDemand = DynamicBrakeRatio();
|
||||
PosRatio = -std::max(std::max(edLeverDemand, std::min(edBCP / MaxBrakePress[0], 1.0)), AnPos) * vhRamp;
|
||||
eimv[eimv_Fzad] = -std::min(1.0, std::max(edLeverDemand, edBCP / MaxBrakePress[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
PosRatio = -std::max(std::min(edBCP * 1.0 / MaxBrakePress[0], 1.0), AnPos) * vhRamp;
|
||||
eimv[eimv_Fzad] = -std::min(1.0, std::max(LocalBrakeRatio(), edBCP / MaxBrakePress[0]));
|
||||
}
|
||||
}
|
||||
tmp = 5;
|
||||
}
|
||||
@@ -7230,10 +7327,26 @@ void TMoverParameters::CheckEIMIC(double dt)
|
||||
{
|
||||
double offset = EIMCtrlAdditionalZeros ? 1.0 : 0.0;
|
||||
double multiplier = (EIMCtrlEmergency ? 1.0 : 0.0) + offset;
|
||||
// gdy SplitEDPneumaticBrake jest wlaczone, sterowanie ujemne (hamowanie ED) bierzemy
|
||||
// z osobnego nastawnika DynamicBrakeCtrl, a nie z hamulca pomocniczego (LocalBrake).
|
||||
// Dodatkowo zapotrzebowanie ED jest ograniczone przez strefe Vh0..Vh1: powyzej Vh1 - pelny ED,
|
||||
// pomiedzy Vh1 a Vh0 - liniowe zanikanie, ponizej Vh0 - zerowe (brak hamowania pneumatycznego
|
||||
// jako uzupelnienia, poniewaz LocalBrake jest oddzielny i operuje wylacznie pneumatyka).
|
||||
double brakeDemand = SplitEDPneumaticBrake ? DynamicBrakeRatio() : LocalBrakeRatio();
|
||||
if (SplitEDPneumaticBrake)
|
||||
{
|
||||
double const vh0 = eimc[eimc_p_Vh0];
|
||||
double const vh1 = eimc[eimc_p_Vh1];
|
||||
if (vh1 > vh0 + 0.001)
|
||||
{
|
||||
double const vhRamp = clamp((Vel - vh0) / (vh1 - vh0), 0.0, 1.0);
|
||||
brakeDemand *= vhRamp;
|
||||
}
|
||||
}
|
||||
switch (EIMCtrlType)
|
||||
{
|
||||
case 0:
|
||||
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : eimic_analog > 0.01 ? eimic_analog : (double)MainCtrlPos / (double)MainCtrlPosNo);
|
||||
eimic = (brakeDemand > 0.01 ? -brakeDemand : eimic_analog > 0.01 ? eimic_analog : (double)MainCtrlPos / (double)MainCtrlPosNo);
|
||||
if (EIMCtrlAdditionalZeros || EIMCtrlEmergency)
|
||||
{
|
||||
if (eimic > 0.001)
|
||||
@@ -7347,7 +7460,9 @@ void TMoverParameters::CheckEIMIC(double dt)
|
||||
eimic = 0; // shut off retarder
|
||||
if ((UniCtrlIntegratedBrakeCtrl == false) && (UniCtrlIntegratedLocalBrakeCtrl == false))
|
||||
{
|
||||
eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : eimic);
|
||||
// w trybie SplitEDPneumaticBrake hamowanie ED przychodzi z osobnego nastawnika,
|
||||
// LocalBrake operuje wylacznie pneumatycznym hamulcem lokomotywy
|
||||
eimic = (brakeDemand > 0.01 ? -brakeDemand : eimic);
|
||||
}
|
||||
}
|
||||
if (LocHandleTimeTraxx)
|
||||
@@ -10707,6 +10822,18 @@ void TMoverParameters::LoadFIZ_Cntrl(std::string const &line)
|
||||
extract_value(DynamicBrakeAmpmeters, "DBAM", line, "");
|
||||
}
|
||||
|
||||
// split ED/pneumatic brake control: when true the local brake operates only on the
|
||||
// pneumatic locomotive cylinder while electrodynamic braking is commanded by a
|
||||
// separate "dynamicbrakectrl" lever (or the negative range of jointctrl).
|
||||
extract_value(SplitEDPneumaticBrake, "SplitEDPneumaticBrake", line, "");
|
||||
// number of stepped positions for the dedicated ED brake controller (default 10)
|
||||
DynamicBrakeCtrlPosNo = 10;
|
||||
extract_value(DynamicBrakeCtrlPosNo, "DBPN", line, "");
|
||||
if (DynamicBrakeCtrlPosNo < 1)
|
||||
{
|
||||
DynamicBrakeCtrlPosNo = 10;
|
||||
}
|
||||
|
||||
extract_value(MainCtrlPosNo, "MCPN", line, "");
|
||||
extract_value(ScndCtrlPosNo, "SCPN", line, "");
|
||||
extract_value(ScndInMain, "SCIM", line, "");
|
||||
|
||||
@@ -319,6 +319,12 @@ int eu07_application::init(int Argc, char *Argv[])
|
||||
return result;
|
||||
}
|
||||
|
||||
// configure the OS console according to Globals.ShowSystemConsole.
|
||||
// must run AFTER init_settings (so the ini-loaded value is honoured) and
|
||||
// BEFORE the first WriteLog below (so colored \033[...] sequences emitted
|
||||
// by utilities/Logs.cpp land in a console with VT processing enabled).
|
||||
init_console();
|
||||
|
||||
WriteLog("Starting MaSzyna rail vehicle simulator (release: " + Global.asVersion + ")");
|
||||
WriteLog("For online documentation and additional files refer to: http://eu07.pl");
|
||||
WriteLog("Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
|
||||
@@ -978,6 +984,102 @@ void eu07_application::init_debug()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Honours Globals.ShowSystemConsole (default: true).
|
||||
//
|
||||
// Windows: if the toggle is on, ensure a console is attached (allocate one when
|
||||
// the binary was linked as the WINDOWS subsystem and none is inherited), then
|
||||
// reopen the C stdio streams onto it and turn on ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
// so the ANSI colour escapes used by utilities/Logs.cpp render correctly.
|
||||
// If the toggle is off, hide the console window (or free an allocated one) so
|
||||
// the GUI launches without a stray cmd window.
|
||||
//
|
||||
// Other platforms: no-op. stdout is the launching terminal (or already detached);
|
||||
// hiding it on Linux/macOS would mean redirecting to /dev/null and is left to the
|
||||
// user's shell (e.g. "./eu07 >/dev/null 2>&1").
|
||||
void eu07_application::init_console()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HWND consoleWnd = ::GetConsoleWindow();
|
||||
const bool hadConsole = (consoleWnd != nullptr);
|
||||
|
||||
if (Global.ShowSystemConsole)
|
||||
{
|
||||
if (!hadConsole)
|
||||
{
|
||||
// no console inherited (e.g. WINDOWS subsystem build, or launched
|
||||
// detached) -- create one and wire stdio to it so printf in
|
||||
// utilities/Logs.cpp actually reaches the user
|
||||
if (::AllocConsole())
|
||||
{
|
||||
FILE *fp = nullptr;
|
||||
freopen_s(&fp, "CONOUT$", "w", stdout);
|
||||
freopen_s(&fp, "CONOUT$", "w", stderr);
|
||||
freopen_s(&fp, "CONIN$", "r", stdin);
|
||||
// keep C++ streams in sync with the redirected C streams
|
||||
std::ios::sync_with_stdio(true);
|
||||
std::cout.clear();
|
||||
std::cerr.clear();
|
||||
std::clog.clear();
|
||||
std::cin.clear();
|
||||
consoleWnd = ::GetConsoleWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// enable ANSI virtual-terminal processing so the colour escapes in
|
||||
// utilities/Logs.cpp ("\033[1;37;41m...", "\033[32m...") render as
|
||||
// colours instead of literal garbage on the conhost.
|
||||
//
|
||||
// IMPORTANT: do NOT rely on GetStdHandle(STD_OUTPUT_HANDLE). After
|
||||
// AllocConsole + freopen_s the CRT may have rewired things, and on a
|
||||
// console-subsystem build the std handle can also point to a redirected
|
||||
// pipe/file rather than the actual console screen buffer -- in either
|
||||
// case SetConsoleMode silently fails and the escape bytes leak through
|
||||
// as text ("←[32m" etc). Open CONOUT$ directly to get the real screen
|
||||
// buffer handle, then flip VT on it.
|
||||
auto enable_vt = [](const char *devName) {
|
||||
HANDLE h = ::CreateFileA(
|
||||
devName,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
nullptr);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
DWORD mode = 0;
|
||||
if (::GetConsoleMode(h, &mode))
|
||||
{
|
||||
::SetConsoleMode(h, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT);
|
||||
}
|
||||
::CloseHandle(h);
|
||||
};
|
||||
// CONOUT$ is the console's active screen buffer; enabling VT on it
|
||||
// affects everything that ends up being written there, regardless of
|
||||
// which FILE* / std handle the writer used
|
||||
enable_vt("CONOUT$");
|
||||
|
||||
if (consoleWnd)
|
||||
{
|
||||
::ShowWindow(consoleWnd, SW_SHOW);
|
||||
// give the console a recognisable title
|
||||
::SetConsoleTitleA("MaSzyna log");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// user wants no console window -- hide whatever we have
|
||||
if (consoleWnd)
|
||||
{
|
||||
::ShowWindow(consoleWnd, SW_HIDE);
|
||||
}
|
||||
// if we'd allocated one ourselves on a previous run path we'd FreeConsole here,
|
||||
// but on first init the console (if any) was inherited from the launcher and
|
||||
// belongs to it -- just hiding the window is the least-surprising behaviour
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void eu07_application::init_files()
|
||||
{
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ private:
|
||||
// methods
|
||||
bool needs_ogl() const;
|
||||
void init_debug();
|
||||
void init_console();
|
||||
void init_files();
|
||||
int init_settings( int Argc, char *Argv[] );
|
||||
int init_locale();
|
||||
|
||||
@@ -17,11 +17,16 @@ gl::cubemap::~cubemap()
|
||||
|
||||
void gl::cubemap::alloc(GLint format, int width, int height, GLenum components, GLenum type)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
for (GLuint tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X; tgt <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; tgt++)
|
||||
glTexImage2D(tgt, 0, format, width, height, 0, components, type, nullptr);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
for (GLuint tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X; tgt <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; tgt++)
|
||||
glTexImage2D(tgt, 0, format, width, height, 0, components, type, nullptr);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
// make the cubemap sample-complete with no mipmaps required.
|
||||
// generate_mipmaps() will later override MIN_FILTER once mips actually exist.
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
void gl::cubemap::bind(int unit)
|
||||
|
||||
@@ -29,6 +29,13 @@ commanddescription_sequence Commands_descriptions = {
|
||||
{"mastercontrollerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerdecreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"mastercontrollerset", command_target::vehicle, command_mode::oneoff},
|
||||
|
||||
{"dynamicbrakecontrollerincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"dynamicbrakecontrollerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"dynamicbrakecontrollerset", command_target::vehicle, command_mode::oneoff},
|
||||
{"dynamicbrakecontrollerincreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"dynamicbrakecontrollerdecreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
|
||||
{"secondcontrollerincrease", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerincreasefast", command_target::vehicle, command_mode::oneoff},
|
||||
{"secondcontrollerdecrease", command_target::vehicle, command_mode::oneoff},
|
||||
@@ -409,6 +416,11 @@ std::unordered_map<std::string, user_command> commandMap = {
|
||||
{"mastercontrollerdecrease", user_command::mastercontrollerdecrease},
|
||||
{"mastercontrollerdecreasefast", user_command::mastercontrollerdecreasefast},
|
||||
{"mastercontrollerset", user_command::mastercontrollerset},
|
||||
{"dynamicbrakecontrollerincrease", user_command::dynamicbrakecontrollerincrease},
|
||||
{"dynamicbrakecontrollerdecrease", user_command::dynamicbrakecontrollerdecrease},
|
||||
{"dynamicbrakecontrollerset", user_command::dynamicbrakecontrollerset},
|
||||
{"dynamicbrakecontrollerincreasefast", user_command::dynamicbrakecontrollerincreasefast},
|
||||
{"dynamicbrakecontrollerdecreasefast", user_command::dynamicbrakecontrollerdecreasefast},
|
||||
{"secondcontrollerincrease", user_command::secondcontrollerincrease},
|
||||
{"secondcontrollerincreasefast", user_command::secondcontrollerincreasefast},
|
||||
{"secondcontrollerdecrease", user_command::secondcontrollerdecrease},
|
||||
|
||||
@@ -24,6 +24,11 @@ enum class user_command
|
||||
mastercontrollerdecrease,
|
||||
mastercontrollerdecreasefast,
|
||||
mastercontrollerset,
|
||||
dynamicbrakecontrollerincrease,
|
||||
dynamicbrakecontrollerdecrease,
|
||||
dynamicbrakecontrollerset,
|
||||
dynamicbrakecontrollerincreasefast,
|
||||
dynamicbrakecontrollerdecreasefast,
|
||||
secondcontrollerincrease,
|
||||
secondcontrollerincreasefast,
|
||||
secondcontrollerdecrease,
|
||||
|
||||
@@ -32,6 +32,13 @@ driverkeyboard_input::default_bindings() {
|
||||
{ user_command::mastercontrollerdecrease, {GLFW_KEY_KP_SUBTRACT, ""} },
|
||||
{ user_command::mastercontrollerdecreasefast, {GLFW_KEY_KP_SUBTRACT | keymodifier::shift, ""} },
|
||||
// mastercontrollerset,
|
||||
|
||||
{ user_command::dynamicbrakecontrollerincrease, {GLFW_KEY_KP_3 | keymodifier::control, ""} },
|
||||
{ user_command::dynamicbrakecontrollerdecrease, {GLFW_KEY_KP_9 | keymodifier::control, ""} },
|
||||
// mastercontrollerset,
|
||||
{ user_command::dynamicbrakecontrollerincreasefast, {GLFW_KEY_KP_3 | keymodifier::control | keymodifier::shift, ""} },
|
||||
{ user_command::dynamicbrakecontrollerdecreasefast, {GLFW_KEY_KP_9 | keymodifier::control | keymodifier::shift, ""} },
|
||||
|
||||
{ user_command::secondcontrollerincrease, {GLFW_KEY_KP_DIVIDE, ""} },
|
||||
{ user_command::secondcontrollerincreasefast, {GLFW_KEY_KP_DIVIDE | keymodifier::shift, ""} },
|
||||
{ user_command::secondcontrollerdecrease, {GLFW_KEY_KP_MULTIPLY, ""} },
|
||||
|
||||
@@ -533,6 +533,9 @@ drivermouse_input::default_bindings() {
|
||||
{ "mainctrl:", {
|
||||
user_command::mastercontrollerset,
|
||||
user_command::none } },
|
||||
{ "dynamicbrakectrl:", {
|
||||
user_command::dynamicbrakecontrollerset,
|
||||
user_command::none } },
|
||||
{ "scndctrl:", {
|
||||
user_command::secondcontrollerset,
|
||||
user_command::none } },
|
||||
|
||||
@@ -312,15 +312,37 @@ void python_taskqueue::exit()
|
||||
m_condition.notify_all();
|
||||
// let them free up their shit before we proceed
|
||||
m_workers = {};
|
||||
// get rid of the leftover tasks
|
||||
// with the workers dead we don't have to worry about concurrent access anymore
|
||||
for (auto task : m_tasks.data)
|
||||
// drop any pending render/upload tasks. the workers are joined at this
|
||||
// point so the locks are strictly defensive, but they cost nothing and
|
||||
// document intent. clearing the deque also actually releases the tasks,
|
||||
// which the previous code did not do (cancel() is a no-op stub).
|
||||
{
|
||||
task->cancel();
|
||||
std::lock_guard<std::mutex> lock(m_tasks.mutex);
|
||||
for (auto &task : m_tasks.data)
|
||||
{
|
||||
task->cancel();
|
||||
}
|
||||
m_tasks.data.clear();
|
||||
}
|
||||
// take a bow
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_uploadtasks.mutex);
|
||||
m_uploadtasks.data.clear();
|
||||
}
|
||||
// reclaim cached python objects while the interpreter is still alive,
|
||||
// so no Py_DECREF lands on a finalized interpreter during later teardown
|
||||
acquire_lock();
|
||||
for (auto &entry : m_renderers)
|
||||
{
|
||||
Py_XDECREF(entry.second);
|
||||
}
|
||||
m_renderers.clear();
|
||||
Py_XDECREF(m_stderr);
|
||||
m_stderr = nullptr;
|
||||
Py_XDECREF(m_main);
|
||||
m_main = nullptr;
|
||||
// take a bow
|
||||
Py_Finalize();
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
// adds specified task along with provided collection of data to the work queue. returns true on success
|
||||
@@ -518,8 +540,10 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
|
||||
// TBD, TODO: add some idle time between tasks in case we're on a single thread cpu?
|
||||
} while (task != nullptr);
|
||||
// if there's nothing left to do wait until there is
|
||||
// but check every now and then on your own to minimize potential deadlock situations
|
||||
Condition.wait_for(std::chrono::seconds(5));
|
||||
// short timeout: notify_all() in exit() can race with the worker's
|
||||
// transition into the wait, and the run loop also drives prompt
|
||||
// shutdown checks
|
||||
Condition.wait_for(std::chrono::milliseconds(250));
|
||||
}
|
||||
// clean up thread state data
|
||||
PyEval_AcquireLock();
|
||||
@@ -527,6 +551,12 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
|
||||
PyThreadState_Clear(threadstate);
|
||||
PyThreadState_Delete(threadstate);
|
||||
PyEval_ReleaseLock();
|
||||
|
||||
// detach the GL context before the worker terminates; some drivers
|
||||
// (NVIDIA on X11, certain Mesa/Wayland configs) hang in process teardown
|
||||
// if a context is still current on a dying thread
|
||||
if (Context)
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
}
|
||||
|
||||
void python_taskqueue::update()
|
||||
|
||||
@@ -8,6 +8,14 @@ vec3 envmap_color( vec3 normal )
|
||||
vec3 refvec = reflect(f_pos.xyz, normal); // view space
|
||||
refvec = vec3(inv_view * vec4(refvec, 0.0)); // world space
|
||||
vec3 envcolor = texture(envmap, refvec).rgb;
|
||||
// Sanitize. The env cubemap can briefly contain NaN/Inf after a
|
||||
// reflection-pass regeneration (m_empty_cubemap was bound during the
|
||||
// face render and on NVIDIA can sample as undefined). Without this
|
||||
// guard, a single bad texel propagates through env_reflection in
|
||||
// apply_lights() and produces one-frame black flashes on glossy
|
||||
// (esp. specgloss) surfaces.
|
||||
if (any(isnan(envcolor)) || any(isinf(envcolor))) envcolor = vec3(0.0);
|
||||
envcolor = max(envcolor, vec3(0.0));
|
||||
#else
|
||||
vec3 envcolor = vec3(0.5);
|
||||
#endif
|
||||
@@ -21,8 +29,13 @@ vec3 envmap_color_lod(vec3 fragnormal, float lod)
|
||||
#if ENVMAP_ENABLED
|
||||
vec3 refvec = reflect(f_pos.xyz, fragnormal); // view space — matches envmap_color exactly
|
||||
refvec = vec3(inv_view * vec4(refvec, 0.0)); // world space — was missing
|
||||
return textureLod(envmap, refvec, lod).rgb;
|
||||
vec3 envcolor = textureLod(envmap, refvec, lod).rgb;
|
||||
// See envmap_color() above — same NaN/Inf sanitize, also needed here
|
||||
// because mipmap generation propagates a single NaN texel across the
|
||||
// whole mip chain.
|
||||
if (any(isnan(envcolor)) || any(isinf(envcolor))) envcolor = vec3(0.0);
|
||||
return max(envcolor, vec3(0.0));
|
||||
#else
|
||||
return vec3(0.5); // was vec3(0.0), match the non-LOD fallback
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,17 @@ vec4 tonemap(vec4 x)
|
||||
// with pureWhite=1.0 it collapses to identity (L*(1+L)/(1+L) = L) and
|
||||
// just clips HDR>1.0 at the framebuffer -> washed-out / burnt look.
|
||||
// ACES gives a smooth highlight shoulder + slight toe contrast.
|
||||
return FBOUT(vec4(ACESFilm(x.rgb), x.a));
|
||||
|
||||
// Last-line-of-defense sanitize. ACESFilm has the form
|
||||
// (x*(a*x+b)) / (x*(c*x+d)+e)
|
||||
// which maps NaN -> NaN and +Inf -> NaN (Inf/Inf). Either turns the
|
||||
// pixel black after framebuffer clamp. A negative HDR input feeds a
|
||||
// negative numerator/denominator and can produce non-physical output
|
||||
// that also looks like a black flash. Clamp to a sensible range
|
||||
// before the curve so a single bad upstream pixel can't escape.
|
||||
vec3 hdr = x.rgb;
|
||||
hdr = mix(hdr, vec3(0.0), vec3(any(isnan(hdr)) || any(isinf(hdr))));
|
||||
hdr = max(hdr, vec3(0.0));
|
||||
return FBOUT(vec4(ACESFilm(hdr), x.a));
|
||||
//return FBOUT(vec4(reinhard(x.rgb), x.a));
|
||||
}
|
||||
|
||||
@@ -1086,6 +1086,12 @@ bool global_settings::ConfigParseDebug(cParser& Parser, const std::string& token
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token == "showsystemconsole")
|
||||
{
|
||||
ParseOne(Parser, ShowSystemConsole);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token == "shakefactor")
|
||||
{
|
||||
ParseOne(Parser, ShakingMultiplierBF);
|
||||
@@ -1516,6 +1522,7 @@ global_settings::export_as_text( std::ostream &Output ) const {
|
||||
export_as_text( Output, "fullphysics", FullPhysics );
|
||||
export_as_text( Output, "debuglog", iWriteLogEnabled );
|
||||
export_as_text( Output, "multiplelogs", MultipleLogs );
|
||||
export_as_text( Output, "showsystemconsole", ShowSystemConsole );
|
||||
export_as_text( Output, "logs.filter", DisabledLogTypes );
|
||||
Output
|
||||
<< "mousescale "
|
||||
|
||||
@@ -86,6 +86,7 @@ struct global_settings {
|
||||
bool priorityLoadText3D{false}; // ladowanie T3D priorytetowo
|
||||
int iWriteLogEnabled{ 3 }; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
|
||||
bool MultipleLogs{ false };
|
||||
bool ShowSystemConsole{ false }; // toggle visibility of the OS console window with log output
|
||||
unsigned int DisabledLogTypes{ 0 };
|
||||
bool ParserLogIncludes{ true };
|
||||
// simulation
|
||||
|
||||
@@ -293,7 +293,7 @@ material_data::assign( std::string const &Replacableskin ) {
|
||||
// check for the pipe method first
|
||||
if( contains( Replacableskin, '|' ) ) {
|
||||
cParser nameparser( Replacableskin );
|
||||
nameparser.getTokens( 4, true, "|" );
|
||||
nameparser.getTokens( 4, false, "|" );
|
||||
int skinindex = 0;
|
||||
std::string texturename; nameparser >> texturename;
|
||||
while( ( texturename != "" ) && ( skinindex < 4 ) ) {
|
||||
|
||||
19427
vehicle/Train.cpp
19427
vehicle/Train.cpp
File diff suppressed because it is too large
Load Diff
@@ -236,11 +236,19 @@ class TTrain {
|
||||
static void OnCommand_aidriverenable( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_aidriverdisable( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_jointcontrollerset( TTrain *Train, command_data const &Command );
|
||||
|
||||
static void OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_mastercontrollerdecrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_mastercontrollerset( TTrain *Train, command_data const &Command );
|
||||
|
||||
static void OnCommand_DynamicBrakeControllerIncrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_DynamicBrakeControllerIncreaseFast( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_DynamicBrakeControllerDecrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_DynamicBrakeControllerDecreaseFast( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_DynamicBrakeControllerSet( TTrain *Train, command_data const &Command );
|
||||
|
||||
static void OnCommand_secondcontrollerincrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_secondcontrollerincreasefast( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_secondcontrollerdecrease( TTrain *Train, command_data const &Command );
|
||||
|
||||
Reference in New Issue
Block a user