mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 10:59:18 +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:
128
Driver.cpp
128
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,15 +3632,13 @@ 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 );
|
||||
}
|
||||
}
|
||||
/*
|
||||
// NOTE: this section moved all cars to the edge of their respective roads
|
||||
// it may have some use eventually for collision avoidance,
|
||||
@@ -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 );
|
||||
}
|
||||
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
|
||||
else {
|
||||
mvControlling->PantFront( true );
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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
|
||||
{ // 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
|
||||
}
|
||||
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] & (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;
|
||||
}
|
||||
*/
|
||||
if ((OrderList[OrderPos] & (Obey_train | Shunt)) ?
|
||||
(iDrivigFlags & moveStopHere) :
|
||||
false)
|
||||
WaitingTime = -WaitingExpireTime; // zakaz ruszania z miejsca bez otrzymania
|
||||
// wolnej drogi
|
||||
else if (mvOccupied->CategoryFlag & 1)
|
||||
{ // jeśli pociąg
|
||||
if (AIControllFlag)
|
||||
|
||||
1
Driver.h
1
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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ) );
|
||||
|
||||
18
TrkFoll.cpp
18
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
|
||||
|
||||
@@ -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
|
||||
|
||||
28
moon.cpp
28
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<float>( m_body.elevref ) ) );
|
||||
position = glm::rotateY( position, glm::radians( static_cast<float>( -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
|
||||
|
||||
2
moon.h
2
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
|
||||
|
||||
33
renderer.cpp
33
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
|
||||
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<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 );
|
||||
::glPushMatrix();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
|
||||
40
sound.cpp
40
sound.cpp
@@ -324,7 +324,13 @@ sound_source::play( int const Flags ) {
|
||||
if( m_pitchvariation == 0.f ) {
|
||||
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 ) {
|
||||
// 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
|
||||
|
||||
3
sound.h
3
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<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
|
||||
|
||||
24
sun.cpp
24
sun.cpp
@@ -54,7 +54,7 @@ cSun::update() {
|
||||
position = glm::rotateX( position, glm::radians( static_cast<float>( m_body.elevref ) ) );
|
||||
position = glm::rotateY( position, glm::radians( static_cast<float>( -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
|
||||
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 );
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user