From 62327d5d080342138f476bd3fec290de3afcd029 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 13 Feb 2018 23:58:31 +0100 Subject: [PATCH] no pneumatic relay sound on brake acting speed change, enabled playback of multiple bookend sounds, extra pantograph control for ai during longer stops, shadow angle calculation tweak, moon appearance tweak, minor bug fixes --- Driver.cpp | 134 ++++++++++++++++++++++++--------------------- Driver.h | 1 + DynObj.cpp | 7 ++- McZapkie/Mover.cpp | 12 ++-- Model3d.cpp | 2 +- Train.cpp | 6 +- TrkFoll.cpp | 18 +++--- World.cpp | 2 +- moon.cpp | 28 +++++----- moon.h | 2 - renderer.cpp | 35 +++++------- simulation.cpp | 5 ++ skydome.cpp | 2 +- sound.cpp | 40 ++++++++++++-- sound.h | 3 + sun.cpp | 26 +++++---- version.h | 2 +- 17 files changed, 185 insertions(+), 140 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 9797d740..92a62931 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1212,8 +1212,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN } else { // zawalidrogi nie ma (albo pojazd jest samochodem), sprawdzić sygnał - if (sSpeedTable[i].iFlags & spShuntSemaphor) // jeśli Tm - w zasadzie to sprawdzić - // komendę! + if (sSpeedTable[i].iFlags & spShuntSemaphor) // jeśli Tm - w zasadzie to sprawdzić komendę! { // jeśli podana prędkość manewrowa if ((OrderCurrentGet() & Obey_train) ? v == 0.0 : false) { // jeśli tryb pociągowy a tarcze ma ShuntVelocity 0 0 @@ -3340,8 +3339,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N iDirectionOrder = -iDirection; // jak się podczepi, to jazda w przeciwną stronę OrderNext(Change_direction); } - WaitingTime = - 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie + WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie } else // if (NewValue2==0.0) //zerowy sprzęg if (NewValue1 >= 0.0) // jeśli ilość wagonów inna niż wszystkie @@ -3358,8 +3356,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N else if (mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag > 0) // z tyłu coś OrderNext(Disconnect); // jak ciągnie, to tylko odczep (NewValue1) wagonów - WaitingTime = - 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie + WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie } if (NewValue1 == -1.0) { @@ -3495,6 +3492,13 @@ TController::UpdateSituation(double dt) { fActionTime += dt; // czas używany przy regulacji prędkości i zamykaniu drzwi LastReactionTime += dt; LastUpdatedTime += dt; + if( ( mvOccupied->Vel < 0.05 ) + && ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) { + IdleTime += dt; + } + else { + IdleTime = 0.0; + } // log vehicle data if( ( WriteLogFlag ) @@ -3628,14 +3632,12 @@ TController::UpdateSituation(double dt) { } } - if (mvOccupied->Vel > 0.0) { + if( mvOccupied->Vel > 1.0 ) { // jeżeli jedzie if( iDrivigFlags & moveDoorOpened ) { // jeśli drzwi otwarte - if( mvOccupied->Vel > 1.0 ) { - // nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości - Doors( false ); - } + // nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości + Doors( false ); } /* // NOTE: this section moved all cars to the edge of their respective roads @@ -3650,40 +3652,60 @@ TController::UpdateSituation(double dt) { mvOccupied->ChangeOffsetH(0.01 * mvOccupied->Vel * dt); // Ra: co to miało być, to nie wiem */ - if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) - { - if ((fOverhead2 >= 0.0) || iOverheadZero) - { // jeśli jazda bezprądowa albo z opuszczonym pantografem + } + + if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) { + + if( mvOccupied->Vel > 0.05 ) { + // is moving + if( ( fOverhead2 >= 0.0 ) || iOverheadZero ) { + // jeśli jazda bezprądowa albo z opuszczonym pantografem while( DecSpeed( true ) ) { ; } // zerowanie napędu } - if ((fOverhead2 > 0.0) || iOverheadDown) - { // jazda z opuszczonymi pantografami - mvControlling->PantFront(false); - mvControlling->PantRear(false); + if( ( fOverhead2 > 0.0 ) || iOverheadDown ) { + // jazda z opuszczonymi pantografami + mvControlling->PantFront( false ); + mvControlling->PantRear( false ); } - else - { // jeśli nie trzeba opuszczać pantografów - if (iDirection >= 0) // jak jedzie w kierunku sprzęgu 0 - mvControlling->PantRear(true); // jazda na tylnym - else - mvControlling->PantFront(true); + else { + // jeśli nie trzeba opuszczać pantografów + // jazda na tylnym + if( iDirection >= 0 ) { + // jak jedzie w kierunku sprzęgu 0 + mvControlling->PantRear( true ); + } + else { + mvControlling->PantFront( true ); + } } - if (mvOccupied->Vel > 10) // opuszczenie przedniego po rozpędzeniu się - { - if (mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > - 1) // o ile jest więcej niż jeden - if (iDirection >= 0) // jak jedzie w kierunku sprzęgu 0 + if( mvOccupied->Vel > 10 ) { + // opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden + if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) { + if( iDirection >= 0 ) // jak jedzie w kierunku sprzęgu 0 { // poczekać na podniesienie tylnego - if (mvControlling->PantRearVolt != - 0.0) // czy jest napięcie zasilające na tylnym? - mvControlling->PantFront(false); // opuszcza od sprzęgu 0 + if( mvControlling->PantRearVolt != 0.0 ) { + // czy jest napięcie zasilające na tylnym? + mvControlling->PantFront( false ); // opuszcza od sprzęgu 0 + } } - else - { // poczekać na podniesienie przedniego - if (mvControlling->PantFrontVolt != - 0.0) // czy jest napięcie zasilające na przednim? - mvControlling->PantRear(false); // opuszcza od sprzęgu 1 + else { // poczekać na podniesienie przedniego + if( mvControlling->PantFrontVolt != 0.0 ) { + // czy jest napięcie zasilające na przednim? + mvControlling->PantRear( false ); // opuszcza od sprzęgu 1 + } } + } + } + } + else { + if( ( IdleTime > 45.0 ) + // NOTE: abs(stoptime) covers either at least 15 sec remaining for a scheduled stop, or 15+ secs spent at a basic stop + && ( std::abs( fStopTime ) > 15.0 ) ) { + // spending a longer at a stop, raise also front pantograph + if( iDirection >= 0 ) // jak jedzie w kierunku sprzęgu 0 + mvControlling->PantFront( true ); + else + mvControlling->PantRear( true ); } } } @@ -4200,29 +4222,19 @@ TController::UpdateSituation(double dt) { } else SetDriverPsyche(); // Ra: było w PrepareEngine(), potrzebne tu? - // no albo przypisujemy -WaitingExpireTime, albo porównujemy z WaitingExpireTime - // if - // ((VelSignal==0.0)&&(WaitingTime>WaitingExpireTime)&&(mvOccupied->RunningTrack.Velmax!=0.0)) - if (OrderList[OrderPos] & - (Shunt | Obey_train | Connect)) // odjechać sam może tylko jeśli jest w trybie jazdy - { // automatyczne ruszanie po odstaniu albo spod SBL - if ((VelSignal == 0.0) && (WaitingTime > 0.0) && - (mvOccupied->RunningTrack.Velmax != 0.0)) - { // jeśli stoi, a upłynął czas oczekiwania i tor ma niezerową prędkość - /* - if (WriteLogFlag) - { - append(AIlogFile); - writeln(AILogFile,ElapsedTime:5:2,": ",Name," V=0 waiting time expired! - (",WaitingTime:4:1,")"); - close(AILogFile); - } - */ - if ((OrderList[OrderPos] & (Obey_train | Shunt)) ? - (iDrivigFlags & moveStopHere) : - false) - WaitingTime = -WaitingExpireTime; // zakaz ruszania z miejsca bez otrzymania - // wolnej drogi + + if (OrderList[OrderPos] & (Shunt | Obey_train | Connect)) { + // odjechać sam może tylko jeśli jest w trybie jazdy + // automatyczne ruszanie po odstaniu albo spod SBL + if( ( VelSignal == 0.0 ) + && ( WaitingTime > 0.0 ) + && ( mvOccupied->RunningTrack.Velmax != 0.0 ) ) { + // jeśli stoi, a upłynął czas oczekiwania i tor ma niezerową prędkość + if( ( OrderList[ OrderPos ] & ( Obey_train | Shunt ) ) + && ( iDrivigFlags & moveStopHere ) ) { + // zakaz ruszania z miejsca bez otrzymania wolnej drogi + WaitingTime = -WaitingExpireTime; + } else if (mvOccupied->CategoryFlag & 1) { // jeśli pociąg if (AIControllFlag) diff --git a/Driver.h b/Driver.h index 4161b7e8..cc8451e6 100644 --- a/Driver.h +++ b/Driver.h @@ -291,6 +291,7 @@ private: double fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku) double WaitingTime = 0.0; // zliczany czas oczekiwania do samoistnego ruszenia double WaitingExpireTime = 31.0; // tyle ma czekać, zanim się ruszy // maksymlany czas oczekiwania do samoistnego ruszenia + double IdleTime {}; // keeps track of time spent at a stop private: //---//---//---//---// koniec zmiennych, poniżej metody //---//---//---//---// void SetDriverPsyche(); diff --git a/DynObj.cpp b/DynObj.cpp index 3de92a8b..4aa0136c 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -1106,9 +1106,10 @@ void TDynamicObject::ABuCheckMyTrack() // do jednej tablicy. Wykonuje sie tylko raz - po to 'ABuChecked' TTrack *OldTrack = MyTrack; TTrack *NewTrack = Axle0.GetTrack(); - if ((NewTrack != OldTrack) && OldTrack) - { - OldTrack->RemoveDynamicObject(this); + if( NewTrack != OldTrack ) { + if( OldTrack ) { + OldTrack->RemoveDynamicObject( this ); + } NewTrack->AddDynamicObject(this); } iAxleFirst = 0; // pojazd powiązany z przednią osią - Axle0 diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index d2e01f42..573f9434 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2974,10 +2974,7 @@ bool TMoverParameters::BrakeDelaySwitch(int BDS) } else rBDS = false; - if( true == rBDS ) { - // if setting was changed emit the sound of pneumatic relay - SetFlag( SoundFlag, sound::pneumatic ); - } + return rBDS; } @@ -8128,7 +8125,10 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) { WriteLog( "Ready to depart" ); CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0; - ScndPipePress = CompressedVolume / VeselVolume; + ScndPipePress = ( + VeselVolume > 0.0 ? + CompressedVolume / VeselVolume : + 0.0 ); PipePress = CntrlPipePress; BrakePress = 0.0; LocalBrakePos = 0; @@ -8633,8 +8633,6 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if( true == Hamulec->SetBDF( brakesetting ) ) { BrakeDelayFlag = brakesetting; OK = true; - // if setting was changed emit the sound of pneumatic relay - SetFlag( SoundFlag, sound::pneumatic ); } else { OK = false; diff --git a/Model3d.cpp b/Model3d.cpp index f060d911..323dd00d 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -1223,7 +1223,7 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic) { if (FileExists(name + ".t3d")) { - LoadFromTextFile(FileName, dynamic); // wczytanie tekstowego + LoadFromTextFile(name + ".t3d", dynamic); // wczytanie tekstowego if( !dynamic ) { // pojazdy dopiero po ustawieniu animacji Init(); // generowanie siatek i zapis E3D diff --git a/Train.cpp b/Train.cpp index 413c6f1d..e6cf14b3 100644 --- a/Train.cpp +++ b/Train.cpp @@ -3805,7 +3805,7 @@ bool TTrain::Update( double const Deltatime ) if( m_linebreakerstate == 2 ) { // for diesels and/or vehicles with toggle switch setup we complete the engine start here // TBD, TODO: arrange a better way to start the diesel engines - if( ( ggMainOffButton.SubModel == nullptr ) + if( ( ggMainOnButton.SubModel == nullptr ) || ( ( mvControlled->EngineType == DieselEngine ) || ( mvControlled->EngineType == DieselElectric ) ) ) { if( mvControlled->MainSwitch( true ) ) { @@ -4277,13 +4277,13 @@ bool TTrain::Update( double const Deltatime ) } btLampkaWylSzybki.Turn( - ( ( (m_linebreakerstate > 0) + ( ( (m_linebreakerstate == 2) || (true == mvControlled->Mains) ) ? true : false ) ); // NOTE: 'off' variant uses the same test, but opposite resulting states btLampkaWylSzybkiOff.Turn( - ( ( ( m_linebreakerstate > 0 ) + ( ( ( m_linebreakerstate == 2 ) || ( true == mvControlled->Mains ) ) ? false : true ) ); diff --git a/TrkFoll.cpp b/TrkFoll.cpp index 9c9f9db9..0cc0f6d1 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -189,18 +189,19 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) */ if (s < 0) { // jeśli przekroczenie toru od strony Point1 - bCanSkip = bPrimary ? pCurrentTrack->CheckDynamicObject(Owner) : false; - if (bCanSkip) // tylko główna oś przenosi pojazd do innego toru - Owner->MyTrack->RemoveDynamicObject( - Owner); // zdejmujemy pojazd z dotychczasowego toru + bCanSkip = ( bPrimary && pCurrentTrack->CheckDynamicObject( Owner ) ); + if( bCanSkip ) { + // tylko główna oś przenosi pojazd do innego toru + // zdejmujemy pojazd z dotychczasowego toru + Owner->MyTrack->RemoveDynamicObject( Owner ); + } dir = fDirection; if (pCurrentTrack->eType == tt_Cross) { if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 0)) return false; // wyjście z błędem } - else if (!SetCurrentTrack(pCurrentTrack->Connected(-1, fDirection), - 0)) // ustawia fDirection + else if (!SetCurrentTrack(pCurrentTrack->Connected(-1, fDirection), 0)) // ustawia fDirection return false; // wyjście z błędem if (dir == fDirection) //(pCurrentTrack->iPrevDirection) { // gdy kierunek bez zmiany (Point1->Point2) @@ -215,8 +216,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) if (bCanSkip) { // jak główna oś, to dodanie pojazdu do nowego toru pCurrentTrack->AddDynamicObject(Owner); - iEventFlag = - 3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru + iEventFlag = 3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru iEventallFlag = 3; // McZapkie-280503: jw, dla eventall1,2 if (!Owner->MyTrack) return false; @@ -225,7 +225,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) } else if (s > pCurrentSegment->GetLength()) { // jeśli przekroczenie toru od strony Point2 - bCanSkip = bPrimary ? pCurrentTrack->CheckDynamicObject(Owner) : false; + bCanSkip = ( bPrimary && pCurrentTrack->CheckDynamicObject( Owner ) ); if (bCanSkip) // tylko główna oś przenosi pojazd do innego toru Owner->MyTrack->RemoveDynamicObject( Owner); // zdejmujemy pojazd z dotychczasowego toru diff --git a/World.cpp b/World.cpp index 5c5533f5..edc44db8 100644 --- a/World.cpp +++ b/World.cpp @@ -2170,7 +2170,7 @@ world_environment::update() { if( moonlightlevel > sunlightlevel ) { // rare situations when the moon is brighter than the sun, typically at night Global.SunAngle = m_moon.getAngle(); - Global.DayLight.position = m_moon.getPosition(); + Global.DayLight.position = m_moon.getDirection(); Global.DayLight.direction = -1.0f * m_moon.getDirection(); keylightintensity = moonlightlevel; // if the moon is up, it overrides the twilight diff --git a/moon.cpp b/moon.cpp index 4bf7e8c5..68bbfe51 100644 --- a/moon.cpp +++ b/moon.cpp @@ -36,11 +36,11 @@ void cMoon::update() { move(); - glm::vec3 position( 0.f, 0.f, -2000.f * Global.fDistanceFactor ); + glm::vec3 position( 0.f, 0.f, -1.f ); position = glm::rotateX( position, glm::radians( static_cast( m_body.elevref ) ) ); position = glm::rotateY( position, glm::radians( static_cast( -m_body.hrang ) ) ); - m_position = position; + m_position = glm::normalize( position ); } void @@ -48,12 +48,13 @@ cMoon::render() { ::glColor4f( 225.f / 255.f, 225.f / 255.f, 255.f / 255.f, 1.f ); // debug line to locate the moon easier + auto const position { m_position * 2000.f }; ::glBegin( GL_LINES ); - ::glVertex3fv( glm::value_ptr( m_position ) ); - ::glVertex3f( m_position.x, 0.f, m_position.z ); + ::glVertex3fv( glm::value_ptr( position ) ); + ::glVertex3f( position.x, 0.f, position.z ); ::glEnd(); ::glPushMatrix(); - ::glTranslatef( m_position.x, m_position.y, m_position.z ); + ::glTranslatef( position.x, position.y, position.z ); ::gluSphere( moonsphere, /* (float)( Global.iWindowHeight / Global.FieldOfView ) * 0.5 * */ ( m_body.distance / 60.2666 ) * 9.037461, 12, 12 ); ::glPopMatrix(); } @@ -61,7 +62,7 @@ cMoon::render() { glm::vec3 cMoon::getDirection() { - return glm::normalize( m_position ); + return m_position; } float @@ -117,14 +118,15 @@ void cMoon::move() { if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; } - double ut = localtime.wHour - + localtime.wMinute / 60.0; // too low resolution, noticeable skips - // NOTE: finer resolution disabled to reduce shadow crawl in current implementation - /* - + localtime.wSecond / 3600.0 // good enough in normal circumstances + double ut = + localtime.wHour + + localtime.wMinute / 60.0 // too low resolution, noticeable skips + + localtime.wSecond / 3600.0; // good enough in normal circumstances +/* + localtime.wMilliseconds / 3600000.0; // for really smooth movement - */ - double daynumber = 367 * localtime.wYear +*/ + double daynumber + = 367 * localtime.wYear - 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4 + 275 * localtime.wMonth / 9 + localtime.wDay diff --git a/moon.h b/moon.h index c0caaa79..eb59a1a7 100644 --- a/moon.h +++ b/moon.h @@ -16,8 +16,6 @@ public: void init(); void update(); void render(); - // returns location of the sun in the 3d scene - glm::vec3 getPosition() { return m_position; } // returns vector pointing at the sun glm::vec3 getDirection(); // returns current elevation above horizon diff --git a/renderer.cpp b/renderer.cpp index 97a79429..16798f5f 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -397,7 +397,12 @@ opengl_renderer::Render() { Timer::subsystem.gfx_total.start(); // note: gfx_total is actually frame total, clean this up Timer::subsystem.gfx_color.start(); // fetch simulation data - m_sunlight = Global.DayLight; + if( World.InitPerformed() ) { + m_sunlight = Global.DayLight; + // quantize sun angle to reduce shadow crawl + auto const quantizationstep { 0.004f }; + m_sunlight.direction = glm::normalize( quantizationstep * glm::roundEven( m_sunlight.direction * ( 1.f / quantizationstep ) ) ); + } // generate new frame m_renderpass.draw_mode = rendermode::none; // force setup anew m_debugtimestext.clear(); @@ -420,24 +425,7 @@ opengl_renderer::Render() { + "; dyn: " + to_string( m_debugstats.dynamics ) + " mod: " + to_string( m_debugstats.models ) + " sub: " + to_string( m_debugstats.submodels ) + "; trk: " + to_string( m_debugstats.paths ) + " shp: " + to_string( m_debugstats.shapes ) + " trc: " + to_string( m_debugstats.traction ) + " lin: " + to_string( m_debugstats.lines ); -/* - float lightcutoff{}, - lightexponent{}, - lightconstant{}, - lightlinear{}; - ::glGetLightfv( GL_LIGHT1, GL_SPOT_CUTOFF, &lightcutoff ); - ::glGetLightfv( GL_LIGHT1, GL_SPOT_EXPONENT, &lightexponent ); - ::glGetLightfv( GL_LIGHT1, GL_CONSTANT_ATTENUATION, &lightconstant ); - ::glGetLightfv( GL_LIGHT1, GL_LINEAR_ATTENUATION, &lightlinear ); - m_debugstatstext = - "light1 cutoff: " + to_string( lightcutoff, 2 ) - + " exponent: " + to_string( lightexponent, 2 ) - + " constant attn: " + to_string( lightconstant, 2 ) - + " linear attn: " + to_string( lightlinear, 3 ); -*/ -/* - m_debugstatstext = "sun hour angle: " + to_string( -World.Environment.m_sun.getHourAngle(), 6 ); -*/ + ++m_framestamp; return true; // for now always succeed @@ -1481,7 +1469,14 @@ opengl_renderer::Render( world_environment *Environment ) { { Bind_Texture( m_moontexture ); glm::vec3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ); - ::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast( 1.0 - Global.fLuminance * 0.5 ) ); + // fade the moon if it's near the sun in the sky, especially during the day + ::glColor4f( + mooncolor.r, mooncolor.g, mooncolor.b, + std::max( + 0.f, + 1.0 + - 0.5 * Global.fLuminance + - 0.65 * std::max( 0.f, glm::dot( Environment->m_sun.getDirection(), Environment->m_moon.getDirection() ) ) ) ); auto const moonposition = modelview * glm::vec4( Environment->m_moon.getDirection(), 1.0f ); ::glPushMatrix(); diff --git a/simulation.cpp b/simulation.cpp index 1251ac4f..54bbf03d 100644 --- a/simulation.cpp +++ b/simulation.cpp @@ -820,6 +820,11 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch } } else { + if( vehicle->MyTrack != nullptr ) { + // rare failure case where vehicle with length of 0 is added to the track, + // treated as error code and consequently deleted, but still remains on the track + vehicle->MyTrack->RemoveDynamicObject( vehicle ); + } delete vehicle; skip_until( Input, "enddynamic" ); return nullptr; diff --git a/skydome.cpp b/skydome.cpp index 18b90505..35d20491 100644 --- a/skydome.cpp +++ b/skydome.cpp @@ -305,7 +305,7 @@ void CSkyDome::RebuildColors() { auto const sunbasedphase = clamp( (1.0f / 15.0f) * ( degreesabovehorizon - 10.0f ), 0.0f, 1.0f ); // correction is applied in linear manner from the bottom, becomes fully in effect for vertices with y = 0.50 auto const heightbasedphase = clamp( vertex.y * 2.0f, 0.0f, 1.0f ); - // this height-based factor is reduced the farther the sky is up in the sky + // this height-based factor is reduced the farther the sun is up in the sky float const shiftfactor = clamp( interpolate(heightbasedphase, sunbasedphase, sunbasedphase), 0.0f, 1.0f ); // h = 210 makes for 'typical' sky tone shiftedcolor = glm::vec3( 210.0f, colorconverter.y, colorconverter.z ); diff --git a/sound.cpp b/sound.cpp index e92bd10c..cc334098 100644 --- a/sound.cpp +++ b/sound.cpp @@ -324,7 +324,13 @@ sound_source::play( int const Flags ) { if( m_pitchvariation == 0.f ) { m_pitchvariation = 0.01f * static_cast( Random( 97.5, 102.5 ) ); } - +/* + if( ( ( m_flags & sound_flags::exclusive ) != 0 ) + && ( sound( sound_id::end ).playing > 0 ) ) { + // request termination of the optional ending bookend for single instance sounds + m_stopend = true; + } +*/ if( sound( sound_id::main ).buffer != null_handle ) { // basic variant: single main sound, with optional bookends play_basic(); @@ -352,8 +358,8 @@ sound_source::play_basic() { } else { // for single part non-looping samples we allow spawning multiple instances, if not prevented by set flags - if( ( sound( sound_id::begin ).buffer == null_handle ) - && ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 ) ) { + if( ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 ) + && ( sound( sound_id::begin ).buffer == null_handle ) ) { insert( sound_id::main ); } } @@ -448,7 +454,7 @@ sound_source::stop( bool const Skipend ) { if( ( false == Skipend ) && ( sound( sound_id::end ).buffer != null_handle ) && ( sound( sound_id::end ).buffer != sound( sound_id::main ).buffer ) // end == main can happen in malformed legacy cases - && ( sound( sound_id::end ).playing == 0 ) ) { +/* && ( sound( sound_id::end ).playing == 0 ) */ ) { // spawn potentially defined sound end sample, if the emitter is currently active insert( sound_id::end ); } @@ -485,7 +491,18 @@ sound_source::update_basic( audio::openal_source &Source ) { } return; } - +/* + if( ( true == m_stopend ) + && ( Source.sounds[ Source.sound_index ] == sound_id::end ) ) { + // kill the sound if it's the bookend sample and stopping it was requested + Source.stop(); + update_counter( sound_id::end, -1 ); + if( sound( sound_id::end ).playing == 0 ) { + m_stopend = false; + } + return; + } +*/ if( sound( sound_id::begin ).buffer != null_handle ) { // potentially a multipart sound // detect the moment when the sound moves from startup sample to the main @@ -562,7 +579,18 @@ sound_source::update_combined( audio::openal_source &Source ) { } return; } - +/* + if( ( true == m_stopend ) + && ( Source.sounds[ Source.sound_index ] == sound_id::end ) ) { + // kill the sound if it's the bookend sample and stopping it was requested + Source.stop(); + update_counter( sound_id::end, -1 ); + if( sound( sound_id::end ).playing == 0 ) { + m_stopend = false; + } + return; + } +*/ if( sound( sound_id::begin ).buffer != null_handle ) { // potentially a multipart sound // detect the moment when the sound moves from startup sample to the main diff --git a/sound.h b/sound.h index 56300924..13143e44 100644 --- a/sound.h +++ b/sound.h @@ -203,6 +203,9 @@ private: sound_properties m_properties; // current properties of the emitted sounds float m_pitchvariation {}; // emitter-specific shift in base pitch bool m_stop { false }; // indicates active sample instances should be terminated +/* + bool m_stopend { false }; // indicates active instances of optional ending sound should be terminated +*/ bool m_playbeginning { true }; // indicates started sounds should be preceeded by opening bookend if there's one std::array m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends std::vector m_soundchunks; // table of samples activated when associated variable is within certain range diff --git a/sun.cpp b/sun.cpp index 0dc2f98b..9f6e0a82 100644 --- a/sun.cpp +++ b/sun.cpp @@ -54,7 +54,7 @@ cSun::update() { position = glm::rotateX( position, glm::radians( static_cast( m_body.elevref ) ) ); position = glm::rotateY( position, glm::radians( static_cast( -m_body.hrang ) ) ); - m_position = position; + m_position = glm::normalize( position ); } void @@ -62,12 +62,13 @@ cSun::render() { ::glColor4f( 255.f / 255.f, 242.f / 255.f, 231.f / 255.f, 1.f ); // debug line to locate the sun easier - ::glBegin( GL_LINES ); - ::glVertex3fv( glm::value_ptr( m_position ) ); - ::glVertex3f( m_position.x, 0.f, m_position.z ); + auto const position { m_position * 2000.f }; + ::glBegin( GL_LINES ); + ::glVertex3fv( glm::value_ptr( position ) ); + ::glVertex3f( position.x, 0.f, position.z ); ::glEnd(); ::glPushMatrix(); - ::glTranslatef( m_position.x, m_position.y, m_position.z ); + ::glTranslatef( position.x, position.y, position.z ); // radius is a result of scaling true distance down to 2km -- it's scaled by equal ratio ::gluSphere( sunsphere, m_body.distance * 9.359157, 12, 12 ); ::glPopMatrix(); @@ -140,14 +141,15 @@ void cSun::move() { if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; } - double ut = localtime.wHour - + localtime.wMinute / 60.0; // too low resolution, noticeable skips - // NOTE: finer resolution disabled to reduce shadow crawl in current implementation - /* - + localtime.wSecond / 3600.0 // good enough in normal circumstances + double ut = + localtime.wHour + + localtime.wMinute / 60.0 // too low resolution, noticeable skips + + localtime.wSecond / 3600.0; // good enough in normal circumstances +/* + localtime.wMilliseconds / 3600000.0; // for really smooth movement - */ - double daynumber = 367 * localtime.wYear +*/ + double daynumber = + 367 * localtime.wYear - 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4 + 275 * localtime.wMonth / 9 + localtime.wDay diff --git a/version.h b/version.h index 3fa33005..66ac26bd 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 210 +#define VERSION_MINOR 213 #define VERSION_REVISION 0