From 05d8af139aea0aa9b740a674a6f792da2a8e64e7 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Mon, 10 May 2021 00:50:54 +0200 Subject: [PATCH 1/5] build 210509. configurable max draw range factor, moon visualization enhancement, night lighting tweak, minor bug fixes --- Globals.cpp | 10 ++++++-- Globals.h | 5 ++-- gl/ubo.h | 9 +++---- moon.cpp | 3 ++- moon.h | 2 +- opengl33renderer.cpp | 53 +++++++++++++++++++++++++-------------- opengl33renderer.h | 2 +- openglrenderer.cpp | 41 +++++++++++++++++++----------- simulation.cpp | 2 ++ simulationenvironment.cpp | 15 ++++++++--- simulationenvironment.h | 1 + uart.cpp | 2 +- version.h | 2 +- 13 files changed, 95 insertions(+), 52 deletions(-) diff --git a/Globals.cpp b/Globals.cpp index d62fab48..0f6f1b07 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -86,8 +86,7 @@ global_settings::ConfigParse(cParser &Parser) { { Parser.getTokens(1); Parser >> BaseDrawRange; - BaseDrawRange = clamp(BaseDrawRange, 500.f, - 5000.f); // arbitrary limits to keep users from hurting themselves + BaseDrawRange = clamp(BaseDrawRange, 500.f, 5000.f); // arbitrary limits to keep users from hurting themselves } else if (token == "fullscreen") { @@ -1009,6 +1008,12 @@ global_settings::ConfigParse_gfx( cParser &Parser, std::string_view const Token Parser.getTokens(1); Parser >> gfx_shadergamma; } + else if (Token == "gfx.drawrange.factor.max") + { + Parser.getTokens(1); + Parser >> gfx_distance_factor_max; + gfx_distance_factor_max = clamp(gfx_distance_factor_max, 1.f, 3.f); + } else { tokenparsed = false; @@ -1230,6 +1235,7 @@ global_settings::export_as_text( std::ostream &Output ) const { export_as_text( Output, "gfx.skippipeline", gfx_skippipeline ); export_as_text( Output, "gfx.extraeffects", gfx_extraeffects ); export_as_text( Output, "gfx.shadergamma", gfx_shadergamma ); + export_as_text( Output, "gfx.drawrange.factor.max", gfx_distance_factor_max ); export_as_text( Output, "python.enabled", python_enabled ); export_as_text( Output, "python.threadedupload", python_threadedupload ); export_as_text( Output, "python.uploadmain", python_uploadmain ); diff --git a/Globals.h b/Globals.h index 9c0f6d3b..cec2e220 100644 --- a/Globals.h +++ b/Globals.h @@ -148,8 +148,8 @@ struct global_settings { bool ResourceMove{ false }; // gfx resources are moved between cpu and gpu side instead of sending a copy bool compress_tex{ true }; // all textures are compressed on gpu side std::string asSky{ "1" }; - double fFpsAverage{ 20.0 }; // oczekiwana wartosć FPS - double fFpsDeviation{ 5.0 }; // odchylenie standardowe FPS + float fFpsAverage{ 0.f }; // oczekiwana wartosć FPS + float fFpsDeviation{ 5.f }; // odchylenie standardowe FPS double fFpsMin{ 30.0 }; // dolna granica FPS, przy której promień scenerii będzie zmniejszany double fFpsMax{ 65.0 }; // górna granica FPS, przy której promień scenerii będzie zwiększany // audio @@ -228,6 +228,7 @@ struct global_settings { bool gfx_extraeffects = true; bool gfx_shadergamma = false; bool gfx_usegles = false; + float gfx_distance_factor_max { 3.f }; std::string exec_on_exit; diff --git a/gl/ubo.h b/gl/ubo.h index 22aa2324..ee900676 100644 --- a/gl/ubo.h +++ b/gl/ubo.h @@ -44,10 +44,10 @@ namespace gl glm::mat4 inv_view; glm::mat4 lightview[MAX_CASCADES]; glm::vec4 cascade_end; - float time; + float time; UBS_PAD( 12 ); }; - static_assert(sizeof(scene_ubs) == 340, "bad size of ubs"); + static_assert(sizeof(scene_ubs) == 352, "bad size of ubs"); const size_t MAX_PARAMS = 3; @@ -62,8 +62,7 @@ namespace gl float emission; float fog_density; float alpha_mult; - float shadow_tone; - UBS_PAD(4); + float shadow_tone; UBS_PAD(12); void set_modelview(const glm::mat4 &mv) { @@ -72,7 +71,7 @@ namespace gl } }; - static_assert(sizeof(model_ubs) == 200 + 16 * MAX_PARAMS, "bad size of ubs"); + static_assert(sizeof(model_ubs) == 208 + 16 * MAX_PARAMS, "bad size of ubs"); struct light_element_ubs { diff --git a/moon.cpp b/moon.cpp index fd93f3ca..ad79b87c 100644 --- a/moon.cpp +++ b/moon.cpp @@ -31,11 +31,12 @@ cMoon::init() { } void -cMoon::update() { +cMoon::update( bool const Includephase ) { m_observer.temp = Global.AirTemperature; move(); + if( Includephase ) { phase(); } glm::vec3 position( 0.f, 0.f, -1.f ); position = glm::rotateX( position, glm::radians( static_cast( m_body.elevref ) ) ); position = glm::rotateY( position, glm::radians( static_cast( -m_body.hrang ) ) ); diff --git a/moon.h b/moon.h index 92fd7243..5e7e3beb 100644 --- a/moon.h +++ b/moon.h @@ -12,7 +12,7 @@ public: // methods: void init(); - void update(); + void update( bool const Includephase = false ); void render(); // returns vector pointing at the sun glm::vec3 getDirection(); diff --git a/opengl33renderer.cpp b/opengl33renderer.cpp index 5f00b30f..e2608334 100644 --- a/opengl33renderer.cpp +++ b/opengl33renderer.cpp @@ -702,7 +702,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION); scene_ubo->update(scene_ubs); - Render(&simulation::Environment); + Render(&simulation::Environment, false); if( Global.gfx_shadowmap_enabled ) setup_shadow_bind_map(); @@ -916,7 +916,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) setup_shadow_unbind_map(); scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION); scene_ubo->update(scene_ubs); - Render(&simulation::Environment); + Render(&simulation::Environment, Global.gfx_skippipeline); // HACK: sun/moon drawing messes up rendering with skippipeline on TODO: investigate and fix // opaque parts... setup_drawing(false); setup_shadow_bind_map(); @@ -1521,7 +1521,7 @@ void opengl33_renderer::setup_sunlight_intensity( float const Factor ) { light_ubo->update( light_ubs ); } -bool opengl33_renderer::Render(world_environment *Environment) +bool opengl33_renderer::Render(world_environment *Environment, bool const Skipcelestialbodies ) { m_shadowcolor = colors::white; // prevent shadow from affecting sky setup_shadow_color( m_shadowcolor ); @@ -1534,6 +1534,7 @@ bool opengl33_renderer::Render(world_environment *Environment) Bind_Material(null_handle); ::glDisable(GL_DEPTH_TEST); + ::glDepthMask(GL_FALSE); ::glPushMatrix(); // skydome @@ -1554,7 +1555,7 @@ bool opengl33_renderer::Render(world_environment *Environment) ::glBlendFunc( GL_SRC_ALPHA, GL_ONE ); // stars - if (Environment->m_stars.m_stars != nullptr) + if (Environment->m_stars.m_stars != nullptr && !Skipcelestialbodies ) { // setup ::glPushMatrix(); @@ -1581,6 +1582,7 @@ bool opengl33_renderer::Render(world_environment *Environment) glm::vec3 suncolor = interpolate(glm::vec3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f), glm::vec3(235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f), duskfactor); // sun +// if( !Skipcelestialbodies ) { Bind_Texture(0, m_suntexture); glm::vec4 color(suncolor.x, suncolor.y, suncolor.z, clamp(1.5f - Global.Overcast, 0.f, 1.f) * fogfactor); @@ -1597,6 +1599,7 @@ bool opengl33_renderer::Render(world_environment *Environment) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } // moon + if( !Skipcelestialbodies ) { Bind_Texture(0, m_moontexture); glm::vec3 mooncolor(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f); @@ -1668,7 +1671,8 @@ bool opengl33_renderer::Render(world_environment *Environment) clamp( Environment->m_moon.getAngle(), 0.f, 90.f ) / 90.f ); model_ubs.param[0] = color; - model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(moonvector, 1.0f)), /*0.00451f*/ size); +// model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(moonvector, 1.0f)), 0.00451f); + model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(moonvector, 1.0f)), size); model_ubs.param[2] = glm::vec4(moonu, moonv, 0.333f, 0.0f); model_ubo->update(model_ubs); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -1711,6 +1715,7 @@ bool opengl33_renderer::Render(world_environment *Environment) gl::program::unbind(); gl::vao::unbind(); ::glPopMatrix(); + ::glDepthMask(GL_TRUE); ::glEnable(GL_DEPTH_TEST); m_sunlight.apply_angle(); @@ -4135,13 +4140,32 @@ void opengl33_renderer::Update(double const Deltatime) // adjust draw ranges etc, based on recent performance // TODO: it doesn't make much sense with vsync - if( Global.targetfps == 0.0f ) { - // automatic adjustment + if( Global.targetfps != 0.f ) { + auto const fps_diff = m_framerate - Global.targetfps; + if( fps_diff < -0.5f ) { + Global.fDistanceFactor = std::min( std::max( 1.0f, Global.fDistanceFactor - 0.05f ), Global.gfx_distance_factor_max ); + } + else if( fps_diff > 0.5f ) { + Global.fDistanceFactor = std::min( std::min( 3.0f, Global.fDistanceFactor + 0.05f ), Global.gfx_distance_factor_max ); + } + } + // legacy framerate parameters + else if( Global.fFpsAverage != 0.f ) { + auto const fps_diff = m_framerate - Global.fFpsAverage; + if( fps_diff < -Global.fFpsDeviation ) { + Global.fDistanceFactor = std::min( std::max( 1.0f, Global.fDistanceFactor - 0.05f ), Global.gfx_distance_factor_max ); + } + else if( fps_diff > Global.fFpsDeviation ) { + Global.fDistanceFactor = std::min( std::min( 3.0f, Global.fDistanceFactor + 0.05f ), Global.gfx_distance_factor_max ); + } + } + // automatic adjustment + else { auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f ); float targetfactor; - if( framerate > 120.0 ) { targetfactor = 3.00f; } - else if( framerate > 90.0 ) { targetfactor = 1.50f; } - else if( framerate > 60.0 ) { targetfactor = 1.25f; } + if( framerate > 120.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 3.00f ); } + else if( framerate > 90.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 1.50f ); } + else if( framerate > 60.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 1.25f ); } else { targetfactor = 1.00f; } if( targetfactor > Global.fDistanceFactor ) { Global.fDistanceFactor = std::min( targetfactor, Global.fDistanceFactor + 0.05f ); @@ -4150,15 +4174,6 @@ void opengl33_renderer::Update(double const Deltatime) Global.fDistanceFactor = std::max( targetfactor, Global.fDistanceFactor - 0.05f ); } } - else { - auto const fps_diff = Global.targetfps - m_framerate; - if( fps_diff > 0.5f ) { - Global.fDistanceFactor = std::max( 1.0f, Global.fDistanceFactor - 0.05f ); - } - else if( fps_diff < 1.0f ) { - Global.fDistanceFactor = std::min( 3.0f, Global.fDistanceFactor + 0.05f ); - } - } if( Global.UpdateMaterials ) { // update resources if there was environmental change diff --git a/opengl33renderer.h b/opengl33renderer.h index 1a05c4b9..e282545e 100644 --- a/opengl33renderer.h +++ b/opengl33renderer.h @@ -234,7 +234,7 @@ class opengl33_renderer : public gfx_renderer { void Render_pass(viewport_config &vp, rendermode const Mode); // creates dynamic environment cubemap bool Render_reflections(viewport_config &vp); - bool Render(world_environment *Environment); + bool Render(world_environment *Environment, bool const Skipcelestialbodies ); void Render(scene::basic_region *Region); void Render(section_sequence::iterator First, section_sequence::iterator Last); void Render(cell_sequence::iterator First, cell_sequence::iterator Last); diff --git a/openglrenderer.cpp b/openglrenderer.cpp index d897fac3..57f3d217 100644 --- a/openglrenderer.cpp +++ b/openglrenderer.cpp @@ -4185,14 +4185,34 @@ opengl_renderer::Update( double const Deltatime ) { m_updateaccumulator = 0.0; m_framerate = 1000.f / ( Timer::subsystem.gfx_total.average() ); - // adjust draw ranges etc, based on recent performance - if( Global.targetfps == 0.0f ) { - // automatic adjustment + // adjust draw ranges etc, based on recent performance + // TODO: it doesn't make much sense with vsync + if( Global.targetfps != 0.f ) { + auto const fps_diff = m_framerate - Global.targetfps; + if( fps_diff < -0.5f ) { + Global.fDistanceFactor = std::min( std::max( 1.0f, Global.fDistanceFactor - 0.05f ), Global.gfx_distance_factor_max ); + } + else if( fps_diff > 0.5f ) { + Global.fDistanceFactor = std::min( std::min( 3.0f, Global.fDistanceFactor + 0.05f ), Global.gfx_distance_factor_max ); + } + } + // legacy framerate parameters + else if( Global.fFpsAverage != 0.f ) { + auto const fps_diff = m_framerate - Global.fFpsAverage; + if( fps_diff < -Global.fFpsDeviation ) { + Global.fDistanceFactor = std::min( std::max( 1.0f, Global.fDistanceFactor - 0.05f ), Global.gfx_distance_factor_max ); + } + else if( fps_diff > Global.fFpsDeviation ) { + Global.fDistanceFactor = std::min( std::min( 3.0f, Global.fDistanceFactor + 0.05f ), Global.gfx_distance_factor_max ); + } + } + // automatic adjustment + else { auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f ); float targetfactor; - if( framerate > 120.0 ) { targetfactor = 3.00f; } - else if( framerate > 90.0 ) { targetfactor = 1.50f; } - else if( framerate > 60.0 ) { targetfactor = 1.25f; } + if( framerate > 120.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 3.00f ); } + else if( framerate > 90.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 1.50f ); } + else if( framerate > 60.f ) { targetfactor = std::min( Global.gfx_distance_factor_max, 1.25f ); } else { targetfactor = 1.00f; } if( targetfactor > Global.fDistanceFactor ) { Global.fDistanceFactor = std::min( targetfactor, Global.fDistanceFactor + 0.05f ); @@ -4201,15 +4221,6 @@ opengl_renderer::Update( double const Deltatime ) { Global.fDistanceFactor = std::max( targetfactor, Global.fDistanceFactor - 0.05f ); } } - else { - auto const fps_diff = Global.targetfps - m_framerate; - if( fps_diff > 0.5f ) { - Global.fDistanceFactor = std::max( 1.0f, Global.fDistanceFactor - 0.05f ); - } - else if( fps_diff < 1.0f ) { - Global.fDistanceFactor = std::min( 3.0f, Global.fDistanceFactor + 0.05f ); - } - } if( Global.UpdateMaterials ) { // update resources if there was environmental change diff --git a/simulation.cpp b/simulation.cpp index b5e13531..9a1bad0f 100644 --- a/simulation.cpp +++ b/simulation.cpp @@ -314,6 +314,8 @@ void state_manager::process_commands() { // HACK: force re-calculation of precipitation Global.Overcast = clamp( Global.Overcast - 0.0001f, 0.0f, 2.0f ); } + + simulation::Environment.update_moon(); } if (commanddata.command == user_command::setweather) { diff --git a/simulationenvironment.cpp b/simulationenvironment.cpp index 6969663e..82406eb0 100644 --- a/simulationenvironment.cpp +++ b/simulationenvironment.cpp @@ -126,7 +126,7 @@ world_environment::update() { Global.DayLight.position = m_moon.getDirection(); Global.DayLight.direction = -1.0f * m_moon.getDirection(); keylightintensity = moonlightlevel; - m_lightintensity = 0.35f; + m_lightintensity = moonlightlevel; // if the moon is up, it overrides the twilight twilightfactor = 0.0f; keylightcolor = glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f ); @@ -165,9 +165,10 @@ world_environment::update() { // tonal impact of skydome color is inversely proportional to how high the sun is above the horizon // (this is pure conjecture, aimed more to 'look right' than be accurate) float const ambienttone = clamp( 1.0f - ( Global.SunAngle / 90.0f ), 0.0f, 1.0f ); - Global.DayLight.ambient[ 0 ] = interpolate( skydomehsv.z, skydomecolour.r, ambienttone ); - Global.DayLight.ambient[ 1 ] = interpolate( skydomehsv.z, skydomecolour.g, ambienttone ); - Global.DayLight.ambient[ 2 ] = interpolate( skydomehsv.z, skydomecolour.b, ambienttone ); + float const ambientintensitynightfactor = 1.f - 0.75f * clamp( -m_sun.getAngle(), 0.0f, 18.0f ) / 18.0f; + Global.DayLight.ambient[ 0 ] = interpolate( skydomehsv.z, skydomecolour.r, ambienttone ) * ambientintensitynightfactor; + Global.DayLight.ambient[ 1 ] = interpolate( skydomehsv.z, skydomecolour.g, ambienttone ) * ambientintensitynightfactor; + Global.DayLight.ambient[ 2 ] = interpolate( skydomehsv.z, skydomecolour.b, ambienttone ) * ambientintensitynightfactor; Global.fLuminance = intensity; @@ -210,6 +211,12 @@ world_environment::update_precipitation() { m_precipitation.update(); } +void +world_environment::update_moon() { + + m_moon.update( true ); +} + void world_environment::update_wind() { diff --git a/simulationenvironment.h b/simulationenvironment.h index a146ddf8..cc33a869 100644 --- a/simulationenvironment.h +++ b/simulationenvironment.h @@ -31,6 +31,7 @@ public: void init(); void update(); void update_precipitation(); + void update_moon(); void time( int const Hour = -1, int const Minute = -1, int const Second = -1 ); // switches between static and dynamic daylight calculation void on_daylight_change(); diff --git a/uart.cpp b/uart.cpp index d2900aef..3ce34458 100644 --- a/uart.cpp +++ b/uart.cpp @@ -199,7 +199,7 @@ void uart_input::poll() if (!sync) { int sync_cnt = 0; int sync_fail = 0; - char sc = 0; + unsigned char sc = 0; while ((ret = sp_blocking_read(port, &sc, 1, 10)) >= 0) { if (conf.debug) WriteLog("uart: read byte: " + std::to_string((int)sc)); diff --git a/version.h b/version.h index dede6b2d..ae0dccc8 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 21 -#define VERSION_MINOR 508 +#define VERSION_MINOR 509 #define VERSION_REVISION 0 From 873364d4052d6ce2ca0fa9638b4020cb984d0ba6 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 19 May 2021 21:57:41 +0200 Subject: [PATCH 2/5] security system magnet interaction enhancement, vehicle startup check tweak --- Classes.h | 1 + Driver.cpp | 40 +++++++++++++++++++++++++++++++++++++++- Event.cpp | 4 ++++ McZapkie/MOVER.h | 2 ++ McZapkie/Mover.cpp | 29 +++++++++++++++++------------ MemCell.cpp | 4 ++++ 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/Classes.h b/Classes.h index 9145e739..284b1aad 100644 --- a/Classes.h +++ b/Classes.h @@ -78,6 +78,7 @@ enum class TCommandType cm_OutsideStation, // cm_Shunt, // unused? cm_EmergencyBrake, + cm_SecuritySystemMagnet, cm_Command // komenda pobierana z komórki }; diff --git a/Driver.cpp b/Driver.cpp index e968e086..71903b69 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -271,6 +271,9 @@ void TSpeedPos::CommandCheck() case TCommandType::cm_EmergencyBrake: fVelNext = -1; break; + case TCommandType::cm_SecuritySystemMagnet: + fVelNext = -1; + break; default: // inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy // nie manewrowa, nie przystanek, nie zatrzymać na SBL @@ -880,6 +883,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN eSignNext = nullptr; IsAtPassengerStop = false; IsScheduledPassengerStopVisible = false; + mvOccupied->SecuritySystem.SHPLock = false; // te flagi są ustawiane tutaj, w razie potrzeby iDrivigFlags &= ~(moveTrackEnd | moveSwitchFound | moveSemaphorFound | /*moveSpeedLimitFound*/ moveStopPointFound ); @@ -1404,9 +1408,29 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo SemNextStopIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód } switch( Point.evEvent->input_command() ) { + // TBD, TODO: expand emergency_brake handling to a more generic security system signal case TCommandType::cm_EmergencyBrake: { pVehicle->RadioStop(); Point.Clear(); // signal received, deactivate + return true; + } + case TCommandType::cm_SecuritySystemMagnet: { + // NOTE: magnet induction calculation presumes the driver is located in the front vehicle + // TBD, TODO: take into account actual position of controlled/occupied vehicle in the consist, whichever comes first + auto const magnetlocation { pVehicles[ end::front ]->MoverParameters->SecuritySystem.MagnetLocation }; + if( Point.fDist < -( magnetlocation ) ) { + mvOccupied->SecuritySystem.SHPLock |= ( !AIControllFlag ); // don't make life difficult for the ai, but a human driver is a fair game + PutCommand( + Point.evEvent->input_text(), + Point.evEvent->input_value( 1 ), + Point.evEvent->input_value( 2 ), + nullptr ); + } + if( Point.fDist < -( magnetlocation + 0.5 ) ) { + Point.Clear(); // magnet passed, deactivate + mvOccupied->SecuritySystem.SHPLock = false; + } + return true; } default: { break; @@ -1415,6 +1439,19 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo } // check signals ahead if( Point.fDist > 0.0 ) { + // bail out early for signals which activate when passed + // TBD: make it an event method? + switch( Point.evEvent->input_command() ) { + case TCommandType::cm_EmergencyBrake: { + return true; + } + case TCommandType::cm_SecuritySystemMagnet: { + return true; + } + default: { + break; + } + } if( Point.IsProperSemaphor( OrderCurrentGet() ) ) { // special rule for cars: ignore stop signals at distance too short to come to a stop @@ -2793,7 +2830,8 @@ bool TController::PrepareEngine() && ( true == IsAnyConverterEnabled ) && ( true == IsAnyCompressorEnabled ) && ( ( mvControlling->ScndPipePress > 4.5 ) || ( mvControlling->VeselVolume == 0.0 ) ) - && ( ( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_RP ) || ( mvOccupied->BrakeHandle == TBrakeHandle::NoHandle ) ) ); + && ( ( static_cast( mvOccupied->fBrakeCtrlPos ) == static_cast( mvOccupied->Handle->GetPos( bh_RP ) ) ) + || ( mvOccupied->BrakeHandle == TBrakeHandle::NoHandle ) ); } if( true == isready ) { diff --git a/Event.cpp b/Event.cpp index f2c7cd8a..d2bf4763 100644 --- a/Event.cpp +++ b/Event.cpp @@ -740,6 +740,10 @@ putvalues_event::deserialize_( cParser &Input, scene::scratch_data &Scratchpad ) m_input.command_type = TCommandType::cm_OutsideStation; m_passive = true; // ma być skanowny, aby AI nie przekraczało W5 } + else if( token == "CabSignal" ) { + m_input.command_type = TCommandType::cm_SecuritySystemMagnet; + m_passive = true; + } else { m_input.command_type = TCommandType::cm_Unknown; } diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index f6b16f6c..c3dc62b0 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -664,6 +664,8 @@ struct TSecuritySystem int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/ bool RadioStop; // czy jest RadioStop bool PoweredUp { false }; // helper, for detection of power state change + bool SHPLock{ false }; // prevents tps reset when true + double MagnetLocation { 0.0 }; // placement of tps magnet, as offset from vehicle front inline bool is_beeping() const { return TestFlag( Status, s_SHPalarm ); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index eb29e1e2..80b7df23 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2664,6 +2664,7 @@ bool TMoverParameters::CabDeactivisation( bool const Enforce ) DirAbsolute = DirActive * CabActive; DepartureSignal = false; // nie buczeć z nieaktywnej kabiny SecuritySystem.Status = s_off; // deactivate alerter TODO: make it part of control based cab selection + SecuritySystem.SHPLock = false; SendCtrlToNext("CabActivisation", 0, CabOccupied); // CabActive==0! } @@ -2827,18 +2828,18 @@ void TMoverParameters::SSReset(void) SetFlag(SecuritySystem.Status, -s_aware); SetFlag(SecuritySystem.Status, -s_CAalarm); SetFlag(SecuritySystem.Status, -s_CAebrake); - // EmergencyBrakeFlag = false; //YB-HN SecuritySystem.VelocityAllowed = -1; } else if (TestFlag(SecuritySystem.Status, s_active)) { - SecuritySystem.SystemBrakeSHPTimer = 0; - SecuritySystem.SystemSoundSHPTimer = 0; - SetFlag(SecuritySystem.Status, -s_active); - SetFlag(SecuritySystem.Status, -s_SHPalarm); - SetFlag(SecuritySystem.Status, -s_SHPebrake); - // EmergencyBrakeFlag = false; //YB-HN - SecuritySystem.VelocityAllowed = -1; + if( false == SecuritySystem.SHPLock ) { + SecuritySystem.SystemBrakeSHPTimer = 0; + SecuritySystem.SystemSoundSHPTimer = 0; + SetFlag( SecuritySystem.Status, -s_active ); + SetFlag( SecuritySystem.Status, -s_SHPalarm ); + SetFlag( SecuritySystem.Status, -s_SHPebrake ); + SecuritySystem.VelocityAllowed = -1; + } } } @@ -10542,7 +10543,7 @@ void TMoverParameters::LoadFIZ_Security( std::string const &line ) { extract_value( SecuritySystem.SoundSignalDelay, "SoundSignalDelay", line, "" ); extract_value( SecuritySystem.EmergencyBrakeDelay, "EmergencyBrakeDelay", line, "" ); extract_value( SecuritySystem.RadioStop, "RadioStop", line, "" ); - + extract_value( SecuritySystem.MagnetLocation, "MagnetLocation", line, "" ); extract_value( EmergencyBrakeWarningSignal, "EmergencyBrakeWarningSignal", line, "" ); } @@ -11487,9 +11488,6 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) BrakeDelay[b] = BrakeDelay[b] * (2.5 + Random(0.0, 0.2)) / 3.0; } - if (TrainType == dt_ET22) - CompressorPower = 0; - Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag); /* ScndPipePress = Compressor; @@ -11505,6 +11503,13 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } } } + + // security system + // by default place the magnet in the vehicle centre + if( SecuritySystem.MagnetLocation == 0 ) { + SecuritySystem.MagnetLocation = Dim.L / 2 - 0.25; + } + SecuritySystem.MagnetLocation = clamp( SecuritySystem.MagnetLocation, 0.0, Dim.L ); return OK; } diff --git a/MemCell.cpp b/MemCell.cpp index f0cd8bca..751543fb 100644 --- a/MemCell.cpp +++ b/MemCell.cpp @@ -86,6 +86,10 @@ TCommandType TMemCell::CommandCheck() eCommand = TCommandType::cm_EmergencyBrake; bCommand = false; } + else if( szText == "CabSignal" ) { + eCommand = TCommandType::cm_SecuritySystemMagnet; + bCommand = false; + } else { eCommand = TCommandType::cm_Unknown; // ciąg nierozpoznany (nie jest komendą) From 696251d71a411e576172f13a8393c8ab34a077c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Mon, 17 May 2021 16:53:02 +0200 Subject: [PATCH 3/5] AI driver has more histeresis when using ep brake --- Driver.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Driver.cpp b/Driver.cpp index 71903b69..6e3ab20a 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -7768,8 +7768,11 @@ void TController::control_braking_force() { fAccGravity < 0.025 ? // HACK: when going downhill be more responsive to desired deceleration fAccThreshold : std::max( -0.2, fAccThreshold ) ) }; + auto const AccMax{ std::min(fBrake_a0[0] + 12 * fBrake_a1[0], mvOccupied->MED_amax) }; + auto const accmargin = ((AccMax > 1.1 * AccDesired) && (fAccGravity < 0.025)) ? + 0.05 : 0.0; if( ( AccDesired < accthreshold ) // jeśli hamować - u góry ustawia się hamowanie na fAccThreshold - && ( ( AbsAccS > AccDesired ) + && ( ( AbsAccS > AccDesired + accmargin) || ( BrakeCtrlPosition < 0 ) ) ) { // hamować bardziej, gdy aktualne opóźnienie hamowania mniejsze niż (AccDesired) cue_action( locale::string::driver_hint_brakingforceincrease ); From eaa3b647e43f376d2014525a31ed02ac3091d461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=B3lik=20Uszasty?= Date: Wed, 19 May 2021 21:48:02 +0200 Subject: [PATCH 4/5] Changed acceleration conditions for AI driver --- Driver.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 6e3ab20a..89392179 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -7549,7 +7549,11 @@ TController::adjust_desired_speed_for_current_speed() { } } // HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts + auto MaxAcc{ 0.5 * (mvOccupied->Couplers[mvOccupied->DirAbsolute >= 0 ? 1 : 0].FmaxC) / fMass }; + MaxAcc *= clamp(vel * 0.2, 0.2, 1.0); + AccDesired = std::min(AccDesired, clamp(MaxAcc, HeavyCargoTrainAcceleration, AccPreferred)); // TBD: expand this behaviour to all trains with car(s) exceeding certain weight? + /* if( ( IsPassengerTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) { AccDesired = std::min( AccDesired, ( iVehicles - ControlledEnginesCount > 8 ? HeavyPassengetTrainAcceleration : PassengetTrainAcceleration ) ); } @@ -7558,7 +7562,7 @@ TController::adjust_desired_speed_for_current_speed() { } if( ( IsHeavyCargoTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) { AccDesired = std::min( AccDesired, HeavyCargoTrainAcceleration ); - } + } */ } else { // for cars the older version works better @@ -7682,7 +7686,7 @@ void TController::control_tractive_force() { auto const velocity { DirectionalVel() }; // jeśli przyspieszenie pojazdu jest mniejsze niż żądane oraz... if( ( AccDesired > EU07_AI_NOACCELERATION ) // don't add power if not asked for actual speed-up - && ( AbsAccS < AccDesired /* - 0.05 */ ) + && (( AbsAccS < AccDesired /* - 0.05 */ ) || (mvOccupied->SpeedCtrlUnit.IsActive && velocity < mvOccupied->SpeedCtrlUnit.FullPowerVelocity)) && ( false == TestFlag( iDrivigFlags, movePress ) ) ) { // ...jeśli prędkość w kierunku czoła jest mniejsza od dozwolonej o margines... if( velocity < ( @@ -7712,7 +7716,7 @@ void TController::control_tractive_force() { else if( ( velocity > VelDesired + SpeedCtrlMargin) || ( fAccGravity < -0.01 ? AccDesired < 0.0 : - ( AbsAccS > AccDesired + 0.05 ) ) + ( AbsAccS > AccDesired + 10.05 ) ) || ( IsAnyCouplerStretched ) ) { // jak za bardzo przyspiesza albo prędkość przekroczona // dodany wyjatek na "pelna w przod" From b4392c25b9c5f2c39b14e3c92e9c151b06630f2b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sat, 22 May 2021 23:29:05 +0200 Subject: [PATCH 5/5] train acceleration logic tweak, train protection system magnet activation tweak --- Driver.cpp | 30 ++++++++++++++++++++---------- McZapkie/Mover.cpp | 4 ++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 89392179..47abcc7b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1418,16 +1418,24 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo // NOTE: magnet induction calculation presumes the driver is located in the front vehicle // TBD, TODO: take into account actual position of controlled/occupied vehicle in the consist, whichever comes first auto const magnetlocation { pVehicles[ end::front ]->MoverParameters->SecuritySystem.MagnetLocation }; + auto const magnetrange { 1.0 }; + auto const ismagnetpassed { Point.fDist < -( magnetlocation + magnetrange ) }; if( Point.fDist < -( magnetlocation ) ) { - mvOccupied->SecuritySystem.SHPLock |= ( !AIControllFlag ); // don't make life difficult for the ai, but a human driver is a fair game - PutCommand( - Point.evEvent->input_text(), - Point.evEvent->input_value( 1 ), - Point.evEvent->input_value( 2 ), - nullptr ); + // NOTE: normally we'd activate the magnet once the leading vehicle passes it + // but on a fresh scan after direction change it would be detected as long as it's under consist, and meet the (simple) activation condition + // thus we're doing a more precise check in such situation (we presume direction change takes place only if the vehicle is standing still) + if( ( mvOccupied->Vel > EU07_AI_NOMOVEMENT ) + || ( false == ismagnetpassed ) ) { + mvOccupied->SecuritySystem.SHPLock |= ( !AIControllFlag ); // don't make life difficult for the ai, but a human driver is a fair game + PutCommand( + Point.evEvent->input_text(), + Point.evEvent->input_value( 1 ), + Point.evEvent->input_value( 2 ), + nullptr ); + } } - if( Point.fDist < -( magnetlocation + 0.5 ) ) { - Point.Clear(); // magnet passed, deactivate + if( ismagnetpassed ) { + Point.Clear(); mvOccupied->SecuritySystem.SHPLock = false; } return true; @@ -7549,8 +7557,10 @@ TController::adjust_desired_speed_for_current_speed() { } } // HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts - auto MaxAcc{ 0.5 * (mvOccupied->Couplers[mvOccupied->DirAbsolute >= 0 ? 1 : 0].FmaxC) / fMass }; - MaxAcc *= clamp(vel * 0.2, 0.2, 1.0); + auto MaxAcc{ 0.5 * mvOccupied->Couplers[(mvOccupied->DirAbsolute >= 0 ? end::rear : end::front)].FmaxC / fMass }; + if( iVehicles - ControlledEnginesCount > 0 ) { + MaxAcc *= clamp( vel * 0.025, 0.2, 1.0 ); + } AccDesired = std::min(AccDesired, clamp(MaxAcc, HeavyCargoTrainAcceleration, AccPreferred)); // TBD: expand this behaviour to all trains with car(s) exceeding certain weight? /* diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 80b7df23..1167c093 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -11507,7 +11507,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) // security system // by default place the magnet in the vehicle centre if( SecuritySystem.MagnetLocation == 0 ) { - SecuritySystem.MagnetLocation = Dim.L / 2 - 0.25; + SecuritySystem.MagnetLocation = Dim.L / 2 - 0.5; } SecuritySystem.MagnetLocation = clamp( SecuritySystem.MagnetLocation, 0.0, Dim.L ); @@ -12042,7 +12042,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C { SecuritySystem.VelocityAllowed = static_cast(floor(CValue1)); SecuritySystem.NextVelocityAllowed = static_cast(floor(CValue2)); - SecuritySystem.SystemSoundSHPTimer = 0; // hunter-091012 +// SecuritySystem.SystemSoundSHPTimer = 0; // hunter-091012 SetFlag(SecuritySystem.Status, s_active); } // else OK:=false;