Merge branch 'milek-dev' into gfx-work

This commit is contained in:
milek7
2019-01-14 23:31:26 +01:00
14 changed files with 226 additions and 180 deletions

View File

@@ -180,9 +180,9 @@ TSpeedPos::TSpeedPos(TTrack *track, double dist, int flag)
Set(track, dist, flag);
};
TSpeedPos::TSpeedPos(basic_event *event, double dist, TOrders order)
TSpeedPos::TSpeedPos(basic_event *event, double dist, double length, TOrders order)
{
Set(event, dist, order);
Set(event, dist, length, order);
};
void TSpeedPos::Clear()
@@ -364,13 +364,20 @@ bool TSpeedPos::IsProperSemaphor(TOrders order)
return false; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej
}
bool TSpeedPos::Set(basic_event *event, double dist, TOrders order)
bool TSpeedPos::Set(basic_event *event, double dist, double length, TOrders order)
{ // zapamiętanie zdarzenia
fDist = dist;
iFlags = spEnabled | spEvent; // event+istotny
iFlags = spEvent;
evEvent = event;
vPos = event->input_location(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?)
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
if( dist + length >= 0 ) {
iFlags |= spEnabled;
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
}
else {
// located behind the tracking consist, don't bother with it
return false;
}
// zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa
// jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania
// WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order));
@@ -580,6 +587,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
if( newspeedpoint.Set(
pEvent,
GetDistanceToEvent( pTrack, pEvent, fLastDir, fCurrentDistance ),
fLength,
OrderCurrentGet() ) ) {
fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować
@@ -1909,72 +1917,83 @@ void TController::AutoRewident()
mvOccupied->BrakeOpModeFlag = i;
}
}
// teraz zerujemy tabelkę opóźnienia hamowania
for (int i = 0; i < BrakeAccTableSize; ++i)
{
fBrake_a0[i+1] = 0;
fBrake_a1[i+1] = 0;
}
// 4. Przeliczanie siły hamowania
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
d = pVehicles[0]; // pojazd na czele składu
while (d) {
for( int i = 0; i < BrakeAccTableSize; ++i ) {
fBrake_a0[ i + 1 ] += d->MoverParameters->BrakeForceR( 0.25, velstep*( 1 + 2 * i ) );
fBrake_a1[ i + 1 ] += d->MoverParameters->BrakeForceR( 1.00, velstep*( 1 + 2 * i ) );
}
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
for (int i = 0; i < BrakeAccTableSize; ++i)
{
fBrake_a1[i+1] -= fBrake_a0[i+1];
fBrake_a0[i+1] /= fMass;
fBrake_a0[i + 1] += 0.001*velstep*(1 + 2 * i);
fBrake_a1[i+1] /= (12*fMass);
}
IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 );
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 );
BrakingInitialLevel = (
IsHeavyCargoTrain ? 1.25 :
IsCargoTrain ? 1.25 :
1.00 );
BrakingLevelIncrease = (
IsHeavyCargoTrain ? 0.25 :
IsCargoTrain ? 0.25 :
0.25 );
if( mvOccupied->TrainType == dt_EZT ) {
if( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) {
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
if( OrderCurrentGet() & Shunt ) {
// for uniform behaviour and compatibility with older scenarios set default acceleration table values for shunting
fAccThreshold = (
mvOccupied->TrainType == dt_EZT ? -0.55 :
mvOccupied->TrainType == dt_DMU ? -0.45 :
-0.2 );
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
if( ( mvOccupied->TrainType == dt_EZT )
&& ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) {
fAccThreshold += 0.10;
}
else {
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
}
fBrakeReaction = 0.25;
}
else if( mvOccupied->TrainType == dt_DMU ) {
fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
fBrakeReaction = 0.25;
}
else if (ustaw > 16) {
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 4 * fBrake_a1[ BrakeAccTableSize ];
fBrakeReaction = 1.00 + fLength*0.004;
}
else {
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 1 * fBrake_a1[ BrakeAccTableSize ];
fBrakeReaction = 1.00 + fLength*0.005;
}
fAccThreshold = fNominalAccThreshold;
/*
if( IsHeavyCargoTrain ) {
// HACK: heavy cargo trains don't activate brakes early enough
fAccThreshold = std::max( -0.2, fAccThreshold );
if( OrderCurrentGet() & Obey_train ) {
// 4. Przeliczanie siły hamowania
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
d = pVehicles[0]; // pojazd na czele składu
while (d) {
for( int i = 0; i < BrakeAccTableSize; ++i ) {
fBrake_a0[ i + 1 ] += d->MoverParameters->BrakeForceR( 0.25, velstep*( 1 + 2 * i ) );
fBrake_a1[ i + 1 ] += d->MoverParameters->BrakeForceR( 1.00, velstep*( 1 + 2 * i ) );
}
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
for (int i = 0; i < BrakeAccTableSize; ++i)
{
fBrake_a1[i+1] -= fBrake_a0[i+1];
fBrake_a0[i+1] /= fMass;
fBrake_a0[i + 1] += 0.001*velstep*(1 + 2 * i);
fBrake_a1[i+1] /= (12*fMass);
}
IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 );
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 );
BrakingInitialLevel = (
IsHeavyCargoTrain ? 1.25 :
IsCargoTrain ? 1.25 :
1.00 );
BrakingLevelIncrease = (
IsHeavyCargoTrain ? 0.25 :
IsCargoTrain ? 0.25 :
0.25 );
if( mvOccupied->TrainType == dt_EZT ) {
if( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) {
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
}
else {
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
}
fBrakeReaction = 0.25;
}
else if( mvOccupied->TrainType == dt_DMU ) {
fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
fBrakeReaction = 0.25;
}
else if (ustaw > 16) {
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 4 * fBrake_a1[ BrakeAccTableSize ];
fBrakeReaction = 1.00 + fLength*0.004;
}
else {
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 1 * fBrake_a1[ BrakeAccTableSize ];
fBrakeReaction = 1.00 + fLength*0.005;
}
fAccThreshold = fNominalAccThreshold;
}
*/
}
double TController::ESMVelocity(bool Main)
@@ -2852,7 +2871,11 @@ bool TController::IncSpeed()
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
auto const useseriesmodevoltage { mvControlling->EnginePowerSource.CollectorParameters.MaxV * ( IsHeavyCargoTrain ? 0.70 : 0.80 ) };
auto const useseriesmodevoltage {
interpolate(
mvControlling->EnginePowerSource.CollectorParameters.MinV,
mvControlling->EnginePowerSource.CollectorParameters.MaxV,
( IsHeavyCargoTrain ? 0.35 : 0.40 ) ) };
auto const useseriesmode = (
( mvControlling->Imax > mvControlling->ImaxLo )
|| ( fVoltage < useseriesmodevoltage )
@@ -2883,10 +2906,12 @@ bool TController::IncSpeed()
if( usefieldshunting ) {
// to dać bocznik
// engage the shuntfield only if there's sufficient power margin to draw from
auto const sufficientpowermargin { fVoltage - useseriesmodevoltage > ( IsHeavyCargoTrain ? 100.0 : 75.0 ) };
OK = (
fVoltage > useseriesmodevoltage + 0.0125 * mvControlling->EnginePowerSource.CollectorParameters.MaxV ?
sufficientpowermargin ?
mvControlling->IncScndCtrl( 1 ) :
false );
true );
}
else {
// jeśli ustawiony bocznik to bocznik na zero po chamsku
@@ -2894,10 +2919,19 @@ bool TController::IncSpeed()
mvControlling->DecScndCtrl( 2 );
}
// kręcimy nastawnik jazdy
// don't draw too much power;
// keep from dropping into series mode when entering/using parallel mode, and from shutting down in the series mode
auto const sufficientpowermargin {
fVoltage - (
mvControlling->RList[ std::min( mvControlling->MainCtrlPos + 1, mvControlling->MainCtrlPosNo ) ].Bn == 1 ?
mvControlling->EnginePowerSource.CollectorParameters.MinV :
useseriesmodevoltage )
> ( IsHeavyCargoTrain ? 80.0 : 60.0 ) };
OK = (
mvControlling->DelayCtrlFlag ?
true :
mvControlling->IncMainCtrl( 1 ) );
( sufficientpowermargin && ( false == mvControlling->DelayCtrlFlag ) ) ?
mvControlling->IncMainCtrl( 1 ) :
true );
// czekaj na 1 pozycji, zanim się nie włączą liniowe
if( true == mvControlling->StLinFlag ) {
iDrivigFlags |= moveIncSpeed;
@@ -3903,12 +3937,13 @@ TController::UpdateSituation(double dt) {
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
}
// crude way to deal with automatic door opening on W4 preventing further ride
// HACK: crude way to deal with automatic door opening on W4 preventing further ride
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
// TODO: check if this situation still happens and the hack is still needed
if( ( false == AIControllFlag )
&& ( iDrivigFlags & moveDoorOpened )
&& ( mvOccupied->DoorCloseCtrl != control_t::driver )
&& ( mvControlling->MainCtrlPos > 0 ) ) {
&& ( mvControlling->MainCtrlPos > ( mvControlling->EngineType != TEngineType::DieselEngine ? 0 : 1 ) ) ) { // for diesel 1st position is effectively 0
Doors( false );
}
@@ -4006,7 +4041,15 @@ TController::UpdateSituation(double dt) {
}
}
}
if( fVoltage < 0.75 * mvControlling->EnginePowerSource.CollectorParameters.MaxV ) {
// TODO: refactor this calculation into a subroutine
auto const useseriesmodevoltage {
interpolate(
mvControlling->EnginePowerSource.CollectorParameters.MinV,
mvControlling->EnginePowerSource.CollectorParameters.MaxV,
( IsHeavyCargoTrain ? 0.35 : 0.40 ) ) };
if( fVoltage <= useseriesmodevoltage ) {
// if the power station is heavily burdened try to reduce the load
switch( mvControlling->EngineType ) {
@@ -5856,12 +5899,20 @@ basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Tr
{ // sprawdzanie eventu w torze, czy jest sygnałowym - skanowanie do tyłu
// NOTE: this method returns only one event which meets the conditions, due to limitations in the caller
// TBD, TODO: clean up the caller and return all suitable events, as in theory things will go awry if the track has more than one signal
auto const dir{ pVehicles[ 0 ]->VectorFront() * pVehicles[ 0 ]->DirectionGet() };
auto const pos{ pVehicles[ 0 ]->HeadPosition() };
auto const &eventsequence { ( fDirection > 0 ? Track->m_events2 : Track->m_events1 ) };
for( auto const &event : eventsequence ) {
if( ( event.second != nullptr )
&& ( event.second->m_passive )
&& ( typeid(*(event.second)) == typeid( getvalues_event ) ) ) {
return event.second;
// since we're checking for events behind us discard the sources in front of the scanning vehicle
auto const sl{ event.second->input_location() }; // położenie komórki pamięci
auto const sem{ sl - pos }; // wektor do komórki pamięci od końca składu
if( dir.x * sem.x + dir.z * sem.z < 0 ) {
// iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu
return event.second;
}
}
}
return nullptr;

View File

@@ -141,7 +141,7 @@ class TSpeedPos
public:
TSpeedPos(TTrack *track, double dist, int flag);
TSpeedPos(basic_event *event, double dist, TOrders order);
TSpeedPos(basic_event *event, double dist, double length, TOrders order);
TSpeedPos() = default;
void Clear();
bool Update();
@@ -150,7 +150,7 @@ class TSpeedPos
void
UpdateDistance( double dist ) {
fDist -= dist; }
bool Set(basic_event *e, double d, TOrders order = Wait_for_orders);
bool Set(basic_event *e, double d, double length, TOrders order = Wait_for_orders);
void Set(TTrack *t, double d, int f);
std::string TableText() const;
std::string GetName() const;

View File

@@ -2780,7 +2780,7 @@ TDynamicObject::update_load_visibility() {
}
*/
auto loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
MoverParameters->MaxLoad == 0.f ?
0.0 :
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
auto const sectionloadpercentage { (
@@ -2814,7 +2814,7 @@ TDynamicObject::update_load_offset() {
if( MoverParameters->LoadType.offset_min == 0.f ) { return; }
auto const loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
MoverParameters->MaxLoad == 0.f ?
0.0 :
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };

View File

@@ -97,7 +97,7 @@ basic_event::event_conditions::test() const {
match_value_2,
flags );
std::string comparisonlog = "Test: MemCompare - ";
std::string comparisonlog = "Test: MemCompare - " + cell->name() + " - ";
comparisonlog +=
"[" + cell->Text() + "]"

View File

@@ -374,6 +374,14 @@ global_settings::ConfigParse(cParser &Parser) {
Parser.getTokens();
Parser >> ResourceMove;
}
else if( token == "gfx.reflections.framerate" ) {
auto const updatespersecond { std::abs( Parser.getToken<double>() ) };
ReflectionUpdatesPerSecond = (
updatespersecond > 0 ?
1000 / std::min( 30.0, updatespersecond ) :
0 );
}
else if (token == "timespeed")
{
// przyspieszenie czasu, zmienna do testów

View File

@@ -115,6 +115,7 @@ struct global_settings {
float depth{ 250.f };
float distance{ 500.f }; // no longer used
} shadowtune;
int ReflectionUpdatesPerSecond{ static_cast<int>( 1000 / ( 1.0 / 300.0 ) ) };
float AnisotropicFiltering{ 8.f }; // requested level of anisotropic filtering. TODO: move it to renderer object
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
GLint iMaxTextureSize{ 4096 }; // maksymalny rozmiar tekstury

View File

@@ -1003,13 +1003,6 @@ public:
TRotation Rot { 0.0, 0.0, 0.0 };
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
#ifdef EU07_USE_OLD_HVCOUPLERS
double HVCouplers[ 2 ][ 2 ]; //przewod WN
enum hvcoupler {
current = 0,
voltage
};
#endif
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
int SoundFlag = 0; /*!o patrz stale sound_ */
double DistCounter = 0.0; /*! licznik kilometrow */

View File

@@ -316,12 +316,6 @@ ActiveCab( Cab )
Couplers[b].DmaxC = 0.1;
Couplers[b].FmaxC = 1000.0;
}
#ifdef EU07_USE_OLD_HVCOUPLERS
for( int side = 0; side < 2; ++side ) {
HVCouplers[ side ][ hvcoupler::current ] = 0.0;
HVCouplers[ side ][ hvcoupler::voltage ] = 0.0;
}
#endif
for( int b = 0; b < 3; ++b ) {
BrakeCylMult[ b ] = 0.0;
}
@@ -816,13 +810,23 @@ void TMoverParameters::UpdateBatteryVoltage(double dt)
&& ( EngineType != TEngineType::WheelsDriven )
&& ( NominalBatteryVoltage > 0 ) ) {
// HACK: allow to draw power also from adjacent converter, applicable for EMUs
// TODO: expand power cables system to include low voltage power transfers
// HACK: emulate low voltage generator powered directly by the diesel engine
auto const converteractive{ (
( ConverterFlag )
|| ( ( ( Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::front ].Connected->ConverterFlag )
|| ( ( ( Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::rear ].Connected->ConverterFlag ) )
|| ( ( EngineType == TEngineType::DieselElectric ) && ( true == Mains ) )
|| ( ( EngineType == TEngineType::DieselEngine ) && ( true == Mains ) ) };
if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery)
{ // 110V
if (!ConverterFlag)
if (!converteractive)
sn1 = (dt * 2.0); // szybki spadek do ok 90V
else
sn1 = 0;
if (ConverterFlag)
if (converteractive)
sn2 = -(dt * 2.0); // szybki wzrost do 110V
else
sn2 = 0;
@@ -846,7 +850,7 @@ void TMoverParameters::UpdateBatteryVoltage(double dt)
sn1 = (dt * 0.0046);
else
sn1 = 0;
if (ConverterFlag)
if (converteractive)
sn2 = -(dt * 50); // szybki wzrost do 110V
else
sn2 = 0;
@@ -1120,33 +1124,18 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
#ifdef EU07_USE_OLD_HVCOUPLERS
HVCouplers[ oppositeside ][ hvcoupler::voltage ] =
std::max(
std::abs( hvc ),
Couplers[ side ].Connected->HVCouplers[ Couplers[ side ].ConnectedNr ][ hvcoupler::voltage ] - HVCouplers[ side ][ hvcoupler::current ] * 0.02 );
#else
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
Couplers[ oppositeside ].power_high.voltage =
std::max(
std::abs( hvc ),
connectedcoupler.power_high.voltage - Couplers[ side ].power_high.current * 0.02 );
#endif
}
else {
#ifdef EU07_USE_OLD_HVCOUPLERS
HVCouplers[ oppositeside ][ hvcoupler::voltage ] = std::abs( hvc ) - HVCouplers[ side ][ hvcoupler::current ] * 0.02;
#else
Couplers[ oppositeside ].power_high.voltage = std::abs( hvc ) - Couplers[ side ].power_high.current * 0.02;
#endif
}
}
#ifdef EU07_USE_OLD_HVCOUPLERS
hvc = HVCouplers[ side::front ][ hvcoupler::voltage ] + HVCouplers[ side::rear ][ hvcoupler::voltage ];
#else
hvc = Couplers[ side::front ].power_high.voltage + Couplers[ side::rear ].power_high.voltage;
#endif
if( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) < 1.0 ) {
// bez napiecia...
@@ -1160,29 +1149,17 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
#ifdef EU07_USE_OLD_HVCOUPLERS
auto const oppositeside = ( Couplers[side].ConnectedNr == side::front ? side::rear : side::front );
HVCouplers[ side ][ hvcoupler::current ] =
Couplers[side].Connected->HVCouplers[oppositeside][hvcoupler::current] +
Itot * HVCouplers[side][hvcoupler::voltage] / hvc; // obciążenie rozkladane stosownie do napiec
#else
auto const &connectedsothercoupler =
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ?
side::rear :
side::front ) ];
Couplers[ side ].power_high.current =
connectedsothercoupler.power_high.current
connectedcoupler.power_high.current
+ Itot * Couplers[ side ].power_high.voltage / hvc; // obciążenie rozkladane stosownie do napiec
#endif
}
else {
#ifdef EU07_USE_OLD_HVCOUPLERS
// pierwszy pojazd
HVCouplers[side][hvcoupler::current] = Itot * HVCouplers[side][hvcoupler::voltage] / hvc;
#else
Couplers[ side ].power_high.current = Itot * Couplers[ side ].power_high.voltage / hvc;
#endif
}
}
}
@@ -1196,19 +1173,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
#ifdef EU07_USE_OLD_HVCOUPLERS
auto const oppositeside = ( Couplers[ side ].ConnectedNr == side::front ? side::rear : side::front );
TotalCurrent += Couplers[ side ].Connected->HVCouplers[ oppositeside ][ hvcoupler::current ];
HVCouplers[ side ][ hvcoupler::current ] = 0.0;
#else
auto const &connectedsothercoupler =
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ?
side::rear :
side::front ) ];
TotalCurrent += connectedsothercoupler.power_high.current;
TotalCurrent += connectedcoupler.power_high.current;
Couplers[ side ].power_high.current = 0.0;
#endif
}
}
}
@@ -1561,18 +1532,18 @@ void TMoverParameters::WaterPumpCheck( double const Timestep ) {
// water heater status check
void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
WaterHeater.is_damaged = (
( true == WaterHeater.is_damaged )
|| ( ( true == WaterHeater.is_active )
&& ( false == WaterPump.is_active ) ) );
WaterHeater.is_active = (
( false == WaterHeater.is_damaged )
&& ( true == Battery )
&& ( true == WaterHeater.is_enabled )
&& ( true == WaterHeater.breaker )
&& ( ( WaterHeater.is_active ) || ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) );
WaterHeater.is_damaged = (
( true == WaterHeater.is_damaged )
|| ( ( true == WaterHeater.is_active )
&& ( false == WaterPump.is_active ) ) );
if( ( WaterHeater.config.temp_max > 0 )
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
WaterHeater.is_active = false;
@@ -4017,11 +3988,9 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
Voltage =
std::max(
RunningTraction.TractionVoltage,
#ifdef EU07_USE_OLD_HVCOUPLERS
std::max( HVCouplers[side::front][hvcoupler::voltage], HVCouplers[side::rear][hvcoupler::voltage] ) );
#else
std::max( Couplers[ side::front ].power_high.voltage, Couplers[ side::rear ].power_high.voltage ) );
#endif
std::max(
Couplers[ side::front ].power_high.voltage,
Couplers[ side::rear ].power_high.voltage ) );
}
else {
Voltage = 0;
@@ -6708,7 +6677,7 @@ TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) {
for( auto const &loadattributes : LoadAttributes ) {
if( Name == loadattributes.name ) {
LoadType = loadattributes;
LoadAmount = Amount;
LoadAmount = clamp( Amount, 0.f, MaxLoad ) ;
return true;
}
}
@@ -6746,7 +6715,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
if( ( LoadAmount <= 0 ) || ( CommandIn.Value1 <= 0 ) ) {
// pusto lub rozładowano żądaną ilość
LoadStatus = 4; // skończony rozładunek
LoadAmount = std::max( 0.f, LoadAmount ); //ładunek nie może być ujemny
LoadAmount = clamp( LoadAmount, 0.f, MaxLoad); //ładunek nie może być ujemny
}
if( LoadAmount == 0.f ) {
AssignLoad(""); // jak nic nie ma, to nie ma też nazwy
@@ -7033,16 +7002,6 @@ std::string TMoverParameters::EngineDescription(int what) const
// *************************************************************************************************
double TMoverParameters::GetTrainsetVoltage(void)
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
#ifdef EU07_USE_OLD_HVCOUPLERS
return std::max(
HVCouplers[ side::front ][ hvcoupler::voltage ],
HVCouplers[ side::rear ][ hvcoupler::voltage ] );
#else
/*
return std::max(
Couplers[ side::front ].power_high.voltage,
Couplers[ side::rear ].power_high.voltage );
*/
return std::max(
( ( ( Couplers[side::front].Connected )
&& ( ( Couplers[ side::front ].CouplingFlag & ctrain_power )
@@ -7056,7 +7015,6 @@ double TMoverParameters::GetTrainsetVoltage(void)
&& ( Couplers[ side::rear ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[ side::rear ].Connected->Couplers[ Couplers[ side::rear ].ConnectedNr ].power_high.voltage :
0.0 ) );
#endif
}
// *************************************************************************************************

View File

@@ -452,9 +452,9 @@ PyObject *TTrain::GetTrainState() {
// basic systems state data
PyDict_SetItemString( dict, "battery", PyGetBool( mvControlled->Battery ) );
PyDict_SetItemString( dict, "linebreaker", PyGetBool( mvControlled->Mains ) );
PyDict_SetItemString( dict, "converter", PyGetBool( mover->ConverterFlag ) );
PyDict_SetItemString( dict, "converter_overload", PyGetBool( mover->ConvOvldFlag ) );
PyDict_SetItemString( dict, "compress", PyGetBool( mover->CompressorFlag ) );
PyDict_SetItemString( dict, "converter", PyGetBool( mvControlled->ConverterFlag ) );
PyDict_SetItemString( dict, "converter_overload", PyGetBool( mvControlled->ConvOvldFlag ) );
PyDict_SetItemString( dict, "compress", PyGetBool( mvControlled->CompressorFlag ) );
// reverser
PyDict_SetItemString( dict, "direction", PyGetInt( mover->ActiveDir ) );
// throttle
@@ -467,34 +467,35 @@ PyObject *TTrain::GetTrainState() {
bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 );
PyDict_SetItemString( dict, "dir_brake", PyGetBool( bEP ) );
bool bPN;
if( ( typeid( *mvControlled->Hamulec ) == typeid( TLSt ) )
|| ( typeid( *mvControlled->Hamulec ) == typeid( TEStED ) ) ) {
if( ( typeid( *mvOccupied->Hamulec ) == typeid( TLSt ) )
|| ( typeid( *mvOccupied->Hamulec ) == typeid( TEStED ) ) ) {
TBrake* temp_ham = mvControlled->Hamulec.get();
TBrake* temp_ham = mvOccupied->Hamulec.get();
bPN = ( static_cast<TLSt*>( temp_ham )->GetEDBCP() > 0.2 );
}
else
bPN = false;
PyDict_SetItemString( dict, "indir_brake", PyGetBool( bPN ) );
PyDict_SetItemString( dict, "brake_delay_flag", PyGetInt( mvControlled->BrakeDelayFlag ));
PyDict_SetItemString( dict, "brake_op_mode_flag", PyGetInt( mvControlled->BrakeOpModeFlag ));
PyDict_SetItemString( dict, "brake_delay_flag", PyGetInt( mvOccupied->BrakeDelayFlag ));
PyDict_SetItemString( dict, "brake_op_mode_flag", PyGetInt( mvOccupied->BrakeOpModeFlag ));
// other controls
PyDict_SetItemString( dict, "ca", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ) );
PyDict_SetItemString( dict, "shp", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ) );
PyDict_SetItemString( dict, "pantpress", PyGetFloat( mvControlled->PantPress ) );
PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) );
PyDict_SetItemString( dict, "radio_channel", PyGetInt( iRadioChannel ) );
PyDict_SetItemString( dict, "door_lock", PyGetInt( mvOccupied->DoorLockEnabled ) );
// movement data
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
PyDict_SetItemString( dict, "sanding", PyGetBool( mover->SandDose ) );
// electric current data
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mover->RunningTraction.TractionVoltage ) );
PyDict_SetItemString( dict, "voltage", PyGetFloat( mover->Voltage ) );
PyDict_SetItemString( dict, "im", PyGetFloat( mover->Im ) );
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
PyDict_SetItemString( dict, "epfuse", PyGetBool( mover->EpFuse ) );
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mvControlled->RunningTraction.TractionVoltage ) );
PyDict_SetItemString( dict, "voltage", PyGetFloat( mvControlled->Voltage ) );
PyDict_SetItemString( dict, "im", PyGetFloat( mvControlled->Im ) );
PyDict_SetItemString( dict, "fuse", PyGetBool( mvControlled->FuseFlag ) );
PyDict_SetItemString( dict, "epfuse", PyGetBool( mvOccupied->EpFuse ) );
// induction motor state data
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
@@ -554,7 +555,7 @@ PyObject *TTrain::GetTrainState() {
PyDict_SetItemString( dict, "train_enginetype", PyGetString( timetable->LocSeries.c_str() ) );
PyDict_SetItemString( dict, "train_engineload", PyGetFloat( timetable->LocLoad ) );
PyDict_SetItemString( dict, "train_stationindex", PyGetInt( driver->StationIndex() ) );
PyDict_SetItemString( dict, "train_stationindex", PyGetInt( driver->iStationStart ) );
auto const stationcount { driver->StationCount() };
PyDict_SetItemString( dict, "train_stationcount", PyGetInt( stationcount ) );
if( stationcount > 0 ) {
@@ -579,6 +580,7 @@ PyObject *TTrain::GetTrainState() {
PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) );
PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) );
PyDict_SetItemString( dict, "air_temperature", PyGetInt( Global.AirTemperature ) );
PyDict_SetItemString( dict, "light_level", PyGetFloat( Global.fLuminance - std::max( 0.f, Global.Overcast - 1.f ) ) );
Application.release_python_lock();
return dict;
@@ -4084,14 +4086,14 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
auto const itemindex = static_cast<int>( Command.command ) - static_cast<int>( user_command::generictoggle0 );
auto &item = Train->ggUniversals[ itemindex ];
/*
if( item.SubModel == nullptr ) {
if( Command.action == GLFW_PRESS ) {
WriteLog( "Train generic item " + std::to_string( itemindex ) + " is missing, or wasn't defined" );
}
return;
}
*/
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( item.GetDesiredValue() < 0.5 ) {
@@ -4995,8 +4997,10 @@ bool TTrain::Update( double const Deltatime )
iUnits[i] = iUnitNo;
cCode[i] = p->MoverParameters->TypeName[p->MoverParameters->TypeName.length() - 1];
asCarName[i] = p->name();
bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp);
bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp);
if( p->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
bPants[iUnitNo - 1][side::front] = ( bPants[iUnitNo - 1][side::front] || p->MoverParameters->PantFrontUp );
bPants[iUnitNo - 1][side::rear] = ( bPants[iUnitNo - 1][side::rear] || p->MoverParameters->PantRearUp );
}
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic));
bSlip[i] = p->MoverParameters->SlippingWheels;
if (p->MoverParameters->CompressorSpeed > 0.00001)
@@ -5459,6 +5463,10 @@ bool TTrain::Update( double const Deltatime )
// others
btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA );
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ side::front ].is_active ) && ( mvControlled->MotorBlowers[ side::rear ].is_active ) );
// universal devices state indicators
for( auto idx = 0; idx < btUniversals.size(); ++idx ) {
btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 );
}
}
else {
// wylaczone
@@ -5514,6 +5522,10 @@ bool TTrain::Update( double const Deltatime )
// others
btLampkaMalfunction.Turn( false );
btLampkaMotorBlowers.Turn( false );
// universal devices state indicators
for( auto &universal : btUniversals ) {
universal.Turn( false );
}
}
{ // yB - wskazniki drugiego czlonu
@@ -6173,7 +6185,9 @@ void TTrain::update_sounds_runningnoise( sound_source &Sound ) {
// volume calculation
auto volume =
Sound.m_amplitudeoffset
+ Sound.m_amplitudefactor * mvOccupied->Vel;
+ Sound.m_amplitudefactor * interpolate(
mvOccupied->Vel / ( 1 + mvOccupied->Vmax ), 1.0,
0.5 ); // scale base volume between 0.5-1.0
if( std::abs( mvOccupied->nrot ) > 0.01 ) {
// hamulce wzmagaja halas
auto const brakeforceratio { (
@@ -6197,7 +6211,7 @@ void TTrain::update_sounds_runningnoise( sound_source &Sound ) {
interpolate(
0.0, 1.0,
clamp(
mvOccupied->Vel / 40.0,
mvOccupied->Vel / 25.0,
0.0, 1.0 ) );
}
@@ -7072,6 +7086,9 @@ void TTrain::clear_cab_controls()
btLampkaHamulecReczny.Clear();
btLampkaBlokadaDrzwi.Clear();
btLampkaDoorLockOff.Clear();
for( auto &universal : btUniversals ) {
universal.Clear();
}
btInstrumentLight.Clear();
btDashboardLight.Clear();
btTimetableLight.Clear();
@@ -7504,7 +7521,17 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-rearrightend:", btLampkaRearRightEndLight },
{ "i-dashboardlight:", btDashboardLight },
{ "i-timetablelight:", btTimetableLight },
{ "i-cablight:", btCabLight }
{ "i-cablight:", btCabLight },
{ "i-universal0:", btUniversals[ 0 ] },
{ "i-universal1:", btUniversals[ 1 ] },
{ "i-universal2:", btUniversals[ 2 ] },
{ "i-universal3:", btUniversals[ 3 ] },
{ "i-universal4:", btUniversals[ 4 ] },
{ "i-universal5:", btUniversals[ 5 ] },
{ "i-universal6:", btUniversals[ 6 ] },
{ "i-universal7:", btUniversals[ 7 ] },
{ "i-universal8:", btUniversals[ 8 ] },
{ "i-universal9:", btUniversals[ 9 ] }
};
auto lookup = lights.find( Label );
if( lookup != lights.end() ) {

View File

@@ -507,6 +507,7 @@ public: // reszta może by?publiczna
TButton btLampkaHamowanie2zes;
TButton btLampkaOpory;
TButton btLampkaWysRozr;
std::array<TButton, 10> btUniversals; // NOTE: temporary arrangement until we have dynamically built control table
TButton btInstrumentLight;
TButton btDashboardLight;
TButton btTimetableLight;

View File

@@ -1122,6 +1122,7 @@ driver_mode::InOutKey()
if( train == nullptr ) {
FreeFlyModeFlag = true; // nadal poza kabiną
Camera.m_owner = nullptr; // detach camera from the vehicle
return;
}

View File

@@ -836,9 +836,14 @@ void opengl_renderer::Render_pass(rendermode const Mode)
// creates dynamic environment cubemap
bool opengl_renderer::Render_reflections()
{
if (Global.ReflectionUpdatesPerSecond == 0)
return false;
auto const &time = simulation::Time.data();
auto const timestamp = time.wDay * 24 * 60 + time.wHour * 60 + time.wMinute;
if ((timestamp - m_environmentupdatetime < 1) && (glm::length(m_renderpass.camera.position() - m_environmentupdatelocation) < 1000.0))
auto const timestamp = time.wMilliseconds + time.wSecond * 1000 + time.wMinute * 1000 * 60 + time.wHour * 1000 * 60 * 60;
if ((timestamp - m_environmentupdatetime < Global.ReflectionUpdatesPerSecond)
&& (glm::length(m_renderpass.camera.position() - m_environmentupdatelocation) < 1000.0))
{
// run update every 5+ mins of simulation time, or at least 1km from the last location
return false;
@@ -2445,6 +2450,7 @@ void opengl_renderer::Render(TSubModel *Submodel)
// we're capping how much effect the distance attenuation can have, otherwise the lights get too tiny at regular distances
float const distancefactor{std::max(0.5f, (Submodel->fSquareMaxDist - TSubModel::fSquareDist) / Submodel->fSquareMaxDist)};
auto const pointsize{std::max(3.f, 5.f * distancefactor * anglefactor)};
auto const resolutionratio { Global.iWindowHeight / 1080.f };
// additionally reduce light strength for farther sources in rain or snow
if (Global.Overcast > 0.75f)
{
@@ -2478,14 +2484,14 @@ void opengl_renderer::Render(TSubModel *Submodel)
{
// fake fog halo
float const fogfactor{interpolate(2.f, 1.f, clamp<float>(Global.fFogEnd / 2000, 0.f, 1.f)) * std::max(1.f, Global.Overcast)};
model_ubs.param[1].x = pointsize * fogfactor * 2.0f;
model_ubs.param[1].x = pointsize * resolutionratio * fogfactor * 2.0f;
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel) * 0.5f);
glDepthMask(GL_FALSE);
draw(Submodel->m_geometry);
glDepthMask(GL_TRUE);
}
model_ubs.param[1].x = pointsize * 2.0f;
model_ubs.param[1].x = pointsize * resolutionratio * 2.0f;
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel));
draw(Submodel->m_geometry);

View File

@@ -185,7 +185,7 @@ init() {
u8"Nastawnik: %2d+%d %c%s",
u8" Prędkość: %d km/h (limit %d km/h%s)%s",
u8", nowy limit: %d km/h za %.1f km",
u8" Pochylenie: %.1f%%%%",
u8" Nachylenie: %.1f%%%%",
u8"Hamulce: %4.1f+%-2.0f%c%s",
u8" Ciśnienie: %.2f kPa (przewód główny: %.2f kPa)",
u8"!CZUWAK! ",

View File

@@ -1 +1 @@
#define VERSION_INFO "M7 (GL3) 31.12.2018, based on milek-4495f6a4, tmj-bdbbaaf"
#define VERSION_INFO "M7 (GL3) 14.01.2018, based on milek-204b6001, tmj-6f48a6e5"