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

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

This commit is contained in:
tmj-fstate
2018-02-13 23:58:31 +01:00
parent e65e01a7a2
commit 62327d5d08
17 changed files with 185 additions and 140 deletions

View File

@@ -1212,8 +1212,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
} }
else else
{ // zawalidrogi nie ma (albo pojazd jest samochodem), sprawdzić sygnał { // zawalidrogi nie ma (albo pojazd jest samochodem), sprawdzić sygnał
if (sSpeedTable[i].iFlags & spShuntSemaphor) // jeśli Tm - w zasadzie to sprawdzić if (sSpeedTable[i].iFlags & spShuntSemaphor) // jeśli Tm - w zasadzie to sprawdzić komendę!
// komendę!
{ // jeśli podana prędkość manewrowa { // jeśli podana prędkość manewrowa
if ((OrderCurrentGet() & Obey_train) ? v == 0.0 : false) if ((OrderCurrentGet() & Obey_train) ? v == 0.0 : false)
{ // jeśli tryb pociągowy a tarcze ma ShuntVelocity 0 0 { // 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ę iDirectionOrder = -iDirection; // jak się podczepi, to jazda w przeciwną stronę
OrderNext(Change_direction); OrderNext(Change_direction);
} }
WaitingTime = WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
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 else // if (NewValue2==0.0) //zerowy sprzęg
if (NewValue1 >= 0.0) // jeśli ilość wagonów inna niż wszystkie 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 > else if (mvOccupied->Couplers[mvOccupied->DirAbsolute > 0 ? 1 : 0].CouplingFlag >
0) // z tyłu coś 0) // z tyłu coś
OrderNext(Disconnect); // jak ciągnie, to tylko odczep (NewValue1) wagonów OrderNext(Disconnect); // jak ciągnie, to tylko odczep (NewValue1) wagonów
WaitingTime = WaitingTime = 0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
0.0; // nie ma co dalej czekać, można zatrąbić i jechać, chyba że już jedzie
} }
if (NewValue1 == -1.0) 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 fActionTime += dt; // czas używany przy regulacji prędkości i zamykaniu drzwi
LastReactionTime += dt; LastReactionTime += dt;
LastUpdatedTime += dt; LastUpdatedTime += dt;
if( ( mvOccupied->Vel < 0.05 )
&& ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) {
IdleTime += dt;
}
else {
IdleTime = 0.0;
}
// log vehicle data // log vehicle data
if( ( WriteLogFlag ) if( ( WriteLogFlag )
@@ -3628,14 +3632,12 @@ TController::UpdateSituation(double dt) {
} }
} }
if (mvOccupied->Vel > 0.0) { if( mvOccupied->Vel > 1.0 ) {
// jeżeli jedzie // jeżeli jedzie
if( iDrivigFlags & moveDoorOpened ) { if( iDrivigFlags & moveDoorOpened ) {
// jeśli drzwi otwarte // jeśli drzwi otwarte
if( mvOccupied->Vel > 1.0 ) { // nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości
// nie zamykać drzwi przy drganiach, bo zatrzymanie na W4 akceptuje niewielkie prędkości Doors( false );
Doors( false );
}
} }
/* /*
// NOTE: this section moved all cars to the edge of their respective roads // 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 * mvOccupied->ChangeOffsetH(0.01 * mvOccupied->Vel *
dt); // Ra: co to miało być, to nie wiem dt); // Ra: co to miało być, to nie wiem
*/ */
if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) }
{
if ((fOverhead2 >= 0.0) || iOverheadZero) if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) {
{ // jeśli jazda bezprądowa albo z opuszczonym pantografem
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 while( DecSpeed( true ) ) { ; } // zerowanie napędu
} }
if ((fOverhead2 > 0.0) || iOverheadDown) if( ( fOverhead2 > 0.0 ) || iOverheadDown ) {
{ // jazda z opuszczonymi pantografami // jazda z opuszczonymi pantografami
mvControlling->PantFront(false); mvControlling->PantFront( false );
mvControlling->PantRear(false); mvControlling->PantRear( false );
} }
else else {
{ // jeśli nie trzeba opuszczać pantografów // jeśli nie trzeba opuszczać pantografów
if (iDirection >= 0) // jak jedzie w kierunku sprzęgu 0 // jazda na tylnym
mvControlling->PantRear(true); // jazda na tylnym if( iDirection >= 0 ) {
else // jak jedzie w kierunku sprzęgu 0
mvControlling->PantFront(true); mvControlling->PantRear( true );
}
else {
mvControlling->PantFront( true );
}
} }
if (mvOccupied->Vel > 10) // opuszczenie przedniego po rozpędzeniu się if( mvOccupied->Vel > 10 ) {
{ // opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden
if (mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
1) // o ile jest więcej niż jeden if( iDirection >= 0 ) // jak jedzie w kierunku sprzęgu 0
if (iDirection >= 0) // jak jedzie w kierunku sprzęgu 0
{ // poczekać na podniesienie tylnego { // poczekać na podniesienie tylnego
if (mvControlling->PantRearVolt != if( mvControlling->PantRearVolt != 0.0 ) {
0.0) // czy jest napięcie zasilające na tylnym? // czy jest napięcie zasilające na tylnym?
mvControlling->PantFront(false); // opuszcza od sprzęgu 0 mvControlling->PantFront( false ); // opuszcza od sprzęgu 0
}
} }
else else { // poczekać na podniesienie przedniego
{ // poczekać na podniesienie przedniego if( mvControlling->PantFrontVolt != 0.0 ) {
if (mvControlling->PantFrontVolt != // czy jest napięcie zasilające na przednim?
0.0) // czy jest napięcie zasilające na przednim? mvControlling->PantRear( false ); // opuszcza od sprzęgu 1
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 else
SetDriverPsyche(); // Ra: było w PrepareEngine(), potrzebne tu? SetDriverPsyche(); // Ra: było w PrepareEngine(), potrzebne tu?
// no albo przypisujemy -WaitingExpireTime, albo porównujemy z WaitingExpireTime
// if if (OrderList[OrderPos] & (Shunt | Obey_train | Connect)) {
// ((VelSignal==0.0)&&(WaitingTime>WaitingExpireTime)&&(mvOccupied->RunningTrack.Velmax!=0.0)) // odjechać sam może tylko jeśli jest w trybie jazdy
if (OrderList[OrderPos] & // automatyczne ruszanie po odstaniu albo spod SBL
(Shunt | Obey_train | Connect)) // odjechać sam może tylko jeśli jest w trybie jazdy if( ( VelSignal == 0.0 )
{ // automatyczne ruszanie po odstaniu albo spod SBL && ( WaitingTime > 0.0 )
if ((VelSignal == 0.0) && (WaitingTime > 0.0) && && ( mvOccupied->RunningTrack.Velmax != 0.0 ) ) {
(mvOccupied->RunningTrack.Velmax != 0.0)) // jeśli stoi, a upłynął czas oczekiwania i tor ma niezerową prędkość
{ // jeśli stoi, a upłynął czas oczekiwania i tor ma niezerową prędkość if( ( OrderList[ OrderPos ] & ( Obey_train | Shunt ) )
/* && ( iDrivigFlags & moveStopHere ) ) {
if (WriteLogFlag) // zakaz ruszania z miejsca bez otrzymania wolnej drogi
{ WaitingTime = -WaitingExpireTime;
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
else if (mvOccupied->CategoryFlag & 1) else if (mvOccupied->CategoryFlag & 1)
{ // jeśli pociąg { // jeśli pociąg
if (AIControllFlag) if (AIControllFlag)

View File

@@ -291,6 +291,7 @@ private:
double fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku) double fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku)
double WaitingTime = 0.0; // zliczany czas oczekiwania do samoistnego ruszenia 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 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 //---//---//---//---// private: //---//---//---//---// koniec zmiennych, poniżej metody //---//---//---//---//
void SetDriverPsyche(); void SetDriverPsyche();

View File

@@ -1106,9 +1106,10 @@ void TDynamicObject::ABuCheckMyTrack()
// do jednej tablicy. Wykonuje sie tylko raz - po to 'ABuChecked' // do jednej tablicy. Wykonuje sie tylko raz - po to 'ABuChecked'
TTrack *OldTrack = MyTrack; TTrack *OldTrack = MyTrack;
TTrack *NewTrack = Axle0.GetTrack(); TTrack *NewTrack = Axle0.GetTrack();
if ((NewTrack != OldTrack) && OldTrack) if( NewTrack != OldTrack ) {
{ if( OldTrack ) {
OldTrack->RemoveDynamicObject(this); OldTrack->RemoveDynamicObject( this );
}
NewTrack->AddDynamicObject(this); NewTrack->AddDynamicObject(this);
} }
iAxleFirst = 0; // pojazd powiązany z przednią osią - Axle0 iAxleFirst = 0; // pojazd powiązany z przednią osią - Axle0

View File

@@ -2974,10 +2974,7 @@ bool TMoverParameters::BrakeDelaySwitch(int BDS)
} }
else else
rBDS = false; rBDS = false;
if( true == rBDS ) {
// if setting was changed emit the sound of pneumatic relay
SetFlag( SoundFlag, sound::pneumatic );
}
return rBDS; return rBDS;
} }
@@ -8128,7 +8125,10 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
{ {
WriteLog( "Ready to depart" ); WriteLog( "Ready to depart" );
CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0; CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0;
ScndPipePress = CompressedVolume / VeselVolume; ScndPipePress = (
VeselVolume > 0.0 ?
CompressedVolume / VeselVolume :
0.0 );
PipePress = CntrlPipePress; PipePress = CntrlPipePress;
BrakePress = 0.0; BrakePress = 0.0;
LocalBrakePos = 0; LocalBrakePos = 0;
@@ -8633,8 +8633,6 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
if( true == Hamulec->SetBDF( brakesetting ) ) { if( true == Hamulec->SetBDF( brakesetting ) ) {
BrakeDelayFlag = brakesetting; BrakeDelayFlag = brakesetting;
OK = true; OK = true;
// if setting was changed emit the sound of pneumatic relay
SetFlag( SoundFlag, sound::pneumatic );
} }
else { else {
OK = false; OK = false;

View File

@@ -1223,7 +1223,7 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
{ {
if (FileExists(name + ".t3d")) if (FileExists(name + ".t3d"))
{ {
LoadFromTextFile(FileName, dynamic); // wczytanie tekstowego LoadFromTextFile(name + ".t3d", dynamic); // wczytanie tekstowego
if( !dynamic ) { if( !dynamic ) {
// pojazdy dopiero po ustawieniu animacji // pojazdy dopiero po ustawieniu animacji
Init(); // generowanie siatek i zapis E3D Init(); // generowanie siatek i zapis E3D

View File

@@ -3805,7 +3805,7 @@ bool TTrain::Update( double const Deltatime )
if( m_linebreakerstate == 2 ) { if( m_linebreakerstate == 2 ) {
// for diesels and/or vehicles with toggle switch setup we complete the engine start here // 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 // TBD, TODO: arrange a better way to start the diesel engines
if( ( ggMainOffButton.SubModel == nullptr ) if( ( ggMainOnButton.SubModel == nullptr )
|| ( ( mvControlled->EngineType == DieselEngine ) || ( ( mvControlled->EngineType == DieselEngine )
|| ( mvControlled->EngineType == DieselElectric ) ) ) { || ( mvControlled->EngineType == DieselElectric ) ) ) {
if( mvControlled->MainSwitch( true ) ) { if( mvControlled->MainSwitch( true ) ) {
@@ -4277,13 +4277,13 @@ bool TTrain::Update( double const Deltatime )
} }
btLampkaWylSzybki.Turn( btLampkaWylSzybki.Turn(
( ( (m_linebreakerstate > 0) ( ( (m_linebreakerstate == 2)
|| (true == mvControlled->Mains) ) ? || (true == mvControlled->Mains) ) ?
true : true :
false ) ); false ) );
// NOTE: 'off' variant uses the same test, but opposite resulting states // NOTE: 'off' variant uses the same test, but opposite resulting states
btLampkaWylSzybkiOff.Turn( btLampkaWylSzybkiOff.Turn(
( ( ( m_linebreakerstate > 0 ) ( ( ( m_linebreakerstate == 2 )
|| ( true == mvControlled->Mains ) ) ? || ( true == mvControlled->Mains ) ) ?
false : false :
true ) ); true ) );

View File

@@ -189,18 +189,19 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
*/ */
if (s < 0) if (s < 0)
{ // jeśli przekroczenie toru od strony Point1 { // jeśli przekroczenie toru od strony Point1
bCanSkip = bPrimary ? pCurrentTrack->CheckDynamicObject(Owner) : false; bCanSkip = ( bPrimary && pCurrentTrack->CheckDynamicObject( Owner ) );
if (bCanSkip) // tylko główna oś przenosi pojazd do innego toru if( bCanSkip ) {
Owner->MyTrack->RemoveDynamicObject( // tylko główna oś przenosi pojazd do innego toru
Owner); // zdejmujemy pojazd z dotychczasowego toru // zdejmujemy pojazd z dotychczasowego toru
Owner->MyTrack->RemoveDynamicObject( Owner );
}
dir = fDirection; dir = fDirection;
if (pCurrentTrack->eType == tt_Cross) if (pCurrentTrack->eType == tt_Cross)
{ {
if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 0)) if (!SetCurrentTrack(pCurrentTrack->Connected(iSegment, fDirection), 0))
return false; // wyjście z błędem return false; // wyjście z błędem
} }
else if (!SetCurrentTrack(pCurrentTrack->Connected(-1, fDirection), else if (!SetCurrentTrack(pCurrentTrack->Connected(-1, fDirection), 0)) // ustawia fDirection
0)) // ustawia fDirection
return false; // wyjście z błędem return false; // wyjście z błędem
if (dir == fDirection) //(pCurrentTrack->iPrevDirection) if (dir == fDirection) //(pCurrentTrack->iPrevDirection)
{ // gdy kierunek bez zmiany (Point1->Point2) { // gdy kierunek bez zmiany (Point1->Point2)
@@ -215,8 +216,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
if (bCanSkip) if (bCanSkip)
{ // jak główna oś, to dodanie pojazdu do nowego toru { // jak główna oś, to dodanie pojazdu do nowego toru
pCurrentTrack->AddDynamicObject(Owner); pCurrentTrack->AddDynamicObject(Owner);
iEventFlag = iEventFlag = 3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru
3; // McZapkie-020602: umozliwienie uruchamiania event1,2 po zmianie toru
iEventallFlag = 3; // McZapkie-280503: jw, dla eventall1,2 iEventallFlag = 3; // McZapkie-280503: jw, dla eventall1,2
if (!Owner->MyTrack) if (!Owner->MyTrack)
return false; return false;
@@ -225,7 +225,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
} }
else if (s > pCurrentSegment->GetLength()) else if (s > pCurrentSegment->GetLength())
{ // jeśli przekroczenie toru od strony Point2 { // 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 if (bCanSkip) // tylko główna oś przenosi pojazd do innego toru
Owner->MyTrack->RemoveDynamicObject( Owner->MyTrack->RemoveDynamicObject(
Owner); // zdejmujemy pojazd z dotychczasowego toru Owner); // zdejmujemy pojazd z dotychczasowego toru

View File

@@ -2170,7 +2170,7 @@ world_environment::update() {
if( moonlightlevel > sunlightlevel ) { if( moonlightlevel > sunlightlevel ) {
// rare situations when the moon is brighter than the sun, typically at night // rare situations when the moon is brighter than the sun, typically at night
Global.SunAngle = m_moon.getAngle(); 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(); Global.DayLight.direction = -1.0f * m_moon.getDirection();
keylightintensity = moonlightlevel; keylightintensity = moonlightlevel;
// if the moon is up, it overrides the twilight // if the moon is up, it overrides the twilight

View File

@@ -36,11 +36,11 @@ void
cMoon::update() { cMoon::update() {
move(); 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<float>( m_body.elevref ) ) ); position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) );
position = glm::rotateY( position, glm::radians( static_cast<float>( -m_body.hrang ) ) ); position = glm::rotateY( position, glm::radians( static_cast<float>( -m_body.hrang ) ) );
m_position = position; m_position = glm::normalize( position );
} }
void void
@@ -48,12 +48,13 @@ cMoon::render() {
::glColor4f( 225.f / 255.f, 225.f / 255.f, 255.f / 255.f, 1.f ); ::glColor4f( 225.f / 255.f, 225.f / 255.f, 255.f / 255.f, 1.f );
// debug line to locate the moon easier // debug line to locate the moon easier
auto const position { m_position * 2000.f };
::glBegin( GL_LINES ); ::glBegin( GL_LINES );
::glVertex3fv( glm::value_ptr( m_position ) ); ::glVertex3fv( glm::value_ptr( position ) );
::glVertex3f( m_position.x, 0.f, m_position.z ); ::glVertex3f( position.x, 0.f, position.z );
::glEnd(); ::glEnd();
::glPushMatrix(); ::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 ); ::gluSphere( moonsphere, /* (float)( Global.iWindowHeight / Global.FieldOfView ) * 0.5 * */ ( m_body.distance / 60.2666 ) * 9.037461, 12, 12 );
::glPopMatrix(); ::glPopMatrix();
} }
@@ -61,7 +62,7 @@ cMoon::render() {
glm::vec3 glm::vec3
cMoon::getDirection() { cMoon::getDirection() {
return glm::normalize( m_position ); return m_position;
} }
float float
@@ -117,14 +118,15 @@ void cMoon::move() {
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; } if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
double ut = localtime.wHour double ut =
+ localtime.wMinute / 60.0; // too low resolution, noticeable skips localtime.wHour
// NOTE: finer resolution disabled to reduce shadow crawl in current implementation + localtime.wMinute / 60.0 // too low resolution, noticeable skips
/* + localtime.wSecond / 3600.0; // good enough in normal circumstances
+ localtime.wSecond / 3600.0 // good enough in normal circumstances /*
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement + 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 - 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4
+ 275 * localtime.wMonth / 9 + 275 * localtime.wMonth / 9
+ localtime.wDay + localtime.wDay

2
moon.h
View File

@@ -16,8 +16,6 @@ public:
void init(); void init();
void update(); void update();
void render(); void render();
// returns location of the sun in the 3d scene
glm::vec3 getPosition() { return m_position; }
// returns vector pointing at the sun // returns vector pointing at the sun
glm::vec3 getDirection(); glm::vec3 getDirection();
// returns current elevation above horizon // returns current elevation above horizon

View File

@@ -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_total.start(); // note: gfx_total is actually frame total, clean this up
Timer::subsystem.gfx_color.start(); Timer::subsystem.gfx_color.start();
// fetch simulation data // 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 // generate new frame
m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_mode = rendermode::none; // force setup anew
m_debugtimestext.clear(); 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 ) + "; 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 ) + "; trk: " + to_string( m_debugstats.paths ) + " shp: " + to_string( m_debugstats.shapes )
+ " trc: " + to_string( m_debugstats.traction ) + " lin: " + to_string( m_debugstats.lines ); + " 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; ++m_framestamp;
return true; // for now always succeed return true; // for now always succeed
@@ -1481,7 +1469,14 @@ opengl_renderer::Render( world_environment *Environment ) {
{ {
Bind_Texture( m_moontexture ); Bind_Texture( m_moontexture );
glm::vec3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ); glm::vec3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 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<float>(
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 ); auto const moonposition = modelview * glm::vec4( Environment->m_moon.getDirection(), 1.0f );
::glPushMatrix(); ::glPushMatrix();

View File

@@ -820,6 +820,11 @@ state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratch
} }
} }
else { 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; delete vehicle;
skip_until( Input, "enddynamic" ); skip_until( Input, "enddynamic" );
return nullptr; return nullptr;

View File

@@ -305,7 +305,7 @@ void CSkyDome::RebuildColors() {
auto const sunbasedphase = clamp( (1.0f / 15.0f) * ( degreesabovehorizon - 10.0f ), 0.0f, 1.0f ); 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 // 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 ); 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 ); float const shiftfactor = clamp( interpolate(heightbasedphase, sunbasedphase, sunbasedphase), 0.0f, 1.0f );
// h = 210 makes for 'typical' sky tone // h = 210 makes for 'typical' sky tone
shiftedcolor = glm::vec3( 210.0f, colorconverter.y, colorconverter.z ); shiftedcolor = glm::vec3( 210.0f, colorconverter.y, colorconverter.z );

View File

@@ -324,7 +324,13 @@ sound_source::play( int const Flags ) {
if( m_pitchvariation == 0.f ) { if( m_pitchvariation == 0.f ) {
m_pitchvariation = 0.01f * static_cast<float>( Random( 97.5, 102.5 ) ); m_pitchvariation = 0.01f * static_cast<float>( 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 ) { if( sound( sound_id::main ).buffer != null_handle ) {
// basic variant: single main sound, with optional bookends // basic variant: single main sound, with optional bookends
play_basic(); play_basic();
@@ -352,8 +358,8 @@ sound_source::play_basic() {
} }
else { else {
// for single part non-looping samples we allow spawning multiple instances, if not prevented by set flags // 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 ) if( ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 )
&& ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 ) ) { && ( sound( sound_id::begin ).buffer == null_handle ) ) {
insert( sound_id::main ); insert( sound_id::main );
} }
} }
@@ -448,7 +454,7 @@ sound_source::stop( bool const Skipend ) {
if( ( false == Skipend ) if( ( false == Skipend )
&& ( sound( sound_id::end ).buffer != null_handle ) && ( 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 ).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 // spawn potentially defined sound end sample, if the emitter is currently active
insert( sound_id::end ); insert( sound_id::end );
} }
@@ -485,7 +491,18 @@ sound_source::update_basic( audio::openal_source &Source ) {
} }
return; 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 ) { if( sound( sound_id::begin ).buffer != null_handle ) {
// potentially a multipart sound // potentially a multipart sound
// detect the moment when the sound moves from startup sample to the main // 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; 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 ) { if( sound( sound_id::begin ).buffer != null_handle ) {
// potentially a multipart sound // potentially a multipart sound
// detect the moment when the sound moves from startup sample to the main // detect the moment when the sound moves from startup sample to the main

View File

@@ -203,6 +203,9 @@ private:
sound_properties m_properties; // current properties of the emitted sounds sound_properties m_properties; // current properties of the emitted sounds
float m_pitchvariation {}; // emitter-specific shift in base pitch float m_pitchvariation {}; // emitter-specific shift in base pitch
bool m_stop { false }; // indicates active sample instances should be terminated 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 bool m_playbeginning { true }; // indicates started sounds should be preceeded by opening bookend if there's one
std::array<sound_data, 3> m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends std::array<sound_data, 3> m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends
std::vector<soundchunk_pair> m_soundchunks; // table of samples activated when associated variable is within certain range std::vector<soundchunk_pair> m_soundchunks; // table of samples activated when associated variable is within certain range

26
sun.cpp
View File

@@ -54,7 +54,7 @@ cSun::update() {
position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) ); position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) );
position = glm::rotateY( position, glm::radians( static_cast<float>( -m_body.hrang ) ) ); position = glm::rotateY( position, glm::radians( static_cast<float>( -m_body.hrang ) ) );
m_position = position; m_position = glm::normalize( position );
} }
void void
@@ -62,12 +62,13 @@ cSun::render() {
::glColor4f( 255.f / 255.f, 242.f / 255.f, 231.f / 255.f, 1.f ); ::glColor4f( 255.f / 255.f, 242.f / 255.f, 231.f / 255.f, 1.f );
// debug line to locate the sun easier // debug line to locate the sun easier
::glBegin( GL_LINES ); auto const position { m_position * 2000.f };
::glVertex3fv( glm::value_ptr( m_position ) ); ::glBegin( GL_LINES );
::glVertex3f( m_position.x, 0.f, m_position.z ); ::glVertex3fv( glm::value_ptr( position ) );
::glVertex3f( position.x, 0.f, position.z );
::glEnd(); ::glEnd();
::glPushMatrix(); ::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 // 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 ); ::gluSphere( sunsphere, m_body.distance * 9.359157, 12, 12 );
::glPopMatrix(); ::glPopMatrix();
@@ -140,14 +141,15 @@ void cSun::move() {
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; } if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
double ut = localtime.wHour double ut =
+ localtime.wMinute / 60.0; // too low resolution, noticeable skips localtime.wHour
// NOTE: finer resolution disabled to reduce shadow crawl in current implementation + localtime.wMinute / 60.0 // too low resolution, noticeable skips
/* + localtime.wSecond / 3600.0; // good enough in normal circumstances
+ localtime.wSecond / 3600.0 // good enough in normal circumstances /*
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement + 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 - 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4
+ 275 * localtime.wMonth / 9 + 275 * localtime.wMonth / 9
+ localtime.wDay + localtime.wDay

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 18 #define VERSION_MAJOR 18
#define VERSION_MINOR 210 #define VERSION_MINOR 213
#define VERSION_REVISION 0 #define VERSION_REVISION 0