16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-24 00:49:18 +02:00

ai direction change logic enhamcement, minor bug fixes

This commit is contained in:
tmj-fstate
2020-05-23 23:19:04 +02:00
parent 10dabd66c3
commit 679741f22f
13 changed files with 218 additions and 134 deletions

View File

@@ -967,18 +967,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie // jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
sSpeedTable[ i ].fVelNext = 0; sSpeedTable[ i ].fVelNext = 0;
} else if( true == IsAtPassengerStop ) { } else if( true == IsAtPassengerStop ) {
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4 // jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
if( !AIControllFlag ) { if( !AIControllFlag ) {
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko // w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
iDrivigFlags &= ~moveStopCloser; iDrivigFlags &= ~moveStopCloser;
} }
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
// drzwi otwierać jednorazowo
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
Doors( true, static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 );
}
if (TrainParams.UpdateMTable( simulation::Time, asNextStop) ) { if (TrainParams.UpdateMTable( simulation::Time, asNextStop) ) {
// to się wykona tylko raz po zatrzymaniu na W4 // to się wykona tylko raz po zatrzymaniu na W4
if( TrainParams.StationIndex < TrainParams.StationCount ) { if( TrainParams.StationIndex < TrainParams.StationCount ) {
@@ -998,6 +992,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
m_lastexchangestop = asNextStop; m_lastexchangestop = asNextStop;
} }
if( false == TrainParams.IsMaintenance() )
// && ( ( iDrivigFlags & moveDoorOpened ) == 0 ) )
{
// drzwi otwierać jednorazowo
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
Doors( true, static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 );
}
if (TrainParams.DirectionChange()) { if (TrainParams.DirectionChange()) {
// jeśli "@" w rozkładzie, to wykonanie dalszych komend // jeśli "@" w rozkładzie, to wykonanie dalszych komend
// wykonanie kolejnej komendy, nie dotyczy ostatniej stacji // wykonanie kolejnej komendy, nie dotyczy ostatniej stacji
@@ -1193,13 +1196,22 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
VelSignalLast = v; //!!! to też koniec ograniczenia VelSignalLast = v; //!!! to też koniec ograniczenia
} }
else else
{ // w trybie manewrowym: skanować od niego wstecz, stanąć po wyjechaniu za { // w trybie manewrowym: skanować od niego wstecz, stanąć po wyjechaniu za sygnalizator i zmienić kierunek
// sygnalizator i zmienić kierunek v = 0.0; // zmiana kierunku może być podanym sygnałem, ale wypadało by zmienić światło wcześniej
v = 0.0; // zmiana kierunku może być podanym sygnałem, ale wypadało by if( !( iDrivigFlags & moveSwitchFound ) ) { // jeśli nie ma rozjazdu
// zmienić światło wcześniej // check for presence of a signal facing the opposite direction
if (!(iDrivigFlags & moveSwitchFound)) // jeśli nie ma rozjazdu // if there's one, we'll want to pass it before changing direction
iDrivigFlags |= moveTrackEnd; // to dalsza jazda trwale ograniczona (W5, basic_event *foundevent = nullptr;
// koniec toru) if( sSpeedTable[ i ].fDist - fMaxProximityDist > 0 ) {
auto scandistance{ sSpeedTable[ i ].fDist + fLength - fMaxProximityDist };
auto *scanvehicle{ pVehicles[ end::rear ] };
auto scandirection{ scanvehicle->DirectionGet() * scanvehicle->RaDirectionGet() };
auto *foundtrack = BackwardTraceRoute( scandistance, scandirection, scanvehicle, foundevent, -1, end::front, false );
}
if( foundevent == nullptr ) {
iDrivigFlags |= moveTrackEnd; // to dalsza jazda trwale ograniczona (W5, koniec toru)
}
}
} }
} }
else if (sSpeedTable[i].iFlags & spStopOnSBL) { else if (sSpeedTable[i].iFlags & spStopOnSBL) {
@@ -3183,7 +3195,7 @@ bool TController::IncSpeed()
return false; return false;
} }
bool OK = true; bool OK = true;
if( ( iDrivigFlags & moveDoorOpened ) if( ( doors_open() )
&& ( VelDesired > 0.0 ) ) { // to prevent door shuffle on stop && ( VelDesired > 0.0 ) ) { // to prevent door shuffle on stop
// zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime) // zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime)
Doors( false ); Doors( false );
@@ -4073,7 +4085,7 @@ void TController::Doors( bool const Open, int const Side ) {
} }
} }
if( ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) if( ( true == doors_open() )
&& ( ( fActionTime > -0.5 ) && ( ( fActionTime > -0.5 )
|| ( false == AIControllFlag ) ) ) { || ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things // ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
@@ -4095,7 +4107,9 @@ void TController::Doors( bool const Open, int const Side ) {
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) { while( vehicle != nullptr ) {
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->Doors.auto_velocity < 0.f ) { if( ( vehicle->MoverParameters->Doors.auto_velocity < 0.f )
&& ( ( vehicle->LoadExchangeTime() == 0.f )
|| ( vehicle->MoverParameters->Vel > 0.1 ) ) ) {
vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local ); // w lokomotywie można by nie zamykać... vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local ); // w lokomotywie można by nie zamykać...
vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local ); vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
} }
@@ -4172,7 +4186,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
if (NewCommand == "Emergency_brake") // wymuszenie zatrzymania, niezależnie kto prowadzi if (NewCommand == "Emergency_brake") // wymuszenie zatrzymania, niezależnie kto prowadzi
{ // Ra: no nadal nie jest zbyt pięknie { // Ra: no nadal nie jest zbyt pięknie
SetVelocity(0, 0, reason); // SetVelocity(0, 0, reason);
mvOccupied->PutCommand("Emergency_brake", 1.0, 1.0, mvOccupied->Loc); mvOccupied->PutCommand("Emergency_brake", 1.0, 1.0, mvOccupied->Loc);
return true; // załatwione return true; // załatwione
} }
@@ -4820,8 +4834,9 @@ TController::UpdateSituation(double dt) {
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open // 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 // TODO: check if this situation still happens and the hack is still needed
if( ( false == AIControllFlag ) if( ( false == AIControllFlag )
&& ( iDrivigFlags & moveDoorOpened ) // && ( iDrivigFlags & moveDoorOpened )
&& ( mvOccupied->Doors.close_control != control_t::driver ) ) { // && ( mvOccupied->Doors.close_control != control_t::driver )
&& ( doors_open() ) ) {
// for diesel engines react when engine is put past idle revolutions // for diesel engines react when engine is put past idle revolutions
// for others straightforward master controller check // for others straightforward master controller check
if( ( mvControlling->EngineType == TEngineType::DieselEngine ? if( ( mvControlling->EngineType == TEngineType::DieselEngine ?
@@ -4866,7 +4881,7 @@ TController::UpdateSituation(double dt) {
if( mvOccupied->Vel > 1.0 ) { if( mvOccupied->Vel > 1.0 ) {
// jeżeli jedzie // jeżeli jedzie
if( iDrivigFlags & moveDoorOpened ) { if( doors_open() ) {
// jeśli drzwi otwarte // jeśli drzwi otwarte
// nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości // nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości
Doors( false ); Doors( false );
@@ -5166,7 +5181,8 @@ TController::UpdateSituation(double dt) {
} }
*/ */
Obstacle = neighbour_data(); Obstacle = neighbour_data();
auto const lookup { frontvehicle->find_vehicle( routescandirection, routescanrange ) }; auto const obstaclescanrange { std::max( ( mvOccupied->CategoryFlag == 2 ? 250.0 : 1000.0 ), routescanrange ) };
auto const lookup { frontvehicle->find_vehicle( routescandirection, obstaclescanrange ) };
if( std::get<bool>( lookup ) == true ) { if( std::get<bool>( lookup ) == true ) {
@@ -5560,6 +5576,7 @@ TController::UpdateSituation(double dt) {
VelNext = VelDesired; // maksymalna prędkość wynikająca z innych czynników niż trajektoria ruchu VelNext = VelDesired; // maksymalna prędkość wynikająca z innych czynników niż trajektoria ruchu
ActualProximityDist = routescanrange; // funkcja Update() może pozostawić wartości bez zmian ActualProximityDist = routescanrange; // funkcja Update() może pozostawić wartości bez zmian
// Ra: odczyt (ActualProximityDist), (VelNext) i (AccPreferred) z tabelki prędkosci // Ra: odczyt (ActualProximityDist), (VelNext) i (AccPreferred) z tabelki prędkosci
TCommandType comm = TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired); TCommandType comm = TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired);
switch (comm) { switch (comm) {
@@ -6218,10 +6235,10 @@ TController::UpdateSituation(double dt) {
} }
// HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts // HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts
// TBD: expand this behaviour to all trains with car(s) exceeding certain weight? // TBD: expand this behaviour to all trains with car(s) exceeding certain weight?
if( IsCargoTrain ) { if( ( IsCargoTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) {
AccDesired = std::min( AccDesired, CargoTrainAcceleration ); AccDesired = std::min( AccDesired, CargoTrainAcceleration );
} }
if( IsHeavyCargoTrain ) { if( ( IsHeavyCargoTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) {
AccDesired = std::min( AccDesired, HeavyCargoTrainAcceleration ); AccDesired = std::min( AccDesired, HeavyCargoTrainAcceleration );
} }
} }
@@ -6919,7 +6936,7 @@ std::string TController::StopReasonText() const
//- rozpoznają tylko zerową prędkość (jako koniec toru i brak podstaw do dalszego skanowania) //- rozpoznają tylko zerową prędkość (jako koniec toru i brak podstaw do dalszego skanowania)
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
bool TController::BackwardTrackBusy(TTrack *Track) bool TController::IsOccupiedByAnotherConsist(TTrack *Track)
{ // najpierw sprawdzamy, czy na danym torze są pojazdy z innego składu { // najpierw sprawdzamy, czy na danym torze są pojazdy z innego składu
if( false == Track->Dynamics.empty() ) { if( false == Track->Dynamics.empty() ) {
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
@@ -6932,13 +6949,13 @@ bool TController::BackwardTrackBusy(TTrack *Track)
return false; // wolny return false; // wolny
}; };
basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Track) basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Track, TDynamicObject *Vehicle, int const Eventdirection, end const End)
{ // sprawdzanie eventu w torze, czy jest sygnałowym - skanowanie do tyłu { // 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 // 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 // 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 dir{ Vehicle->VectorFront() * Vehicle->DirectionGet() };
auto const pos{ pVehicles[ 0 ]->HeadPosition() }; auto const pos{ End == end::front ? Vehicle->RearPosition() : Vehicle->HeadPosition() };
auto const &eventsequence { ( fDirection > 0 ? Track->m_events2 : Track->m_events1 ) }; auto const &eventsequence { ( fDirection * Eventdirection > 0 ? Track->m_events2 : Track->m_events1 ) };
for( auto const &event : eventsequence ) { for( auto const &event : eventsequence ) {
if( ( event.second != nullptr ) if( ( event.second != nullptr )
&& ( event.second->m_passive ) && ( event.second->m_passive )
@@ -6946,7 +6963,8 @@ basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Tr
// since we're checking for events behind us discard the sources in front of the scanning vehicle // 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 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 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 ) { auto const isahead { dir.x * sem.x + dir.z * sem.z > 0 };
if( ( End == end::front ? isahead : !isahead ) ) {
// iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu // iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu
return event.second; return event.second;
} }
@@ -6955,30 +6973,29 @@ basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Tr
return nullptr; return nullptr;
}; };
TTrack * TController::BackwardTraceRoute(double &fDistance, double &fDirection, TTrack *Track, basic_event *&Event) TTrack * TController::BackwardTraceRoute(double &fDistance, double &fDirection, TDynamicObject *Vehicle, basic_event *&Event, int const Eventdirection, end const End, bool const Untiloccupied )
{ // szukanie sygnalizatora w kierunku przeciwnym jazdy (eventu odczytu komórki pamięci) { // szukanie sygnalizatora w kierunku przeciwnym jazdy (eventu odczytu komórki pamięci)
TTrack *pTrackChVel = Track; // tor ze zmianą prędkości auto *Track = Vehicle->GetTrack();
TTrack *pTrackFrom; // odcinek poprzedni, do znajdywania końca dróg double fCurrentDistance = Vehicle->RaTranslationGet(); // aktualna pozycja na torze
double fDistChVel = -1; // odległość do toru ze zmianą prędkości
double fCurrentDistance = pVehicle->RaTranslationGet(); // aktualna pozycja na torze
double s = 0;
if (fDirection > 0) // jeśli w kierunku Point2 toru if (fDirection > 0) // jeśli w kierunku Point2 toru
fCurrentDistance = Track->Length() - fCurrentDistance; fCurrentDistance = Track->Length() - fCurrentDistance;
if (BackwardTrackBusy(Track)) double s = 0;
{ // jak tor zajęty innym składem, to nie ma po co skanować
fDistance = 0; // to na tym torze stoimy if( Track->VelocityGet() == 0.0 ) { // jak prędkosć 0 albo uszkadza, to nie ma po co skanować
return NULL; // stop, skanowanie nie dało sensownych rezultatów fDistance = s; // to na tym torze stoimy
return nullptr; // stop, skanowanie nie dało sensownych rezultatów
} }
if ((Event = CheckTrackEventBackward(fDirection, Track)) != NULL) if (Untiloccupied && IsOccupiedByAnotherConsist(Track))
{ // jak tor zajęty innym składem, to nie ma po co skanować
fDistance = s; // to na tym torze stoimy
return nullptr; // stop, skanowanie nie dało sensownych rezultatów
}
if ((Event = CheckTrackEventBackward(fDirection, Track, Vehicle, Eventdirection, End)) != nullptr)
{ // jeśli jest semafor na tym torze { // jeśli jest semafor na tym torze
fDistance = 0; // to na tym torze stoimy fDistance = s; // to na tym torze stoimy
return Track; return Track;
} }
if ((Track->VelocityGet() == 0.0) || (Track->iDamageFlag & 128)) TTrack *pTrackFrom; // odcinek poprzedni, do znajdywania końca dróg
{ // jak prędkosć 0 albo uszkadza, to nie ma po co skanować
fDistance = 0; // to na tym torze stoimy
return NULL; // stop, skanowanie nie dało sensownych rezultatów
}
while (s < fDistance) while (s < fDistance)
{ {
// Track->ScannedFlag=true; //do pokazywania przeskanowanych torów // Track->ScannedFlag=true; //do pokazywania przeskanowanych torów
@@ -6997,31 +7014,34 @@ TTrack * TController::BackwardTraceRoute(double &fDistance, double &fDirection,
Track = Track->CurrentPrev(); // może być NULL Track = Track->CurrentPrev(); // może być NULL
} }
if (Track == pTrackFrom) if (Track == pTrackFrom)
Track = NULL; // koniec, tak jak dla torów Track = nullptr; // koniec, tak jak dla torów
if( ( Track ?
( ( Track->VelocityGet() == 0.0 ) // gdy dalej toru nie ma albo zerowa prędkość, albo uszkadza pojazd
|| ( Track->iDamageFlag & 128 ) // zwraca NULL, że skanowanie nie dało sensownych rezultatów
|| ( true == BackwardTrackBusy( Track ) ) ) : if( Track == nullptr ) {
true ) )
{ // gdy dalej toru nie ma albo zerowa prędkość, albo uszkadza pojazd
fDistance = s; fDistance = s;
return NULL; // zwraca NULL, że skanowanie nie dało sensownych rezultatów return nullptr;
}
if( Track->VelocityGet() == 0.0 )
{
fDistance = s;
return nullptr;
}
if( Untiloccupied && IsOccupiedByAnotherConsist( Track ) ) {
fDistance = s;
return nullptr;
} }
fCurrentDistance = Track->Length(); fCurrentDistance = Track->Length();
if ((Event = CheckTrackEventBackward(fDirection, Track)) != NULL) if ((Event = CheckTrackEventBackward(fDirection, Track, Vehicle, Eventdirection, End)) != nullptr)
{ // znaleziony tor z eventem { // znaleziony tor z eventem
fDistance = s; fDistance = s;
return Track; return Track;
} }
} }
Event = NULL; // jak dojdzie tu, to nie ma semafora Event = nullptr; // jak dojdzie tu, to nie ma semafora
if (fDistChVel < 0) // zwraca ostatni sprawdzony tor
{ // zwraca ostatni sprawdzony tor fDistance = s;
fDistance = s; return Track;
return Track;
}
fDistance = fDistChVel; // odległość do zmiany prędkości
return pTrackChVel; // i tor na którym się zmienia
} }
// sprawdzanie zdarzeń semaforów i ograniczeń szlakowych // sprawdzanie zdarzeń semaforów i ograniczeń szlakowych
@@ -7071,8 +7091,8 @@ TCommandType TController::BackwardScan()
double scandist = scanmax; // zmodyfikuje na rzeczywiście przeskanowane double scandist = scanmax; // zmodyfikuje na rzeczywiście przeskanowane
basic_event *e = NULL; // event potencjalnie od semafora basic_event *e = NULL; // event potencjalnie od semafora
// opcjonalnie może być skanowanie od "wskaźnika" z przodu, np. W5, Tm=Ms1, koniec toru wg drugiej osi w kierunku ruchu // opcjonalnie może być skanowanie od "wskaźnika" z przodu, np. W5, Tm=Ms1, koniec toru wg drugiej osi w kierunku ruchu
TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[0]->GetTrack(), e); TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[end::front], e);
auto const dir = startdir * pVehicles[0]->VectorFront(); // wektor w kierunku jazdy/szukania auto const dir = startdir * pVehicles[end::front]->VectorFront(); // wektor w kierunku jazdy/szukania
if( !scantrack ) { if( !scantrack ) {
// jeśli wstecz wykryto koniec toru to raczej nic się nie da w takiej sytuacji zrobić // jeśli wstecz wykryto koniec toru to raczej nic się nie da w takiej sytuacji zrobić
return TCommandType::cm_Unknown; return TCommandType::cm_Unknown;
@@ -7095,7 +7115,7 @@ TCommandType TController::BackwardScan()
if( typeid( *e ) == typeid( getvalues_event ) ) if( typeid( *e ) == typeid( getvalues_event ) )
{ // przesłać info o zbliżającym się semaforze { // przesłać info o zbliżającym się semaforze
#if LOGBACKSCAN #if LOGBACKSCAN
edir += "(" + ( e->asNodeName ) + ")"; edir += "(" + ( e->name() ) + ")";
#endif #endif
auto sl = e->input_location(); // położenie komórki pamięci auto sl = e->input_location(); // położenie komórki pamięci
auto sem = sl - pos; // wektor do komórki pamięci od końca składu auto sem = sl - pos; // wektor do komórki pamięci od końca składu
@@ -7147,7 +7167,7 @@ TCommandType TController::BackwardScan()
WriteLog( WriteLog(
edir + " - [SetVelocity] [" edir + " - [SetVelocity] ["
+ to_string( vmechmax, 2 ) + "] [" + to_string( vmechmax, 2 ) + "] ["
+ to_string( e->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" ); + to_string( e->input_value( 2 ), 2 ) + "]" );
#endif #endif
return ( return (
vmechmax > 0 ? vmechmax > 0 ?
@@ -7191,7 +7211,7 @@ TCommandType TController::BackwardScan()
WriteLog( WriteLog(
edir + " - [ShuntVelocity] [" edir + " - [ShuntVelocity] ["
+ to_string( vmechmax, 2 ) + "] [" + to_string( vmechmax, 2 ) + "] ["
+ to_string( e->value( 2 ), 2 ) + "]" ); + to_string( e->input_value( 2 ), 2 ) + "]" );
#endif #endif
return ( return (
vmechmax > 0 ? vmechmax > 0 ?

View File

@@ -408,9 +408,9 @@ private:
void TableClear(); void TableClear();
int TableDirection() { return iTableDirection; } int TableDirection() { return iTableDirection; }
// Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu // Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu
bool BackwardTrackBusy( TTrack *Track ); bool IsOccupiedByAnotherConsist( TTrack *Track );
basic_event *CheckTrackEventBackward( double fDirection, TTrack *Track ); basic_event *CheckTrackEventBackward( double fDirection, TTrack *Track, TDynamicObject *Vehicle, int const Eventdirection = 1, end const End = end::rear );
TTrack *BackwardTraceRoute( double &fDistance, double &fDirection, TTrack *Track, basic_event *&Event ); TTrack *BackwardTraceRoute( double &fDistance, double &fDirection, TDynamicObject *Vehicle, basic_event *&Event, int const Eventdirection = 1, end const End = end::rear, bool const Untiloccupied = true );
void SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos ); void SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos );
TCommandType BackwardScan(); TCommandType BackwardScan();
std::string TableText( std::size_t const Index ) const; std::string TableText( std::size_t const Index ) const;

View File

@@ -589,10 +589,10 @@ private:
inline Math3D::vector3 GetWorldPosition( Math3D::vector3 const &Location ) const { inline Math3D::vector3 GetWorldPosition( Math3D::vector3 const &Location ) const {
return vPosition + mMatrix * Location; } return vPosition + mMatrix * Location; }
// pobranie współrzędnych czoła // pobranie współrzędnych czoła
inline Math3D::vector3 HeadPosition() { inline Math3D::vector3 HeadPosition() const {
return vCoulpler[iDirection ^ 1]; }; return vCoulpler[iDirection ^ 1]; };
// pobranie współrzędnych tyłu // pobranie współrzędnych tyłu
inline Math3D::vector3 RearPosition() { inline Math3D::vector3 RearPosition() const {
return vCoulpler[iDirection]; }; return vCoulpler[iDirection]; };
inline Math3D::vector3 CouplerPosition( end const End ) const { inline Math3D::vector3 CouplerPosition( end const End ) const {
return vCoulpler[ End ]; } return vCoulpler[ End ]; }

View File

@@ -1545,7 +1545,7 @@ public:
double eimv[21]; double eimv[21];
static std::vector<std::string> const eimv_labels; static std::vector<std::string> const eimv_labels;
double SpeedCtrlTimer = 0; /*zegar dzialania tempomatu z wybieralna predkoscia*/ double SpeedCtrlTimer = 0; /*zegar dzialania tempomatu z wybieralna predkoscia*/
double eimicSpeedCtrl = 0; /*pozycja sugerowana przez tempomat*/ double eimicSpeedCtrl = 1; /*pozycja sugerowana przez tempomat*/
double eimicSpeedCtrlIntegral = 0; /*calkowany blad ustawienia predkosci*/ double eimicSpeedCtrlIntegral = 0; /*calkowany blad ustawienia predkosci*/
double NewSpeed = 0; /*nowa predkosc do zadania*/ double NewSpeed = 0; /*nowa predkosc do zadania*/
double MED_EPVC_CurrentTime = 0; /*aktualny czas licznika czasu korekcji siły EP*/ double MED_EPVC_CurrentTime = 0; /*aktualny czas licznika czasu korekcji siły EP*/

View File

@@ -1310,8 +1310,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
compute_movement_( dt ); compute_movement_( dt );
// security system // security system
if (!DebugModeFlag) SecuritySystemCheck(dt1);
SecuritySystemCheck(dt1);
return d; return d;
}; };
@@ -2907,6 +2906,11 @@ void TMoverParameters::SecuritySystemCheck(double dt)
RadiostopSwitch(false); RadiostopSwitch(false);
// SecuritySystem.Status = 0; //deaktywacja czuwaka // SecuritySystem.Status = 0; //deaktywacja czuwaka
} }
// automatic reset in debug mode
if( DebugModeFlag ) {
SSReset();
}
} }
// ************************************************************************************************* // *************************************************************************************************
@@ -7132,6 +7136,7 @@ void TMoverParameters::CheckSpeedCtrl(double dt)
eimicSpeedCtrl = 1; eimicSpeedCtrl = 1;
eimicSpeedCtrlIntegral = 0; eimicSpeedCtrlIntegral = 0;
SpeedCtrlUnit.Parking = false; SpeedCtrlUnit.Parking = false;
SendCtrlToNext( "SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabActive );
} }
} }

View File

@@ -787,7 +787,7 @@ opengl_texture::unbind(size_t unit)
} }
bool bool
opengl_texture::create() { opengl_texture::create( bool const Static ) {
if( data_state != resource_state::good && !is_rendertarget ) { if( data_state != resource_state::good && !is_rendertarget ) {
// don't bother until we have useful texture data // don't bother until we have useful texture data
@@ -934,6 +934,8 @@ opengl_texture::create() {
make_request(); make_request();
} }
is_static = Static;
is_ready = true; is_ready = true;
} }
@@ -945,6 +947,7 @@ void
opengl_texture::release() { opengl_texture::release() {
if( id == -1 ) { return; } if( id == -1 ) { return; }
if( is_static ) { return; }
if( true == Global.ResourceMove ) { if( true == Global.ResourceMove ) {
// if resource move is enabled we don't keep a cpu side copy after upload // if resource move is enabled we don't keep a cpu side copy after upload

View File

@@ -31,7 +31,7 @@ struct opengl_texture {
static void static void
unbind( size_t unit ); unbind( size_t unit );
bool bool
create(); create( bool const Static = false );
// releases resources allocated on the opengl end, storing local copy if requested // releases resources allocated on the opengl end, storing local copy if requested
void void
release(); release();
@@ -78,6 +78,7 @@ private:
void gles_match_internalformat( GLuint format ); void gles_match_internalformat( GLuint format );
// members // members
bool is_static = false; // is excluded from garbage collection
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
int samples = 1; int samples = 1;
int layers = 1; int layers = 1;

View File

@@ -2437,8 +2437,8 @@ void TTrain::OnCommand_pantographcompressorvalveenable( TTrain *Train, command_d
auto const valveispresent { auto const valveispresent {
( Train->ggPantCompressorValve.SubModel != nullptr ) ( Train->ggPantCompressorValve.SubModel != nullptr )
|| ( ( Train->iCabn == 0 ) || ( ( Train->mvOccupied == Train->mvPantographUnit )
&& ( Train->mvControlled == Train->mvOccupied ) ) }; && ( Train->iCabn == 0 ) ) };
if( false == valveispresent ) { if( false == valveispresent ) {
// tylko w maszynowym, unless actual device is present // tylko w maszynowym, unless actual device is present
@@ -2458,8 +2458,8 @@ void TTrain::OnCommand_pantographcompressorvalvedisable( TTrain *Train, command_
auto const valveispresent { auto const valveispresent {
( Train->ggPantCompressorValve.SubModel != nullptr ) ( Train->ggPantCompressorValve.SubModel != nullptr )
|| ( ( Train->iCabn == 0 ) || ( ( Train->mvOccupied == Train->mvPantographUnit )
&& ( Train->mvControlled == Train->mvOccupied ) ) }; && ( Train->iCabn == 0 ) ) };
if( false == valveispresent ) { if( false == valveispresent ) {
// tylko w maszynowym, unless actual device is present // tylko w maszynowym, unless actual device is present
@@ -2477,11 +2477,12 @@ void TTrain::OnCommand_pantographcompressorvalvedisable( TTrain *Train, command_
void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data const &Command ) {
if( ( Train->ggPantCompressorValve.SubModel == nullptr ) // tylko w maszynowym, unless actual device is present
&& ( Train->mvControlled->TrainType == dt_EZT ? auto const switchispresent {
( Train->mvOccupied == Train->mvPantographUnit ) : ( Train->m_controlmapper.contains( "pantcompressor_sw:" ) )
( Train->iCabn != 0 ) ) ) { || ( ( Train->mvOccupied == Train->mvPantographUnit )
// tylko w maszynowym && ( Train->iCabn == 0 ) ) };
if( false == switchispresent ) {
return; return;
} }
@@ -7869,7 +7870,8 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
tex->make_stub(); tex->make_stub();
} }
tex->create(); tex->create( true ); // make the surface static so it doesn't get destroyed by garbage collector if the user spends long time outside cab
// TBD, TODO: keep texture handles around, so we can undo the static switch when the user changes cabs?
auto touch_list = std::make_shared<std::vector<glm::vec2>>(); auto touch_list = std::make_shared<std::vector<glm::vec2>>();
auto rt = std::make_shared<python_rt>(); auto rt = std::make_shared<python_rt>();

View File

@@ -369,6 +369,7 @@ timetable_panel::update() {
( owner->iStationStart < table.StationIndex ) ( owner->iStationStart < table.StationIndex )
&& ( i < table.StationIndex ) && ( i < table.StationIndex )
&& ( ( tableline->Ah < 0 ) // pass-through, always valid && ( ( tableline->Ah < 0 ) // pass-through, always valid
|| ( tableline->is_maintenance ) // maintenance stop, always valid
|| ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) }; || ( time.wHour * 60 + time.wMinute + time.wSecond * 0.0167 >= tableline->Dh * 60 + tableline->Dm ) ) ) };
auto const loadchangeinprogress { ( ( static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) }; auto const loadchangeinprogress { ( ( static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) };
auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) }; auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) };

View File

@@ -77,6 +77,7 @@ void opengl_material::finalize(bool Loadnow)
if (key.size() > 0 && key[0] != '_') if (key.size() > 0 && key[0] != '_')
{ {
key.erase( key.find_first_not_of( "-1234567890" ) );
size_t num = std::stoi(key) - 1; size_t num = std::stoi(key) - 1;
if (num < gl::MAX_TEXTURES) { if (num < gl::MAX_TEXTURES) {
textures[num] = GfxRenderer->Fetch_Texture(value, Loadnow); textures[num] = GfxRenderer->Fetch_Texture(value, Loadnow);
@@ -99,8 +100,11 @@ void opengl_material::finalize(bool Loadnow)
textures[ lookup->second ] = GfxRenderer->Fetch_Texture( value, Loadnow ); textures[ lookup->second ] = GfxRenderer->Fetch_Texture( value, Loadnow );
} }
else { else {
log_error( "unknown texture binding: " + key ); // ignore unrecognized texture bindings in legacy render mode, it's most likely data for more advanced shaders
is_good = false; if( Global.GfxRenderer == "default" ) {
log_error( "unknown texture binding: " + key );
is_good = false;
}
} }
} }
else { else {
@@ -129,49 +133,65 @@ void opengl_material::finalize(bool Loadnow)
} }
} }
if( !shader ) { // TBD, TODO: move material validation to renderer, to eliminate branching?
is_good = false; if( Global.GfxRenderer == "default" ) {
return;
}
for (auto it : parse_info->param_mapping) if( !shader ) {
{ is_good = false;
std::string key = it.first; return;
glm::vec4 value = it.second.data;
if (key.size() > 1 && key[0] != '_')
{
size_t num = std::stoi(key) - 1;
if (num < gl::MAX_PARAMS) {
params[num] = value;
}
else {
log_error("invalid param binding: " + std::to_string(num));
is_good = false;
}
} }
else if (key.size() > 2)
for (auto it : parse_info->param_mapping)
{ {
key.erase(0, 1); std::string key = it.first;
key.pop_back(); glm::vec4 value = it.second.data;
if (shader->param_conf.find(key) != shader->param_conf.end())
if (key.size() > 1 && key[0] != '_')
{ {
gl::shader::param_entry entry = shader->param_conf[key]; size_t num = std::stoi(key) - 1;
for (size_t i = 0; i < entry.size; i++) if (num < gl::MAX_PARAMS) {
params[entry.location][entry.offset + i] = value[i]; params[num] = value;
}
else {
log_error("invalid param binding: " + std::to_string(num));
is_good = false;
}
}
else if (key.size() > 2)
{
key.erase(0, 1);
key.pop_back();
if (shader->param_conf.find(key) != shader->param_conf.end())
{
gl::shader::param_entry entry = shader->param_conf[key];
for (size_t i = 0; i < entry.size; i++)
params[entry.location][entry.offset + i] = value[i];
}
else {
log_error("unknown param binding: " + key);
is_good = false;
}
} }
else { else {
log_error("unknown param binding: " + key); log_error("unrecognized param binding: " + key);
is_good = false; is_good = false;
} }
} }
else { }
log_error("unrecognized param binding: " + key); parse_info.reset();
}
if( Global.GfxRenderer != "default" ) {
// basic texture validation for legacy branch
for( auto texturehandle : textures ) {
if( texturehandle == null_handle ) {
break;
}
if( GfxRenderer->Texture( texturehandle ).id <= 0 ) {
is_good = false; is_good = false;
} }
} }
return;
parse_info.reset();
} }
if( !shader ) { if( !shader ) {
@@ -206,7 +226,10 @@ void opengl_material::finalize(bool Loadnow)
{ {
gl::shader::texture_entry &entry = it.second; gl::shader::texture_entry &entry = it.second;
texture_handle handle = textures[entry.id]; texture_handle handle = textures[entry.id];
if (handle) { // NOTE: texture validation at this stage relies on forced texture load behaviour during its create() call
// TODO: move texture id validation to later stage if/when deferred texture loading is implemented
if( ( handle )
&& ( GfxRenderer->Texture( handle ).id > 0 ) ) {
GfxRenderer->Texture(handle).set_components_hint((GLint)entry.components); GfxRenderer->Texture(handle).set_components_hint((GLint)entry.components);
} }
else { else {
@@ -476,7 +499,9 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
if( ( false == isgenerated ) if( ( false == isgenerated )
&& ( false == locator.first.empty() ) ) { && ( false == locator.first.empty() ) ) {
// try to parse located file resource // try to parse located file resource
cParser materialparser( locator.first + locator.second, cParser::buffer_FILE ); cParser materialparser(
locator.first + locator.second,
cParser::buffer_FILE );
if( true == material.deserialize( materialparser, Loadnow ) ) { if( true == material.deserialize( materialparser, Loadnow ) ) {
material.name = locator.first; material.name = locator.first;
} }
@@ -485,12 +510,11 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
// if there's no .mat file, this can be either autogenerated texture, // if there's no .mat file, this can be either autogenerated texture,
// or legacy method of referring just to diffuse texture directly. // or legacy method of referring just to diffuse texture directly.
// wrap basic material around it in either case // wrap basic material around it in either case
material.textures[0] = GfxRenderer->Fetch_Texture( Filename, Loadnow ); auto const texturehandle { GfxRenderer->Fetch_Texture( Filename, Loadnow ) };
if( material.textures[0] != null_handle ) if( texturehandle != null_handle ) {
{
// use texture path and name to tell the newly created materials apart // use texture path and name to tell the newly created materials apart
material.name = GfxRenderer->Texture( material.textures[0] ).name; material.name = GfxRenderer->Texture( texturehandle ).name;
/*
// material would attach default shader anyway, but it would spit to error log // material would attach default shader anyway, but it would spit to error log
try try
{ {
@@ -501,6 +525,13 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
ErrorLog("invalid shader: " + std::string(e.what())); ErrorLog("invalid shader: " + std::string(e.what()));
} }
} }
*/
// HACK: create parse info for material finalize() method
cParser materialparser(
"texture1: " + Filename,
cParser::buffer_TEXT );
material.deserialize( materialparser, Loadnow );
}
} }
if( false == material.name.empty() ) { if( false == material.name.empty() ) {

View File

@@ -1779,7 +1779,7 @@ void opengl33_renderer::Bind_Material( material_handle const Material, TSubModel
{ {
if (Material != null_handle) if (Material != null_handle)
{ {
auto &material = m_materials.material(Material); auto const &material { m_materials.material( Material ) };
if( false == material.is_good ) { if( false == material.is_good ) {
// use failure indicator instead // use failure indicator instead

View File

@@ -115,6 +115,7 @@ opengl_renderer::Init( GLFWwindow *Window ) {
m_reflectiontexture = Fetch_Texture( "fx/reflections" ); m_reflectiontexture = Fetch_Texture( "fx/reflections" );
} }
m_smoketexture = Fetch_Texture( "fx/smoke" ); m_smoketexture = Fetch_Texture( "fx/smoke" );
m_invalid_material = Fetch_Material( "fx/invalid" );
#ifdef EU07_USE_PICKING_FRAMEBUFFER #ifdef EU07_USE_PICKING_FRAMEBUFFER
// pick buffer resources // pick buffer resources
@@ -1705,11 +1706,30 @@ opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow
void void
opengl_renderer::Bind_Material( material_handle const Material, TSubModel const *sm, lighting_data const *lighting ) { opengl_renderer::Bind_Material( material_handle const Material, TSubModel const *sm, lighting_data const *lighting ) {
auto const &material = m_materials.material( Material ); if( Material != null_handle ) {
if( false == Global.BasicRenderer ) {
m_textures.bind( m_normaltextureunit, material.textures[1] ); auto const &material { m_materials.material( Material ) };
if( false == material.is_good ) {
// use failure indicator instead
if( Material != m_invalid_material ) {
Bind_Material( m_invalid_material );
}
return;
}
if( false == Global.BasicRenderer ) {
m_textures.bind( m_normaltextureunit, material.textures[1] );
}
m_textures.bind( m_diffusetextureunit, material.textures[0] );
}
else {
// null material, unbind all textures
if( false == Global.BasicRenderer ) {
m_textures.bind( m_normaltextureunit, null_handle );
}
m_textures.bind( m_diffusetextureunit, null_handle );
} }
m_textures.bind( m_diffusetextureunit, material.textures[0] );
} }
opengl_material const & opengl_material const &

View File

@@ -278,6 +278,7 @@ private:
texture_handle m_reflectiontexture { -1 }; texture_handle m_reflectiontexture { -1 };
texture_handle m_smoketexture { -1 }; texture_handle m_smoketexture { -1 };
GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements
material_handle m_invalid_material;
// TODO: refactor framebuffer stuff into an object // TODO: refactor framebuffer stuff into an object
bool m_framebuffersupport { false }; bool m_framebuffersupport { false };
#ifdef EU07_USE_PICKING_FRAMEBUFFER #ifdef EU07_USE_PICKING_FRAMEBUFFER