diff --git a/Driver.cpp b/Driver.cpp index 5c8b7a10..b5db66dc 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -746,7 +746,10 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) else if( sSpeedTable[ iLast ].trTrack == tLast ) { // otherwise just mark the last added track as the final one // TODO: investigate exactly how we can wind up not marking the last existing track as actual end - sSpeedTable[ iLast ].iFlags |= ( spEnabled | spEnd ); + if( false == TestFlag( sSpeedTable[ iLast ].trTrack->iCategoryFlag, 0x100 ) ) { + // don't mark portals, as these aren't exactly track ends, but teleport devices + sSpeedTable[ iLast ].iFlags |= ( spEnabled | spEnd ); + } } // to ostatnia pozycja, bo NULL nic nie da, a może się podpiąć obrotnica, czy jakieś transportery return; diff --git a/DynObj.cpp b/DynObj.cpp index 6b20af95..8b15d1f3 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -1642,7 +1642,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" else if (DriverType == "reardriver") DriverType = "2"; // sterujący kabiną -1 else if (DriverType == "passenger") - DriverType = "p"; // to do przemyślenia + DriverType = ""; // legacy type, no longer needed else if (DriverType == "nobody") DriverType = ""; // nikt nie siedzi @@ -3341,8 +3341,7 @@ bool TDynamicObject::Update(double dt, double dt1) ( MoverParameters->DynamicBrakeFlag && MoverParameters->ResistorsFlag ) ? 0 : std::abs( MoverParameters->Itot ) ) - + MoverParameters->TotalCurrent; // prąd pobierany przez pojazd - bez - // sensu z tym (TotalCurrent) + + MoverParameters->TotalCurrent; // prąd pobierany przez pojazd - bez sensu z tym (TotalCurrent) // TotalCurrent to bedzie prad nietrakcyjny (niezwiazany z napedem) // fCurrent+=fabs(MoverParameters->Voltage)*1e-6; //prąd płynący przez woltomierz, rozładowuje kondensator orgromowy 4µF double fPantCurrent = fCurrent; // normalnie cały prąd przez jeden pantograf @@ -3387,8 +3386,16 @@ bool TDynamicObject::Update(double dt, double dt1) if (p->hvPowerWire) { auto const lastvoltage { MoverParameters->PantFrontVolt }; // TODO: wyliczyć trzeba prąd przypadający na pantograf i wstawić do GetVoltage() - MoverParameters->PantFrontVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, fPantCurrent ); - fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf + if( lastvoltage == 0.0 ) { + // HACK: retrieve the wire voltage for calculations down the road without blowing up the supply + MoverParameters->PantFrontVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, 0.0 ); + } + else { + MoverParameters->PantFrontVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, fPantCurrent ); + if( MoverParameters->PantFrontVolt > 0.0 ) { + fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf (unless it doesn't) + } + } // TODO: refactor reaction to voltage change to mover as sound event for specific pantograph if( ( lastvoltage == 0.0 ) && ( MoverParameters->PantFrontVolt > 0.0 ) ) { @@ -3421,8 +3428,16 @@ bool TDynamicObject::Update(double dt, double dt1) if (p->hvPowerWire) { auto const lastvoltage { MoverParameters->PantRearVolt }; // TODO: wyliczyć trzeba prąd przypadający na pantograf i wstawić do GetVoltage() - MoverParameters->PantRearVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, fPantCurrent ); - fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf + if( lastvoltage == 0.0 ) { + // HACK: retrieve the wire voltage for calculations down the road without blowing up the supply + MoverParameters->PantRearVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, 0.0 ); + } + else { + MoverParameters->PantRearVolt = p->hvPowerWire->VoltageGet( MoverParameters->PantographVoltage, fPantCurrent ); + if( MoverParameters->PantRearVolt > 0.0 ) { + fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf (unless it doesn't) + } + } // TODO: refactor reaction to voltage change to mover as sound event for specific pantograph if( ( lastvoltage == 0.0 ) && ( MoverParameters->PantRearVolt > 0.0 ) ) { diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 9a3a5d18..447def89 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1651,8 +1651,8 @@ void TMoverParameters::ConverterCheck( double const Timestep ) { if( ( ConverterAllow ) && ( ConverterAllowLocal ) && ( false == PantPressLockActive ) - && ( ( Mains ) - || ( GetAnyTrainsetVoltage() > 0.0 ) ) ) { + // HACK: allow carriages to operate converter without (missing) fuse prerequisite + && ( ( Power > 1.0 ? Mains : GetAnyTrainsetVoltage() > 0.0 ) ) ) { // delay timer can be optionally configured, and is set anew whenever converter goes off if( ConverterStartDelayTimer <= 0.0 ) { ConverterFlag = true; diff --git a/Traction.cpp b/Traction.cpp index 7e81285f..376fe7fd 100644 --- a/Traction.cpp +++ b/Traction.cpp @@ -486,18 +486,21 @@ double TTraction::VoltageGet(double u, double i) psPowered->CurrentGet( res ) * res : 0.0 ); } + if( ( psPower[0] && psPower[0]->Fuse() ) + || ( psPower[1] && psPower[1]->Fuse() ) ) { + // if either power source is out, so are we + return 0.0; + } + double r0t, r1t, r0g, r1g; double i0, i1; r0t = fResistance[0]; //średni pomysł, ale lepsze niż nic r1t = fResistance[1]; // bo nie uwzględnia spadków z innych pojazdów if (psPower[0] && psPower[1]) { // gdy przęsło jest zasilane z obu stron - mamy trójkąt: res, r0t, r1t - // yB: Gdy wywali podstacja, to zaczyna się robić nieciekawie - napięcie w sekcji na jednym - // końcu jest równe zasilaniu, - // yB: a na drugim końcu jest równe 0. Kolejna sprawa to rozróżnienie uszynienia sieci na - // podstacji/odłączniku (czyli - // yB: potencjał masy na sieci) od braku zasilania (czyli odłączenie źródła od sieci i brak - // jego wpływu na napięcie). + // yB: Gdy wywali podstacja, to zaczyna się robić nieciekawie - napięcie w sekcji na jednym końcu jest równe zasilaniu, + // yB: a na drugim końcu jest równe 0. Kolejna sprawa to rozróżnienie uszynienia sieci na podstacji/odłączniku (czyli + // yB: potencjał masy na sieci) od braku zasilania (czyli odłączenie źródła od sieci i brak jego wpływu na napięcie). if ((r0t > 0.0) && (r1t > 0.0)) { // rezystancje w mianowniku nie mogą być zerowe r0g = res + r0t + (res * r0t) / r1t; // przeliczenie z trójkąta na gwiazdę diff --git a/TractionPower.cpp b/TractionPower.cpp index 48ff6d4a..cbe4d9cd 100644 --- a/TractionPower.cpp +++ b/TractionPower.cpp @@ -121,8 +121,7 @@ double TTractionPowerSource::CurrentGet(double res) return 0; } if ((res > 0) || ((res < 0) && (Recuperation || true))) - TotalAdmitance += - 1.0 / res; // połączenie równoległe rezystancji jest równoważne sumie admitancji + TotalAdmitance += 1.0 / res; // połączenie równoległe rezystancji jest równoważne sumie admitancji float NomVolt = (TotalPreviousAdmitance < 0 ? NominalVoltage * 1.083 : NominalVoltage); TotalCurrent = (TotalPreviousAdmitance != 0.0) ? NomVolt / (InternalRes + 1.0 / TotalPreviousAdmitance) : diff --git a/TractionPower.h b/TractionPower.h index 171f2879..d96f401d 100644 --- a/TractionPower.h +++ b/TractionPower.h @@ -28,6 +28,8 @@ public: void VoltageSet(double const v) { NominalVoltage = v; }; void PowerSet(TTractionPowerSource *ps); + bool Fuse() const { + return ( FastFuse || SlowFuse ); } // members TTractionPowerSource *psNode[ 2 ] = { nullptr, nullptr }; // zasilanie na końcach dla sekcji bool bSection = false; // czy jest sekcją diff --git a/Train.cpp b/Train.cpp index b85389da..580d4e02 100644 --- a/Train.cpp +++ b/Train.cpp @@ -6061,7 +6061,7 @@ bool TTrain::Update( double const Deltatime ) (std::abs(mvControlled->Im) > 0)) { ggEngineVoltage.UpdateValue( - (x * (mvControlled->PantographVoltage - + (x * (std::abs(mvControlled->EngineVoltage) - mvControlled->RList[mvControlled->MainCtrlActualPos].R * std::abs(mvControlled->Im)) / mvControlled->RList[mvControlled->MainCtrlActualPos].Mn)); diff --git a/drivermode.cpp b/drivermode.cpp index 1ec7c49e..d1b8ba27 100644 --- a/drivermode.cpp +++ b/drivermode.cpp @@ -420,7 +420,7 @@ driver_mode::update_camera( double const Deltatime ) { if( Camera.m_owner == nullptr ) { if( controlled && LengthSquared3( controlled->GetPosition() - Camera.Pos ) < ( 1500 * 1500 ) ) { // gdy bliżej niż 1.5km - Camera.LookAt = controlled->GetPosition(); + Camera.LookAt = controlled->GetPosition() + 0.4 * controlled->VectorUp() * controlled->MoverParameters->Dim.H; } else { TDynamicObject *d = std::get( simulation::Region->find_vehicle( Global.pCamera.Pos, 300, false, false ) ); @@ -437,7 +437,7 @@ driver_mode::update_camera( double const Deltatime ) { if( d ) pDynamicNearest = d; // zmiana na nowy, jeśli coś znaleziony niepusty if( pDynamicNearest ) - Camera.LookAt = pDynamicNearest->GetPosition() + 0.5 * pDynamicNearest->VectorUp() * pDynamicNearest->MoverParameters->Dim.H; + Camera.LookAt = pDynamicNearest->GetPosition() + 0.4 * pDynamicNearest->VectorUp() * pDynamicNearest->MoverParameters->Dim.H; } Camera.RaLook(); // jednorazowe przestawienie kamery } diff --git a/opengl33renderer.cpp b/opengl33renderer.cpp index a04026e8..fc18c9dc 100644 --- a/opengl33renderer.cpp +++ b/opengl33renderer.cpp @@ -580,7 +580,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) scene_ubs.time = Timer::GetTime(); scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION); - scene_ubs.inv_view = glm::inverse( glm::mat4{ glm::mat3{ m_renderpass.pass_camera.modelview() } } ); + scene_ubs.inv_view = glm::inverse( glm::mat4{ glm::mat3{ m_colorpass.pass_camera.modelview() } } ); scene_ubo->update(scene_ubs); scene_ubo->bind_uniform(); @@ -657,7 +657,8 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) setup_drawing(true); m_renderpass.draw_stats = {}; - glm::mat4 future; + model_ubs.future = glm::mat4(); + glm::mat4 future; if (Global.pCamera.m_owner != nullptr) { auto const *vehicle = Global.pCamera.m_owner; @@ -665,7 +666,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) future = glm::translate(mv, -glm::vec3(vehicle->get_future_movement())) * glm::inverse(mv); } - model_ubs.future = glm::mat4(); + Update_Lights( simulation::Lights ); glDebug("render environment"); @@ -683,8 +684,8 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) // precipitation happens when overcast is in 1-2 range if (!FreeFlyModeFlag && Global.Overcast <= 1.0f && Global.render_cab) { - glDebug("render cab opaque"); - // cache shadow colour in case we need to account for cab light + glDebug("render opaque cab"); + model_ubs.future = glm::mat4(); auto const *vehicle{ simulation::Train->Dynamic() }; if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( glm::min( colors::white, m_shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); @@ -715,9 +716,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) // cab render if (false == FreeFlyModeFlag && Global.render_cab) { - glDebug("render translucent cab"); model_ubs.future = glm::mat4(); - // cache shadow colour in case we need to account for cab light auto *vehicle { simulation::Train->Dynamic() }; if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( glm::min( colors::white, m_shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); @@ -725,16 +724,22 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) if (Global.Overcast > 1.0f) { // with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab - setup_drawing(false); + glDebug( "render opaque cab" ); + setup_drawing(false); Render_cab(vehicle, vehicle->InteriorLightLevel, false); - Render_interior( false ); + Render_interior(false); setup_drawing(true); - Render_interior( true ); + Render_interior(true); } - Render_cab(vehicle, vehicle->InteriorLightLevel, true); + glDebug( "render translucent cab" ); + Render_cab(vehicle, vehicle->InteriorLightLevel, true); if( vehicle->InteriorLightLevel > 0.f ) { setup_shadow_color( m_shadowcolor ); } + if( Global.Overcast > 1.0f ) { + // with the cab in place we can (finally) safely draw translucent part of the occupied vehicle + Render_Alpha( vehicle ); + } } Timer::subsystem.gfx_color.stop(); @@ -950,7 +955,7 @@ bool opengl33_renderer::Render_interior( bool const Alpha ) { while( dynamic != nullptr ) { glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.pass_camera.position() }; - float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor }; + float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) }; dynamics.emplace_back( squaredistance, dynamic ); dynamic = dynamic->NextC( coupling::permanent ); } @@ -959,7 +964,7 @@ bool opengl33_renderer::Render_interior( bool const Alpha ) { while( dynamic != nullptr ) { glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.pass_camera.position() }; - float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor }; + float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) }; dynamics.emplace_back( squaredistance, dynamic ); dynamic = dynamic->PrevC( coupling::permanent ); } @@ -1909,8 +1914,6 @@ void opengl33_renderer::Render(scene::basic_region *Region) { case rendermode::color: { - Update_Lights(simulation::Lights); - Render(std::begin(m_sectionqueue), std::end(m_sectionqueue)); // draw queue is filled while rendering sections if (EditorModeFlag && m_current_viewport->main) @@ -2343,7 +2346,7 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic) { case rendermode::shadows: { - squaredistance = glm::length2(glm::vec3{glm::dvec3{Dynamic->vPosition - m_renderpass.viewport_camera.position()}} / Global.ZoomFactor) / Global.fDistanceFactor; + squaredistance = glm::length2(glm::vec3{glm::dvec3{Dynamic->vPosition - m_renderpass.viewport_camera.position()}} / Global.ZoomFactor); if( false == FreeFlyModeFlag ) { // filter out small details if we're in vehicle cab squaredistance = std::max( 100.f * 100.f, squaredistance ); @@ -2352,7 +2355,7 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic) } default: { - squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor) / Global.fDistanceFactor; + squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor); // TODO: filter out small details based on fidelity setting break; } @@ -3332,7 +3335,7 @@ bool opengl33_renderer::Render_Alpha(TDynamicObject *Dynamic) case rendermode::shadows: default: { - squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor) / Global.fDistanceFactor; + squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor); break; } } @@ -3971,7 +3974,7 @@ void opengl33_renderer::Update_Lights(light_array &Lights) Bind_Texture( gl::HEADLIGHT_TEX, m_headlightstexture ); // arrange the light array from closest to farthest from current position of the camera - auto const camera = m_renderpass.pass_camera.position(); + auto const camera = m_colorpass.pass_camera.position(); std::sort( std::begin(Lights.data), std::end(Lights.data), [&camera](light_array::light_record const &Left, light_array::light_record const &Right) { diff --git a/openglrenderer.cpp b/openglrenderer.cpp index 2315f290..124f4404 100644 --- a/openglrenderer.cpp +++ b/openglrenderer.cpp @@ -751,7 +751,7 @@ bool opengl_renderer::Render_interior( bool const Alpha ) { while( dynamic != nullptr ) { glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.camera.position() }; - float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor }; + float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) }; dynamics.emplace_back( squaredistance, dynamic ); dynamic = dynamic->NextC( coupling::permanent ); } @@ -760,7 +760,7 @@ bool opengl_renderer::Render_interior( bool const Alpha ) { while( dynamic != nullptr ) { glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.camera.position() }; - float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor }; + float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) }; dynamics.emplace_back( squaredistance, dynamic ); dynamic = dynamic->PrevC( coupling::permanent ); } @@ -2249,7 +2249,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.camera.position(); switch( m_renderpass.draw_mode ) { case rendermode::shadows: { - squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor; + squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ); if( false == FreeFlyModeFlag ) { // filter out small details if we're in vehicle cab squaredistance = std::max( 100.f * 100.f, squaredistance ); @@ -2257,13 +2257,13 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { break; } case rendermode::cabshadows: { - squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor; + squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ); // filter out small details squaredistance = std::max( 100.f * 100.f, squaredistance ); break; } default: { - squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor; + squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ); // TODO: filter out small details based on fidelity setting break; } @@ -3432,11 +3432,11 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { float squaredistance; switch( m_renderpass.draw_mode ) { case rendermode::shadows: { - squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor; + squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ); break; } default: { - squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor; + squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ); break; } } diff --git a/version.h b/version.h index 4fdd6647..44c490d7 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 20 -#define VERSION_MINOR 108 +#define VERSION_MINOR 112 #define VERSION_REVISION 0