mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 18:39:18 +02:00
ai direction change logic enhamcement, minor bug fixes
This commit is contained in:
152
Driver.cpp
152
Driver.cpp
@@ -973,12 +973,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
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) ) {
|
||||
// to się wykona tylko raz po zatrzymaniu na W4
|
||||
if( TrainParams.StationIndex < TrainParams.StationCount ) {
|
||||
@@ -998,6 +992,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
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()) {
|
||||
// jeśli "@" w rozkładzie, to wykonanie dalszych komend
|
||||
// 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
|
||||
}
|
||||
else
|
||||
{ // w trybie manewrowym: skanować od niego wstecz, stanąć po wyjechaniu za
|
||||
// sygnalizator i zmienić kierunek
|
||||
v = 0.0; // zmiana kierunku może być podanym sygnałem, ale wypadało by
|
||||
// zmienić światło wcześniej
|
||||
if (!(iDrivigFlags & moveSwitchFound)) // jeśli nie ma rozjazdu
|
||||
iDrivigFlags |= moveTrackEnd; // to dalsza jazda trwale ograniczona (W5,
|
||||
// koniec toru)
|
||||
{ // w trybie manewrowym: skanować od niego wstecz, stanąć po wyjechaniu za sygnalizator i zmienić kierunek
|
||||
v = 0.0; // zmiana kierunku może być podanym sygnałem, ale wypadało by zmienić światło wcześniej
|
||||
if( !( iDrivigFlags & moveSwitchFound ) ) { // jeśli nie ma rozjazdu
|
||||
// check for presence of a signal facing the opposite direction
|
||||
// if there's one, we'll want to pass it before changing direction
|
||||
basic_event *foundevent = nullptr;
|
||||
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) {
|
||||
@@ -3183,7 +3195,7 @@ bool TController::IncSpeed()
|
||||
return false;
|
||||
}
|
||||
bool OK = true;
|
||||
if( ( iDrivigFlags & moveDoorOpened )
|
||||
if( ( doors_open() )
|
||||
&& ( VelDesired > 0.0 ) ) { // to prevent door shuffle on stop
|
||||
// zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime)
|
||||
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 )
|
||||
|| ( false == AIControllFlag ) ) ) {
|
||||
// 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
|
||||
while( vehicle != nullptr ) {
|
||||
// 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::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
|
||||
{ // 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);
|
||||
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
|
||||
// TODO: check if this situation still happens and the hack is still needed
|
||||
if( ( false == AIControllFlag )
|
||||
&& ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( mvOccupied->Doors.close_control != control_t::driver ) ) {
|
||||
// && ( iDrivigFlags & moveDoorOpened )
|
||||
// && ( mvOccupied->Doors.close_control != control_t::driver )
|
||||
&& ( doors_open() ) ) {
|
||||
// for diesel engines react when engine is put past idle revolutions
|
||||
// for others straightforward master controller check
|
||||
if( ( mvControlling->EngineType == TEngineType::DieselEngine ?
|
||||
@@ -4866,7 +4881,7 @@ TController::UpdateSituation(double dt) {
|
||||
|
||||
if( mvOccupied->Vel > 1.0 ) {
|
||||
// jeżeli jedzie
|
||||
if( iDrivigFlags & moveDoorOpened ) {
|
||||
if( doors_open() ) {
|
||||
// jeśli drzwi otwarte
|
||||
// nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości
|
||||
Doors( false );
|
||||
@@ -5166,7 +5181,8 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
*/
|
||||
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 ) {
|
||||
|
||||
@@ -5560,6 +5576,7 @@ TController::UpdateSituation(double dt) {
|
||||
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
|
||||
// Ra: odczyt (ActualProximityDist), (VelNext) i (AccPreferred) z tabelki prędkosci
|
||||
|
||||
TCommandType comm = TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired);
|
||||
|
||||
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
|
||||
// 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 );
|
||||
}
|
||||
if( IsHeavyCargoTrain ) {
|
||||
if( ( IsHeavyCargoTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) {
|
||||
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)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool TController::BackwardTrackBusy(TTrack *Track)
|
||||
bool TController::IsOccupiedByAnotherConsist(TTrack *Track)
|
||||
{ // najpierw sprawdzamy, czy na danym torze są pojazdy z innego składu
|
||||
if( false == Track->Dynamics.empty() ) {
|
||||
for( auto dynamic : Track->Dynamics ) {
|
||||
@@ -6932,13 +6949,13 @@ bool TController::BackwardTrackBusy(TTrack *Track)
|
||||
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
|
||||
// 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 ) };
|
||||
auto const dir{ Vehicle->VectorFront() * Vehicle->DirectionGet() };
|
||||
auto const pos{ End == end::front ? Vehicle->RearPosition() : Vehicle->HeadPosition() };
|
||||
auto const &eventsequence { ( fDirection * Eventdirection > 0 ? Track->m_events2 : Track->m_events1 ) };
|
||||
for( auto const &event : eventsequence ) {
|
||||
if( ( event.second != nullptr )
|
||||
&& ( 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
|
||||
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 ) {
|
||||
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
|
||||
return event.second;
|
||||
}
|
||||
@@ -6955,30 +6973,29 @@ basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Tr
|
||||
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)
|
||||
TTrack *pTrackChVel = Track; // tor ze zmianą prędkości
|
||||
TTrack *pTrackFrom; // odcinek poprzedni, do znajdywania końca dróg
|
||||
double fDistChVel = -1; // odległość do toru ze zmianą prędkości
|
||||
double fCurrentDistance = pVehicle->RaTranslationGet(); // aktualna pozycja na torze
|
||||
double s = 0;
|
||||
auto *Track = Vehicle->GetTrack();
|
||||
double fCurrentDistance = Vehicle->RaTranslationGet(); // aktualna pozycja na torze
|
||||
if (fDirection > 0) // jeśli w kierunku Point2 toru
|
||||
fCurrentDistance = Track->Length() - fCurrentDistance;
|
||||
if (BackwardTrackBusy(Track))
|
||||
{ // jak tor zajęty innym składem, to nie ma po co skanować
|
||||
fDistance = 0; // to na tym torze stoimy
|
||||
return NULL; // stop, skanowanie nie dało sensownych rezultatów
|
||||
double s = 0;
|
||||
|
||||
if( Track->VelocityGet() == 0.0 ) { // jak prędkosć 0 albo uszkadza, 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)) != 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
|
||||
fDistance = 0; // to na tym torze stoimy
|
||||
fDistance = s; // to na tym torze stoimy
|
||||
return Track;
|
||||
}
|
||||
if ((Track->VelocityGet() == 0.0) || (Track->iDamageFlag & 128))
|
||||
{ // 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
|
||||
}
|
||||
TTrack *pTrackFrom; // odcinek poprzedni, do znajdywania końca dróg
|
||||
while (s < fDistance)
|
||||
{
|
||||
// Track->ScannedFlag=true; //do pokazywania przeskanowanych torów
|
||||
@@ -6997,32 +7014,35 @@ TTrack * TController::BackwardTraceRoute(double &fDistance, double &fDirection,
|
||||
Track = Track->CurrentPrev(); // może być NULL
|
||||
}
|
||||
if (Track == pTrackFrom)
|
||||
Track = NULL; // koniec, tak jak dla torów
|
||||
if( ( Track ?
|
||||
( ( Track->VelocityGet() == 0.0 )
|
||||
|| ( Track->iDamageFlag & 128 )
|
||||
|| ( true == BackwardTrackBusy( Track ) ) ) :
|
||||
true ) )
|
||||
{ // gdy dalej toru nie ma albo zerowa prędkość, albo uszkadza pojazd
|
||||
Track = nullptr; // koniec, tak jak dla torów
|
||||
|
||||
// gdy dalej toru nie ma albo zerowa prędkość, albo uszkadza pojazd
|
||||
// zwraca NULL, że skanowanie nie dało sensownych rezultatów
|
||||
if( Track == nullptr ) {
|
||||
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();
|
||||
if ((Event = CheckTrackEventBackward(fDirection, Track)) != NULL)
|
||||
if ((Event = CheckTrackEventBackward(fDirection, Track, Vehicle, Eventdirection, End)) != nullptr)
|
||||
{ // znaleziony tor z eventem
|
||||
fDistance = s;
|
||||
return Track;
|
||||
}
|
||||
}
|
||||
Event = NULL; // jak dojdzie tu, to nie ma semafora
|
||||
if (fDistChVel < 0)
|
||||
{ // zwraca ostatni sprawdzony tor
|
||||
Event = nullptr; // jak dojdzie tu, to nie ma semafora
|
||||
// zwraca ostatni sprawdzony tor
|
||||
fDistance = s;
|
||||
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
|
||||
void TController::SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos )
|
||||
@@ -7071,8 +7091,8 @@ TCommandType TController::BackwardScan()
|
||||
double scandist = scanmax; // zmodyfikuje na rzeczywiście przeskanowane
|
||||
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
|
||||
TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[0]->GetTrack(), e);
|
||||
auto const dir = startdir * pVehicles[0]->VectorFront(); // wektor w kierunku jazdy/szukania
|
||||
TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[end::front], e);
|
||||
auto const dir = startdir * pVehicles[end::front]->VectorFront(); // wektor w kierunku jazdy/szukania
|
||||
if( !scantrack ) {
|
||||
// jeśli wstecz wykryto koniec toru to raczej nic się nie da w takiej sytuacji zrobić
|
||||
return TCommandType::cm_Unknown;
|
||||
@@ -7095,7 +7115,7 @@ TCommandType TController::BackwardScan()
|
||||
if( typeid( *e ) == typeid( getvalues_event ) )
|
||||
{ // przesłać info o zbliżającym się semaforze
|
||||
#if LOGBACKSCAN
|
||||
edir += "(" + ( e->asNodeName ) + ")";
|
||||
edir += "(" + ( e->name() ) + ")";
|
||||
#endif
|
||||
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
|
||||
@@ -7147,7 +7167,7 @@ TCommandType TController::BackwardScan()
|
||||
WriteLog(
|
||||
edir + " - [SetVelocity] ["
|
||||
+ to_string( vmechmax, 2 ) + "] ["
|
||||
+ to_string( e->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" );
|
||||
+ to_string( e->input_value( 2 ), 2 ) + "]" );
|
||||
#endif
|
||||
return (
|
||||
vmechmax > 0 ?
|
||||
@@ -7191,7 +7211,7 @@ TCommandType TController::BackwardScan()
|
||||
WriteLog(
|
||||
edir + " - [ShuntVelocity] ["
|
||||
+ to_string( vmechmax, 2 ) + "] ["
|
||||
+ to_string( e->value( 2 ), 2 ) + "]" );
|
||||
+ to_string( e->input_value( 2 ), 2 ) + "]" );
|
||||
#endif
|
||||
return (
|
||||
vmechmax > 0 ?
|
||||
|
||||
6
Driver.h
6
Driver.h
@@ -408,9 +408,9 @@ private:
|
||||
void TableClear();
|
||||
int TableDirection() { return iTableDirection; }
|
||||
// Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu
|
||||
bool BackwardTrackBusy( TTrack *Track );
|
||||
basic_event *CheckTrackEventBackward( double fDirection, TTrack *Track );
|
||||
TTrack *BackwardTraceRoute( double &fDistance, double &fDirection, TTrack *Track, basic_event *&Event );
|
||||
bool IsOccupiedByAnotherConsist( 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, 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 );
|
||||
TCommandType BackwardScan();
|
||||
std::string TableText( std::size_t const Index ) const;
|
||||
|
||||
4
DynObj.h
4
DynObj.h
@@ -589,10 +589,10 @@ private:
|
||||
inline Math3D::vector3 GetWorldPosition( Math3D::vector3 const &Location ) const {
|
||||
return vPosition + mMatrix * Location; }
|
||||
// pobranie współrzędnych czoła
|
||||
inline Math3D::vector3 HeadPosition() {
|
||||
inline Math3D::vector3 HeadPosition() const {
|
||||
return vCoulpler[iDirection ^ 1]; };
|
||||
// pobranie współrzędnych tyłu
|
||||
inline Math3D::vector3 RearPosition() {
|
||||
inline Math3D::vector3 RearPosition() const {
|
||||
return vCoulpler[iDirection]; };
|
||||
inline Math3D::vector3 CouplerPosition( end const End ) const {
|
||||
return vCoulpler[ End ]; }
|
||||
|
||||
@@ -1545,7 +1545,7 @@ public:
|
||||
double eimv[21];
|
||||
static std::vector<std::string> const eimv_labels;
|
||||
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 NewSpeed = 0; /*nowa predkosc do zadania*/
|
||||
double MED_EPVC_CurrentTime = 0; /*aktualny czas licznika czasu korekcji siły EP*/
|
||||
|
||||
@@ -1310,7 +1310,6 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
|
||||
compute_movement_( dt );
|
||||
|
||||
// security system
|
||||
if (!DebugModeFlag)
|
||||
SecuritySystemCheck(dt1);
|
||||
|
||||
return d;
|
||||
@@ -2907,6 +2906,11 @@ void TMoverParameters::SecuritySystemCheck(double dt)
|
||||
RadiostopSwitch(false);
|
||||
// SecuritySystem.Status = 0; //deaktywacja czuwaka
|
||||
}
|
||||
|
||||
// automatic reset in debug mode
|
||||
if( DebugModeFlag ) {
|
||||
SSReset();
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
@@ -7132,6 +7136,7 @@ void TMoverParameters::CheckSpeedCtrl(double dt)
|
||||
eimicSpeedCtrl = 1;
|
||||
eimicSpeedCtrlIntegral = 0;
|
||||
SpeedCtrlUnit.Parking = false;
|
||||
SendCtrlToNext( "SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabActive );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -787,7 +787,7 @@ opengl_texture::unbind(size_t unit)
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_texture::create() {
|
||||
opengl_texture::create( bool const Static ) {
|
||||
|
||||
if( data_state != resource_state::good && !is_rendertarget ) {
|
||||
// don't bother until we have useful texture data
|
||||
@@ -934,6 +934,8 @@ opengl_texture::create() {
|
||||
make_request();
|
||||
}
|
||||
|
||||
is_static = Static;
|
||||
|
||||
is_ready = true;
|
||||
}
|
||||
|
||||
@@ -945,6 +947,7 @@ void
|
||||
opengl_texture::release() {
|
||||
|
||||
if( id == -1 ) { return; }
|
||||
if( is_static ) { return; }
|
||||
|
||||
if( true == Global.ResourceMove ) {
|
||||
// if resource move is enabled we don't keep a cpu side copy after upload
|
||||
|
||||
@@ -31,7 +31,7 @@ struct opengl_texture {
|
||||
static void
|
||||
unbind( size_t unit );
|
||||
bool
|
||||
create();
|
||||
create( bool const Static = false );
|
||||
// releases resources allocated on the opengl end, storing local copy if requested
|
||||
void
|
||||
release();
|
||||
@@ -78,6 +78,7 @@ private:
|
||||
void gles_match_internalformat( GLuint format );
|
||||
|
||||
// members
|
||||
bool is_static = false; // is excluded from garbage collection
|
||||
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
|
||||
int samples = 1;
|
||||
int layers = 1;
|
||||
|
||||
22
Train.cpp
22
Train.cpp
@@ -2437,8 +2437,8 @@ void TTrain::OnCommand_pantographcompressorvalveenable( TTrain *Train, command_d
|
||||
|
||||
auto const valveispresent {
|
||||
( Train->ggPantCompressorValve.SubModel != nullptr )
|
||||
|| ( ( Train->iCabn == 0 )
|
||||
&& ( Train->mvControlled == Train->mvOccupied ) ) };
|
||||
|| ( ( Train->mvOccupied == Train->mvPantographUnit )
|
||||
&& ( Train->iCabn == 0 ) ) };
|
||||
|
||||
if( false == valveispresent ) {
|
||||
// tylko w maszynowym, unless actual device is present
|
||||
@@ -2458,8 +2458,8 @@ void TTrain::OnCommand_pantographcompressorvalvedisable( TTrain *Train, command_
|
||||
|
||||
auto const valveispresent {
|
||||
( Train->ggPantCompressorValve.SubModel != nullptr )
|
||||
|| ( ( Train->iCabn == 0 )
|
||||
&& ( Train->mvControlled == Train->mvOccupied ) ) };
|
||||
|| ( ( Train->mvOccupied == Train->mvPantographUnit )
|
||||
&& ( Train->iCabn == 0 ) ) };
|
||||
|
||||
if( false == valveispresent ) {
|
||||
// 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 ) {
|
||||
|
||||
if( ( Train->ggPantCompressorValve.SubModel == nullptr )
|
||||
&& ( Train->mvControlled->TrainType == dt_EZT ?
|
||||
( Train->mvOccupied == Train->mvPantographUnit ) :
|
||||
( Train->iCabn != 0 ) ) ) {
|
||||
// tylko w maszynowym
|
||||
// tylko w maszynowym, unless actual device is present
|
||||
auto const switchispresent {
|
||||
( Train->m_controlmapper.contains( "pantcompressor_sw:" ) )
|
||||
|| ( ( Train->mvOccupied == Train->mvPantographUnit )
|
||||
&& ( Train->iCabn == 0 ) ) };
|
||||
if( false == switchispresent ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7869,7 +7870,8 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
||||
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 rt = std::make_shared<python_rt>();
|
||||
|
||||
@@ -369,6 +369,7 @@ timetable_panel::update() {
|
||||
( owner->iStationStart < table.StationIndex )
|
||||
&& ( i < table.StationIndex )
|
||||
&& ( ( 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 ) ) ) };
|
||||
auto const loadchangeinprogress { ( ( static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) ) > 0 ) };
|
||||
auto const isatpassengerstop { ( true == owner->IsAtPassengerStop ) && ( vehicle->MoverParameters->Vel < 1.0 ) };
|
||||
|
||||
47
material.cpp
47
material.cpp
@@ -77,6 +77,7 @@ void opengl_material::finalize(bool Loadnow)
|
||||
|
||||
if (key.size() > 0 && key[0] != '_')
|
||||
{
|
||||
key.erase( key.find_first_not_of( "-1234567890" ) );
|
||||
size_t num = std::stoi(key) - 1;
|
||||
if (num < gl::MAX_TEXTURES) {
|
||||
textures[num] = GfxRenderer->Fetch_Texture(value, Loadnow);
|
||||
@@ -99,10 +100,13 @@ void opengl_material::finalize(bool Loadnow)
|
||||
textures[ lookup->second ] = GfxRenderer->Fetch_Texture( value, Loadnow );
|
||||
}
|
||||
else {
|
||||
// ignore unrecognized texture bindings in legacy render mode, it's most likely data for more advanced shaders
|
||||
if( Global.GfxRenderer == "default" ) {
|
||||
log_error( "unknown texture binding: " + key );
|
||||
is_good = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log_error("unrecognized texture binding: " + key);
|
||||
is_good = false;
|
||||
@@ -129,6 +133,9 @@ void opengl_material::finalize(bool Loadnow)
|
||||
}
|
||||
}
|
||||
|
||||
// TBD, TODO: move material validation to renderer, to eliminate branching?
|
||||
if( Global.GfxRenderer == "default" ) {
|
||||
|
||||
if( !shader ) {
|
||||
is_good = false;
|
||||
return;
|
||||
@@ -170,10 +177,23 @@ void opengl_material::finalize(bool Loadnow)
|
||||
is_good = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( !shader ) {
|
||||
is_good = false;
|
||||
return;
|
||||
@@ -206,7 +226,10 @@ void opengl_material::finalize(bool Loadnow)
|
||||
{
|
||||
gl::shader::texture_entry &entry = it.second;
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@@ -476,7 +499,9 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
if( ( false == isgenerated )
|
||||
&& ( false == locator.first.empty() ) ) {
|
||||
// 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 ) ) {
|
||||
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,
|
||||
// or legacy method of referring just to diffuse texture directly.
|
||||
// wrap basic material around it in either case
|
||||
material.textures[0] = GfxRenderer->Fetch_Texture( Filename, Loadnow );
|
||||
if( material.textures[0] != null_handle )
|
||||
{
|
||||
auto const texturehandle { GfxRenderer->Fetch_Texture( Filename, Loadnow ) };
|
||||
if( texturehandle != null_handle ) {
|
||||
// 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
|
||||
try
|
||||
{
|
||||
@@ -501,6 +525,13 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
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() ) {
|
||||
|
||||
@@ -1779,7 +1779,7 @@ void opengl33_renderer::Bind_Material( material_handle const Material, TSubModel
|
||||
{
|
||||
if (Material != null_handle)
|
||||
{
|
||||
auto &material = m_materials.material(Material);
|
||||
auto const &material { m_materials.material( Material ) };
|
||||
|
||||
if( false == material.is_good ) {
|
||||
// use failure indicator instead
|
||||
|
||||
@@ -115,6 +115,7 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
m_reflectiontexture = Fetch_Texture( "fx/reflections" );
|
||||
}
|
||||
m_smoketexture = Fetch_Texture( "fx/smoke" );
|
||||
m_invalid_material = Fetch_Material( "fx/invalid" );
|
||||
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
// pick buffer resources
|
||||
@@ -1705,12 +1706,31 @@ opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow
|
||||
void
|
||||
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 ) {
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
opengl_material const &
|
||||
opengl_renderer::Material( material_handle const Material ) const {
|
||||
|
||||
@@ -278,6 +278,7 @@ private:
|
||||
texture_handle m_reflectiontexture { -1 };
|
||||
texture_handle m_smoketexture { -1 };
|
||||
GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements
|
||||
material_handle m_invalid_material;
|
||||
// TODO: refactor framebuffer stuff into an object
|
||||
bool m_framebuffersupport { false };
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
|
||||
Reference in New Issue
Block a user