16
0
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:
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

@@ -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 ?

View File

@@ -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;

View File

@@ -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 ]; }

View File

@@ -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*/

View File

@@ -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 );
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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>();

View File

@@ -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 ) };

View File

@@ -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() ) {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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