diff --git a/Camera.cpp b/Camera.cpp index 0c7c21ca..ef589bc5 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -25,17 +25,13 @@ void TCamera::Init(vector3 NPos, vector3 NAngle) { vUp = vector3(0, 1, 0); - // pOffset= vector3(-0.8,0,0); - CrossDist = 10; Velocity = vector3(0, 0, 0); Pitch = NAngle.x; Yaw = NAngle.y; Roll = NAngle.z; Pos = NPos; - // Type= tp_Follow; Type = (Global::bFreeFly ? tp_Free : tp_Follow); - // Type= tp_Free; }; void TCamera::OnCursorMove(double x, double y) diff --git a/Camera.h b/Camera.h index a6346f52..09135908 100644 --- a/Camera.h +++ b/Camera.h @@ -46,13 +46,10 @@ class TCamera vector3 LookAt; // współrzędne punktu, na który ma patrzeć vector3 vUp; vector3 Velocity; - vector3 CrossPos; - double CrossDist; void Init(vector3 NPos, vector3 NAngle); - void Reset() - { - Pitch = Yaw = Roll = 0; - }; + inline + void Reset() { + Pitch = Yaw = Roll = 0; }; void OnCursorMove(double const x, double const y); void OnCommand( command_data const &Command ); void Update(); diff --git a/Driver.cpp b/Driver.cpp index 3c9b9780..bf99e184 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -46,12 +46,12 @@ ProjectEventOnTrack( TEvent const *Event, TTrack const *Track, double const Dire ( 1.0 - nearestpoint ) * segment->GetLength() ); // measure from point2 }; -double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double start_dist, int iter = 0, bool back = false) +double GetDistanceToEvent(TTrack const *track, TEvent const *event, double scan_dir, double start_dist, int iter = 0, bool back = false) { if( track == nullptr ) { return start_dist; } auto const segment = track->CurrentSegment(); - vector3 const pos_event = event->PositionGet(); + auto const pos_event = event->PositionGet(); double len1, len2; double sd = scan_dir; double seg_len = scan_dir > 0 ? 0.0 : 1.0; @@ -63,15 +63,15 @@ double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double len1 = len2; seg_len += scan_dir > 0 ? dzielnik : -dzielnik; len2 = (pos_event - segment->FastGetPoint(seg_len)).LengthSquared(); - krok++; - } while ((len1 > len2) && (seg_len >= dzielnik && (seg_len <= (1 - dzielnik)))); + ++krok; + } while ((len1 > len2) && (seg_len >= dzielnik && (seg_len <= (1.0 - dzielnik)))); //trzeba sprawdzić czy seg_len nie osiągnął skrajnych wartości, bo wtedy // trzeba sprawdzić tor obok if (1 == krok) sd = -sd; // jeśli tylko jeden krok tzn, że event przy poprzednim sprawdzaym torze - if (((seg_len <= dzielnik) || (seg_len > (1 - dzielnik))) && (iter < 3)) + if (((1 == krok) || (seg_len <= dzielnik) || (seg_len > (1.0 - dzielnik))) && (iter < 3)) { // przejście na inny tor - track = track->Neightbour(int(sd), sd); + track = track->Connected(int(sd), sd); start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength(); return GetDistanceToEvent(track, event, sd, start_dist, ++iter, 1 == krok ? true : false); } @@ -616,7 +616,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) fCurrentDistance += fTrackLength; // doliczenie kolejnego odcinka do przeskanowanej długości tLast = pTrack; // odhaczenie, że sprawdzony fLastVel = pTrack->VelocityGet(); // prędkość na poprzednio sprawdzonym odcinku - pTrack = pTrack->Neightbour( + pTrack = pTrack->Connected( ( pTrack->eType == tt_Cross ? (sSpeedTable[iLast].iFlags >> 28) : static_cast(fLastDir) ), @@ -3919,6 +3919,13 @@ TController::UpdateSituation(double dt) { fStopTime = 0.0; // nie ma na co czekać z odczepianiem } } + else { + if( mvOccupied->Vel > 0.0 ) { + // 1st phase(?) + // bring it to stop if it's not already stopped + SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie + } + } } // odczepiania else // to poniżej jeśli ilość wagonów ujemna if (iDrivigFlags & movePress) @@ -3985,8 +3992,8 @@ TController::UpdateSituation(double dt) { } else { // samochod (sokista też) - fMinProximityDist = std::max( 4.0, mvOccupied->Vel * 0.2 ); - fMaxProximityDist = std::max( 8.0, mvOccupied->Vel * 0.375 ); //[m] + fMinProximityDist = std::max( 3.0, mvOccupied->Vel * 0.2 ); + fMaxProximityDist = std::max( 9.0, mvOccupied->Vel * 0.375 ); //[m] // margines prędkości powodujący załączenie napędu fVelMinus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania @@ -4259,12 +4266,17 @@ TController::UpdateSituation(double dt) { && ( coupler->CouplingFlag == coupling::faux ) ) { // mamy coś z przodu podłączone sprzęgiem wirtualnym // wyliczanie optymalnego przyspieszenia do jazdy na widoczność +/* ActualProximityDist = std::min( ActualProximityDist, vehicle->fTrackBlock - ( mvOccupied->CategoryFlag & 2 ? fMinProximityDist : // cars can bunch up tighter fMaxProximityDist ) ); // other vehicle types less so +*/ + ActualProximityDist = std::min( + ActualProximityDist, + vehicle->fTrackBlock ); double k = coupler->Connected->Vel; // prędkość pojazdu z przodu (zakładając, // że jedzie w tę samą stronę!!!) if( k < vel + 10 ) { @@ -4323,36 +4335,47 @@ TController::UpdateSituation(double dt) { } // sprawdzamy możliwe ograniczenia prędkości - if (OrderCurrentGet() & (Shunt | Obey_train)) // w Connect nie, bo moveStopHere - // odnosi się do stanu po połączeniu - if (iDrivigFlags & moveStopHere) // jeśli ma czekać na wolną drogę - if (vel == 0.0) // a stoi - if (VelNext == 0.0) // a wyjazdu nie ma - VelDesired = 0.0; // to ma stać - if (fStopTime < 0) // czas postoju przed dalszą jazdą (np. na przystanku) + if( OrderCurrentGet() & ( Shunt | Obey_train ) ) { + // w Connect nie, bo moveStopHere odnosi się do stanu po połączeniu + if( ( iDrivigFlags & moveStopHere ) + && ( vel == 0.0 ) + && ( VelNext == 0.0 ) ) { + // jeśli ma czekać na wolną drogę, stoi a wyjazdu nie ma, to ma stać + VelDesired = 0.0; + } + } + if( fStopTime < 0 ) { + // czas postoju przed dalszą jazdą (np. na przystanku) VelDesired = 0.0; // jak ma czekać, to nie ma jazdy - // else if (VelSignal<0) - // VelDesired=fVelMax; //ile fabryka dala (Ra: uwzględione wagony) - else if (VelSignal >= 0) // jeśli skład był zatrzymany na początku i teraz już może jechać - VelDesired = Global::Min0RSpeed(VelDesired, VelSignal); - - if (mvOccupied->RunningTrack.Velmax >= - 0) // ograniczenie prędkości z trajektorii ruchu + } + else if( VelSignal >= 0 ) { + // jeśli skład był zatrzymany na początku i teraz już może jechać VelDesired = - Global::Min0RSpeed(VelDesired, - mvOccupied->RunningTrack.Velmax); // uwaga na ograniczenia szlakowej! - if (VelforDriver >= 0) // tu jest zero przy zmianie kierunku jazdy - VelDesired = Global::Min0RSpeed(VelDesired, VelforDriver); // Ra: tu może być 40, jeśli - // mechanik nie ma znajomości - // szlaaku, albo kierowca jeździ - // 70 - if (TrainParams) - if (TrainParams->CheckTrainLatency() < 5.0) - if (TrainParams->TTVmax > 0.0) - VelDesired = Global::Min0RSpeed( - VelDesired, - TrainParams - ->TTVmax); // jesli nie spozniony to nie przekraczać rozkladowej + Global::Min0RSpeed( + VelDesired, + VelSignal ); + } + if( mvOccupied->RunningTrack.Velmax >= 0 ) { + // ograniczenie prędkości z trajektorii ruchu + VelDesired = + Global::Min0RSpeed( + VelDesired, + mvOccupied->RunningTrack.Velmax ); // uwaga na ograniczenia szlakowej! + } + if( VelforDriver >= 0 ) { + // tu jest zero przy zmianie kierunku jazdy + // Ra: tu może być 40, jeśli mechanik nie ma znajomości szlaaku, albo kierowca jeździ 70 + VelDesired = Global::Min0RSpeed( VelDesired, VelforDriver ); + } + if( ( TrainParams != nullptr ) + && ( TrainParams->CheckTrainLatency() < 5.0 ) + && ( TrainParams->TTVmax > 0.0 ) ) { + // jesli nie spozniony to nie przekraczać rozkladowej + VelDesired = + Global::Min0RSpeed( + VelDesired, + TrainParams->TTVmax ); + } if (VelDesired > 0.0) if( ( ( iDrivigFlags & moveStopHere ) == 0 ) || ( ( SemNextIndex != -1 ) @@ -4448,10 +4471,16 @@ TController::UpdateSituation(double dt) { VelDesired = Global::Min0RSpeed( VelDesired, VelNext ); */ if( VelNext == 0.0 ) { - // hamowanie tak, aby stanąć - VelDesired = VelNext; - AccDesired = ( VelNext * VelNext - vel * vel ) / ( 25.92 * ( ActualProximityDist + 0.1 - 0.5*fMinProximityDist ) ); - AccDesired = std::min( AccDesired, fAccThreshold ); + if( mvOccupied->CategoryFlag & 1 ) { + // hamowanie tak, aby stanąć + VelDesired = VelNext; + AccDesired = ( VelNext * VelNext - vel * vel ) / ( 25.92 * ( ActualProximityDist + 0.1 - 0.5*fMinProximityDist ) ); + AccDesired = std::min( AccDesired, fAccThreshold ); + } + else { + // for cars (and others) coast at low speed until we hit min proximity range + VelDesired = Global::Min0RSpeed( VelDesired, 5.0 ); + } } } else { diff --git a/Driver.h b/Driver.h index 1d6e410e..12c91d2a 100644 --- a/Driver.h +++ b/Driver.h @@ -212,13 +212,12 @@ private: // parametry aktualnego składu double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca - public: double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca - private: double fReady = 0.0; // poziom odhamowania wagonów bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow +private: double LastUpdatedTime = 0.0; // czas od ostatniego logu double ElapsedTime = 0.0; // czas od poczatku logu double deltalog = 0.05; // przyrost czasu @@ -227,26 +226,21 @@ private: // parametry aktualnego składu double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations TAction eAction = actSleep; // aktualny stan public: - inline TAction GetAction() - { - return eAction; - } + inline + TAction GetAction() { + return eAction; } bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista int iRouteWanted = 3; // oczekiwany kierunek jazdy (0-stop,1-lewo,2-prawo,3-prosto) np. odpala // migacz lub czeka na stan zwrotnicy private: TDynamicObject *pVehicle = nullptr; // pojazd w którym siedzi sterujący - TDynamicObject - *pVehicles[2]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane) + TDynamicObject *pVehicles[2]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane) TMoverParameters *mvControlling = nullptr; // jakim pojazdem steruje (może silnikowym w EZT) TMoverParameters *mvOccupied = nullptr; // jakim pojazdem hamuje TTrainParameters *TrainParams = nullptr; // rozkład jazdy zawsze jest, nawet jeśli pusty - // int TrainNumber; //numer rozkladowy tego pociagu - // AnsiString OrderCommand; //komenda pobierana z pojazdu - // double OrderValue; //argument komendy int iRadioChannel = 1; // numer aktualnego kanału radiowego - TTextSound *tsGuardSignal = nullptr; // komunikat od kierownika int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia) + TTextSound *tsGuardSignal = nullptr; // komunikat od kierownika public: double AccPreferred = 0.0; // preferowane przyspieszenie (wg psychiki kierującego, zmniejszana przy wykryciu kolizji) double AccDesired = AccPreferred; // przyspieszenie, jakie ma utrzymywać (<0:nie przyspieszaj,<-0.1:hamuj) diff --git a/DynObj.cpp b/DynObj.cpp index f3c24d7f..13c65909 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -1262,71 +1262,65 @@ int TDynamicObject::Dettach(int dir) .CouplingFlag; // sprzęg po rozłączaniu (czego się nie da odpiąć } -void TDynamicObject::CouplersDettach(double MinDist, int MyScanDir) -{ // funkcja rozłączajaca podłączone sprzęgi, - // jeśli odległość przekracza (MinDist) +void TDynamicObject::CouplersDettach(double MinDist, int MyScanDir) { + // funkcja rozłączajaca podłączone sprzęgi, jeśli odległość przekracza (MinDist) // MinDist - dystans minimalny, dla ktorego mozna rozłączać - if (MyScanDir > 0) - { - if (PrevConnected) // pojazd od strony sprzęgu 0 - { - if (MoverParameters->Couplers[0].CoupleDist > MinDist) { - // sprzęgi wirtualne zawsze przekraczają - - if ((PrevConnectedNo ? PrevConnected->NextConnected : - PrevConnected->PrevConnected) == this) - { // Ra: nie rozłączamy znalezionego, jeżeli nie do nas - // podłączony (może jechać w - // innym kierunku) - PrevConnected->MoverParameters->Couplers[PrevConnectedNo].Connected = NULL; - if (PrevConnectedNo == 0) - { - PrevConnected->PrevConnectedNo = 2; // sprzęg 0 nie podłączony - PrevConnected->PrevConnected = NULL; - } - else if (PrevConnectedNo == 1) - { - PrevConnected->NextConnectedNo = 2; // sprzęg 1 nie podłączony - PrevConnected->NextConnected = NULL; - } + if (MyScanDir > 0) { + // pojazd od strony sprzęgu 0 + if( ( PrevConnected != nullptr ) + && ( MoverParameters->Couplers[ TMoverParameters::side::front ].CoupleDist > MinDist ) ) { + // sprzęgi wirtualne zawsze przekraczają + if( ( PrevConnectedNo == TMoverParameters::side::front ? + PrevConnected->PrevConnected : + PrevConnected->NextConnected ) + == this ) { + // Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony + // (może jechać w innym kierunku) + PrevConnected->MoverParameters->Couplers[PrevConnectedNo].Connected = nullptr; + if( PrevConnectedNo == TMoverParameters::side::front ) { + // sprzęg 0 nie podłączony + PrevConnected->PrevConnectedNo = 2; + PrevConnected->PrevConnected = nullptr; + } + else if( PrevConnectedNo == TMoverParameters::side::rear ) { + // sprzęg 1 nie podłączony + PrevConnected->NextConnectedNo = 2; + PrevConnected->NextConnected = nullptr; } - - // za to zawsze odłączamy siebie - PrevConnected = NULL; - PrevConnectedNo = 2; // sprzęg 0 nie podłączony - MoverParameters->Couplers[0].Connected = nullptr; } + // za to zawsze odłączamy siebie + PrevConnected = nullptr; + PrevConnectedNo = 2; // sprzęg 0 nie podłączony + MoverParameters->Couplers[ TMoverParameters::side::front ].Connected = nullptr; } } - else - { - if (NextConnected) // pojazd od strony sprzęgu 1 - { - if (MoverParameters->Couplers[1].CoupleDist > MinDist) { - // sprzęgi wirtualne zawsze przekraczają - - if ((NextConnectedNo ? NextConnected->NextConnected : - NextConnected->PrevConnected) == this) - { // Ra: nie rozłączamy znalezionego, jeżeli nie do nas - // podłączony (może jechać w - // innym kierunku) - NextConnected->MoverParameters->Couplers[NextConnectedNo].Connected = NULL; - if (NextConnectedNo == 0) - { - NextConnected->PrevConnectedNo = 2; // sprzęg 0 nie podłączony - NextConnected->PrevConnected = NULL; - } - else if (NextConnectedNo == 1) - { - NextConnected->NextConnectedNo = 2; // sprzęg 1 nie podłączony - NextConnected->NextConnected = NULL; - } + else { + // pojazd od strony sprzęgu 1 + if( ( NextConnected != nullptr ) + && ( MoverParameters->Couplers[ TMoverParameters::side::rear ].CoupleDist > MinDist ) ) { + // sprzęgi wirtualne zawsze przekraczają + if( ( NextConnectedNo == TMoverParameters::side::front ? + NextConnected->PrevConnected : + NextConnected->NextConnected ) + == this) { + // Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony + // (może jechać w innym kierunku) + NextConnected->MoverParameters->Couplers[ NextConnectedNo ].Connected = nullptr; + if( NextConnectedNo == TMoverParameters::side::front ) { + // sprzęg 0 nie podłączony + NextConnected->PrevConnectedNo = 2; + NextConnected->PrevConnected = nullptr; + } + else if( NextConnectedNo == TMoverParameters::side::rear ) { + // sprzęg 1 nie podłączony + NextConnected->NextConnectedNo = 2; + NextConnected->NextConnected = nullptr; } - - NextConnected = NULL; - NextConnectedNo = 2; // sprzęg 1 nie podłączony - MoverParameters->Couplers[1].Connected = nullptr; } + // za to zawsze odłączamy siebie + NextConnected = nullptr; + NextConnectedNo = 2; // sprzęg 1 nie podłączony + MoverParameters->Couplers[1].Connected = nullptr; } } } @@ -1337,15 +1331,7 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) // pojazdu // ScanDir=1 - od strony Coupler0, ScanDir=-1 - od strony Coupler1 auto const initialdirection = Direction; // zapamiętanie kierunku poszukiwań na torze początkowym, względem sprzęgów -/* - TTrackFollower const *firstaxle = (initialdirection > 0 ? &Axle0 : &Axle1); // można by to trzymać w trainset - TTrack const *track = firstaxle->GetTrack(); // tor na którym "stoi" skrajny wózek - // (może być inny niż tor pojazdu) - if( firstaxle->GetDirection() < 0 ) { - // czy oś jest ustawiona w stronę Point1? - Direction = -Direction; // jeśli tak, to kierunek szukania będzie przeciwny - } -*/ + TTrack const *track = RaTrackGet(); if( RaDirectionGet() < 0 ) { // czy oś jest ustawiona w stronę Point1? @@ -1428,6 +1414,18 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) if( foundobject->MoverParameters->Couplers[ foundcoupler ].CouplingFlag == coupling::faux ) { // Ra: wpinamy się wirtualnym tylko jeśli znaleziony ma wirtualny sprzęg + if( ( foundcoupler == TMoverParameters::side::front ? + foundobject->PrevConnected : + foundobject->NextConnected ) + != this ) { + // but first break existing connection of the target, + // otherwise we risk leaving the target's connected vehicle with active one-side connection + foundobject->CouplersDettach( + 1.0, + ( foundcoupler == TMoverParameters::side::front ? + 1 : + -1 ) ); + } foundobject->MoverParameters->Attach( foundcoupler, mycoupler, this->MoverParameters, coupling::faux ); if( foundcoupler == TMoverParameters::side::front ) { @@ -1452,18 +1450,18 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance ) } } - // odległość do najbliższego pojazdu w linii prostej - // Ra: jeśli dwa samochody się mijają na odcinku przed zawrotką, to odległość między nimi nie może być liczona w linii prostej! - fTrackBlock = MoverParameters->Couplers[mycoupler].CoupleDist; - if( track->iCategoryFlag & 254 ) { - // jeśli samochód - if( distance > MoverParameters->Dim.L + foundobject->MoverParameters->Dim.L ) { - // przeskanowana odległość większa od długości pojazdów - // else if (ActDistCouplers[ mycoupler ].CoupleDist ); + } + if( ( false == TestFlag( track->iCategoryFlag, 1 ) ) + && ( distance > 50.0 ) ) { + // Ra: jeśli dwa samochody się mijają na odcinku przed zawrotką, to odległość między nimi nie może być liczona w linii prostej! + // NOTE: the distance is approximated, and additionally less accurate for cars heading in opposite direction + fTrackBlock = distance - ( 0.5 * ( MoverParameters->Dim.L + foundobject->MoverParameters->Dim.L ) ); } } else { @@ -2577,15 +2575,19 @@ bool TDynamicObject::Update(double dt, double dt1) tp.CategoryFlag = MyTrack->iCategoryFlag & 15; tp.DamageFlag = MyTrack->iDamageFlag; tp.QualityFlag = MyTrack->iQualityFlag; - if ((MoverParameters->Couplers[0].CouplingFlag > 0) && - (MoverParameters->Couplers[1].CouplingFlag > 0)) - { + + // couplers + if( ( MoverParameters->Couplers[ 0 ].CouplingFlag != coupling::faux ) + && ( MoverParameters->Couplers[ 1 ].CouplingFlag != coupling::faux ) ) { + MoverParameters->InsideConsist = true; } - else - { + else { + MoverParameters->InsideConsist = false; } + // + // napiecie sieci trakcyjnej // Ra 15-01: przeliczenie poboru prądu powinno być robione wcześniej, żeby na // tym etapie były diff --git a/EU07.cpp b/EU07.cpp index 78d26c69..5879c7e3 100644 --- a/EU07.cpp +++ b/EU07.cpp @@ -309,10 +309,7 @@ int main(int argc, char *argv[]) { std::string token(argv[i]); - if (token == "-modifytga") - Global::iModifyTGA = -1; - else if (token == "-e3d") - { + if (token == "-e3d") { if (Global::iConvertModels > 0) Global::iConvertModels = -Global::iConvertModels; else @@ -328,8 +325,12 @@ int main(int argc, char *argv[]) } else { - std::cout << "usage: " << std::string(argv[0]) << " [-s sceneryfilepath] " - << "[-v vehiclename] [-modifytga] [-e3d]" << std::endl; + std::cout + << "usage: " << std::string(argv[0]) + << " [-s sceneryfilepath]" + << " [-v vehiclename]" + << " [-e3d]" + << std::endl; return -1; } } @@ -438,37 +439,31 @@ int main(int argc, char *argv[]) if( !joyGetNumDevs() ) WriteLog( "No joystick" ); */ - if( Global::iModifyTGA < 0 ) { // tylko modyfikacja TGA, bez uruchamiania symulacji - Global::iMaxTextureSize = 64; //żeby nie zamulać pamięci - World.ModifyTGA(); // rekurencyjne przeglądanie katalogów - } - else { - if( Global::iConvertModels < 0 ) { - Global::iConvertModels = -Global::iConvertModels; - World.CreateE3D( "models\\" ); // rekurencyjne przeglądanie katalogów - World.CreateE3D( "dynamic\\", true ); - } // po zrobieniu E3D odpalamy normalnie scenerię, by ją zobaczyć + if( Global::iConvertModels < 0 ) { + Global::iConvertModels = -Global::iConvertModels; + World.CreateE3D( "models\\" ); // rekurencyjne przeglądanie katalogów + World.CreateE3D( "dynamic\\", true ); + } // po zrobieniu E3D odpalamy normalnie scenerię, by ją zobaczyć - Console::On(); // włączenie konsoli + Console::On(); // włączenie konsoli - try { - while( ( false == glfwWindowShouldClose( window ) ) - && ( true == World.Update() ) - && ( true == GfxRenderer.Render() ) ) { - glfwPollEvents(); - input::Keyboard.poll(); - if( true == Global::InputMouse ) { input::Mouse.poll(); } - if( true == Global::InputGamepad ) { input::Gamepad.poll(); } - } + try { + while( ( false == glfwWindowShouldClose( window ) ) + && ( true == World.Update() ) + && ( true == GfxRenderer.Render() ) ) { + glfwPollEvents(); + input::Keyboard.poll(); + if( true == Global::InputMouse ) { input::Mouse.poll(); } + if( true == Global::InputGamepad ) { input::Gamepad.poll(); } } - catch( std::bad_alloc const &Error ) { - - ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) ); - return -1; - } - - Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej) } + catch( std::bad_alloc const &Error ) { + + ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) ); + return -1; + } + + Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej) TPythonInterpreter::killInstance(); delete pConsole; diff --git a/Event.cpp b/Event.cpp index 42ee01c3..5461c74d 100644 --- a/Event.cpp +++ b/Event.cpp @@ -140,10 +140,7 @@ void TEvent::Conditions(cParser *parser, std::string s) void TEvent::Load(cParser *parser, vector3 *org) { - int i; - int ti; std::string token; - //string str; bEnabled = true; // zmieniane na false dla eventów używanych do skanowania sygnałów @@ -247,47 +244,47 @@ void TEvent::Load(cParser *parser, vector3 *org) *parser >> token; Conditions(parser, token); // sprawdzanie warunków break; - case tp_CopyValues: - Params[9].asText = NULL; + case tp_CopyValues: { + Params[9].asText = nullptr; iFlags = update_memstring | update_memval1 | update_memval2; // normalanie trzy - i = 0; + int paramidx { 0 }; parser->getTokens(); *parser >> token; // nazwa drugiej komórki (źródłowej) - while (token.compare("endevent") != 0) - { - switch (++i) + while (token.compare("endevent") != 0) { + + switch (++paramidx) { // znaczenie kolejnych parametrów case 1: // nazwa drugiej komórki (źródłowej) Params[9].asText = new char[token.size() + 1]; // usuwane i zamieniane na wskaźnik strcpy(Params[9].asText, token.c_str()); break; case 2: // maska wartości - iFlags = stol_def(token, - (update_memstring | update_memval1 | update_memval2)); + iFlags = stol_def(token, (update_memstring | update_memval1 | update_memval2)); break; } parser->getTokens(); *parser >> token; } break; - case tp_WhoIs: + } + case tp_WhoIs: { iFlags = update_memstring | update_memval1 | update_memval2; // normalanie trzy - i = 0; + int paramidx { 0 }; parser->getTokens(); *parser >> token; // nazwa drugiej komórki (źródłowej) - while (token.compare("endevent") != 0) - { - switch (++i) - { // znaczenie kolejnych parametrów - case 1: // maska wartości - iFlags = stol_def(token, - (update_memstring | update_memval1 | update_memval2)); - break; + while( token.compare( "endevent" ) != 0 ) { + switch( ++paramidx ) { // znaczenie kolejnych parametrów + case 1: // maska wartości + iFlags = stol_def( token, ( update_memstring | update_memval1 | update_memval2 ) ); + break; + default: + break; } parser->getTokens(); *parser >> token; } break; + } case tp_GetValues: case tp_LogValues: parser->getTokens(); //"endevent" @@ -384,25 +381,27 @@ void TEvent::Load(cParser *parser, vector3 *org) parser->getTokens(); *parser >> token; break; - case tp_Lights: - i = 0; - do - { + case tp_Lights: { + int paramidx { 0 }; + do { parser->getTokens(); *parser >> token; - if (token.compare("endevent") != 0) - { - // str = AnsiString(token.c_str()); - if (i < 8) - Params[i].asdouble = atof(token.c_str()); // teraz może mieć ułamek - i++; + if( token.compare( "endevent" ) != 0 ) { + + if( paramidx < 8 ) { + Params[ paramidx ].asdouble = atof( token.c_str() ); // teraz może mieć ułamek + ++paramidx; + } + else { + ErrorLog( "Bad event: lights event \"" + asName + "\" with more than 8 parameters" ); + } } - } while (token.compare("endevent") != 0); + } while( token.compare( "endevent" ) != 0 ); break; + } case tp_Visible: // zmiana wyświetlania obiektu parser->getTokens(); *parser >> token; - // str = AnsiString(token.c_str()); Params[0].asInt = atoi(token.c_str()); parser->getTokens(); *parser >> token; @@ -410,7 +409,6 @@ void TEvent::Load(cParser *parser, vector3 *org) case tp_Velocity: parser->getTokens(); *parser >> token; - // str = AnsiString(token.c_str()); Params[0].asdouble = atof(token.c_str()) * 0.28; parser->getTokens(); *parser >> token; @@ -544,38 +542,46 @@ void TEvent::Load(cParser *parser, vector3 *org) parser->getTokens(); *parser >> token; break; - case tp_Multiple: - i = 0; - ti = 0; // flaga dla else + case tp_Multiple: { + int paramidx { 0 }; + bool ti { false }; // flaga dla else parser->getTokens(); *parser >> token; - // str = AnsiString(token.c_str()); - while (token != "endevent" && token != "condition" && - token != "randomdelay") - { - if ((token.substr(0, 5) != "none_") ? (i < 8) : false) - { // eventy rozpoczynające się od "none_" są ignorowane - if (token != "else") - { - Params[i].asText = new char[token.size() + 1]; - strcpy(Params[i].asText, token.c_str()); - if (ti) - iFlags |= conditional_else << i; // oflagowanie dla eventów "else" - i++; + + while( ( token != "endevent" ) + && ( token != "condition" ) + && ( token != "randomdelay" ) ) { + + if( token != "else" ) { + if( token.substr( 0, 5 ) != "none_" ) { + // eventy rozpoczynające się od "none_" są ignorowane + if( paramidx < 8 ) { + Params[ paramidx ].asText = new char[ token.size() + 1 ]; + strcpy( Params[ paramidx ].asText, token.c_str() ); + if( ti ) { + // oflagowanie dla eventów "else" + iFlags |= conditional_else << paramidx; + } + ++paramidx; + } + else { + ErrorLog( "Bad event: multi-event \"" + asName + "\" with more than 8 events; discarding link to event \"" + token + "\"" ); + } + } + else { + WriteLog( "Multi-event \"" + asName + "\" ignored link to event \"" + token + "\"" ); } - else - ti = !ti; // zmiana flagi dla słowa "else" } - else if (i >= 8) - ErrorLog("Bad event: \"" + token + "\" ignored in multiple \"" + asName + "\"!"); - else - WriteLog("Event \"" + token + "\" ignored in multiple \"" + asName + "\"!"); + else { + // zmiana flagi dla słowa "else" + ti = !ti; + } parser->getTokens(); *parser >> token; - // str = AnsiString(token.c_str()); } Conditions(parser, token); // sprawdzanie warunków break; + } case tp_Voltage: // zmiana napięcia w zasilaczu (TractionPowerSource) case tp_Friction: // zmiana przyczepnosci na scenerii parser->getTokens(); diff --git a/Globals.cpp b/Globals.cpp index 780b5697..5702dc55 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -55,11 +55,8 @@ double Global::fTimeAngleDeg = 0.0; // godzina w postaci kąta float Global::fClockAngleDeg[6]; // kąty obrotu cylindrów dla zegara cyfrowego std::string Global::szTexturesTGA = ".tga"; // lista tekstur od TGA std::string Global::szTexturesDDS = ".dds"; // lista tekstur od DDS -int Global::iKeyLast = 0; // ostatnio naciśnięty klawisz w celu logowania int Global::iPause = 0; // 0x10; // globalna pauza ruchu bool Global::bActive = true; // czy jest aktywnym oknem -int Global::iErorrCounter = 0; // licznik sprawdzań do śledzenia błędów OpenGL -int Global::iTextures = 0; // licznik użytych tekstur TWorld *Global::pWorld = NULL; cParser *Global::pParser = NULL; TCamera *Global::pCamera = NULL; // parametry kamery @@ -74,8 +71,6 @@ double Global::pCameraRotation; double Global::pCameraRotationDeg; std::vector Global::FreeCameraInit; std::vector Global::FreeCameraInitAngle; -float Global::Background[3] = {0.2f, 0.4f, 0.33f}; -GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f}; GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f}; double Global::fFogStart = 1700; double Global::fFogEnd = 2000; @@ -122,10 +117,6 @@ bool Global::bEnableTraction = true; bool Global::bLoadTraction = true; bool Global::bLiveTraction = true; float Global::AnisotropicFiltering = 8.0f; // requested level of anisotropic filtering. TODO: move it to renderer object -int Global::iDefaultFiltering = 9; // domyślne rozmywanie tekstur TGA bez alfa -int Global::iBallastFiltering = 9; // domyślne rozmywanie tekstur podsypki -int Global::iRailProFiltering = 5; // domyślne rozmywanie tekstur szyn -int Global::iDynamicFiltering = 5; // domyślne rozmywanie tekstur pojazdów bool Global::bUseVBO = true; // czy jest VBO w karcie graficznej (czy użyć) std::string Global::LastGLError; GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury @@ -138,7 +129,6 @@ bool Global::bGlutFont = false; // czy tekst generowany przez GLUT32.DLL //int Global::iConvertModels = 7; // tworzenie plików binarnych, +2-optymalizacja transformów int Global::iConvertModels{ 0 }; // temporary override, to prevent generation of .e3d not compatible with old exe int Global::iSlowMotionMask = -1; // maska wyłączanych właściwości dla zwiększenia FPS -int Global::iModifyTGA = 7; // czy korygować pliki TGA dla szybszego wczytywania // bool Global::bTerrainCompact=true; //czy zapisać teren w pliku TAnimModel *Global::pTerrainCompact = NULL; // do zapisania terenu w pliku std::string Global::asTerrainModel = ""; // nazwa obiektu terenu do zapisania w pliku @@ -146,17 +136,13 @@ double Global::fFpsAverage = 20.0; // oczekiwana wartosć FPS double Global::fFpsDeviation = 5.0; // odchylenie standardowe FPS double Global::fFpsMin = 30.0; // dolna granica FPS, przy której promień scenerii będzie zmniejszany double Global::fFpsMax = 65.0; // górna granica FPS, przy której promień scenerii będzie zwiększany -double Global::fFpsRadiusMax = 3000.0; // maksymalny promień renderowania -int Global::iFpsRadiusMax = 225; // maksymalny promień renderowania -double Global::fRadiusFactor = 1.1; // współczynnik jednorazowej zmiany promienia scenerii +bool Global::FullPhysics { true }; // full calculations performed for each simulation step // parametry testowe (do testowania scenerii i obiektów) bool Global::bWireFrame = false; bool Global::bSoundEnabled = true; int Global::iWriteLogEnabled = 3; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów bool Global::MultipleLogs{ false }; -bool Global::bManageNodes = true; -bool Global::bDecompressDDS = false; // czy programowa dekompresja DDS // parametry do kalibracji // kolejno współczynniki dla potęg 0, 1, 2, 3 wartości odczytanej z urządzenia @@ -180,10 +166,8 @@ int Global::iPoKeysPWM[7] = {0, 1, 2, 3, 4, 5, 6}; // bool Global::bTimeChange=false; //Ra: ZiomalCl wyłączył starą wersję nocy // bool Global::bRenderAlpha=true; //Ra: wywaliłam tę flagę bool Global::bnewAirCouplers = true; -bool Global::bDoubleAmbient = false; // podwójna jasność ambient double Global::fTimeSpeed = 1.0; // przyspieszenie czasu, zmienna do testów bool Global::bHideConsole = false; // hunter-271211: ukrywanie konsoli -int Global::iBpp = 32; // chyba już nie używa się kart, na których 16bpp coś poprawi //randomizacja std::mt19937 Global::random_engine = std::mt19937(std::time(NULL)); // maciek001: konfiguracja wstępna portu COM @@ -276,13 +260,6 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(1, false); Parser >> Global::fDistanceFactor; } - else if (token == "bpp") - { - - Parser.getTokens(); - Parser >> token; - Global::iBpp = (token == "32" ? 32 : 16); - } else if (token == "fullscreen") { @@ -332,11 +309,11 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(); Parser >> WriteLogFlag; } - else if (token == "physicsdeactivation") + else if (token == "fullphysics") { // McZapkie-291103 - usypianie fizyki Parser.getTokens(); - Parser >> PhysicActivationFlag; + Parser >> Global::FullPhysics; } else if (token == "debuglog") { @@ -409,18 +386,6 @@ void Global::ConfigParse(cParser &Parser) Parser >> token; Global::asSky = (token == "yes" ? "1" : "0"); } - else if (token == "managenodes") - { - - Parser.getTokens(); - Parser >> Global::bManageNodes; - } - else if (token == "decompressdds") - { - - Parser.getTokens(); - Parser >> Global::bDecompressDDS; - } else if (token == "defaultext") { // ShaXbee - domyslne rozszerzenie tekstur @@ -444,30 +409,6 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(); Parser >> Global::bnewAirCouplers; } - else if (token == "defaultfiltering") - { - - Parser.getTokens(1, false); - Parser >> Global::iDefaultFiltering; - } - else if (token == "ballastfiltering") - { - - Parser.getTokens(1, false); - Parser >> Global::iBallastFiltering; - } - else if (token == "railprofiltering") - { - - Parser.getTokens(1, false); - Parser >> Global::iRailProFiltering; - } - else if (token == "dynamicfiltering") - { - - Parser.getTokens(1, false); - Parser >> Global::iDynamicFiltering; - } else if( token == "anisotropicfiltering" ) { Parser.getTokens( 1, false ); @@ -513,12 +454,6 @@ void Global::ConfigParse(cParser &Parser) else if (size <= 8192) { Global::iMaxTextureSize = 8192; } else { Global::iMaxTextureSize = 16384; } } - else if (token == "doubleambient") - { - // podwójna jasność ambient - Parser.getTokens(); - Parser >> Global::bDoubleAmbient; - } else if (token == "movelight") { // numer dnia w roku albo -1 @@ -624,12 +559,6 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(1, false); Parser >> Global::iSlowMotionMask; } - else if (token == "modifytga") - { - // czy korygować pliki TGA dla szybszego wczytywania - Parser.getTokens(1, false); - Parser >> Global::iModifyTGA; - } else if (token == "hideconsole") { // hunter-271211: ukrywanie konsoli @@ -654,12 +583,6 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(1, false); Parser >> Global::fFpsDeviation; } - else if (token == "fpsradiusmax") - { - // maksymalny promień renderowania - Parser.getTokens(1, false); - Parser >> Global::fFpsRadiusMax; - } else if (token == "calibratein") { // parametry kalibracji wejść @@ -807,14 +730,6 @@ void Global::ConfigParse(cParser &Parser) Parser >> token; TPythonInterpreter::getInstance()->setScreenRendererPriority(token.c_str()); } - else if (token == "background") - { - - Parser.getTokens(3, false); - Parser >> Global::Background[0] // r - >> Global::Background[1] // g - >> Global::Background[2]; // b - } else if( token == "input.gamepad" ) { // czy grupować eventy o tych samych nazwach Parser.getTokens(); diff --git a/Globals.h b/Globals.h index 37fefd65..77abf302 100644 --- a/Globals.h +++ b/Globals.h @@ -130,25 +130,13 @@ class TTranscript float fHide; // czas ukrycia/usunięcia std::string asText; // tekst gotowy do wyświetlenia (usunięte znaczniki czasu) bool bItalic; // czy kursywa (dźwięk nieistotny dla prowadzącego) -/* - int iNext; // następna używana linijka, żeby nie przestawiać fizycznie tabeli -*/ }; -/* -#define MAX_TRANSCRIPTS 30 -*/ class TTranscripts { // klasa obsługująca napisy do dźwięków -/* - TTranscript aLines[MAX_TRANSCRIPTS]; // pozycje na napisy do wyświetlenia -*/ public: std::deque aLines; -/* - int iCount; // liczba zajętych pozycji - int iStart; // pierwsza istotna pozycja w tabeli, żeby sortować przestawiając numerki -*/ + private: float fRefreshTime; @@ -166,7 +154,6 @@ class Global { private: public: - // double Global::tSinceStart; static int Keys[MaxKeys]; static bool RealisticControlMode; // controls ability to steer the vehicle from outside views static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie @@ -179,23 +166,17 @@ class Global static int iWindowWidth; static int iWindowHeight; static float fDistanceFactor; - static int iBpp; static bool bFullScreen; static bool VSync; static bool bFreeFly; - // float RunningTime; static bool bWireFrame; static bool bSoundEnabled; // McZapkie-131202 - // static bool bRenderAlpha; static bool bAdjustScreenFreq; static bool bEnableTraction; static bool bLoadTraction; static float fFriction; static bool bLiveTraction; - static bool bManageNodes; - static bool bDecompressDDS; - // bool WFreeFly; static float Global::fMouseXScale; static float Global::fMouseYScale; static double fFogStart; @@ -217,11 +198,8 @@ class Global static int iWriteLogEnabled; // maska bitowa: 1-zapis do pliku, 2-okienko static bool MultipleLogs; // McZapkie-221002: definicja swiatla dziennego - static float Background[3]; - static GLfloat AtmoColor[]; static GLfloat FogColor[]; static float Overcast; - // static bool bTimeChange; // TODO: put these things in the renderer static float BaseDrawRange; @@ -236,19 +214,22 @@ class Global float depth; float distance; } shadowtune; + static bool bUseVBO; // czy jest VBO w karcie graficznej + static float AnisotropicFiltering; // requested level of anisotropic filtering. TODO: move it to renderer object + static int ScreenWidth; // current window dimensions. TODO: move it to renderer + static int ScreenHeight; + static float ZoomFactor; // determines current camera zoom level. TODO: move it to the renderer + static float FieldOfView; // vertical field of view for the camera. TODO: move it to the renderer + static GLint iMaxTextureSize; // maksymalny rozmiar tekstury + static int iMultisampling; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px + static bool FullPhysics; // full calculations performed for each simulation step static int iSlowMotion; static TDynamicObject *changeDynObj; static double ABuDebug; static std::string asSky; static bool bnewAirCouplers; // Ra: nowe zmienne globalne - static float AnisotropicFiltering; // requested level of anisotropic filtering. TODO: move it to renderer object - static int iDefaultFiltering; // domyślne rozmywanie tekstur TGA - static int iBallastFiltering; // domyślne rozmywanie tekstury podsypki - static int iRailProFiltering; // domyślne rozmywanie tekstury szyn - static int iDynamicFiltering; // domyślne rozmywanie tekstur pojazdów - static bool bUseVBO; // czy jest VBO w karcie graficznej static std::string LastGLError; static int iFeedbackMode; // tryb pracy informacji zwrotnej static int iFeedbackPort; // dodatkowy adres dla informacji zwrotnych @@ -259,18 +240,12 @@ class Global static GLFWwindow *window; static bool shiftState; //m7todo: brzydko static bool ctrlState; - static int ScreenWidth; // current window dimensions. TODO: move it to renderer - static int ScreenHeight; - static float ZoomFactor; // determines current camera zoom level. TODO: move it to the renderer - static float FieldOfView; // vertical field of view for the camera. TODO: move it to the renderer static int iCameraLast; static std::string asVersion; // z opisem - static GLint iMaxTextureSize; // maksymalny rozmiar tekstury static bool ControlPicking; // indicates controls pick mode is active static bool InputMouse; // whether control pick mode can be activated static int iTextMode; // tryb pracy wyświetlacza tekstowego static int iScreenMode[12]; // numer ekranu wyświetlacza tekstowego - static bool bDoubleAmbient; // podwójna jasność ambient static double fMoveLight; // numer dnia w roku albo -1 static bool FakeLight; // toggle between fixed and dynamic daylight static bool bSmoothTraction; // wygładzanie drutów @@ -281,18 +256,13 @@ class Global static double fLatitudeDeg; // szerokość geograficzna static std::string szTexturesTGA; // lista tekstur od TGA static std::string szTexturesDDS; // lista tekstur od DDS - static int iMultisampling; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px static bool DLFont; // switch indicating presence of basic font static bool bGlutFont; // tekst generowany przez GLUT - static int iKeyLast; // ostatnio naciśnięty klawisz w celu logowania static int iPause; // globalna pauza ruchu: b0=start,b1=klawisz,b2=tło,b3=lagi,b4=wczytywanie static bool bActive; // czy jest aktywnym oknem static int iConvertModels; // tworzenie plików binarnych - static int iErorrCounter; // licznik sprawdzań do śledzenia błędów OpenGL static bool bInactivePause; // automatyczna pauza, gdy okno nieaktywne - static int iTextures; // licznik użytych tekstur static int iSlowMotionMask; // maska wyłączanych właściwości - static int iModifyTGA; // czy korygować pliki TGA dla szybszego wczytywania static bool bHideConsole; // hunter-271211: ukrywanie konsoli static TWorld *pWorld; // wskaźnik na świat do usuwania pojazdów @@ -304,9 +274,6 @@ class Global static double fFpsDeviation; // odchylenie standardowe FPS static double fFpsMin; // dolna granica FPS, przy której promień scenerii będzie zmniejszany static double fFpsMax; // górna granica FPS, przy której promień scenerii będzie zwiększany - static double fFpsRadiusMax; // maksymalny promień renderowania - static int iFpsRadiusMax; // maksymalny promień renderowania w rozmiarze tabeli sektorów - static double fRadiusFactor; // współczynnik zmiany promienia static TCamera *pCamera; // parametry kamery static TDynamicObject *pUserDynamic; // pojazd użytkownika, renderowany bez trzęsienia static double fCalibrateIn[6][6]; // parametry kalibracyjne wejść z pulpitu diff --git a/Ground.cpp b/Ground.cpp index 8c2a349d..36173b84 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -1870,7 +1870,7 @@ bool TGround::Init(std::string File) } else { - ErrorLog("Scene parsing error in file \"" + parser.Name() + "\" (line " + std::to_string( parser.Line() ) + "), unexpected token \"" + token + "\""); + ErrorLog("Bad node: node parsing error, encountered in file \"" + parser.Name() + "\" (line " + std::to_string( parser.Line() - 1 ) + ")"); // break; } } @@ -2022,10 +2022,13 @@ bool TGround::Init(std::string File) { // Ra: ustawienie parametrów OpenGL przeniesione do FirstInit WriteLog("Scenery atmo definition"); parser.getTokens(3); +/* + // disabled, no longer used parser >> Global::AtmoColor[0] >> Global::AtmoColor[1] >> Global::AtmoColor[2]; +*/ parser.getTokens(2); parser >> Global::fFogStart @@ -2175,11 +2178,11 @@ bool TGround::Init(std::string File) { // możliwość przedefiniowania parametrów w scenerii Global::ConfigParse(parser); // parsowanie dodatkowych ustawień } - else if (str != "") - { // pomijanie od nierozpoznanej komendy do jej zakończenia - if ((token.length() > 2) && (atof(token.c_str()) == 0.0)) - { // jeśli nie liczba, to spróbować pominąć komendę - WriteLog("Unrecognized command: " + str); + else if (str != "") { + // pomijanie od nierozpoznanej komendy do jej zakończenia + if ((token.length() > 2) && (atof(token.c_str()) == 0.0)) { + // jeśli nie liczba, to spróbować pominąć komendę + WriteLog( "Unrecognized command: \"" + str + "\" encountered in file \"" + parser.Name() + "\" (line " + std::to_string( parser.Line() - 1 ) + ")" ); str = "end" + str; do { @@ -2188,8 +2191,10 @@ bool TGround::Init(std::string File) parser >> token; } while ((token != "") && (token.compare(str.c_str()) != 0)); } - else // jak liczba to na pewno błąd - Error("Unrecognized command: " + str); + else { + // jak liczba to na pewno błąd + ErrorLog( "Unrecognized command: \"" + str + "\" encountered in file \"" + parser.Name() + "\" (line " + std::to_string( parser.Line() - 1 ) + ")" ); + } } token = ""; @@ -3381,46 +3386,76 @@ bool TGround::CheckQuery() } } break; - case tp_WhoIs: // pobranie nazwy pociągu do komórki pamięci - if (tmpEvent->iFlags & update_load) - { // jeśli pytanie o ładunek - if (tmpEvent->iFlags & update_memadd) // jeśli typ pojazdu + case tp_WhoIs: { + // pobranie nazwy pociągu do komórki pamięci + if (tmpEvent->iFlags & update_load) { + // jeśli pytanie o ładunek + if( tmpEvent->iFlags & update_memadd ) { + // jeśli typ pojazdu + // TODO: define and recognize individual request types + auto const owner = ( + ( ( tmpEvent->Activator->Mechanik != nullptr ) && ( tmpEvent->Activator->Mechanik->Primary() ) ) ? + tmpEvent->Activator->Mechanik : + tmpEvent->Activator->ctOwner ); + auto const consistbrakelevel = ( + owner != nullptr ? + owner->fReady : + -1.0 ); + tmpEvent->Params[ 9 ].asMemCell->UpdateValues( tmpEvent->Activator->MoverParameters->TypeName, // typ pojazdu + consistbrakelevel, 0, // na razie nic - 0, // na razie nic - tmpEvent->iFlags & - (update_memstring | update_memval1 | update_memval2)); - else // jeśli parametry ładunku + tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) ); + + WriteLog( + "whois request (" + to_string( tmpEvent->iFlags ) + ") " + + "[name: " + tmpEvent->Activator->MoverParameters->TypeName + "], " + + "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], " + + "[]" ); + } + else { + // jeśli parametry ładunku tmpEvent->Params[ 9 ].asMemCell->UpdateValues( tmpEvent->Activator->MoverParameters->LoadType, // nazwa ładunku tmpEvent->Activator->MoverParameters->Load, // aktualna ilość tmpEvent->Activator->MoverParameters->MaxLoad, // maksymalna ilość - tmpEvent->iFlags & - (update_memstring | update_memval1 | update_memval2)); + tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) ); + + WriteLog( + "whois request (" + to_string( tmpEvent->iFlags ) + ") " + + "[load type: " + tmpEvent->Activator->MoverParameters->LoadType + "], " + + "[current load: " + to_string( tmpEvent->Activator->MoverParameters->Load, 2 ) + "], " + + "[max load: " + to_string( tmpEvent->Activator->MoverParameters->MaxLoad, 2 ) + "]" ); + } } else if (tmpEvent->iFlags & update_memadd) { // jeśli miejsce docelowe pojazdu tmpEvent->Params[ 9 ].asMemCell->UpdateValues( tmpEvent->Activator->asDestination, // adres docelowy tmpEvent->Activator->DirectionGet(), // kierunek pojazdu względem czoła składu (1=zgodny,-1=przeciwny) - tmpEvent->Activator->MoverParameters ->Power, // moc pojazdu silnikowego: 0 dla wagonu + tmpEvent->Activator->MoverParameters->Power, // moc pojazdu silnikowego: 0 dla wagonu tmpEvent->iFlags & (update_memstring | update_memval1 | update_memval2)); + + WriteLog( + "whois request (" + to_string( tmpEvent->iFlags ) + ") " + + "[destination: " + tmpEvent->Activator->asDestination + "], " + + "[direction: " + to_string( tmpEvent->Activator->DirectionGet() ) + "], " + + "[engine power: " + to_string( tmpEvent->Activator->MoverParameters->Power, 2 ) + "]" ); } else if (tmpEvent->Activator->Mechanik) if (tmpEvent->Activator->Mechanik->Primary()) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! tmpEvent->Params[ 9 ].asMemCell->UpdateValues( tmpEvent->Activator->Mechanik->TrainName(), - tmpEvent->Activator->Mechanik->StationCount() - - tmpEvent->Activator->Mechanik - ->StationIndex(), // ile przystanków do końca + tmpEvent->Activator->Mechanik->StationCount() - tmpEvent->Activator->Mechanik->StationIndex(), // ile przystanków do końca tmpEvent->Activator->Mechanik->IsStop() ? 1 : 0, // 1, gdy ma tu zatrzymanie tmpEvent->iFlags); WriteLog("Train detected: " + tmpEvent->Activator->Mechanik->TrainName()); } break; + } case tp_LogValues: // zapisanie zawartości komórki pamięci do logu if (tmpEvent->Params[9].asMemCell) // jeśli była podana nazwa komórki WriteLog("Memcell \"" + tmpEvent->asNodeName + "\": " + diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index bcb743c9..c53b59f3 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -191,8 +191,6 @@ static int const sound_relay = 16; static int const sound_manyrelay = 32; static int const sound_brakeacc = 64; -static bool PhysicActivationFlag = false; - //szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType //zamienione na flagi bitowe, aby szybko wybierać grupę (np. EZT+SZT) static int const dt_Default = 0; @@ -813,7 +811,6 @@ public: voltage }; #endif - int ScanCounter = 0; /*pomocnicze do skanowania sprzegow*/ bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/ int SoundFlag = 0; /*!o patrz stale sound_ */ double DistCounter = 0.0; /*! licznik kilometrow */ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 088e0074..b1c7251c 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -473,7 +473,7 @@ bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters * coupler.Connected = ConnectTo; // tak podpiąć (do siebie) zawsze można, najwyżej będzie wirtualny CouplerDist( ConnectNo ); // przeliczenie odległości pomiędzy sprzęgami - if (CouplingType == ctrain_virtual) + if (CouplingType == coupling::faux) return false; // wirtualny więcej nic nie robi auto &othercoupler = ConnectTo->Couplers[ coupler.ConnectedNr ]; @@ -555,21 +555,29 @@ bool TMoverParameters::Dettach(int ConnectNo) return false; // jeszcze nie rozłączony }; -void TMoverParameters::SetCoupleDist() -{ // przeliczenie odległości sprzęgów - if (Couplers[0].Connected) - { - CouplerDist(0); - if (CategoryFlag & 2) - { // Ra: dla samochodów zderzanie kul to za mało +// przeliczenie odległości sprzęgów +void TMoverParameters::SetCoupleDist() { +/* + double const MaxDist = 100.0; // 2x average max proximity distance. TODO: rearrange ito something more elegant +*/ + for( int coupleridx = 0; coupleridx <= 1; ++coupleridx ) { + + if( Couplers[ coupleridx ].Connected == nullptr ) { continue; } + + CouplerDist( coupleridx ); + if( CategoryFlag & 2 ) { + // Ra: dla samochodów zderzanie kul to za mało + // NOTE: whatever calculation was supposed to be here, ain't } - } - if (Couplers[1].Connected) - { - CouplerDist(1); - if (CategoryFlag & 2) - { // Ra: dla samochodów zderzanie kul to za mało +/* + if( ( Couplers[ coupleridx ].CouplingFlag == coupling::faux ) + && ( Couplers[ coupleridx ].CoupleDist > MaxDist ) ) { + // zerwij kontrolnie wirtualny sprzeg + // Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest wirtualny + Couplers[ coupleridx ].Connected = nullptr; + Couplers[ coupleridx ].ConnectedNr = 2; } +*/ } }; @@ -3725,14 +3733,12 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) else { Voltage = 0; } - //if (Mains && /*(abs(CabNo) < 2) &&*/ ( - // EngineType == ElectricInductionMotor)) // potem ulepszyc! pantogtrafy! - // Voltage = RunningTraction.TractionVoltage; if (Power > 0) FTrain = TractionForce(dt); else FTrain = 0; + Fb = BrakeForce(RunningTrack); Fwheels = FTrain - Fb * Sign(V); if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test @@ -3785,9 +3791,6 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) // McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty // ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam - // zakomentowalem PhysicActivationFlag bo cos nie dzialalo i fizyka byla liczona zawsze. - // if (PhysicActivationFlag) - //{ if ((CabNo == 0) && (Vel < 0.0001) && (abs(AccS) < 0.0001) && (TrainType != dt_EZT)) { if (!PhysicActivation) @@ -3806,7 +3809,6 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) } else PhysicActivation = true; - //}; } double TMoverParameters::BrakeForceR(double ratio, double velocity) @@ -3965,8 +3967,8 @@ double TMoverParameters::Adhesive(double staticfriction) } // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 return adhesion; -*/ - /* //wersja druga + + //wersja druga if( true == SlippingWheels ) { if( true == SandDose ) { adhesion = 0.48; } @@ -3977,12 +3979,15 @@ double TMoverParameters::Adhesive(double staticfriction) if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); } else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); } } - adhesion *= ( 11.0 - 2 * Random() ) / 10.0; */ +// adhesion *= ( 0.9 + 0.2 * Random() ); +*/ //wersja3 by youBy - uwzględnia naturalne mikropoślizgi i wpływ piasecznicy, usuwa losowość z pojazdu double Vwheels = nrot * M_PI * WheelDiameter; // predkosc liniowa koła wynikająca z obrotowej double deltaV = V - Vwheels; //poślizg - różnica prędkości w punkcie styku koła i szyny deltaV = std::max(0.0, std::abs(deltaV) - 0.25); //mikropoślizgi do ok. 0,25 m/s nie zrywają przyczepności - adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose? sandfactor : 1) - (1 - adh_factor)*(deltaV / (deltaV + slipfactor))); + Vwheels = std::abs( Vwheels ); + adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose? sandfactor : 1) - (1 - adh_factor)*(deltaV / (deltaV + slipfactor))); + return adhesion; } @@ -4052,24 +4057,11 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt) // blablabla // ABu: proby znalezienia problemu ze zle odbijajacymi sie skladami //if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then - if ((Couplers[CouplerN].CouplingFlag == ctrain_virtual) && (Couplers[CouplerN].CoupleDist > 0)) - { - CF = 0; // kontrola zderzania sie - OK - ScanCounter++; - if ((newdist > MaxDist) || ((ScanCounter > MaxCount) && (newdist > MinDist))) - //if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then - { // zerwij kontrolnie wirtualny sprzeg - // Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest - // wirtualny -// Couplers[CouplerN].Connected = NULL; - ScanCounter = static_cast(Random(500.0)); // Q: TODO: cy dobrze przetlumaczone? - // WriteLog(FloatToStr(ScanCounter)); - } - } - else - { - if (Couplers[CouplerN].CouplingFlag == ctrain_virtual) - { + if( ( Couplers[ CouplerN ].CouplingFlag != coupling::faux ) + || ( Couplers[ CouplerN ].CoupleDist < 0 ) ) { + + if( Couplers[ CouplerN ].CouplingFlag == coupling::faux ) { + BetaAvg = Couplers[CouplerN].beta; Fmax = (Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB) * CouplerTune; } @@ -4145,18 +4137,20 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt) //***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie} { Couplers[CouplerN].CheckCollision = true; - if ((Couplers[CouplerN].CouplerType == Automatic) && - (Couplers[CouplerN].CouplingFlag == - 0)) // sprzeganie wagonow z samoczynnymi sprzegami} + if( ( Couplers[ CouplerN ].CouplerType == Automatic ) + && ( Couplers[ CouplerN ].CouplingFlag == coupling::faux ) ) { + // sprzeganie wagonow z samoczynnymi sprzegami} // CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic; - Couplers[CouplerN].CouplingFlag = - ctrain_coupler | ctrain_pneumatic | ctrain_controll; // EN57 + // EN57 + Couplers[ CouplerN ].CouplingFlag = coupling::coupler | coupling::brakehose | coupling::mainhose | coupling::control; + } } } } - if (Couplers[CouplerN].CouplingFlag != ctrain_virtual) + if( Couplers[ CouplerN ].CouplingFlag != coupling::faux ) { // uzgadnianie prawa Newtona - Couplers[CouplerN].Connected->Couplers[1 - CouplerN].CForce = -CF; + Couplers[ CouplerN ].Connected->Couplers[ 1 - CouplerN ].CForce = -CF; + } return CF; } @@ -6806,7 +6800,6 @@ void TMoverParameters::LoadFIZ_Wheels( std::string const &line ) { extract_value( TrackW, "Tw", line, "" ); extract_value( AxleInertialMoment, "AIM", line, "" ); - if( AxleInertialMoment <= 0.0 ) { AxleInertialMoment = 1.0; } extract_value( AxleArangement, "Axle", line, "" ); NPoweredAxles = s2NPW( AxleArangement ); @@ -6814,11 +6807,21 @@ void TMoverParameters::LoadFIZ_Wheels( std::string const &line ) { BearingType = ( extract_value( "BearingType", line ) == "Roll" ) ? - 1 : - 0; + 1 : + 0; extract_value( ADist, "Ad", line, "" ); extract_value( BDist, "Bd", line, "" ); + + if( AxleInertialMoment <= 0.0 ) { +/* + AxleInertialMoment = 1.0; +*/ + // approximation formula by youby + auto const k = 472.0; // arbitrary constant + AxleInertialMoment = k / 4.0 * std::pow( WheelDiameter, 4.0 ) * NAxles; + Mred = k * std::pow( WheelDiameter, 2.0 ) * NAxles; + } } void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { diff --git a/McZapkie/mctools.cpp b/McZapkie/mctools.cpp index f249de8f..2b63e841 100644 --- a/McZapkie/mctools.cpp +++ b/McZapkie/mctools.cpp @@ -19,6 +19,7 @@ Copyright (C) 2007-2014 Maciej Cierniak bool DebugModeFlag = false; bool FreeFlyModeFlag = false; +bool EditorModeFlag = true; bool DebugCameraFlag = false; double Max0R(double x1, double x2) diff --git a/McZapkie/mctools.h b/McZapkie/mctools.h index 75a263fb..1110e5f6 100644 --- a/McZapkie/mctools.h +++ b/McZapkie/mctools.h @@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/. extern bool DebugModeFlag; extern bool FreeFlyModeFlag; +extern bool EditorModeFlag; extern bool DebugCameraFlag; /*funkcje matematyczne*/ diff --git a/Timer.cpp b/Timer.cpp index 1ddd600b..e78b50a7 100644 --- a/Timer.cpp +++ b/Timer.cpp @@ -66,9 +66,9 @@ void ResetTimers() }; LONGLONG fr, count, oldCount; -// LARGE_INTEGER fr,count; -void UpdateTimers(bool pause) -{ + +void UpdateTimers(bool pause) { + QueryPerformanceFrequency((LARGE_INTEGER *)&fr); QueryPerformanceCounter((LARGE_INTEGER *)&count); DeltaRenderTime = double(count - oldCount) / double(fr); @@ -78,18 +78,14 @@ void UpdateTimers(bool pause) fSoundTimer += DeltaTime; if (fSoundTimer > 0.1) fSoundTimer = 0.0; - /* - double CurrentTime= double(count)/double(fr);//GetTickCount(); - DeltaTime= (CurrentTime-OldTime); - OldTime= CurrentTime; - */ + if (DeltaTime > 1.0) DeltaTime = 1.0; } else DeltaTime = 0.0; // wszystko stoi, bo czas nie płynie - oldCount = count; + oldCount = count; // Keep track of the time lapse and frame count #if _WIN32_WINNT >= _WIN32_WINNT_VISTA double fTime = ::GetTickCount64() * 0.001f; // Get current time in seconds @@ -106,6 +102,7 @@ void UpdateTimers(bool pause) } fSimulationTime += DeltaTime; }; -}; + +}; // namespace timer //--------------------------------------------------------------------------- diff --git a/Track.cpp b/Track.cpp index 6814d710..ed464b22 100644 --- a/Track.cpp +++ b/Track.cpp @@ -2340,7 +2340,7 @@ void TTrack::ConnectionsLog() } }; -TTrack * TTrack::Neightbour(int s, double &d) +TTrack * TTrack::Connected(int s, double &d) const { // zwraca wskaźnik na sąsiedni tor, w kierunku określonym znakiem (s), odwraca (d) w razie // niezgodności kierunku torów TTrack *t; // nie zmieniamy kierunku (d), jeśli nie ma toru dalej diff --git a/Track.h b/Track.h index 323bfb69..91ea6138 100644 --- a/Track.h +++ b/Track.h @@ -205,7 +205,7 @@ public: return trNext; }; inline TTrack *CurrentPrev() const { return trPrev; }; - TTrack * Neightbour(int s, double &d); + TTrack *Connected(int s, double &d) const; bool SetConnections(int i); bool Switch(int i, double t = -1.0, double d = -1.0); bool SwitchForced(int i, TDynamicObject *o); diff --git a/Train.cpp b/Train.cpp index c6f54547..8610ebce 100644 --- a/Train.cpp +++ b/Train.cpp @@ -296,7 +296,6 @@ TTrain::TTrain() { fPPress = fNPress = 0; // asMessage=""; - fMechCroach = 0.25; pMechShake = vector3(0, 0, 0); vMechMovement = vector3(0, 0, 0); pMechOffset = vector3(0, 0, 0); @@ -389,8 +388,7 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) */ MechSpring.Init(0.015, 250); vMechVelocity = vector3(0, 0, 0); - pMechOffset = vector3(-0.4, 3.3, 5.5); - fMechCroach = 0.5; + pMechOffset = vector3( 0, 0, 0 ); fMechSpringX = 1; fMechSpringY = 0.5; fMechSpringZ = 0.5; @@ -1430,10 +1428,14 @@ void TTrain::OnCommand_pantographcompressorvalvetoggle( TTrain *Train, command_d if( Train->mvControlled->bPantKurek3 == false ) { // connect pantographs with primary tank Train->mvControlled->bPantKurek3 = true; + // visual feedback: + Train->ggPantCompressorValve.UpdateValue( 0.0 ); } else { // connect pantograps with pantograph compressor Train->mvControlled->bPantKurek3 = false; + // visual feedback: + Train->ggPantCompressorValve.UpdateValue( 1.0 ); } } } @@ -1456,10 +1458,14 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // press or hold to activate Train->mvControlled->PantCompFlag = true; + // visual feedback: + Train->ggPantCompressorButton.UpdateValue( 1.0 ); } else { // release to disable Train->mvControlled->PantCompFlag = false; + // visual feedback: + Train->ggPantCompressorButton.UpdateValue( 0.0 ); } } @@ -4627,35 +4633,38 @@ bool TTrain::Update( double const Deltatime ) ggBrakeCtrl.UpdateValue(mvOccupied->fBrakeCtrlPos); ggBrakeCtrl.Update(); } - if (ggLocalBrake.SubModel) - { - if (DynamicObject->Mechanik ? - (DynamicObject->Mechanik->AIControllFlag ? false : (Global::iFeedbackMode == 4 || (Global::bMWDmasterEnable && Global::bMWDBreakEnable))) : - false) // nie blokujemy AI - { // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba - // Firleju: dlatego kasujemy i zastepujemy funkcją w Console - if ((mvOccupied->BrakeLocHandle == FD1)) - { - double b = Console::AnalogCalibrateGet(1); - b *= 10.0; - b = clamp( b, 0.0, LocalBrakePosNo); // przycięcie zmiennej do granic - ggLocalBrake.UpdateValue(b); // przesów bez zaokrąglenia - if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FD1 break position = " + to_string(b)); - mvOccupied->LocalBrakePos = - int(1.09 * b); // sposób zaokrąglania jest do ustalenia + + if( ggLocalBrake.SubModel ) { + + if( ( DynamicObject->Mechanik != nullptr ) + && ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI + && ( mvOccupied->BrakeLocHandle == FD1 ) + && ( ( Global::iFeedbackMode == 4 ) + || ( Global::bMWDmasterEnable && Global::bMWDBreakEnable ) ) ) { + // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba + // Firleju: dlatego kasujemy i zastepujemy funkcją w Console + auto const b = clamp( + Console::AnalogCalibrateGet( 1 ) * 10.0, + 0.0, + ManualBrakePosNo ); + ggLocalBrake.UpdateValue( b ); // przesów bez zaokrąglenia + mvOccupied->LocalBrakePos = int( 1.09 * b ); // sposób zaokrąglania jest do ustalenia + if( ( true == Global::bMWDdebugEnable ) + && ( ( Global::iMWDDebugMode & 4 ) != 0 ) ) { + WriteLog( "FD1 break position = " + to_string( b ) ); } - else // standardowa prodedura z kranem powiązanym z klawiaturą - ggLocalBrake.UpdateValue(double(mvOccupied->LocalBrakePos)); } - else // standardowa prodedura z kranem powiązanym z klawiaturą - ggLocalBrake.UpdateValue(double(mvOccupied->LocalBrakePos)); + else { + // standardowa prodedura z kranem powiązanym z klawiaturą + ggLocalBrake.UpdateValue( double( mvOccupied->LocalBrakePos ) ); + } ggLocalBrake.Update(); } - if (ggManualBrake.SubModel != NULL) - { + if (ggManualBrake.SubModel != nullptr) { ggManualBrake.UpdateValue(double(mvOccupied->ManualBrakePos)); ggManualBrake.Update(); } + ggAlarmChain.Update(); ggBrakeProfileCtrl.Update(); ggBrakeProfileG.Update(); ggBrakeProfileR.Update(); @@ -5629,6 +5638,8 @@ bool TTrain::Update( double const Deltatime ) ggPantRearButtonOff.Update(); ggPantSelectedDownButton.Update(); ggPantAllDownButton.Update(); + ggPantCompressorButton.Update(); + ggPantCompressorValve.Update(); ggUpperLightButton.Update(); ggLeftLightButton.Update(); @@ -6273,8 +6284,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) } void TTrain::MechStop() -{ // likwidacja ruchu kamery w kabinie (po powrocie - // przez [F4]) +{ // likwidacja ruchu kamery w kabinie (po powrocie przez [F4]) pMechPosition = vector3(0, 0, 0); pMechShake = vector3(0, 0, 0); vMechMovement = vector3(0, 0, 0); @@ -6503,6 +6513,8 @@ void TTrain::clear_cab_controls() ggPantRearButtonOff.Clear(); ggPantSelectedDownButton.Clear(); ggPantAllDownButton.Clear(); + ggPantCompressorButton.Clear(); + ggPantCompressorValve.Clear(); ggZbS.Clear(); ggI1B.Clear(); ggI2B.Clear(); @@ -6649,6 +6661,15 @@ void TTrain::set_cab_controls() { 0.0 : 1.0 ) ); } + // auxiliary compressor + ggPantCompressorValve.PutValue( + mvControlled->bPantKurek3 ? + 0.0 : // default setting is pantographs connected with primary tank + 1.0 ); + ggPantCompressorButton.PutValue( + mvControlled->PantCompFlag ? + 1.0 : + 0.0 ); // converter if( mvOccupied->ConvSwitchType != "impulse" ) { ggConverterButton.PutValue( @@ -7067,6 +7088,8 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "pantalloff_sw:", ggPantAllDownButton }, { "pantselected_sw:", ggPantSelectedButton }, { "pantselectedoff_sw:", ggPantSelectedDownButton }, + { "pantcompressor_sw:", ggPantCompressorButton }, + { "pantcompressorvalve_sw:", ggPantCompressorValve }, { "trainheating_sw:", ggTrainHeatingButton }, { "signalling_sw:", ggSignallingButton }, { "door_signalling_sw:", ggDoorSignallingButton }, diff --git a/Train.h b/Train.h index 90a5ac6d..80b67bc0 100644 --- a/Train.h +++ b/Train.h @@ -299,6 +299,8 @@ public: // reszta może by?publiczna TGauge ggPantAllDownButton; TGauge ggPantSelectedButton; TGauge ggPantSelectedDownButton; + TGauge ggPantCompressorButton; + TGauge ggPantCompressorValve; // Winger 020304 - wlacznik ogrzewania TGauge ggTrainHeatingButton; TGauge ggSignallingButton; @@ -376,7 +378,6 @@ public: // reszta może by?publiczna vector3 pMechShake; vector3 vMechVelocity; // McZapkie: do poruszania sie po kabinie - double fMechCroach; // McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc TCab Cabine[maxcab + 1]; // przedzial maszynowy, kabina 1 (A), kabina 2 (B) int iCabn; diff --git a/TrkFoll.cpp b/TrkFoll.cpp index c48ecac6..ceddcb1c 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -206,10 +206,10 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) dir = fDirection; if (pCurrentTrack->eType == tt_Cross) { - if (!SetCurrentTrack(pCurrentTrack->Neightbour(iSegment, fDirection), 0)) + if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 0)) return false; // wyjście z błędem } - else if (!SetCurrentTrack(pCurrentTrack->Neightbour(-1, fDirection), + else if (!SetCurrentTrack(pCurrentTrack->Connected(-1, fDirection), 0)) // ustawia fDirection return false; // wyjście z błędem if (dir == fDirection) //(pCurrentTrack->iPrevDirection) @@ -243,10 +243,10 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) dir = fDirection; if (pCurrentTrack->eType == tt_Cross) { - if (!SetCurrentTrack(pCurrentTrack->Neightbour(iSegment, fDirection), 1)) + if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 1)) return false; // wyjście z błędem } - else if (!SetCurrentTrack(pCurrentTrack->Neightbour(1, fDirection), + else if (!SetCurrentTrack(pCurrentTrack->Connected(1, fDirection), 1)) // ustawia fDirection return false; // wyjście z błędem if (dir != fDirection) //(pCurrentTrack->iNextDirection) diff --git a/World.cpp b/World.cpp index e573e275..8aa6ee88 100644 --- a/World.cpp +++ b/World.cpp @@ -183,14 +183,10 @@ simulation_time::julian_day() const { TWorld::TWorld() { - // randomize(); - // Randomize(); Train = NULL; - // Aspect=1; for (int i = 0; i < 10; ++i) KeyEvents[i] = NULL; // eventy wyzwalane klawiszami cyfrowymi Global::iSlowMotion = 0; - // Global::changeDynObj=NULL; pDynamicNearest = NULL; fTimeBuffer = 0.0; // bufor czasu aktualizacji dla stałego kroku fizyki fMaxDt = 0.01; //[s] początkowy krok czasowy fizyki @@ -199,7 +195,6 @@ TWorld::TWorld() TWorld::~TWorld() { - Global::bManageNodes = false; // Ra: wyłączenie wyrejestrowania, bo się sypie TrainDelete(); // Ground.Free(); //Ra: usunięcie obiektów przed usunięciem dźwięków - sypie się TSoundsManager::Free(); @@ -218,61 +213,6 @@ void TWorld::TrainDelete(TDynamicObject *d) Global::pUserDynamic = NULL; // tego też nie ma }; -/* Ra: do opracowania: wybor karty graficznej ~Intel gdy są dwie... -BOOL GetDisplayMonitorInfo(int nDeviceIndex, LPSTR lpszMonitorInfo) -{ - FARPROC EnumDisplayDevices; - HINSTANCE hInstUser32; - DISPLAY_DEVICE DispDev; - char szSaveDeviceName[33]; // 32 + 1 for the null-terminator - BOOL bRet = TRUE; - HRESULT hr; - - hInstUser32 = LoadLibrary("c:\\windows\User32.DLL"); - if (!hInstUser32) return FALSE; - - // Get the address of the EnumDisplayDevices function - EnumDisplayDevices = (FARPROC)GetProcAddress(hInstUser32,"EnumDisplayDevicesA"); - if (!EnumDisplayDevices) { - FreeLibrary(hInstUser32); - return FALSE; - } - - ZeroMemory(&DispDev, sizeof(DispDev)); - DispDev.cb = sizeof(DispDev); - - // After the first call to EnumDisplayDevices, - // DispDev.DeviceString is the adapter name - if (EnumDisplayDevices(NULL, nDeviceIndex, &DispDev, 0)) - { - hr = StringCchCopy(szSaveDeviceName, 33, DispDev.DeviceName); - if (FAILED(hr)) - { - // TODO: write error handler - } - - // After second call, DispDev.DeviceString is the - // monitor name for that device - EnumDisplayDevices(szSaveDeviceName, 0, &DispDev, 0); - - // In the following, lpszMonitorInfo must be 128 + 1 for - // the null-terminator. - hr = StringCchCopy(lpszMonitorInfo, 129, DispDev.DeviceString); - if (FAILED(hr)) - { - // TODO: write error handler - } - - } else { - bRet = FALSE; - } - - FreeLibrary(hInstUser32); - - return bRet; -} -*/ - bool TWorld::Init( GLFWwindow *Window ) { auto timestart = std::chrono::system_clock::now(); @@ -822,11 +762,6 @@ void TWorld::OnKeyDown(int cKey) } } } - // switch (cKey) - //{case 'a': //ignorowanie repetycji - // case 'A': Global::iKeyLast=cKey; break; - // default: Global::iKeyLast=0; - //} } void TWorld::OnMouseMove(double x, double y) @@ -837,12 +772,14 @@ void TWorld::OnMouseMove(double x, double y) void TWorld::InOutKey( bool const Near ) { // przełączenie widoku z kabiny na zewnętrzny i odwrotnie FreeFlyModeFlag = !FreeFlyModeFlag; // zmiana widoku - if (FreeFlyModeFlag) - { // jeżeli poza kabiną, przestawiamy w jej okolicę - OK + if (FreeFlyModeFlag) { + // jeżeli poza kabiną, przestawiamy w jej okolicę - OK Global::pUserDynamic = NULL; // bez renderowania względem kamery - if (Train) - { // Train->Dynamic()->ABuSetModelShake(vector3(0,0,0)); - Train->Silence(); // wyłączenie dźwięków kabiny + if (Train) { + // cache current cab position so there's no need to set it all over again after each out-in switch + Train->pMechSittingPosition = Train->pMechOffset; + // wyłączenie dźwięków kabiny + Train->Silence(); Train->Dynamic()->bDisplayCab = false; DistantView( Near ); } @@ -1048,8 +985,15 @@ bool TWorld::Update() // this means at count > 20 simulation and render are going to desync. is that right? // NOTE: experimentally changing this to prevent the desync. // TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps - for( int updateidx = 0; updateidx < updatecount; ++updateidx ) { - Ground.Update( dt / updatecount, 1 ); // tu zrobić tylko coklatkową aktualizację przesunięć + if( true == Global::FullPhysics ) { + // default calculation mode, each step calculated separately + for( int updateidx = 0; updateidx < updatecount; ++updateidx ) { + Ground.Update( dt / updatecount, 1 ); + } + } + else { + // slightly simplified calculation mode; can lead to errors + Ground.Update( dt / updatecount, updatecount ); } // yB dodał przyspieszacz fizyki @@ -2020,26 +1964,6 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz) } }; -//--------------------------------------------------------------------------- -void TWorld::ModifyTGA(const std::string &dir) -{ // rekurencyjna modyfikacje plików TGA -/* TODO: implement version without Borland stuff - TSearchRec sr; - if (FindFirst(dir + "*.*", faDirectory | faArchive, sr) == 0) - { - do - { - if (sr.Name[1] != '.') - if ((sr.Attr & faDirectory)) // jeśli katalog, to rekurencja - ModifyTGA(dir + sr.Name + "/"); - else if (sr.Name.LowerCase().SubString(sr.Name.Length() - 3, 4) == ".tga") - TTexturesManager::GetTextureID(NULL, NULL, AnsiString(dir + sr.Name).c_str()); - } while (FindNext(sr) == 0); - FindClose(sr); - } -*/ -}; - //--------------------------------------------------------------------------- void TWorld::CreateE3D(std::string const &Path, bool Dynamic) diff --git a/World.h b/World.h index 54517e7c..ac97a1dd 100644 --- a/World.h +++ b/World.h @@ -140,7 +140,6 @@ private: bool m_init{ false }; // indicates whether initial update of the world was performed public: - void ModifyTGA(std::string const &dir = ""); void CreateE3D(std::string const &dir = "", bool dyn = false); void CabChange(TDynamicObject *old, TDynamicObject *now); // handles vehicle change flag diff --git a/mouseinput.cpp b/mouseinput.cpp index 3709740c..be72ce1d 100644 --- a/mouseinput.cpp +++ b/mouseinput.cpp @@ -68,93 +68,105 @@ void mouse_input::button( int const Button, int const Action ) { if( false == Global::ControlPicking ) { return; } + if( true == FreeFlyModeFlag ) { - // for now we're only interested in cab controls - return; - } - - user_command &mousecommand = ( - Button == GLFW_MOUSE_BUTTON_LEFT ? - m_mousecommandleft : - m_mousecommandright - ); - - if( Action == GLFW_RELEASE ) { - if( mousecommand != user_command::none ) { - // NOTE: basic keyboard controls don't have any parameters - // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 - // TODO: pass correct entity id once the missing systems are in place - m_relay.post( mousecommand, 0, 0, Action, 0 ); - mousecommand = user_command::none; - } - else { - // if it's the right mouse button that got released and we had no command active, we were potentially in view panning mode; stop it + // world editor controls + // currently we only handle view panning in this mode + if( Action == GLFW_RELEASE ) { + // if it's the right mouse button that got released we were potentially in view panning mode; stop it if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { m_pickmodepanning = false; } } - // if we were in varying command repeat rate, we can stop that now. done without any conditions, to catch some unforeseen edge cases - m_varyingpollrate = false; + else { + // button press + if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { + // the right button activates mouse panning mode + m_pickmodepanning = true; + } + } } else { - // if not release then it's press - auto train = World.train(); - if( train != nullptr ) { - auto lookup = m_mousecommands.find( train->GetLabel( GfxRenderer.Update_Pick_Control() ) ); - if( lookup != m_mousecommands.end() ) { - mousecommand = ( - Button == GLFW_MOUSE_BUTTON_LEFT ? - lookup->second.left : - lookup->second.right - ); - if( mousecommand != user_command::none ) { - // check manually for commands which have 'fast' variants launched with shift modifier - if( Global::shiftState ) { + // cab controls mode + user_command &mousecommand = ( + Button == GLFW_MOUSE_BUTTON_LEFT ? + m_mousecommandleft : + m_mousecommandright + ); + + if( Action == GLFW_RELEASE ) { + if( mousecommand != user_command::none ) { + // NOTE: basic keyboard controls don't have any parameters + // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 + // TODO: pass correct entity id once the missing systems are in place + m_relay.post( mousecommand, 0, 0, Action, 0 ); + mousecommand = user_command::none; + } + else { + // if it's the right mouse button that got released and we had no command active, we were potentially in view panning mode; stop it + if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { + m_pickmodepanning = false; + } + } + // if we were in varying command repeat rate, we can stop that now. done without any conditions, to catch some unforeseen edge cases + m_varyingpollrate = false; + } + else { + // if not release then it's press + auto train = World.train(); + if( train != nullptr ) { + auto lookup = m_mousecommands.find( train->GetLabel( GfxRenderer.Update_Pick_Control() ) ); + if( lookup != m_mousecommands.end() ) { + mousecommand = ( + Button == GLFW_MOUSE_BUTTON_LEFT ? + lookup->second.left : + lookup->second.right + ); + if( mousecommand != user_command::none ) { + // check manually for commands which have 'fast' variants launched with shift modifier + if( Global::shiftState ) { + switch( mousecommand ) { + case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; } + case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; } + case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; } + case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; } + case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; } + case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; } + default: { break; } + } + } + // NOTE: basic keyboard controls don't have any parameters + // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 + // TODO: pass correct entity id once the missing systems are in place + m_relay.post( mousecommand, 0, 0, Action, 0 ); + m_updateaccumulator = 0.0; // prevent potential command repeat right after issuing one + switch( mousecommand ) { - case user_command::mastercontrollerincrease: { mousecommand = user_command::mastercontrollerincreasefast; break; } - case user_command::mastercontrollerdecrease: { mousecommand = user_command::mastercontrollerdecreasefast; break; } - case user_command::secondcontrollerincrease: { mousecommand = user_command::secondcontrollerincreasefast; break; } - case user_command::secondcontrollerdecrease: { mousecommand = user_command::secondcontrollerdecreasefast; break; } - case user_command::independentbrakeincrease: { mousecommand = user_command::independentbrakeincreasefast; break; } - case user_command::independentbrakedecrease: { mousecommand = user_command::independentbrakedecreasefast; break; } - default: { break; } - } - } - // NOTE: basic keyboard controls don't have any parameters - // as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0 - // TODO: pass correct entity id once the missing systems are in place - m_relay.post( mousecommand, 0, 0, Action, 0 ); - m_updateaccumulator = 0.0; // prevent potential command repeat right after issuing one -/* - if( mousecommand == user_command::mastercontrollerincrease ) { - m_updateaccumulator -= 0.15; // extra pause on first increase of master controller - } -*/ - switch( mousecommand ) { - case user_command::mastercontrollerincrease: - case user_command::mastercontrollerdecrease: - case user_command::secondcontrollerincrease: - case user_command::secondcontrollerdecrease: - case user_command::trainbrakeincrease: - case user_command::trainbrakedecrease: - case user_command::independentbrakeincrease: - case user_command::independentbrakedecrease: { - // these commands trigger varying repeat rate mode, - // which scales the rate based on the distance of the cursor from its point when the command was first issued - m_commandstartcursor = m_cursorposition; - m_varyingpollrate = true; - break; - } - default: { - break; + case user_command::mastercontrollerincrease: + case user_command::mastercontrollerdecrease: + case user_command::secondcontrollerincrease: + case user_command::secondcontrollerdecrease: + case user_command::trainbrakeincrease: + case user_command::trainbrakedecrease: + case user_command::independentbrakeincrease: + case user_command::independentbrakedecrease: { + // these commands trigger varying repeat rate mode, + // which scales the rate based on the distance of the cursor from its point when the command was first issued + m_commandstartcursor = m_cursorposition; + m_varyingpollrate = true; + break; + } + default: { + break; + } } } } - } - else { - // if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode - if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { - m_pickmodepanning = true; + else { + // if we don't have any recognized element under the cursor and the right button was pressed, enter view panning mode + if( Button == GLFW_MOUSE_BUTTON_RIGHT ) { + m_pickmodepanning = true; + } } } } diff --git a/renderer.cpp b/renderer.cpp index 530e4c25..46f896e9 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -423,14 +423,23 @@ opengl_renderer::Render_pass( rendermode const Mode ) { ::glEnable( GL_TEXTURE_2D ); } #endif +#ifdef EU07_NEW_CAB_RENDERCODE + if( World.Train != nullptr ) { + // cab render is performed without shadows, due to low resolution and number of models without windows :| + switch_units( true, false, false ); + Render_cab( World.Train->Dynamic(), false ); + } +#endif + switch_units( true, true, true ); Render( &World.Ground ); // ...translucent parts setup_drawing( true ); Render_Alpha( &World.Ground ); - // cab render is performed without shadows, due to low resolution and number of models without windows :| - switch_units( true, false, false ); - // cab render is done in translucent phase to deal with badly configured vehicles - if( World.Train != nullptr ) { Render_cab( World.Train->Dynamic() ); } + if( World.Train != nullptr ) { + // cab render is performed without shadows, due to low resolution and number of models without windows :| + switch_units( true, false, false ); + Render_cab( World.Train->Dynamic(), true ); + } if( m_environmentcubetexturesupport ) { // restore default texture matrix for reflections cube map @@ -1621,8 +1630,8 @@ opengl_renderer::Render( TGroundNode *Node ) { break; } } - if( ( distancesquared > Node->fSquareRadius ) - || ( distancesquared < Node->fSquareMinRadius ) ) { + if( ( distancesquared < Node->fSquareMinRadius ) + || ( distancesquared >= Node->fSquareRadius ) ) { return false; } @@ -1906,7 +1915,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) { // rendering kabiny gdy jest oddzielnym modelem i ma byc wyswietlana bool -opengl_renderer::Render_cab( TDynamicObject *Dynamic ) { +opengl_renderer::Render_cab( TDynamicObject *Dynamic, bool const Alpha ) { if( Dynamic == nullptr ) { @@ -1943,8 +1952,19 @@ opengl_renderer::Render_cab( TDynamicObject *Dynamic ) { ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, glm::value_ptr( Dynamic->InteriorLight * Dynamic->InteriorLightLevel ) ); } // render +#ifdef EU07_NEW_CAB_RENDERCODE + if( true == Alpha ) { + // translucent parts + Render_Alpha( Dynamic->mdKabina, Dynamic->Material(), 0.0 ); + } + else { + // opaque parts + Render( Dynamic->mdKabina, Dynamic->Material(), 0.0 ); + } +#else Render( Dynamic->mdKabina, Dynamic->Material(), 0.0 ); Render_Alpha( Dynamic->mdKabina, Dynamic->Material(), 0.0 ); +#endif // post-render restore if( Dynamic->fShade > 0.0f ) { // change light level based on light level of the occupied track @@ -2030,7 +2050,7 @@ opengl_renderer::Render( TSubModel *Submodel ) { if( ( Submodel->iVisible ) && ( TSubModel::fSquareDist >= Submodel->fSquareMinDist ) - && ( TSubModel::fSquareDist <= Submodel->fSquareMaxDist ) ) { + && ( TSubModel::fSquareDist < Submodel->fSquareMaxDist ) ) { if( Submodel->iFlags & 0xC000 ) { ::glPushMatrix(); @@ -2412,8 +2432,8 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) { break; } } - if( ( distancesquared > Node->fSquareRadius ) - || ( distancesquared < Node->fSquareMinRadius ) ) { + if( ( distancesquared < Node->fSquareMinRadius ) + || ( distancesquared >= Node->fSquareRadius ) ) { return false; } @@ -2675,7 +2695,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { // renderowanie przezroczystych przez DL if( ( Submodel->iVisible ) && ( TSubModel::fSquareDist >= Submodel->fSquareMinDist ) - && ( TSubModel::fSquareDist <= Submodel->fSquareMaxDist ) ) { + && ( TSubModel::fSquareDist < Submodel->fSquareMaxDist ) ) { if( Submodel->iFlags & 0xC000 ) { ::glPushMatrix(); diff --git a/renderer.h b/renderer.h index 067f64c0..70141315 100644 --- a/renderer.h +++ b/renderer.h @@ -285,7 +285,7 @@ private: void Render( TTrack *Track ); bool - Render_cab( TDynamicObject *Dynamic ); + Render_cab( TDynamicObject *Dynamic, bool const Alpha = false ); void Render( TMemCell *Memcell ); bool diff --git a/version.h b/version.h index 998e22bf..50d73e58 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 905 +#define VERSION_MINOR 911 #define VERSION_REVISION 0