mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 06:29:18 +02:00
build 180923. basic precipitation visualization system, minor bug fixes
This commit is contained in:
88
Driver.cpp
88
Driver.cpp
@@ -238,9 +238,16 @@ void TSpeedPos::CommandCheck()
|
||||
case TCommandType::cm_PassengerStopPoint:
|
||||
// nie ma dostępu do rozkładu
|
||||
// przystanek, najwyżej AI zignoruje przy analizie tabelki
|
||||
// if ((iFlags & spPassengerStopPoint) == 0)
|
||||
fVelNext = 0.0; // TrainParams->IsStop()?0.0:-1.0; //na razie tak
|
||||
fVelNext = 0.0;
|
||||
iFlags |= spPassengerStopPoint; // niestety nie da się w tym miejscu współpracować z rozkładem
|
||||
/*
|
||||
// NOTE: not used for now as it might be unnecessary
|
||||
// special case, potentially override any set speed limits if requested
|
||||
// NOTE: we test it here because for the time being it's only used for passenger stops
|
||||
if( TestFlag( iFlags, spDontApplySpeedLimit ) ) {
|
||||
fVelNext = -1;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case TCommandType::cm_SetProximityVelocity:
|
||||
// musi zostać gdyż inaczej nie działają manewry
|
||||
@@ -879,7 +886,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
// TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie
|
||||
// jest dobry pomysł
|
||||
sSpeedTable[i].iFlags = 0; // nie liczy się już
|
||||
sSpeedTable[i].fVelNext = -1; // jechać
|
||||
continue; // nie analizować prędkości
|
||||
}
|
||||
} // koniec obsługi przelotu na W4
|
||||
@@ -1035,9 +1041,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
iDrivigFlags |= moveStopCloser; // do następnego W4 podjechać blisko (z dociąganiem)
|
||||
sSpeedTable[i].iFlags = 0; // nie liczy się już zupełnie (nie wyśle SetVelocity)
|
||||
sSpeedTable[i].fVelNext = -1; // można jechać za W4
|
||||
if( ( sSpeedTable[ i ].fDist <= 0.0 ) && ( eSignNext == sSpeedTable[ i ].evEvent ) ) {
|
||||
// sanity check, if we're held by this stop point, let us go
|
||||
VelSignalLast = -1;
|
||||
}
|
||||
if (go == TCommandType::cm_Unknown) // jeśli nie było komendy wcześniej
|
||||
go = TCommandType::cm_Ready; // gotów do odjazdu z W4 (semafor może
|
||||
// zatrzymać)
|
||||
go = TCommandType::cm_Ready; // gotów do odjazdu z W4 (semafor może zatrzymać)
|
||||
if( false == tsGuardSignal.empty() ) {
|
||||
// jeśli mamy głos kierownika, to odegrać
|
||||
iDrivigFlags |= moveGuardSignal;
|
||||
@@ -1061,14 +1070,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
// if the consist can change direction through a simple cab change it doesn't need fiddling with recognition of passenger stops
|
||||
iDrivigFlags &= ~( moveStopPoint );
|
||||
}
|
||||
fLastStopExpDist = -1.0f; // nie ma rozkładu, nie ma usuwania stacji
|
||||
sSpeedTable[i].iFlags = 0; // W4 nie liczy się już (nie wyśle SetVelocity)
|
||||
sSpeedTable[i].fVelNext = -1; // można jechać za W4
|
||||
fLastStopExpDist = -1.0f; // nie ma rozkładu, nie ma usuwania stacji
|
||||
// wykonanie kolejnego rozkazu (Change_direction albo Shunt)
|
||||
// FIX: don't automatically advance if there's disconnect procedure in progress
|
||||
if( false == TestFlag( OrderCurrentGet(), Disconnect ) ) {
|
||||
JumpToNextOrder();
|
||||
if( ( sSpeedTable[ i ].fDist <= 0.0 ) && ( eSignNext == sSpeedTable[ i ].evEvent ) ) {
|
||||
// sanity check, if we're held by this stop point, let us go
|
||||
VelSignalLast = -1;
|
||||
}
|
||||
// wykonanie kolejnego rozkazu (Change_direction albo Shunt)
|
||||
JumpToNextOrder();
|
||||
// ma się nie ruszać aż do momentu podania sygnału
|
||||
iDrivigFlags |= moveStopHere | moveStartHorn;
|
||||
continue; // nie analizować prędkości
|
||||
@@ -1094,36 +1104,42 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
}
|
||||
else if (sSpeedTable[i].iFlags & spEvent) // W4 może się deaktywować
|
||||
{ // jeżeli event, może być potrzeba wysłania komendy, aby ruszył
|
||||
// sprawdzanie eventów pasywnych miniętych
|
||||
if( (sSpeedTable[ i ].fDist < 0.0) && (SemNextIndex == i) )
|
||||
{
|
||||
if( Global.iWriteLogEnabled & 8 ) {
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", passed semaphor " + sSpeedTable[ SemNextIndex ].GetName() );
|
||||
if( sSpeedTable[ i ].fDist < 0.0 ) {
|
||||
// sprawdzanie eventów pasywnych miniętych
|
||||
/*
|
||||
if( ( eSignNext != nullptr ) && ( sSpeedTable[ i ].evEvent == eSignNext ) ) {
|
||||
VelSignalLast = sSpeedTable[ i ].fVelNext;
|
||||
}
|
||||
SemNextIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód
|
||||
}
|
||||
if( (sSpeedTable[ i ].fDist < 0.0) && (SemNextStopIndex == i) )
|
||||
{
|
||||
if( Global.iWriteLogEnabled & 8 ) {
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", passed semaphor " + sSpeedTable[ SemNextStopIndex ].GetName() );
|
||||
}
|
||||
SemNextStopIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód
|
||||
}
|
||||
if (sSpeedTable[i].fDist > 0.0 &&
|
||||
sSpeedTable[i].IsProperSemaphor(OrderCurrentGet()))
|
||||
{
|
||||
if( SemNextIndex == -1 ) {
|
||||
// jeśli jest mienięty poprzedni semafor a wcześniej
|
||||
// byl nowy to go dorzucamy do zmiennej, żeby cały czas widział najbliższy
|
||||
SemNextIndex = i;
|
||||
*/
|
||||
if( SemNextIndex == i ) {
|
||||
if( Global.iWriteLogEnabled & 8 ) {
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", next semaphor is " + sSpeedTable[ SemNextIndex ].GetName() );
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", passed semaphor " + sSpeedTable[ SemNextIndex ].GetName() );
|
||||
}
|
||||
SemNextIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód
|
||||
}
|
||||
if( ( SemNextStopIndex == -1 )
|
||||
|| ( ( sSpeedTable[SemNextStopIndex].fVelNext != 0 )
|
||||
&& ( sSpeedTable[ i ].fVelNext == 0 ) ) ) {
|
||||
SemNextStopIndex = i;
|
||||
if( SemNextStopIndex == i ) {
|
||||
if( Global.iWriteLogEnabled & 8 ) {
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", passed semaphor " + sSpeedTable[ SemNextStopIndex ].GetName() );
|
||||
}
|
||||
SemNextStopIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód
|
||||
}
|
||||
}
|
||||
if( sSpeedTable[ i ].fDist > 0.0 ) {
|
||||
// check signals ahead
|
||||
if( sSpeedTable[ i ].IsProperSemaphor( OrderCurrentGet() ) ) {
|
||||
if( SemNextIndex == -1 ) {
|
||||
// jeśli jest mienięty poprzedni semafor a wcześniej
|
||||
// byl nowy to go dorzucamy do zmiennej, żeby cały czas widział najbliższy
|
||||
SemNextIndex = i;
|
||||
if( Global.iWriteLogEnabled & 8 ) {
|
||||
WriteLog( "Speed table update for " + OwnerName() + ", next semaphor is " + sSpeedTable[ SemNextIndex ].GetName() );
|
||||
}
|
||||
}
|
||||
if( ( SemNextStopIndex == -1 )
|
||||
|| ( ( sSpeedTable[ SemNextStopIndex ].fVelNext != 0 )
|
||||
&& ( sSpeedTable[ i ].fVelNext == 0 ) ) ) {
|
||||
SemNextStopIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sSpeedTable[i].iFlags & spOutsideStation)
|
||||
|
||||
4
Driver.h
4
Driver.h
@@ -119,8 +119,8 @@ enum TSpeedPosFlag
|
||||
spSemaphor = 0x4000, // semafor pociągowy
|
||||
spRoadVel = 0x8000, // zadanie prędkości drogowej
|
||||
spSectionVel = 0x20000, // odcinek z ograniczeniem
|
||||
spProximityVelocity = 0x40000, // odcinek z ograniczeniem i podaną jego długościa
|
||||
spEndOfTable = 0x10000 // zatkanie tabelki
|
||||
spProximityVelocity = 0x40000 // odcinek z ograniczeniem i podaną jego długościa
|
||||
// spDontApplySpeedLimit = 0x10000 // this point won't apply its speed limit. potentially set by the scanning vehicle
|
||||
};
|
||||
|
||||
class TSpeedPos
|
||||
|
||||
10
DynObj.cpp
10
DynObj.cpp
@@ -2014,7 +2014,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
||||
auto const indexstart { 1 };
|
||||
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||
auto const huntingchance { std::atoi( ActPar.substr( indexstart, indexend ).c_str() ) };
|
||||
MoverParameters->TruckHunting = ( Random( 0, 100 ) <= huntingchance );
|
||||
MoverParameters->TruckHunting = ( Random( 0, 100 ) < huntingchance );
|
||||
ActPar.erase( 0, indexend );
|
||||
break;
|
||||
}
|
||||
@@ -2396,12 +2396,12 @@ void TDynamicObject::Move(double fDistance)
|
||||
// normalizacja potrzebna z powodu pochylenia (vFront)
|
||||
vUp = CrossProduct(vFront, vLeft); // wektor w górę, będzie jednostkowy
|
||||
modelRot.z = atan2(-vFront.x, vFront.z); // kąt obrotu pojazdu [rad]; z ABuBogies()
|
||||
double a = ((Axle1.GetRoll() + Axle0.GetRoll())); // suma przechyłek
|
||||
if (a != 0.0)
|
||||
auto const roll { Roll() }; // suma przechyłek
|
||||
if (roll != 0.0)
|
||||
{ // wyznaczanie przechylenia tylko jeśli jest przechyłka
|
||||
// można by pobrać wektory normalne z toru...
|
||||
mMatrix.Identity(); // ta macierz jest potrzebna głównie do wyświetlania
|
||||
mMatrix.Rotation(a * 0.5, vFront); // obrót wzdłuż osi o przechyłkę
|
||||
mMatrix.Rotation(roll * 0.5, vFront); // obrót wzdłuż osi o przechyłkę
|
||||
vUp = mMatrix * vUp; // wektor w górę pojazdu (przekręcenie na przechyłce)
|
||||
// vLeft=mMatrix*DynamicObject->vLeft;
|
||||
// vUp=CrossProduct(vFront,vLeft); //wektor w górę
|
||||
@@ -2838,7 +2838,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
// TTrackParam tp;
|
||||
tp.Width = MyTrack->fTrackWidth;
|
||||
// McZapkie-250202
|
||||
tp.friction = MyTrack->fFriction * Global.fFriction;
|
||||
tp.friction = MyTrack->fFriction * Global.fFriction * Global.FrictionWeatherFactor;
|
||||
tp.CategoryFlag = MyTrack->iCategoryFlag & 15;
|
||||
tp.DamageFlag = MyTrack->iDamageFlag;
|
||||
tp.QualityFlag = MyTrack->iQualityFlag;
|
||||
|
||||
2
DynObj.h
2
DynObj.h
@@ -546,6 +546,8 @@ private:
|
||||
return iAxleFirst ?
|
||||
Axle1.pPosition :
|
||||
Axle0.pPosition; };
|
||||
inline double Roll() {
|
||||
return ( ( Axle1.GetRoll() + Axle0.GetRoll() ) ); }
|
||||
/*
|
||||
// TODO: check if scanning takes into account direction when selecting axle
|
||||
// if it does, replace the version above
|
||||
|
||||
@@ -65,6 +65,7 @@ struct global_settings {
|
||||
bool RealisticControlMode{ false }; // controls ability to steer the vehicle from outside views
|
||||
bool bEnableTraction{ true };
|
||||
float fFriction{ 1.f }; // mnożnik tarcia - KURS90
|
||||
float FrictionWeatherFactor { 1.f };
|
||||
bool bLiveTraction{ true };
|
||||
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
||||
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
||||
|
||||
49
Train.cpp
49
Train.cpp
@@ -527,9 +527,9 @@ PyObject *TTrain::GetTrainState() {
|
||||
PyDict_SetItemString( dict, "unit_no", PyGetInt( iUnitNo ) );
|
||||
|
||||
for( int i = 0; i < 20; i++ ) {
|
||||
PyDict_SetItemString( dict, ( "doors_" + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 0 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_r_" + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 1 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_l_" + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 2 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 0 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_r_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 1 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_l_" + std::to_string( i + 1 ) ).c_str(), PyGetBool( bDoors[ i ][ 2 ] ) );
|
||||
PyDict_SetItemString( dict, ( "doors_no_" + std::to_string( i + 1 ) ).c_str(), PyGetInt( iDoorNo[ i ] ) );
|
||||
PyDict_SetItemString( dict, ( "code_" + std::to_string( i + 1 ) ).c_str(), PyGetString( ( std::to_string( iUnits[ i ] ) + cCode[ i ] ).c_str() ) );
|
||||
PyDict_SetItemString( dict, ( "car_name" + std::to_string( i + 1 ) ).c_str(), PyGetString( asCarName[ i ].c_str() ) );
|
||||
@@ -4529,31 +4529,14 @@ void TTrain::UpdateMechPosition(double dt)
|
||||
2 :
|
||||
DynamicObject->MoverParameters->ActiveCab );
|
||||
if( !DebugModeFlag ) { // sprawdzaj więzy //Ra: nie tu!
|
||||
if( pMechPosition.x < Cabine[ iCabn ].CabPos1.x )
|
||||
pMechPosition.x = Cabine[ iCabn ].CabPos1.x;
|
||||
if( pMechPosition.x > Cabine[ iCabn ].CabPos2.x )
|
||||
pMechPosition.x = Cabine[ iCabn ].CabPos2.x;
|
||||
if( pMechPosition.z < Cabine[ iCabn ].CabPos1.z )
|
||||
pMechPosition.z = Cabine[ iCabn ].CabPos1.z;
|
||||
if( pMechPosition.z > Cabine[ iCabn ].CabPos2.z )
|
||||
pMechPosition.z = Cabine[ iCabn ].CabPos2.z;
|
||||
if( pMechPosition.y > Cabine[ iCabn ].CabPos1.y + 1.8 )
|
||||
pMechPosition.y = Cabine[ iCabn ].CabPos1.y + 1.8;
|
||||
if( pMechPosition.y < Cabine[ iCabn ].CabPos1.y + 0.5 )
|
||||
pMechPosition.y = Cabine[ iCabn ].CabPos2.y + 0.5;
|
||||
|
||||
if( pMechOffset.x < Cabine[ iCabn ].CabPos1.x )
|
||||
pMechOffset.x = Cabine[ iCabn ].CabPos1.x;
|
||||
if( pMechOffset.x > Cabine[ iCabn ].CabPos2.x )
|
||||
pMechOffset.x = Cabine[ iCabn ].CabPos2.x;
|
||||
if( pMechOffset.z < Cabine[ iCabn ].CabPos1.z )
|
||||
pMechOffset.z = Cabine[ iCabn ].CabPos1.z;
|
||||
if( pMechOffset.z > Cabine[ iCabn ].CabPos2.z )
|
||||
pMechOffset.z = Cabine[ iCabn ].CabPos2.z;
|
||||
if( pMechOffset.y > Cabine[ iCabn ].CabPos1.y + 1.8 )
|
||||
pMechOffset.y = Cabine[ iCabn ].CabPos1.y + 1.8;
|
||||
if( pMechOffset.y < Cabine[ iCabn ].CabPos1.y + 0.5 )
|
||||
pMechOffset.y = Cabine[ iCabn ].CabPos2.y + 0.5;
|
||||
pMechPosition.x = clamp( pMechPosition.x, Cabine[ iCabn ].CabPos1.x, Cabine[ iCabn ].CabPos2.x );
|
||||
pMechPosition.y = clamp( pMechPosition.y, Cabine[ iCabn ].CabPos1.y + 0.5, Cabine[ iCabn ].CabPos2.y + 1.8 );
|
||||
pMechPosition.z = clamp( pMechPosition.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z );
|
||||
|
||||
pMechOffset.x = clamp( pMechOffset.x, Cabine[ iCabn ].CabPos1.x, Cabine[ iCabn ].CabPos2.x );
|
||||
pMechOffset.y = clamp( pMechOffset.y, Cabine[ iCabn ].CabPos1.y + 0.5, Cabine[ iCabn ].CabPos2.y + 1.8 );
|
||||
pMechOffset.z = clamp( pMechOffset.z, Cabine[ iCabn ].CabPos1.z, Cabine[ iCabn ].CabPos2.z );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5863,7 +5846,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
dsbSlipAlarm.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// szum w czasie jazdy
|
||||
if( ( false == FreeFlyModeFlag )
|
||||
&& ( false == Global.CabWindowOpen )
|
||||
@@ -5875,6 +5858,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
// don't play the optional ending sound if the listener switches views
|
||||
rsRunningNoise.stop( true == FreeFlyModeFlag );
|
||||
}
|
||||
*/
|
||||
// hunting oscillation noise
|
||||
if( ( false == FreeFlyModeFlag )
|
||||
&& ( false == Global.CabWindowOpen )
|
||||
@@ -5882,6 +5866,15 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
&& ( IsHunting ) ) {
|
||||
|
||||
update_sounds_runningnoise( rsHuntingNoise );
|
||||
// modify calculated sound volume by hunting amount
|
||||
auto const huntingamount =
|
||||
interpolate(
|
||||
0.0, 1.0,
|
||||
clamp(
|
||||
( mvOccupied->Vel - HuntingShake.fadein_begin ) / ( HuntingShake.fadein_end - HuntingShake.fadein_begin ),
|
||||
0.0, 1.0 ) );
|
||||
|
||||
rsHuntingNoise.gain( rsHuntingNoise.gain() * huntingamount );
|
||||
}
|
||||
else {
|
||||
// don't play the optional ending sound if the listener switches views
|
||||
|
||||
@@ -224,6 +224,8 @@ driver_mode::update() {
|
||||
|
||||
update_camera( deltarealtime );
|
||||
|
||||
simulation::Environment.update_precipitation(); // has to be launched after camera step to work properly
|
||||
|
||||
Timer::subsystem.sim_total.stop();
|
||||
|
||||
simulation::Region->update_sounds();
|
||||
@@ -951,6 +953,7 @@ driver_mode::InOutKey( bool const Near )
|
||||
train->Dynamic()->ABuSetModelShake( { 0, 0, 0 } );
|
||||
train->MechStop();
|
||||
FollowView(); // na pozycję mecha
|
||||
train->UpdateMechPosition( m_secondaryupdaterate );
|
||||
}
|
||||
else
|
||||
FreeFlyModeFlag = true; // nadal poza kabiną
|
||||
|
||||
@@ -330,6 +330,9 @@
|
||||
<ClCompile Include="ref\imgui\imgui_widgets.cpp">
|
||||
<Filter>Source Files\imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="precipitation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Globals.h">
|
||||
@@ -608,6 +611,9 @@
|
||||
<ClInclude Include="editoruipanels.h">
|
||||
<Filter>Header Files\application\mode_editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="precipitation.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
@@ -43,12 +43,16 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
|
||||
if( key == Global.Weather ) {
|
||||
// weather textures override generic (pri 0) and seasonal (pri 1) textures
|
||||
// seasonal weather textures (pri 1+2=3) override generic weather (pri 2) textures
|
||||
// skip the opening bracket
|
||||
auto const value { Input.getToken<std::string>( true, "\n\r\t ;" ) };
|
||||
while( true == deserialize_mapping( Input, Priority + 2, Loadnow ) ) {
|
||||
; // all work is done in the header
|
||||
}
|
||||
}
|
||||
else if( key == Global.Season ) {
|
||||
// seasonal textures override generic textures
|
||||
// skip the opening bracket
|
||||
auto const value { Input.getToken<std::string>( true, "\n\r\t ;" ) };
|
||||
while( true == deserialize_mapping( Input, 1, Loadnow ) ) {
|
||||
; // all work is done in the header
|
||||
}
|
||||
|
||||
197
precipitation.cpp
Normal file
197
precipitation.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "precipitation.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "openglmatrixstack.h"
|
||||
#include "renderer.h"
|
||||
#include "timer.h"
|
||||
#include "simulation.h"
|
||||
#include "train.h"
|
||||
|
||||
basic_precipitation::~basic_precipitation() {
|
||||
// TODO: release allocated resources
|
||||
}
|
||||
|
||||
void
|
||||
basic_precipitation::create( int const Tesselation ) {
|
||||
|
||||
auto const heightfactor { 10.f }; // height-to-radius factor
|
||||
m_moverate *= heightfactor;
|
||||
auto const verticaltexturestretchfactor { 1.5f }; // crude motion blur
|
||||
|
||||
// create geometry chunk
|
||||
auto const latitudes { 3 }; // just a cylinder with end cones
|
||||
auto const longitudes { Tesselation };
|
||||
auto const longitudehalfstep { 0.5f * static_cast<float>( 2.0 * M_PI * 1.f / longitudes ) }; // for crude uv correction
|
||||
|
||||
std::uint16_t index = 0;
|
||||
|
||||
// auto const radius { 25.f }; // cylinder radius
|
||||
std::vector<float> radii { 25.f, 10.f, 5.f, 1.f };
|
||||
for( auto radius : radii ) {
|
||||
|
||||
for( int i = 0; i <= latitudes; ++i ) {
|
||||
|
||||
auto const latitude{ static_cast<float>( M_PI * ( -0.5f + (float)( i ) / latitudes ) ) };
|
||||
auto const z{ std::sin( latitude ) };
|
||||
auto const zr{ std::cos( latitude ) };
|
||||
|
||||
for( int j = 0; j <= longitudes; ++j ) {
|
||||
// NOTE: for the first and last row half of the points we create end up unused but, eh
|
||||
auto const longitude{ static_cast<float>( 2.0 * M_PI * (float)( j ) / longitudes ) };
|
||||
auto const x{ std::cos( longitude ) };
|
||||
auto const y{ std::sin( longitude ) };
|
||||
// NOTE: cartesian to opengl swap would be: -x, -z, -y
|
||||
m_vertices.emplace_back( glm::vec3( -x * zr, -z * heightfactor, -y * zr ) * radius );
|
||||
// uvs
|
||||
// NOTE: first and last row receives modified u values to deal with limitation of mapping onto triangles
|
||||
auto u = (
|
||||
i == 0 ? longitude + longitudehalfstep :
|
||||
i == latitudes ? longitude - longitudehalfstep :
|
||||
longitude );
|
||||
m_uvs.emplace_back(
|
||||
u / ( 2.0 * M_PI ) * radius,
|
||||
1.f - (float)( i ) / latitudes * radius * heightfactor * 0.5f / verticaltexturestretchfactor );
|
||||
|
||||
if( ( i == 0 ) || ( j == 0 ) ) {
|
||||
// initial edge of the dome, don't start indices yet
|
||||
++index;
|
||||
}
|
||||
else {
|
||||
// the end cones are built from one triangle of each quad, the middle rows use both
|
||||
if( i < latitudes ) {
|
||||
m_indices.emplace_back( index - 1 - ( longitudes + 1 ) );
|
||||
m_indices.emplace_back( index - 1 );
|
||||
m_indices.emplace_back( index );
|
||||
}
|
||||
if( i > 1 ) {
|
||||
m_indices.emplace_back( index );
|
||||
m_indices.emplace_back( index - ( longitudes + 1 ) );
|
||||
m_indices.emplace_back( index - 1 - ( longitudes + 1 ) );
|
||||
}
|
||||
++index;
|
||||
}
|
||||
} // longitude
|
||||
} // latitude
|
||||
} // radius
|
||||
}
|
||||
|
||||
bool
|
||||
basic_precipitation::init() {
|
||||
|
||||
create( 18 );
|
||||
|
||||
// TODO: select texture based on current overcast level
|
||||
if( Global.Weather == "rain:" ) {
|
||||
m_texture = GfxRenderer.Fetch_Texture( "fx/rain_medium" );
|
||||
m_moverateweathertypefactor = 2.f;
|
||||
}
|
||||
else if( Global.Weather == "snow:" ) {
|
||||
m_texture = GfxRenderer.Fetch_Texture( "fx/snow_medium" );
|
||||
m_moverateweathertypefactor = 1.25f;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
basic_precipitation::update() {
|
||||
|
||||
auto const timedelta { static_cast<float>( ( DebugModeFlag ? Timer::GetDeltaTime() : Timer::GetDeltaTime() ) ) };
|
||||
|
||||
if( timedelta == 0.0 ) { return; }
|
||||
|
||||
m_textureoffset += m_moverate * m_moverateweathertypefactor * timedelta;
|
||||
m_textureoffset = clamp_circular( m_textureoffset, 1.f );
|
||||
|
||||
auto cameramove { glm::dvec3{ Global.pCamera.Pos - m_camerapos} };
|
||||
cameramove.y = 0.0; // vertical movement messes up vector calculation
|
||||
|
||||
m_camerapos = Global.pCamera.Pos;
|
||||
|
||||
// intercept sudden user-induced camera jumps
|
||||
if( m_freeflymode != FreeFlyModeFlag ) {
|
||||
m_freeflymode = FreeFlyModeFlag;
|
||||
if( true == m_freeflymode ) {
|
||||
// cache last precipitation vector in the cab
|
||||
m_cabcameramove = m_cameramove;
|
||||
// don't carry previous precipitation vector to a new unrelated location
|
||||
m_cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
else {
|
||||
// restore last cached precipitation vector
|
||||
m_cameramove = m_cabcameramove;
|
||||
}
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
if( m_windowopen != Global.CabWindowOpen ) {
|
||||
m_windowopen = Global.CabWindowOpen;
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
if( ( simulation::Train != nullptr ) && ( simulation::Train->iCabn != m_activecab ) ) {
|
||||
m_activecab = simulation::Train->iCabn;
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
if( glm::length( cameramove ) > 100.0 ) {
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
|
||||
m_cameramove = m_cameramove * std::max( 0.0, 1.0 - 5.0 * timedelta ) + cameramove * ( 30.0 * timedelta );
|
||||
if( std::abs( m_cameramove.x ) < 0.001 ) { m_cameramove.x = 0.0; }
|
||||
if( std::abs( m_cameramove.y ) < 0.001 ) { m_cameramove.y = 0.0; }
|
||||
if( std::abs( m_cameramove.z ) < 0.001 ) { m_cameramove.z = 0.0; }
|
||||
}
|
||||
|
||||
void
|
||||
basic_precipitation::render() {
|
||||
|
||||
GfxRenderer.Bind_Texture( m_texture );
|
||||
|
||||
// cache entry state
|
||||
::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
|
||||
|
||||
if( m_vertexbuffer == -1 ) {
|
||||
// build the buffers
|
||||
::glGenBuffers( 1, &m_vertexbuffer );
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer );
|
||||
::glBufferData( GL_ARRAY_BUFFER, m_vertices.size() * sizeof( glm::vec3 ), m_vertices.data(), GL_STATIC_DRAW );
|
||||
|
||||
::glGenBuffers( 1, &m_uvbuffer );
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, m_uvbuffer );
|
||||
::glBufferData( GL_ARRAY_BUFFER, m_uvs.size() * sizeof( glm::vec2 ), m_uvs.data(), GL_STATIC_DRAW );
|
||||
|
||||
::glGenBuffers( 1, &m_indexbuffer );
|
||||
::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer );
|
||||
::glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof( unsigned short ), m_indices.data(), GL_STATIC_DRAW );
|
||||
// NOTE: vertex and index source data is superfluous past this point, but, eh
|
||||
}
|
||||
// positions
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, m_vertexbuffer );
|
||||
::glVertexPointer( 3, GL_FLOAT, sizeof( glm::vec3 ), reinterpret_cast<void const*>( 0 ) );
|
||||
::glEnableClientState( GL_VERTEX_ARRAY );
|
||||
// uvs
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, m_uvbuffer );
|
||||
::glClientActiveTexture( m_textureunit );
|
||||
::glTexCoordPointer( 2, GL_FLOAT, sizeof( glm::vec2 ), reinterpret_cast<void const*>( 0 ) );
|
||||
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
// uv transformation matrix
|
||||
::glMatrixMode( GL_TEXTURE );
|
||||
::glLoadIdentity();
|
||||
::glTranslatef( 0.f, m_textureoffset, 0.f );
|
||||
// indices
|
||||
::glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indexbuffer );
|
||||
::glDrawElements( GL_TRIANGLES, static_cast<GLsizei>( m_indices.size() ), GL_UNSIGNED_SHORT, reinterpret_cast<void const*>( 0 ) );
|
||||
// cleanup
|
||||
::glLoadIdentity();
|
||||
::glMatrixMode( GL_MODELVIEW );
|
||||
::glPopClientAttrib();
|
||||
}
|
||||
59
precipitation.h
Normal file
59
precipitation.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
// based on "Rendering Falling Rain and Snow"
|
||||
// by Niniane Wang, Bretton Wade
|
||||
|
||||
class basic_precipitation {
|
||||
|
||||
public:
|
||||
// constructors
|
||||
basic_precipitation() = default;
|
||||
// destructor
|
||||
~basic_precipitation();
|
||||
// methods
|
||||
inline
|
||||
void
|
||||
set_unit( GLint const Textureunit ) {
|
||||
m_textureunit = Textureunit; }
|
||||
bool
|
||||
init();
|
||||
void
|
||||
update();
|
||||
void
|
||||
render();
|
||||
|
||||
glm::dvec3 m_cameramove{ 0.0 };
|
||||
|
||||
private:
|
||||
// methods
|
||||
void create( int const Tesselation );
|
||||
|
||||
// members
|
||||
std::vector<glm::vec3> m_vertices;
|
||||
std::vector<glm::vec2> m_uvs;
|
||||
std::vector<std::uint16_t> m_indices;
|
||||
GLuint m_vertexbuffer { (GLuint)-1 };
|
||||
GLuint m_uvbuffer { (GLuint)-1 };
|
||||
GLuint m_indexbuffer { (GLuint)-1 };
|
||||
GLint m_textureunit { 0 };
|
||||
texture_handle m_texture { -1 };
|
||||
float m_textureoffset { 0.f };
|
||||
float m_moverate { 30 * 0.001f };
|
||||
float m_moverateweathertypefactor { 1.f }; // medium-dependent; 1.0 for snow, faster for rain
|
||||
glm::dvec3 m_camerapos { 0.0 };
|
||||
bool m_freeflymode { true };
|
||||
bool m_windowopen { true };
|
||||
int m_activecab{ 0 };
|
||||
glm::dvec3 m_cabcameramove{ 0.0 };
|
||||
};
|
||||
71
renderer.cpp
71
renderer.cpp
@@ -129,6 +129,7 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
std::vector<GLint>{ m_normaltextureunit, m_diffusetextureunit } );
|
||||
m_textures.assign_units( m_helpertextureunit, m_shadowtextureunit, m_normaltextureunit, m_diffusetextureunit ); // TODO: add reflections unit
|
||||
ui_layer::set_unit( m_diffusetextureunit );
|
||||
simulation::Environment.m_precipitation.set_unit( m_diffusetextureunit );
|
||||
select_unit( m_diffusetextureunit );
|
||||
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
@@ -550,7 +551,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
#endif
|
||||
if( false == FreeFlyModeFlag ) {
|
||||
// without rain/snow we can render the cab early to limit the overdraw
|
||||
if( ( false == FreeFlyModeFlag )
|
||||
&& ( Global.Overcast <= 1.f ) ) { // precipitation happens when overcast is in 1-2 range
|
||||
switch_units( true, true, false );
|
||||
setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
|
||||
// cache shadow colour in case we need to account for cab light
|
||||
@@ -570,8 +573,10 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
// ...translucent parts
|
||||
setup_drawing( true );
|
||||
Render_Alpha( simulation::Region );
|
||||
// precipitation; done at the end, only before cab render
|
||||
Render_precipitation();
|
||||
// cab render
|
||||
if( false == FreeFlyModeFlag ) {
|
||||
// cab render is performed without shadows, due to low resolution and number of models without windows :|
|
||||
switch_units( true, true, false );
|
||||
setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
|
||||
// cache shadow colour in case we need to account for cab light
|
||||
@@ -580,6 +585,12 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||
setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
|
||||
}
|
||||
if( Global.Overcast > 1.f ) {
|
||||
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||
setup_drawing( false );
|
||||
Render_cab( vehicle, false );
|
||||
setup_drawing( true );
|
||||
}
|
||||
Render_cab( vehicle, true );
|
||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||
setup_shadow_color( shadowcolor );
|
||||
@@ -590,7 +601,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
// restore default texture matrix for reflections cube map
|
||||
select_unit( m_helpertextureunit );
|
||||
::glMatrixMode( GL_TEXTURE );
|
||||
::glPopMatrix();
|
||||
// ::glPopMatrix();
|
||||
::glLoadIdentity();
|
||||
select_unit( m_diffusetextureunit );
|
||||
::glMatrixMode( GL_MODELVIEW );
|
||||
}
|
||||
@@ -1011,7 +1023,8 @@ opengl_renderer::setup_matrices() {
|
||||
// special case, for colour render pass setup texture matrix for reflections cube map
|
||||
select_unit( m_helpertextureunit );
|
||||
::glMatrixMode( GL_TEXTURE );
|
||||
::glPushMatrix();
|
||||
// ::glPushMatrix();
|
||||
::glLoadIdentity();
|
||||
::glMultMatrixf( glm::value_ptr( glm::inverse( glm::mat4{ glm::mat3{ m_renderpass.camera.modelview() } } ) ) );
|
||||
select_unit( m_diffusetextureunit );
|
||||
}
|
||||
@@ -1459,7 +1472,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
// sun
|
||||
{
|
||||
Bind_Texture( m_suntexture );
|
||||
::glColor4f( suncolor.x, suncolor.y, suncolor.z, 1.0f );
|
||||
::glColor4f( suncolor.x, suncolor.y, suncolor.z, clamp( 1.5f - Global.Overcast, 0.f, 1.f ) );
|
||||
auto const sunvector = Environment->m_sun.getDirection();
|
||||
auto const sunposition = modelview * glm::vec4( sunvector.x, sunvector.y, sunvector.z, 1.0f );
|
||||
|
||||
@@ -2807,6 +2820,54 @@ opengl_renderer::Render( TMemCell *Memcell ) {
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render_precipitation() {
|
||||
|
||||
if( Global.Overcast <= 1.f ) { return; }
|
||||
|
||||
switch_units( true, false, false );
|
||||
|
||||
// ::glColor4fv( glm::value_ptr( glm::vec4( glm::min( glm::vec3( Global.fLuminance ), glm::vec3( 1 ) ), 1 ) ) );
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
interpolate(
|
||||
0.5f * ( Global.DayLight.diffuse + Global.DayLight.ambient ),
|
||||
colors::white,
|
||||
0.5f * clamp<float>( Global.fLuminance, 0.f, 1.f ) ) ) );
|
||||
::glPushMatrix();
|
||||
|
||||
auto const velocity { simulation::Environment.m_precipitation.m_cameramove * -1.0 };
|
||||
if( glm::length2( velocity ) > 0.0 ) {
|
||||
auto const forward{ glm::normalize( velocity ) };
|
||||
if( false == FreeFlyModeFlag ) {
|
||||
// counter potential vehicle roll
|
||||
auto const roll { simulation::Train->Dynamic()->Roll() };
|
||||
if( roll != 0.0 ) {
|
||||
::glRotated( roll, forward.x, 0.0, forward.z );
|
||||
}
|
||||
}
|
||||
auto left { glm::cross( forward, {0.0,1.0,0.0} ) };
|
||||
auto const rotationangle {
|
||||
std::min(
|
||||
45.0,
|
||||
( FreeFlyModeFlag ?
|
||||
5 * glm::length( velocity ) :
|
||||
simulation::Train->Dynamic()->GetVelocity() * 0.2 ) ) };
|
||||
::glRotated( rotationangle, left.x, 0.0, left.z );
|
||||
}
|
||||
|
||||
// TBD: leave lighting on to allow vehicle lights to affect it?
|
||||
::glDisable( GL_LIGHTING );
|
||||
// momentarily disable depth write, to allow vehicle cab drawn afterwards to mask it instead of leaving it 'inside'
|
||||
::glDepthMask( GL_FALSE );
|
||||
|
||||
simulation::Environment.m_precipitation.render();
|
||||
|
||||
::glDepthMask( GL_TRUE );
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render_Alpha( scene::basic_region *Region ) {
|
||||
|
||||
|
||||
@@ -294,6 +294,8 @@ private:
|
||||
Render_cab( TDynamicObject const *Dynamic, bool const Alpha = false );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
void
|
||||
Render_precipitation();
|
||||
void
|
||||
Render_Alpha( scene::basic_region *Region );
|
||||
void
|
||||
|
||||
35
scene.cpp
35
scene.cpp
@@ -986,6 +986,37 @@ basic_region::update_traction( TDynamicObject *Vehicle, int const Pantographinde
|
||||
}
|
||||
}
|
||||
|
||||
// checks whether specified file is a valid region data file
|
||||
bool
|
||||
basic_region::is_scene( std::string const &Scenariofile ) const {
|
||||
|
||||
auto filename { Scenariofile };
|
||||
while( filename[ 0 ] == '$' ) {
|
||||
// trim leading $ char rainsted utility may add to the base name for modified .scn files
|
||||
filename.erase( 0, 1 );
|
||||
}
|
||||
erase_extension( filename );
|
||||
filename = Global.asCurrentSceneryPath + filename;
|
||||
filename += EU07_FILEEXTENSION_REGION;
|
||||
|
||||
if( false == FileExists( filename ) ) {
|
||||
return false;
|
||||
}
|
||||
// file type and version check
|
||||
std::ifstream input( filename, std::ios::binary );
|
||||
|
||||
uint32_t headermain{ sn_utils::ld_uint32( input ) };
|
||||
uint32_t headertype{ sn_utils::ld_uint32( input ) };
|
||||
|
||||
if( ( headermain != EU07_FILEHEADER
|
||||
|| ( headertype != EU07_FILEVERSION_REGION ) ) ) {
|
||||
// wrong file type
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// stores content of the class in file with specified name
|
||||
void
|
||||
basic_region::serialize( std::string const &Scenariofile ) const {
|
||||
@@ -1062,7 +1093,9 @@ basic_region::deserialize( std::string const &Scenariofile ) {
|
||||
// section index, followed by section data size, followed by section data
|
||||
auto *§ion { m_sections[ sn_utils::ld_uint32( input ) ] };
|
||||
auto const sectionsize { sn_utils::ld_uint32( input ) };
|
||||
section = new basic_section();
|
||||
if( section == nullptr ) {
|
||||
section = new basic_section();
|
||||
}
|
||||
section->deserialize( input );
|
||||
}
|
||||
|
||||
|
||||
4
scene.h
4
scene.h
@@ -53,6 +53,7 @@ struct scratch_data {
|
||||
bool is_open { false };
|
||||
} trainset;
|
||||
|
||||
std::string name;
|
||||
bool initialized { false };
|
||||
};
|
||||
|
||||
@@ -321,6 +322,9 @@ public:
|
||||
// legacy method, updates sounds around camera
|
||||
void
|
||||
update_sounds();
|
||||
// checks whether specified file is a valid region data file
|
||||
bool
|
||||
is_scene( std::string const &Scenariofile ) const;
|
||||
// stores content of the class in file with specified name
|
||||
void
|
||||
serialize( std::string const &Scenariofile ) const;
|
||||
|
||||
@@ -76,6 +76,9 @@ world_environment::init() {
|
||||
m_moon.init();
|
||||
m_stars.init();
|
||||
m_clouds.Init();
|
||||
m_precipitation.init();
|
||||
|
||||
m_precipitationsound.deserialize( "rain-sound-loop", sound_type::single );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -147,6 +150,24 @@ world_environment::update() {
|
||||
// but quite effective way to make the distant items blend with background better
|
||||
// NOTE: base brightness calculation provides scaled up value, so we bring it back to 'real' one here
|
||||
Global.FogColor = m_skydome.GetAverageHorizonColor();
|
||||
|
||||
// weather-related simulation factors
|
||||
// TODO: dynamic change of air temperature and overcast levels
|
||||
if( Global.Weather == "rain:" ) {
|
||||
// reduce friction in rain
|
||||
Global.FrictionWeatherFactor = 0.85f;
|
||||
m_precipitationsound.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else if( Global.Weather == "snow:" ) {
|
||||
// reduce friction due to snow
|
||||
Global.FrictionWeatherFactor = 0.75f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
world_environment::update_precipitation() {
|
||||
|
||||
m_precipitation.update();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -14,6 +14,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "moon.h"
|
||||
#include "stars.h"
|
||||
#include "skydome.h"
|
||||
#include "precipitation.h"
|
||||
#include "sound.h"
|
||||
|
||||
class opengl_renderer;
|
||||
|
||||
@@ -26,6 +28,7 @@ public:
|
||||
// methods
|
||||
void init();
|
||||
void update();
|
||||
void update_precipitation();
|
||||
void time( int const Hour = -1, int const Minute = -1, int const Second = -1 );
|
||||
// switches between static and dynamic daylight calculation
|
||||
void toggle_daylight();
|
||||
@@ -41,6 +44,9 @@ private:
|
||||
cSun m_sun;
|
||||
cMoon m_moon;
|
||||
TSky m_clouds;
|
||||
basic_precipitation m_precipitation;
|
||||
|
||||
sound_source m_precipitationsound { sound_placement::external, -1 };
|
||||
};
|
||||
|
||||
namespace simulation {
|
||||
|
||||
@@ -37,9 +37,11 @@ state_serializer::deserialize( std::string const &Scenariofile ) {
|
||||
// TODO: check first for presence of serialized binary files
|
||||
// if this fails, fall back on the legacy text format
|
||||
scene::scratch_data importscratchpad;
|
||||
importscratchpad.name = Scenariofile;
|
||||
if( Scenariofile != "$.scn" ) {
|
||||
// compilation to binary file isn't supported for rainsted-created overrides
|
||||
importscratchpad.binary.terrain = Region->deserialize( Scenariofile );
|
||||
// NOTE: we postpone actual loading of the scene until we process time, season and weather data
|
||||
importscratchpad.binary.terrain = Region->is_scene( Scenariofile ) ;
|
||||
}
|
||||
// NOTE: for the time being import from text format is a given, since we don't have full binary serialization
|
||||
cParser scenarioparser( Scenariofile, cParser::buffer_FILE, Global.asCurrentSceneryPath, Global.bLoadTraction );
|
||||
@@ -266,6 +268,12 @@ state_serializer::deserialize_firstinit( cParser &Input, scene::scratch_data &Sc
|
||||
|
||||
if( true == Scratchpad.initialized ) { return; }
|
||||
|
||||
if( true == Scratchpad.binary.terrain ) {
|
||||
// at this stage it should be safe to import terrain from the binary scene file
|
||||
// TBD: postpone loading furter and only load required blocks during the simulation?
|
||||
Region->deserialize( Scratchpad.name );
|
||||
}
|
||||
|
||||
simulation::Paths.InitTracks();
|
||||
simulation::Traction.InitTraction();
|
||||
simulation::Events.InitEvents();
|
||||
|
||||
Reference in New Issue
Block a user