mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 19:19:19 +02:00
tmj merge (broken)
This commit is contained in:
@@ -422,9 +422,8 @@ TAnimModel::~TAnimModel()
|
||||
bool TAnimModel::Init(TModel3d *pNewModel)
|
||||
{
|
||||
fBlinkTimer = double(Random(1000 * fOffTime)) / (1000 * fOffTime);
|
||||
;
|
||||
pModel = pNewModel;
|
||||
return (pModel != NULL);
|
||||
return (pModel != nullptr);
|
||||
}
|
||||
|
||||
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
|
||||
@@ -578,10 +577,10 @@ void TAnimModel::RaPrepare()
|
||||
switch (lightmode)
|
||||
{
|
||||
case ls_Blink: // migotanie
|
||||
state = fBlinkTimer < fOnTime;
|
||||
state = ( fBlinkTimer < fOnTime );
|
||||
break;
|
||||
case ls_Dark: // zapalone, gdy ciemno
|
||||
state = Global::fLuminance <= ( lsLights[i] - 3.0 );
|
||||
state = ( Global::fLuminance <= ( lsLights[i] - 3.0 ) );
|
||||
break;
|
||||
default: // zapalony albo zgaszony
|
||||
state = (lightmode == ls_On);
|
||||
|
||||
@@ -71,7 +71,7 @@ void TButton::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *pMod
|
||||
if( ( pModelOn == nullptr )
|
||||
&& ( pModelOff == nullptr ) ) {
|
||||
// if we failed to locate even one state submodel, cry
|
||||
ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + pModel1->NameGet() + "\"" );
|
||||
ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + pModel1->NameGet() + "\"", logtype::model );
|
||||
}
|
||||
|
||||
// pass submodel location to defined sounds
|
||||
@@ -105,7 +105,7 @@ TButton::model_offset() const {
|
||||
|
||||
return (
|
||||
submodel != nullptr ?
|
||||
submodel->offset( 1.f ) :
|
||||
submodel->offset( 2.5f ) :
|
||||
glm::vec3() );
|
||||
}
|
||||
|
||||
|
||||
@@ -282,16 +282,16 @@ void Console::ValueSet(int x, double y)
|
||||
{
|
||||
x = Global::iPoKeysPWM[x];
|
||||
if (Global::iCalibrateOutDebugInfo == x)
|
||||
WriteLog("CalibrateOutDebugInfo: oryginal=" + std::to_string(y), false);
|
||||
WriteLog("CalibrateOutDebugInfo: oryginal=" + std::to_string(y));
|
||||
if (Global::fCalibrateOutMax[x] > 0)
|
||||
{
|
||||
y = clamp( y, 0.0, Global::fCalibrateOutMax[x]);
|
||||
if (Global::iCalibrateOutDebugInfo == x)
|
||||
WriteLog(" cutted=" + std::to_string(y), false);
|
||||
WriteLog(" cutted=" + std::to_string(y));
|
||||
y = y / Global::fCalibrateOutMax[x]; // sprowadzenie do <0,1> jeśli podana
|
||||
// maksymalna wartość
|
||||
if (Global::iCalibrateOutDebugInfo == x)
|
||||
WriteLog(" fraction=" + std::to_string(y), false);
|
||||
WriteLog(" fraction=" + std::to_string(y));
|
||||
}
|
||||
double temp = (((((Global::fCalibrateOut[x][5] * y) + Global::fCalibrateOut[x][4]) * y +
|
||||
Global::fCalibrateOut[x][3]) *
|
||||
|
||||
170
DynObj.cpp
170
DynObj.cpp
@@ -2977,7 +2977,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
// crude bump simulation, drop down on even axles, move back up on the odd ones
|
||||
MoverParameters->AccVert +=
|
||||
interpolate(
|
||||
0.25, 0.50,
|
||||
0.01, 0.05,
|
||||
clamp(
|
||||
GetVelocity() / ( 1 + MoverParameters->Vmax ),
|
||||
0.0, 1.0 ) )
|
||||
@@ -3699,6 +3699,7 @@ void TDynamicObject::RenderSounds() {
|
||||
}
|
||||
// szum w czasie jazdy
|
||||
if( ( GetVelocity() > 0.5 )
|
||||
&& ( false == rsOuterNoise.empty() )
|
||||
&& ( // compound test whether the vehicle belongs to user-driven consist (as these don't emit outer noise in cab view)
|
||||
FreeFlyModeFlag ? true : // in external view all vehicles emit outer noise
|
||||
// Global::pWorld->train() == nullptr ? true : // (can skip this check, with no player train the external view is a given)
|
||||
@@ -3707,12 +3708,22 @@ void TDynamicObject::RenderSounds() {
|
||||
Global::CabWindowOpen ? true : // sticking head out we get to hear outer noise
|
||||
false ) ) {
|
||||
|
||||
volume = rsOuterNoise.m_amplitudefactor * MoverParameters->Vel + rsOuterNoise.m_amplitudeoffset;
|
||||
frequency = rsOuterNoise.m_frequencyfactor * MoverParameters->Vel + rsOuterNoise.m_frequencyoffset;
|
||||
// frequency calculation
|
||||
auto const normalizer { (
|
||||
true == rsOuterNoise.is_combined() ?
|
||||
MoverParameters->Vmax * 0.01f :
|
||||
1.f ) };
|
||||
frequency =
|
||||
rsOuterNoise.m_frequencyoffset
|
||||
+ rsOuterNoise.m_frequencyfactor * MoverParameters->Vel * normalizer;
|
||||
|
||||
// volume calculation
|
||||
volume =
|
||||
rsOuterNoise.m_amplitudeoffset +
|
||||
rsOuterNoise.m_amplitudefactor * MoverParameters->Vel;
|
||||
if( brakeforceratio > 0.0 ) {
|
||||
// hamulce wzmagaja halas
|
||||
volume *= 1 + 0.25 * brakeforceratio;
|
||||
volume *= 1 + 0.125 * brakeforceratio;
|
||||
}
|
||||
// scale volume by track quality
|
||||
volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21;
|
||||
@@ -3725,10 +3736,15 @@ void TDynamicObject::RenderSounds() {
|
||||
MoverParameters->Vel / 40.0,
|
||||
0.0, 1.0 ) );
|
||||
|
||||
rsOuterNoise
|
||||
.pitch( frequency ) // arbitrary limits to prevent the pitch going out of whack
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
if( volume > 0.05 ) {
|
||||
rsOuterNoise
|
||||
.pitch( frequency ) // arbitrary limits to prevent the pitch going out of whack
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
rsOuterNoise.stop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// don't play the optional ending sound if the listener switches views
|
||||
@@ -3979,9 +3995,12 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
}
|
||||
else {
|
||||
// Ra: tu wczytywanie modelu ładunku jest w porządku
|
||||
if( false == asLoadName.empty() ) {
|
||||
// try first specialized version of the load model, vehiclename_loadname
|
||||
mdLoad = TModelsManager::GetModel( BaseDir + TypeName + "_" + MoverParameters->LoadType + ".t3d", true );
|
||||
if( false == asLoadName.empty() ) {
|
||||
// try first specialized version of the load model, vehiclename_loadname
|
||||
auto const specializedloadfilename { BaseDir + TypeName + "_" + MoverParameters->LoadType + ".t3d" };
|
||||
if( true == FileExists( specializedloadfilename ) ) {
|
||||
mdLoad = TModelsManager::GetModel( specializedloadfilename, true );
|
||||
}
|
||||
if( mdLoad == nullptr ) {
|
||||
// if this fails, try generic load model
|
||||
mdLoad = TModelsManager::GetModel( asLoadName, true );
|
||||
@@ -4231,15 +4250,15 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
{ // gdy ktoś przesadził ze skalowaniem
|
||||
pants[i].fParamPants->fHeight =
|
||||
0.0; // niech będzie odczyt z pantfactors:
|
||||
ErrorLog("Bad model: " + asModel + ", scale of " +
|
||||
(sm->pName) + " is " +
|
||||
std::to_string(100.0 * det) + "%");
|
||||
ErrorLog(
|
||||
"Bad model: " + asModel + ", scale of " + (sm->pName) + " is " + std::to_string(100.0 * det) + "%",
|
||||
logtype::model );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ErrorLog("Bad model: " + asFileName + " - missed submodel " + asAnimName); // brak ramienia
|
||||
ErrorLog("Bad model: " + asFileName + " - missed submodel " + asAnimName, logtype::model); // brak ramienia
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4273,7 +4292,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
}
|
||||
}
|
||||
else
|
||||
ErrorLog( "Bad model: " + asFileName + " - missed submodel " + asAnimName ); // brak ramienia
|
||||
ErrorLog( "Bad model: " + asFileName + " - missed submodel " + asAnimName, logtype::model ); // brak ramienia
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4579,16 +4598,19 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
m_powertrainsounds.motor.m_amplitudefactor /= amplitudedivisor;
|
||||
}
|
||||
|
||||
else if( token == "ventilator:" ) {
|
||||
else if( token == "inverter:" ) {
|
||||
// plik z dzwiekiem wentylatora, mnozniki i ofsety amp. i czest.
|
||||
m_powertrainsounds.inverter.deserialize( parser, sound_type::single, sound_parameters::range | sound_parameters::amplitude | sound_parameters::frequency );
|
||||
m_powertrainsounds.inverter.owner( this );
|
||||
}
|
||||
|
||||
else if( token == "ventilator:" ) {
|
||||
// plik z dzwiekiem wentylatora, mnozniki i ofsety amp. i czest.
|
||||
m_powertrainsounds.rsWentylator.deserialize( parser, sound_type::single, sound_parameters::range | sound_parameters::amplitude | sound_parameters::frequency );
|
||||
m_powertrainsounds.rsWentylator.owner( this );
|
||||
|
||||
if( ( MoverParameters->EngineType == ElectricSeriesMotor )
|
||||
|| ( MoverParameters->EngineType == ElectricInductionMotor ) ) {
|
||||
m_powertrainsounds.rsWentylator.m_amplitudefactor /= MoverParameters->RVentnmax;
|
||||
m_powertrainsounds.rsWentylator.m_frequencyfactor /= MoverParameters->RVentnmax;
|
||||
}
|
||||
m_powertrainsounds.rsWentylator.m_amplitudefactor /= MoverParameters->RVentnmax;
|
||||
m_powertrainsounds.rsWentylator.m_frequencyfactor /= MoverParameters->RVentnmax;
|
||||
}
|
||||
|
||||
else if(token == "transmission:") {
|
||||
@@ -5503,12 +5525,13 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
|| ( Vehicle.EngineType == Dumb ) ) {
|
||||
|
||||
// frequency calculation
|
||||
auto normalizer { 1.f };
|
||||
if( true == engine.is_combined() ) {
|
||||
// for combined engine sound we calculate sound point in rpm, to make .mmd files setup easier
|
||||
// NOTE: we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range
|
||||
normalizer = 60.f * 0.01f;
|
||||
}
|
||||
auto const normalizer { (
|
||||
true == engine.is_combined() ?
|
||||
// for combined engine sound we calculate sound point in rpm, to make .mmd files setup easier
|
||||
// NOTE: we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range
|
||||
60.f * 0.01f :
|
||||
// for legacy single-piece sounds the standard frequency calculation is left untouched
|
||||
1.f ) };
|
||||
frequency =
|
||||
engine.m_frequencyoffset
|
||||
+ engine.m_frequencyfactor * std::abs( Vehicle.enrot ) * normalizer;
|
||||
@@ -5545,15 +5568,11 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
}
|
||||
|
||||
if( engine_volume >= 0.05 ) {
|
||||
engine
|
||||
.pitch( frequency )
|
||||
.gain( engine_volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
|
||||
auto enginerevvolume { 0.f };
|
||||
if( ( Vehicle.EngineType == DieselElectric )
|
||||
|| ( Vehicle.EngineType == DieselEngine ) ) {
|
||||
// diesel engine revolutions increase
|
||||
float enginerevvolume { 0 };
|
||||
// diesel engine revolutions increase; it can potentially decrease volume of base engine sound
|
||||
if( engine_revs_last != -1.f ) {
|
||||
// calculate potential recent increase of engine revolutions
|
||||
auto const revolutionsperminute { Vehicle.enrot * 60 };
|
||||
@@ -5568,25 +5587,36 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
&& ( revolutionsdifference > 1.0 * Deltatime ) ) {
|
||||
engine_revs_change = clamp( engine_revs_change + 5.0 * Deltatime, 0.0, 1.25 );
|
||||
}
|
||||
enginerevvolume = engine_revs_change;
|
||||
enginerevvolume = 0.8 * engine_revs_change;
|
||||
}
|
||||
engine_revs_last = Vehicle.enrot * 60;
|
||||
|
||||
if( false == engine_revving.is_combined() ) {
|
||||
// if the sound comes with multiple samples we reuse rpm-based calculation from the engine
|
||||
frequency = engine_revving.m_frequencyoffset + engine_revving.m_frequencyfactor * 1.0;
|
||||
}
|
||||
auto const enginerevfrequency { (
|
||||
true == engine_revving.is_combined() ?
|
||||
// if the sound contains multiple samples we reuse rpm-based calculation from the engine
|
||||
frequency :
|
||||
engine_revving.m_frequencyoffset + 1.f * engine_revving.m_frequencyfactor ) };
|
||||
|
||||
if( enginerevvolume > 0.02 ) {
|
||||
engine_revving
|
||||
.pitch( frequency )
|
||||
.pitch( enginerevfrequency )
|
||||
.gain( enginerevvolume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
.play( sound_flags::exclusive );
|
||||
}
|
||||
else {
|
||||
engine_revving.stop();
|
||||
}
|
||||
}
|
||||
} // diesel engines
|
||||
|
||||
// multi-part revving sound pieces replace base engine sound, single revving simply gets mixed with the base
|
||||
auto const enginevolume { (
|
||||
( ( enginerevvolume > 0.02 ) && ( true == engine_revving.is_combined() ) ) ?
|
||||
std::max( 0.0, engine_volume - enginerevvolume ) :
|
||||
engine_volume ) };
|
||||
engine
|
||||
.pitch( frequency )
|
||||
.gain( enginevolume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
} // enginevolume > 0.05
|
||||
}
|
||||
else {
|
||||
@@ -5754,7 +5784,34 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
if( motor_volume < 0.05 ) {
|
||||
motor.stop();
|
||||
}
|
||||
// inverter sounds
|
||||
if( Vehicle.EngineType == ElectricInductionMotor ) {
|
||||
if( Vehicle.InverterFrequency > 0.1 ) {
|
||||
|
||||
volume = inverter.m_amplitudeoffset + inverter.m_amplitudefactor * std::sqrt( std::fabs( Vehicle.dizel_fill ) );
|
||||
|
||||
inverter
|
||||
.pitch( inverter.m_frequencyoffset + inverter.m_frequencyfactor * Vehicle.InverterFrequency )
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
inverter.stop();
|
||||
}
|
||||
}
|
||||
// ventillator sounds
|
||||
if( Vehicle.RventRot > 0.1 ) {
|
||||
|
||||
rsWentylator
|
||||
.pitch( rsWentylator.m_frequencyoffset + rsWentylator.m_frequencyfactor * Vehicle.RventRot )
|
||||
.gain( rsWentylator.m_amplitudeoffset + rsWentylator.m_amplitudefactor * Vehicle.RventRot )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
// ...otherwise shut down the sound
|
||||
rsWentylator.stop();
|
||||
}
|
||||
// relay sounds
|
||||
auto const soundflags { Vehicle.SoundFlag };
|
||||
if( TestFlag( soundflags, sound::relay ) ) {
|
||||
// przekaznik - gdy bezpiecznik, automatyczny rozruch itp
|
||||
@@ -5764,7 +5821,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
.pitch(
|
||||
true == motor_shuntfield.is_combined() ?
|
||||
Vehicle.ScndCtrlActualPos * 0.01f :
|
||||
motor_shuntfield.m_frequencyoffset + 1.f * motor_shuntfield.m_frequencyfactor )
|
||||
motor_shuntfield.m_frequencyoffset + motor_shuntfield.m_frequencyfactor * 1.f )
|
||||
.gain(
|
||||
motor_shuntfield.m_amplitudeoffset + (
|
||||
true == TestFlag( soundflags, sound::loud ) ?
|
||||
@@ -5788,7 +5845,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
.pitch(
|
||||
true == motor_relay.is_combined() ?
|
||||
Vehicle.MainCtrlActualPos * 0.01f :
|
||||
motor_relay.m_frequencyoffset + 1.f * motor_relay.m_frequencyfactor )
|
||||
motor_relay.m_frequencyoffset + motor_relay.m_frequencyfactor * 1.f )
|
||||
.gain(
|
||||
motor_relay.m_amplitudeoffset + (
|
||||
true == TestFlag( soundflags, sound::loud ) ?
|
||||
@@ -5799,32 +5856,11 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
|
||||
}
|
||||
}
|
||||
|
||||
if( ( Vehicle.EngineType == ElectricSeriesMotor )
|
||||
|| ( Vehicle.EngineType == ElectricInductionMotor ) ) {
|
||||
|
||||
if( Vehicle.RventRot > 0.1 ) {
|
||||
// play ventilator sound if the ventilators are rotating fast enough...
|
||||
volume = (
|
||||
Vehicle.EngineType == ElectricInductionMotor ?
|
||||
rsWentylator.m_amplitudefactor * std::sqrt( std::fabs( Vehicle.dizel_fill ) ) + rsWentylator.m_amplitudeoffset :
|
||||
rsWentylator.m_amplitudefactor * Vehicle.RventRot + rsWentylator.m_amplitudeoffset );
|
||||
|
||||
rsWentylator
|
||||
.pitch( rsWentylator.m_frequencyfactor * Vehicle.RventRot + rsWentylator.m_frequencyoffset )
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
// ...otherwise shut down the sound
|
||||
rsWentylator.stop();
|
||||
}
|
||||
}
|
||||
|
||||
if( Vehicle.TrainType == dt_ET40 ) {
|
||||
if( Vehicle.Vel > 0.1 ) {
|
||||
transmission
|
||||
.pitch( transmission.m_frequencyfactor * ( Vehicle.Vel ) + transmission.m_frequencyoffset )
|
||||
.gain( transmission.m_amplitudefactor * ( Vehicle.Vel ) + transmission.m_amplitudeoffset )
|
||||
.pitch( transmission.m_frequencyoffset + transmission.m_frequencyfactor * Vehicle.Vel )
|
||||
.gain( transmission.m_amplitudeoffset + transmission.m_amplitudefactor * Vehicle.Vel )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
|
||||
1
DynObj.h
1
DynObj.h
@@ -284,6 +284,7 @@ private:
|
||||
};
|
||||
|
||||
struct powertrain_sounds {
|
||||
sound_source inverter { sound_placement::engine };
|
||||
sound_source motor { sound_placement::external }; // generally traction motor
|
||||
double motor_volume { 0.0 }; // MC: pomocnicze zeby gladziej silnik buczal
|
||||
float motor_momentum { 0.f }; // recent change in motor revolutions
|
||||
|
||||
@@ -99,7 +99,7 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
||||
scale *= mul;
|
||||
TSubModel *submodel = md1->GetFromName( submodelname );
|
||||
if( scale == 0.0 ) {
|
||||
ErrorLog( "Bad model: scale of 0.0 defined for sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\". Forcing scale of 1.0 to prevent division by 0" );
|
||||
ErrorLog( "Bad model: scale of 0.0 defined for sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\". Forcing scale of 1.0 to prevent division by 0", logtype::model );
|
||||
scale = 1.0;
|
||||
}
|
||||
if (submodel) // jeśli nie znaleziony
|
||||
@@ -107,7 +107,7 @@ bool TGauge::Load( cParser &Parser, TDynamicObject const *Owner, TModel3d *md1,
|
||||
else if (md2) // a jest podany drugi model (np. zewnętrzny)
|
||||
submodel = md2->GetFromName(submodelname); // to może tam będzie, co za różnica gdzie
|
||||
if( submodel == nullptr ) {
|
||||
ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\"" );
|
||||
ErrorLog( "Bad model: failed to locate sub-model \"" + submodelname + "\" in 3d model \"" + md1->NameGet() + "\"", logtype::model );
|
||||
}
|
||||
|
||||
std::map<std::string, TGaugeType> gaugetypes {
|
||||
|
||||
19
Globals.cpp
19
Globals.cpp
@@ -115,6 +115,8 @@ std::string Global::LastGLError;
|
||||
GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury
|
||||
bool Global::bSmoothTraction { true }; // wygładzanie drutów starym sposobem
|
||||
float Global::SplineFidelity { 1.f }; // determines segment size during conversion of splines to geometry
|
||||
bool Global::ResourceSweep { true }; // gfx resource garbage collection
|
||||
bool Global::ResourceMove { false }; // gfx resources are moved between cpu and gpu side instead of sending a copy
|
||||
std::string Global::szDefaultExt = Global::szTexturesDDS; // domyślnie od DDS
|
||||
int Global::iMultisampling = 2; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||
bool Global::DLFont{ false }; // switch indicating presence of basic font
|
||||
@@ -138,7 +140,8 @@ float Global::AudioVolume = 1.5f;
|
||||
std::string Global::AudioRenderer;
|
||||
|
||||
int Global::iWriteLogEnabled = 3; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
|
||||
bool Global::MultipleLogs{ false };
|
||||
bool Global::MultipleLogs { false };
|
||||
unsigned int Global::DisabledLogTypes { 0 };
|
||||
|
||||
// parametry do kalibracji
|
||||
// kolejno współczynniki dla potęg 0, 1, 2, 3 wartości odczytanej z urządzenia
|
||||
@@ -322,6 +325,10 @@ void Global::ConfigParse(cParser &Parser)
|
||||
Parser.getTokens();
|
||||
Parser >> Global::MultipleLogs;
|
||||
}
|
||||
else if( token == "logs.filter" ) {
|
||||
Parser.getTokens();
|
||||
Parser >> Global::DisabledLogTypes;
|
||||
}
|
||||
else if( token == "adjustscreenfreq" )
|
||||
{
|
||||
// McZapkie-240403 - czestotliwosc odswiezania ekranu
|
||||
@@ -523,6 +530,16 @@ void Global::ConfigParse(cParser &Parser)
|
||||
Parser >> splinefidelity;
|
||||
Global::SplineFidelity = clamp( splinefidelity, 1.f, 4.f );
|
||||
}
|
||||
else if( token == "gfx.resource.sweep" ) {
|
||||
|
||||
Parser.getTokens();
|
||||
Parser >> Global::ResourceSweep;
|
||||
}
|
||||
else if( token == "gfx.resource.move" ) {
|
||||
|
||||
Parser.getTokens();
|
||||
Parser >> Global::ResourceMove;
|
||||
}
|
||||
else if (token == "timespeed")
|
||||
{
|
||||
// przyspieszenie czasu, zmienna do testów
|
||||
|
||||
@@ -181,6 +181,7 @@ public:
|
||||
static std::string asCurrentDynamicPath;
|
||||
static int iWriteLogEnabled; // maska bitowa: 1-zapis do pliku, 2-okienko
|
||||
static bool MultipleLogs;
|
||||
static unsigned int DisabledLogTypes;
|
||||
// McZapkie-170602: zewnetrzna definicja pojazdu uzytkownika
|
||||
static std::string asHumanCtrlVehicle;
|
||||
// world environment
|
||||
@@ -212,6 +213,8 @@ public:
|
||||
static bool bSmoothTraction; // wygładzanie drutów
|
||||
static float SplineFidelity; // determines segment size during conversion of splines to geometry
|
||||
static GLfloat FogColor[];
|
||||
static bool ResourceSweep; // gfx resource garbage collection
|
||||
static bool ResourceMove; // gfx resources are moved between cpu and gpu side instead of sending a copy
|
||||
// sound renderer variables
|
||||
static bool bSoundEnabled;
|
||||
static float AudioVolume;
|
||||
|
||||
96
Logs.cpp
96
Logs.cpp
@@ -62,78 +62,50 @@ std::string filename_scenery() {
|
||||
}
|
||||
}
|
||||
|
||||
void WriteConsoleOnly(const char *str, double value) {
|
||||
#ifdef _WIN32
|
||||
std::snprintf(logbuffer , sizeof(logbuffer), "%s %f \n", str, value);
|
||||
// stdout= GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD wr = 0;
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), logbuffer, (DWORD)strlen(logbuffer), &wr, NULL);
|
||||
// WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),endstring,strlen(endstring),&wr,NULL);
|
||||
#endif
|
||||
}
|
||||
void WriteLog( const char *str, logtype const Type ) {
|
||||
|
||||
void WriteConsoleOnly(const char *str, bool newline)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// printf("%n ffafaf /n",str);
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
DWORD wr = 0;
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), str, (DWORD)strlen(str), &wr, NULL);
|
||||
if (newline)
|
||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), endstring, (DWORD)strlen(endstring), &wr, NULL);
|
||||
#endif
|
||||
}
|
||||
if( str == nullptr ) { return; }
|
||||
if( true == TestFlag( Global::DisabledLogTypes, Type ) ) { return; }
|
||||
|
||||
void WriteLog(const char *str, double value) {
|
||||
if (Global::iWriteLogEnabled & 1) {
|
||||
if( !output.is_open() ) {
|
||||
|
||||
if (Global::iWriteLogEnabled) {
|
||||
if (str) {
|
||||
std::snprintf(logbuffer, sizeof(logbuffer), "%s %f", str, value);
|
||||
WriteLog(logbuffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void WriteLog(const char *str, bool newline)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
if (Global::iWriteLogEnabled & 1)
|
||||
{
|
||||
if( !output.is_open() ) {
|
||||
|
||||
std::string const filename =
|
||||
( Global::MultipleLogs ?
|
||||
std::string const filename =
|
||||
( Global::MultipleLogs ?
|
||||
"logs/log (" + filename_scenery() + ") " + filename_date() + ".txt" :
|
||||
"log.txt" );
|
||||
output.open( filename, std::ios::trunc );
|
||||
}
|
||||
output << str;
|
||||
if (newline)
|
||||
output << "\n";
|
||||
output.flush();
|
||||
output.open( filename, std::ios::trunc );
|
||||
}
|
||||
// hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana
|
||||
if (Global::iWriteLogEnabled & 2)
|
||||
WriteConsoleOnly(str, newline);
|
||||
output << str << "\n";
|
||||
output.flush();
|
||||
}
|
||||
};
|
||||
|
||||
void ErrorLog(const char *str)
|
||||
{ // Ra: bezwarunkowa rejestracja poważnych błędów
|
||||
if( Global::iWriteLogEnabled & 2 ) {
|
||||
// hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana
|
||||
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN | FOREGROUND_INTENSITY );
|
||||
DWORD wr = 0;
|
||||
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), str, (DWORD)strlen( str ), &wr, NULL );
|
||||
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), endstring, (DWORD)strlen( endstring ), &wr, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Ra: bezwarunkowa rejestracja poważnych błędów
|
||||
void ErrorLog( const char *str, logtype const Type ) {
|
||||
|
||||
if( str == nullptr ) { return; }
|
||||
if( true == TestFlag( Global::DisabledLogTypes, Type ) ) { return; }
|
||||
|
||||
if (!errors.is_open()) {
|
||||
|
||||
std::string const filename =
|
||||
( Global::MultipleLogs ?
|
||||
"logs/errors (" + filename_scenery() + ") " + filename_date() + ".txt" :
|
||||
"errors.txt" );
|
||||
"logs/errors (" + filename_scenery() + ") " + filename_date() + ".txt" :
|
||||
"errors.txt" );
|
||||
errors.open( filename, std::ios::trunc );
|
||||
errors << "EU07.EXE " + Global::asVersion << "\n";
|
||||
}
|
||||
if (str)
|
||||
errors << str;
|
||||
errors << "\n";
|
||||
|
||||
errors << str << "\n";
|
||||
errors.flush();
|
||||
};
|
||||
|
||||
@@ -152,15 +124,15 @@ void Error(const char *&asMessage, bool box)
|
||||
WriteLog(asMessage);
|
||||
}
|
||||
|
||||
void ErrorLog(const std::string &str, bool newline)
|
||||
void ErrorLog(const std::string &str, logtype const Type )
|
||||
{
|
||||
ErrorLog(str.c_str());
|
||||
WriteLog(str.c_str(), newline);
|
||||
ErrorLog( str.c_str(), Type );
|
||||
WriteLog( str.c_str(), Type );
|
||||
}
|
||||
|
||||
void WriteLog(const std::string &str, bool newline)
|
||||
void WriteLog(const std::string &str, logtype const Type )
|
||||
{ // Ra: wersja z AnsiString jest zamienna z Error()
|
||||
WriteLog(str.c_str(), newline);
|
||||
WriteLog( str.c_str(), Type );
|
||||
};
|
||||
|
||||
void CommLog(const char *str)
|
||||
|
||||
25
Logs.h
25
Logs.h
@@ -10,13 +10,18 @@ http://mozilla.org/MPL/2.0/.
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
void WriteConsoleOnly(const char *str, double value);
|
||||
void WriteConsoleOnly(const char *str, bool newline = true);
|
||||
void WriteLog(const char *str, double value);
|
||||
void WriteLog(const char *str, bool newline = true);
|
||||
void Error(const std::string &asMessage, bool box = false);
|
||||
void Error(const char* &asMessage, bool box = false);
|
||||
void ErrorLog(const std::string &str, bool newline = true);
|
||||
void WriteLog(const std::string &str, bool newline = true);
|
||||
void CommLog(const char *str);
|
||||
void CommLog(const std::string &str);
|
||||
enum logtype : unsigned int {
|
||||
|
||||
generic = 0x1,
|
||||
file = 0x2,
|
||||
model = 0x4,
|
||||
texture = 0x8
|
||||
};
|
||||
|
||||
void WriteLog( const char *str, logtype const Type = logtype::generic );
|
||||
void Error( const std::string &asMessage, bool box = false );
|
||||
void Error( const char* &asMessage, bool box = false );
|
||||
void ErrorLog( const std::string &str, logtype const Type = logtype::generic );
|
||||
void WriteLog( const std::string &str, logtype const Type = logtype::generic );
|
||||
void CommLog( const char *str );
|
||||
void CommLog( const std::string &str );
|
||||
|
||||
@@ -84,7 +84,7 @@ extern int ConversionError;
|
||||
const double Steel2Steel_friction = 0.15; //tarcie statyczne
|
||||
const double g = 9.81; //przyspieszenie ziemskie
|
||||
const double SandSpeed = 0.1; //ile kg/s}
|
||||
const double RVentSpeed = 0.4; //rozpedzanie sie wentylatora obr/s^2}
|
||||
const double RVentSpeed = 3.5; //rozpedzanie sie wentylatora obr/s^2}
|
||||
const double RVentMinI = 50.0; //przy jakim pradzie sie wylaczaja}
|
||||
const double Pirazy2 = 6.2831853071794f;
|
||||
#define PI 3.1415926535897f
|
||||
@@ -816,6 +816,7 @@ public:
|
||||
double eimc[26];
|
||||
bool EIMCLogForce; //
|
||||
static std::vector<std::string> const eimc_labels;
|
||||
double InverterFrequency { 0.0 }; // current frequency of power inverters
|
||||
/*-dla wagonow*/
|
||||
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
|
||||
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
|
||||
@@ -944,17 +945,21 @@ public:
|
||||
bool InsideConsist = false;
|
||||
/*-zmienne dla lokomotywy elektrycznej*/
|
||||
TTractionParam RunningTraction;/*parametry sieci trakcyjnej najblizej lokomotywy*/
|
||||
double enrot = 0.0;
|
||||
double Im = 0.0;
|
||||
double Itot = 0.0;
|
||||
double enrot = 0.0; // ilosc obrotow silnika
|
||||
double Im = 0.0; // prad silnika
|
||||
/*
|
||||
// currently not used
|
||||
double IHeating = 0.0;
|
||||
double ITraction = 0.0;
|
||||
*/
|
||||
double Itot = 0.0; // prad calkowity
|
||||
double TotalCurrent = 0.0;
|
||||
// momenty
|
||||
double Mm = 0.0;
|
||||
double Mw = 0.0;
|
||||
// sily napedne
|
||||
double Fw = 0.0;
|
||||
double Ft = 0.0;
|
||||
/*ilosc obrotow, prad silnika i calkowity, momenty, sily napedne*/
|
||||
//Ra: Im jest ujemny, jeśli lok jedzie w stronę sprzęgu 1
|
||||
//a ujemne powinien być przy odwróconej polaryzacji sieci...
|
||||
//w wielu miejscach jest używane abs(Im)
|
||||
|
||||
@@ -605,11 +605,12 @@ void TMoverParameters::BrakeLevelSet(double b)
|
||||
if (fBrakeCtrlPos == b)
|
||||
return; // nie przeliczać, jak nie ma zmiany
|
||||
fBrakeCtrlPos = b;
|
||||
BrakeCtrlPosR = b;
|
||||
if (fBrakeCtrlPos < Handle->GetPos(bh_MIN))
|
||||
fBrakeCtrlPos = Handle->GetPos(bh_MIN); // odcięcie
|
||||
else if (fBrakeCtrlPos > Handle->GetPos(bh_MAX))
|
||||
fBrakeCtrlPos = Handle->GetPos(bh_MAX);
|
||||
// TODO: verify whether BrakeCtrlPosR and fBrakeCtrlPos can be rolled into single variable
|
||||
BrakeCtrlPosR = fBrakeCtrlPos;
|
||||
int x = static_cast<int>(std::floor(fBrakeCtrlPos)); // jeśli odwołujemy się do BrakeCtrlPos w pośrednich, to musi być
|
||||
// obcięte a nie zaokrągone
|
||||
while ((x > BrakeCtrlPos) && (BrakeCtrlPos < BrakeCtrlPosNo)) // jeśli zwiększyło się o 1
|
||||
@@ -4237,46 +4238,24 @@ double TMoverParameters::TractionForce(double dt)
|
||||
*/
|
||||
// hunter-091012: przeniesione z if ActiveDir<>0 (zeby po zejsciu z kierunku dalej spadala predkosc wentylatorow)
|
||||
// wentylatory rozruchowe
|
||||
// TODO: move this to update, it doesn't exactly have much to do with traction
|
||||
if( true == Mains ) {
|
||||
// TBD, TODO: move this to update, it doesn't exactly have much to do with traction
|
||||
switch( EngineType ) {
|
||||
|
||||
switch( EngineType ) {
|
||||
case ElectricInductionMotor: {
|
||||
// TBD, TODO: currently ignores RVentType, fix this?
|
||||
auto const tmpV { std::abs( eimv[ eimv_fp ] ) };
|
||||
|
||||
if( ( RlistSize > 0 )
|
||||
&& ( ( std::abs( eimv[ eimv_If ] ) > 1.0 )
|
||||
|| ( tmpV > 0.1 ) ) ) {
|
||||
|
||||
int i = 0;
|
||||
while( ( i < RlistSize - 1 )
|
||||
&& ( DElist[ i + 1 ].RPM < tmpV ) ) {
|
||||
++i;
|
||||
}
|
||||
RventRot =
|
||||
( tmpV - DElist[ i ].RPM )
|
||||
/ std::max( 1.0, ( DElist[ i + 1 ].RPM - DElist[ i ].RPM ) )
|
||||
* ( DElist[ i + 1 ].GenPower - DElist[ i ].GenPower )
|
||||
+ DElist[ i ].GenPower;
|
||||
}
|
||||
else {
|
||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ElectricSeriesMotor: {
|
||||
case ElectricSeriesMotor: {
|
||||
if( true == Mains ) {
|
||||
switch( RVentType ) {
|
||||
|
||||
case 1: { // manual
|
||||
if( ( ActiveDir != 0 )
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt;
|
||||
}
|
||||
else {
|
||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||
RventRot = std::max( 0.0, RventRot - RVentSpeed * dt );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: { // automatic
|
||||
if( ( std::abs( Itot ) > RVentMinI )
|
||||
&& ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) {
|
||||
@@ -4287,30 +4266,36 @@ double TMoverParameters::TractionForce(double dt)
|
||||
RventRot += ( RVentnmax * Im / ImaxLo - RventRot ) * RVentSpeed * dt;
|
||||
}
|
||||
else {
|
||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||
RventRot = std::max( 0.0, RventRot - RVentSpeed * dt );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
} // rventtype
|
||||
} // mains
|
||||
else {
|
||||
RventRot = std::max( 0.0, RventRot - RVentSpeed * dt );
|
||||
}
|
||||
case DieselElectric: {
|
||||
}
|
||||
|
||||
case DieselElectric: {
|
||||
if( true == Mains ) {
|
||||
// TBD, TODO: currently ignores RVentType, fix this?
|
||||
RventRot += clamp( DElist[ MainCtrlPos ].RPM - RventRot, -100.0, 50.0 ) * dt;
|
||||
break;
|
||||
}
|
||||
case DieselEngine:
|
||||
default: {
|
||||
break;
|
||||
else {
|
||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||
}
|
||||
} // enginetype
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt );
|
||||
}
|
||||
RventRot = std::max( 0.0, RventRot );
|
||||
|
||||
if (ActiveDir != 0)
|
||||
switch (EngineType)
|
||||
@@ -4443,29 +4428,36 @@ double TMoverParameters::TractionForce(double dt)
|
||||
}
|
||||
else // jazda ciapongowa
|
||||
{
|
||||
|
||||
auto power = Power;
|
||||
if( true == Heating ) { power -= HeatingPower; }
|
||||
if( power < 0.0 ) { power = 0.0; }
|
||||
tmp = std::min( DElist[ MainCtrlPos ].GenPower, power );// Power - HeatingPower * double( Heating ));
|
||||
// NOTE: very crude way to approximate power generated at current rpm instead of instant top output
|
||||
auto const currentgenpower { (
|
||||
DElist[ MainCtrlPos ].RPM > 0 ?
|
||||
DElist[ MainCtrlPos ].GenPower * ( 60.0 * enrot / DElist[ MainCtrlPos ].RPM ) :
|
||||
0.0 ) };
|
||||
|
||||
tmp = std::min( power, currentgenpower );
|
||||
|
||||
PosRatio = DElist[MainCtrlPos].GenPower / DElist[MainCtrlPosNo].GenPower;
|
||||
PosRatio = currentgenpower / DElist[MainCtrlPosNo].GenPower;
|
||||
// stosunek mocy teraz do mocy max
|
||||
if ((MainCtrlPos > 0) && (ConverterFlag))
|
||||
if (tmpV <
|
||||
(Vhyp * power /
|
||||
DElist[MainCtrlPosNo].GenPower)) // czy na czesci prostej, czy na hiperboli
|
||||
Ft = (Ftmax -
|
||||
((Ftmax - 1000.0 * DElist[MainCtrlPosNo].GenPower / (Vhyp + Vadd)) *
|
||||
(tmpV / Vhyp) / PowerCorRatio)) *
|
||||
PosRatio; // posratio - bo sila jakos tam sie rozklada
|
||||
if( ( MainCtrlPos > 0 ) && ( ConverterFlag ) ) {
|
||||
|
||||
// Ft:=(Ftmax - (Ftmax - (1000.0 * DEList[MainCtrlPosNo].genpower /
|
||||
//(Vhyp+Vadd) / PowerCorRatio)) * (tmpV/Vhyp)) * PosRatio //wersja z Megapacka
|
||||
else // na hiperboli //1.107 -
|
||||
// wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka
|
||||
Ft = 1000.0 * tmp / (tmpV + Vadd) /
|
||||
PowerCorRatio; // tu jest zawarty stosunek mocy
|
||||
if( tmpV < ( Vhyp * power / DElist[ MainCtrlPosNo ].GenPower ) ) {
|
||||
// czy na czesci prostej, czy na hiperboli
|
||||
Ft = ( Ftmax
|
||||
- ( ( Ftmax - 1000.0 * DElist[ MainCtrlPosNo ].GenPower / ( Vhyp + Vadd ) )
|
||||
* ( tmpV / Vhyp )
|
||||
/ PowerCorRatio ) )
|
||||
* PosRatio; // posratio - bo sila jakos tam sie rozklada
|
||||
}
|
||||
else {
|
||||
// na hiperboli
|
||||
// 1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka
|
||||
Ft = 1000.0 * tmp / ( tmpV + Vadd ) /
|
||||
PowerCorRatio; // tu jest zawarty stosunek mocy
|
||||
}
|
||||
}
|
||||
else
|
||||
Ft = 0; // jak nastawnik na zero, to sila tez zero
|
||||
|
||||
@@ -4506,32 +4498,40 @@ double TMoverParameters::TractionForce(double dt)
|
||||
Im = DElist[MainCtrlPos].Imax;
|
||||
}
|
||||
|
||||
if (Im > 0) // jak pod obciazeniem
|
||||
if (Flat) // ograniczenie napiecia w pradnicy - plaszczak u gory
|
||||
Voltage = 1000.0 * tmp / abs(Im);
|
||||
else // charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa
|
||||
|
||||
{
|
||||
Voltage = sqrt(abs(square(DElist[MainCtrlPos].Umax) -
|
||||
square(DElist[MainCtrlPos].Umax * Im /
|
||||
DElist[MainCtrlPos].Imax))) *
|
||||
(MainCtrlPos - 1) +
|
||||
(1.0 - Im / DElist[MainCtrlPos].Imax) * DElist[MainCtrlPos].Umax *
|
||||
(MainCtrlPosNo - MainCtrlPos);
|
||||
Voltage = Voltage / (MainCtrlPosNo - 1);
|
||||
Voltage = Min0R(Voltage, (1000.0 * tmp / abs(Im)));
|
||||
if (Voltage < (Im * 0.05))
|
||||
Voltage = Im * 0.05;
|
||||
if( Im > 0 ) {
|
||||
// jak pod obciazeniem
|
||||
if( true == Flat ) {
|
||||
// ograniczenie napiecia w pradnicy - plaszczak u gory
|
||||
Voltage = 1000.0 * tmp / std::abs( Im );
|
||||
}
|
||||
if ((Voltage > DElist[MainCtrlPos].Umax) ||
|
||||
(Im == 0)) // gdy wychodzi za duze napiecie
|
||||
Voltage = DElist[MainCtrlPos].Umax *
|
||||
int(ConverterFlag); // albo przy biegu jalowym (jest cos takiego?)
|
||||
else {
|
||||
// charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa
|
||||
Voltage =
|
||||
std::sqrt(
|
||||
std::abs(
|
||||
square( DElist[ MainCtrlPos ].Umax )
|
||||
- square( DElist[ MainCtrlPos ].Umax * Im / DElist[ MainCtrlPos ].Imax ) ) )
|
||||
* ( MainCtrlPos - 1 )
|
||||
+ ( 1.0 - Im / DElist[ MainCtrlPos ].Imax ) * DElist[ MainCtrlPos ].Umax * ( MainCtrlPosNo - MainCtrlPos );
|
||||
Voltage /= ( MainCtrlPosNo - 1 );
|
||||
Voltage = clamp(
|
||||
Voltage,
|
||||
Im * 0.05, ( 1000.0 * tmp / std::abs( Im ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( Voltage > DElist[ MainCtrlPos ].Umax )
|
||||
|| ( Im == 0 ) ) {
|
||||
// gdy wychodzi za duze napiecie albo przy biegu jalowym (jest cos takiego?)
|
||||
Voltage = DElist[ MainCtrlPos ].Umax * ( ConverterFlag ? 1 : 0 );
|
||||
}
|
||||
|
||||
EnginePower = Voltage * Im / 1000.0;
|
||||
|
||||
/*
|
||||
// NOTE: this part is experimentally disabled, as it generated early traction force drop for undetermined purpose
|
||||
if ((tmpV > 2) && (EnginePower < tmp))
|
||||
Ft = Ft * EnginePower / tmp;
|
||||
*/
|
||||
}
|
||||
|
||||
if ((Imax > 1) && (Im > Imax))
|
||||
@@ -4705,8 +4705,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ); // TODO: check whether we need to send this EMU-wide
|
||||
}
|
||||
}
|
||||
if ((Mains))
|
||||
{
|
||||
if( true == Mains ) {
|
||||
|
||||
dtrans = Hamulec->GetEDBCP();
|
||||
if (((DoorLeftOpened) || (DoorRightOpened)))
|
||||
@@ -4874,35 +4873,56 @@ double TMoverParameters::TractionForce(double dt)
|
||||
Itot = eimv[eimv_Ipoj] * (0.01 + Min0R(0.99, 0.99 - Vadd));
|
||||
|
||||
EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000;
|
||||
// power inverters
|
||||
auto const tmpV { std::abs( eimv[ eimv_fp ] ) };
|
||||
|
||||
if( ( RlistSize > 0 )
|
||||
&& ( ( std::abs( eimv[ eimv_If ] ) > 1.0 )
|
||||
|| ( tmpV > 0.1 ) ) ) {
|
||||
|
||||
int i = 0;
|
||||
while( ( i < RlistSize - 1 )
|
||||
&& ( DElist[ i + 1 ].RPM < tmpV ) ) {
|
||||
++i;
|
||||
}
|
||||
InverterFrequency =
|
||||
( tmpV - DElist[ i ].RPM )
|
||||
/ std::max( 1.0, ( DElist[ i + 1 ].RPM - DElist[ i ].RPM ) )
|
||||
* ( DElist[ i + 1 ].GenPower - DElist[ i ].GenPower )
|
||||
+ DElist[ i ].GenPower;
|
||||
}
|
||||
else {
|
||||
InverterFrequency = 0.0;
|
||||
}
|
||||
|
||||
Mm = eimv[eimv_M] * DirAbsolute;
|
||||
Mw = Mm * Transmision.Ratio;
|
||||
Fw = Mw * 2.0 / WheelDiameter;
|
||||
Ft = Fw * NPoweredAxles;
|
||||
eimv[eimv_Fr] = DirAbsolute * Ft / 1000;
|
||||
// RventRot;
|
||||
}
|
||||
} // mains
|
||||
else
|
||||
{
|
||||
Im = 0;
|
||||
Mm = 0;
|
||||
Mw = 0;
|
||||
Fw = 0;
|
||||
Ft = 0;
|
||||
Itot = 0;
|
||||
dizel_fill = 0;
|
||||
EnginePower = 0;
|
||||
Im = 0.0;
|
||||
Mm = 0.0;
|
||||
Mw = 0.0;
|
||||
Fw = 0.0;
|
||||
Ft = 0.0;
|
||||
Itot = 0.0;
|
||||
dizel_fill = 0.0;
|
||||
EnginePower = 0.0;
|
||||
{
|
||||
for (int i = 0; i < 21; ++i)
|
||||
eimv[i] = 0;
|
||||
eimv[i] = 0.0;
|
||||
}
|
||||
Hamulec->SetED(0);
|
||||
RventRot = 0.0; //(Hamulec as TLSt).SetLBP(LocBrakePress);
|
||||
Hamulec->SetED(0.0);
|
||||
InverterFrequency = 0.0; //(Hamulec as TLSt).SetLBP(LocBrakePress);
|
||||
}
|
||||
break;
|
||||
} // ElectricInductionMotor
|
||||
|
||||
case None:
|
||||
{
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
} // case EngineType
|
||||
|
||||
43
Model3d.cpp
43
Model3d.cpp
@@ -375,6 +375,15 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
glm::length( glm::vec3( glm::column( matrix, 0 ) ) ),
|
||||
glm::length( glm::vec3( glm::column( matrix, 1 ) ) ),
|
||||
glm::length( glm::vec3( glm::column( matrix, 2 ) ) ) };
|
||||
if( ( std::abs( scale.x - 1.0f ) > 0.01 )
|
||||
|| ( std::abs( scale.y - 1.0f ) > 0.01 )
|
||||
|| ( std::abs( scale.z - 1.0f ) > 0.01 ) ) {
|
||||
ErrorLog( "Bad model: transformation matrix for sub-model \"" + pName + "\" imposes geometry scaling (factors: " + to_string( scale ) + ")", logtype::model );
|
||||
m_normalizenormals = (
|
||||
( ( std::abs( scale.x - scale.y ) < 0.01f ) && ( std::abs( scale.y - scale.z ) < 0.01f ) ) ?
|
||||
rescale :
|
||||
normalize );
|
||||
}
|
||||
}
|
||||
if (eType < TP_ROTATOR)
|
||||
{ // wczytywanie wierzchołków
|
||||
@@ -455,7 +464,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
--facecount; // o jeden trójkąt mniej
|
||||
iNumVerts -= 3; // czyli o 3 wierzchołki
|
||||
i -= 3; // wczytanie kolejnego w to miejsce
|
||||
WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(rawvertexcount-2) + "-" + std::to_string(rawvertexcount));
|
||||
WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(rawvertexcount-2) + "-" + std::to_string(rawvertexcount), logtype::model );
|
||||
}
|
||||
if (i > 0) {
|
||||
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
|
||||
@@ -467,7 +476,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
--facecount; // o jeden trójkąt mniej
|
||||
iNumVerts -= 3; // czyli o 3 wierzchołki
|
||||
i -= 3; // wczytanie kolejnego w to miejsce
|
||||
WriteLog( "Bad model: too large triangle ignored in: \"" + pName + "\"" );
|
||||
WriteLog( "Bad model: too large triangle ignored in: \"" + pName + "\"", logtype::model );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -506,14 +515,14 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
vertexnormal += facenormals[ adjacenvertextidx / 3 ];
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad model: opposite normals in the same smoothing group, check sub-model \"" + pName + "\" for two-sided faces and/or scaling" );
|
||||
ErrorLog( "Bad model: opposite normals in the same smoothing group, check sub-model \"" + pName + "\" for two-sided faces and/or scaling", logtype::model );
|
||||
}
|
||||
// i szukanie od kolejnego trójkąta
|
||||
adjacenvertextidx = SeekFaceNormal(sg, adjacenvertextidx / 3 + 1, sg[faceidx], Vertices[vertexidx].position, Vertices);
|
||||
}
|
||||
// Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe
|
||||
if( glm::length2( vertexnormal ) == 0.0f ) {
|
||||
WriteLog( "Bad model: zero lenght normal vector generated for sub-model \"" + pName + "\"" );
|
||||
WriteLog( "Bad model: zero lenght normal vector generated for sub-model \"" + pName + "\"", logtype::model );
|
||||
}
|
||||
Vertices[ vertexidx ].normal = (
|
||||
glm::length2( vertexnormal ) > 0.0f ?
|
||||
@@ -1167,7 +1176,7 @@ TSubModel::offset( float const Geometrytestoffsetthreshold ) const {
|
||||
|
||||
auto offset { glm::vec3 { glm::make_mat4( parentmatrix.readArray() ) * glm::vec4 { 0, 0, 0, 1 } } };
|
||||
|
||||
if( glm::length2( offset ) < Geometrytestoffsetthreshold ) {
|
||||
if( glm::length( offset ) < Geometrytestoffsetthreshold ) {
|
||||
// offset of zero generally means the submodel has optimized identity matrix
|
||||
// for such cases we resort to an estimate from submodel geometry
|
||||
// TODO: do proper bounding area calculation for submodel when loading mesh and grab the centre point from it here
|
||||
@@ -1235,7 +1244,7 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
|
||||
Root ? (iSubModelsCount > 0) : false; // brak pliku albo problem z wczytaniem
|
||||
if (false == result)
|
||||
{
|
||||
ErrorLog("Failed to load 3d model \"" + FileName + "\"");
|
||||
ErrorLog("Bad model: failed to load 3d model \"" + FileName + "\"");
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@@ -1518,6 +1527,11 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
if( submodel.eType < TP_ROTATOR ) {
|
||||
// normal vectors debug routine
|
||||
auto normallength = glm::length2( vertex.normal );
|
||||
if( ( false == submodel.m_normalizenormals )
|
||||
&& ( std::abs( normallength - 1.0f ) > 0.01f ) ) {
|
||||
submodel.m_normalizenormals = TSubModel::normalize; // we don't know if uniform scaling would suffice
|
||||
WriteLog( "Bad model: non-unit normal vector(s) encountered during sub-model geometry deserialization", logtype::model );
|
||||
}
|
||||
}
|
||||
}
|
||||
// remap geometry type for custom type submodels
|
||||
@@ -1642,7 +1656,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad model: reference to nonexistent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
|
||||
ErrorLog( "Bad model: reference to nonexistent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ), logtype::model );
|
||||
m_material = null_handle;
|
||||
}
|
||||
}
|
||||
@@ -1679,12 +1693,21 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
glm::length( glm::vec3( glm::column( matrix, 0 ) ) ),
|
||||
glm::length( glm::vec3( glm::column( matrix, 1 ) ) ),
|
||||
glm::length( glm::vec3( glm::column( matrix, 2 ) ) ) };
|
||||
if( ( std::abs( scale.x - 1.0f ) > 0.01 )
|
||||
|| ( std::abs( scale.y - 1.0f ) > 0.01 )
|
||||
|| ( std::abs( scale.z - 1.0f ) > 0.01 ) ) {
|
||||
ErrorLog( "Bad model: transformation matrix for sub-model \"" + pName + "\" imposes geometry scaling (factors: " + to_string( scale ) + ")", logtype::model );
|
||||
m_normalizenormals = (
|
||||
( ( std::abs( scale.x - scale.y ) < 0.01f ) && ( std::abs( scale.y - scale.z ) < 0.01f ) ) ?
|
||||
rescale :
|
||||
normalize );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
||||
{ // wczytanie modelu z pliku binarnego
|
||||
WriteLog("Loading binary format 3d model data from \"" + FileName + "\"...");
|
||||
WriteLog( "Loading binary format 3d model data from \"" + FileName + "\"...", logtype::model );
|
||||
|
||||
std::string fn = FileName;
|
||||
std::replace(fn.begin(), fn.end(), '\\', '/');
|
||||
@@ -1699,12 +1722,12 @@ void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
||||
deserialize(file, size, dynamic);
|
||||
file.close();
|
||||
|
||||
WriteLog("Finished loading 3d model data from \"" + FileName + "\"");
|
||||
WriteLog( "Finished loading 3d model data from \"" + FileName + "\"", logtype::model );
|
||||
};
|
||||
|
||||
void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
|
||||
{ // wczytanie submodelu z pliku tekstowego
|
||||
WriteLog("Loading text format 3d model data from \"" + FileName + "\"...");
|
||||
WriteLog( "Loading text format 3d model data from \"" + FileName + "\"...", logtype::model );
|
||||
iFlags |= 0x0200; // wczytano z pliku tekstowego (właścicielami tablic są submodle)
|
||||
cParser parser(FileName, cParser::buffer_FILE); // Ra: tu powinno być "models\\"...
|
||||
TSubModel *SubModel;
|
||||
|
||||
60
Texture.cpp
60
Texture.cpp
@@ -40,7 +40,7 @@ opengl_texture::load() {
|
||||
|
||||
if( name.size() < 3 ) { goto fail; }
|
||||
|
||||
WriteLog( "Loading texture data from \"" + name + "\"" );
|
||||
WriteLog( "Loading texture data from \"" + name + "\"", logtype::texture );
|
||||
|
||||
data_state = resource_state::loading;
|
||||
{
|
||||
@@ -69,7 +69,7 @@ opengl_texture::load() {
|
||||
|
||||
fail:
|
||||
data_state = resource_state::failed;
|
||||
ErrorLog( "Failed to load texture \"" + name + "\"" );
|
||||
ErrorLog( "Bad texture: failed to load texture \"" + name + "\"" );
|
||||
// NOTE: temporary workaround for texture assignment errors
|
||||
id = 0;
|
||||
return;
|
||||
@@ -138,7 +138,7 @@ opengl_texture::load_BMP() {
|
||||
BITMAPINFO info;
|
||||
unsigned int infosize = header.bfOffBits - sizeof( BITMAPFILEHEADER );
|
||||
if( infosize > sizeof( info ) ) {
|
||||
WriteLog( "Warning - BMP header is larger than expected, possible format difference." );
|
||||
WriteLog( "Warning - BMP header is larger than expected, possible format difference.", logtype::texture );
|
||||
}
|
||||
file.read( (char *)&info, std::min( (size_t)infosize, sizeof( info ) ) );
|
||||
|
||||
@@ -147,7 +147,7 @@ opengl_texture::load_BMP() {
|
||||
|
||||
if( info.bmiHeader.biCompression != BI_RGB ) {
|
||||
|
||||
ErrorLog( "Compressed BMP textures aren't supported." );
|
||||
ErrorLog( "Bad texture: compressed BMP textures aren't supported.", logtype::texture );
|
||||
data_state = resource_state::failed;
|
||||
return;
|
||||
}
|
||||
@@ -336,7 +336,7 @@ opengl_texture::load_DDS() {
|
||||
*/
|
||||
if( datasize == 0 ) {
|
||||
// catch malformed .dds files
|
||||
WriteLog( "File \"" + name + "\" is malformed and holds no texture data." );
|
||||
WriteLog( "Bad texture: file \"" + name + "\" is malformed and holds no texture data.", logtype::texture );
|
||||
data_state = resource_state::failed;
|
||||
return;
|
||||
}
|
||||
@@ -377,7 +377,7 @@ opengl_texture::load_TEX() {
|
||||
hasalpha = true;
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Unrecognized TEX texture sub-format: " + std::string(head) );
|
||||
ErrorLog( "Bad texture: unrecognized TEX texture sub-format: " + std::string(head), logtype::texture );
|
||||
data_state = resource_state::failed;
|
||||
return;
|
||||
};
|
||||
@@ -636,10 +636,12 @@ opengl_texture::create() {
|
||||
}
|
||||
}
|
||||
|
||||
// TBD, TODO: keep the texture data if we start doing some gpu data cleaning down the road
|
||||
data.clear();
|
||||
data.shrink_to_fit();
|
||||
data_state = resource_state::none;
|
||||
if( ( true == Global::ResourceMove )
|
||||
|| ( false == Global::ResourceSweep ) ) {
|
||||
// if garbage collection is disabled we don't expect having to upload the texture more than once
|
||||
data = std::vector<char>();
|
||||
data_state = resource_state::none;
|
||||
}
|
||||
is_ready = true;
|
||||
}
|
||||
|
||||
@@ -648,19 +650,35 @@ opengl_texture::create() {
|
||||
|
||||
// releases resources allocated on the opengl end, storing local copy if requested
|
||||
void
|
||||
opengl_texture::release( bool const Backup ) {
|
||||
opengl_texture::release() {
|
||||
|
||||
if( id == -1 ) { return; }
|
||||
|
||||
if( true == Backup ) {
|
||||
// query texture details needed to perform the backup...
|
||||
if( true == Global::ResourceMove ) {
|
||||
// if resource move is enabled we don't keep a cpu side copy after upload
|
||||
// so need to re-acquire the data before release
|
||||
// TBD, TODO: instead of vram-ram transfer fetch the data 'normally' from the disk using worker thread
|
||||
::glBindTexture( GL_TEXTURE_2D, id );
|
||||
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&data_format );
|
||||
GLint datasize;
|
||||
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&datasize );
|
||||
data.resize( datasize );
|
||||
// ...fetch the data...
|
||||
::glGetCompressedTexImage( GL_TEXTURE_2D, 0, &data[ 0 ] );
|
||||
GLint datasize {};
|
||||
GLint iscompressed {};
|
||||
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &iscompressed );
|
||||
if( iscompressed == GL_TRUE ) {
|
||||
// texture is compressed on the gpu side
|
||||
// query texture details needed to perform the backup...
|
||||
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &data_format );
|
||||
::glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &datasize );
|
||||
data.resize( datasize );
|
||||
// ...fetch the data...
|
||||
::glGetCompressedTexImage( GL_TEXTURE_2D, 0, &data[ 0 ] );
|
||||
}
|
||||
else {
|
||||
// for whatever reason texture didn't get compressed during upload
|
||||
// fallback on plain rgba storage...
|
||||
data_format = GL_RGBA;
|
||||
data.resize( data_width * data_height * 4 );
|
||||
// ...fetch the data...
|
||||
::glGetTexImage( GL_TEXTURE_2D, 0, data_format, GL_UNSIGNED_BYTE, &data[ 0 ] );
|
||||
}
|
||||
// ...and update texture object state
|
||||
data_mapcount = 1; // we keep copy of only top mipmap level
|
||||
data_state = resource_state::good;
|
||||
@@ -816,7 +834,7 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
|
||||
if( true == filename.empty() ) {
|
||||
// there's nothing matching in the databank nor on the disk, report failure
|
||||
ErrorLog( "Texture file missing: \"" + Filename + "\"" );
|
||||
ErrorLog( "Bad file: failed do locate texture file \"" + Filename + "\"", logtype::file );
|
||||
return npos;
|
||||
}
|
||||
|
||||
@@ -831,7 +849,7 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
m_textures.emplace_back( texture, std::chrono::steady_clock::time_point() );
|
||||
m_texturemappings.emplace( filename, textureindex );
|
||||
|
||||
WriteLog( "Created texture object for \"" + filename + "\"" );
|
||||
WriteLog( "Created texture object for \"" + filename + "\"", logtype::texture );
|
||||
|
||||
if( true == Loadnow ) {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ struct opengl_texture {
|
||||
create();
|
||||
// releases resources allocated on the opengl end, storing local copy if requested
|
||||
void
|
||||
release( bool const Backup = true );
|
||||
release();
|
||||
inline
|
||||
int
|
||||
width() const {
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
int data_width{ 0 },
|
||||
data_height{ 0 },
|
||||
data_mapcount{ 0 };
|
||||
GLuint data_format{ 0 },
|
||||
GLint data_format{ 0 },
|
||||
data_components{ 0 };
|
||||
/*
|
||||
std::atomic<bool> is_loaded{ false }; // indicates the texture data was loaded and can be processed
|
||||
|
||||
204
Train.cpp
204
Train.cpp
@@ -322,7 +322,6 @@ TTrain::TTrain() {
|
||||
pMechOffset = vector3(0, 0, 0);
|
||||
fBlinkTimer = 0;
|
||||
fHaslerTimer = 0;
|
||||
keybrakecount = 0;
|
||||
DynamicSet(NULL); // ustawia wszystkie mv*
|
||||
iCabLightFlag = 0;
|
||||
// hunter-091012
|
||||
@@ -470,6 +469,7 @@ PyObject *TTrain::GetTrainState() {
|
||||
PyDict_SetItemString( dict, "shp", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ) );
|
||||
PyDict_SetItemString( dict, "pantpress", PyGetFloat( mvControlled->PantPress ) );
|
||||
PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) );
|
||||
PyDict_SetItemString( dict, "radio_channel", PyGetInt( iRadioChannel ) );
|
||||
// movement data
|
||||
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
||||
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
||||
@@ -551,6 +551,24 @@ bool TTrain::is_eztoer() const {
|
||||
&& ( mvControlled->ActiveDir != 0 ) ); // od yB
|
||||
}
|
||||
|
||||
// moves train brake lever to specified position, potentially emits switch sound if conditions are met
|
||||
void TTrain::set_train_brake( double const Position ) {
|
||||
|
||||
auto const originalbrakeposition { static_cast<int>( 100.0 * mvOccupied->fBrakeCtrlPos ) };
|
||||
|
||||
mvOccupied->BrakeLevelSet( Position );
|
||||
|
||||
if( static_cast<int>( 100.0 * mvOccupied->fBrakeCtrlPos ) == originalbrakeposition ) { return; }
|
||||
|
||||
if( ( true == is_eztoer() )
|
||||
&& ( false == (
|
||||
( ( originalbrakeposition / 100 == 0 ) || ( originalbrakeposition / 100 >= 5 ) )
|
||||
&& ( ( mvOccupied->BrakeCtrlPos == 0 ) || ( mvOccupied->BrakeCtrlPos >= 5 ) ) ) ) ) {
|
||||
// sound feedback if the lever movement activates one of the switches
|
||||
dsbPneumaticSwitch.play();
|
||||
}
|
||||
}
|
||||
|
||||
// locates nearest vehicle belonging to the consist
|
||||
TDynamicObject *
|
||||
TTrain::find_nearest_consist_vehicle() const {
|
||||
@@ -799,14 +817,7 @@ void TTrain::OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Co
|
||||
Train->mvOccupied->BrakeLevelAdd( Global::fBrakeStep * Command.time_delta );
|
||||
}
|
||||
else {
|
||||
if( Train->mvOccupied->BrakeLevelAdd( Global::fBrakeStep * Command.time_delta ) ) {
|
||||
// nieodpowiedni warunek; true, jeśli można dalej kręcić
|
||||
Train->keybrakecount = 0;
|
||||
if( ( Train->is_eztoer() ) && ( Train->mvOccupied->BrakeCtrlPos < 3 ) ) {
|
||||
// Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
}
|
||||
Train->set_train_brake( Train->mvOccupied->fBrakeCtrlPos + Global::fBrakeStep * Command.time_delta );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -819,21 +830,7 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co
|
||||
Train->mvOccupied->BrakeLevelAdd( -Global::fBrakeStep * Command.time_delta );
|
||||
}
|
||||
else {
|
||||
// nową wersję dostarczył ZiomalCl ("fixed looped sound in ezt when using NUM_9 key")
|
||||
if( ( Train->mvOccupied->BrakeCtrlPos > -1 )
|
||||
|| ( Train->keybrakecount > 1 ) ) {
|
||||
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( Train->mvOccupied->BrakeCtrlPos != -1 ) ) {
|
||||
// Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
Train->mvOccupied->BrakeLevelAdd( -Global::fBrakeStep * Command.time_delta );
|
||||
}
|
||||
else
|
||||
Train->keybrakecount += 1;
|
||||
// koniec wersji dostarczonej przez ZiomalCl
|
||||
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global::fBrakeStep * Command.time_delta );
|
||||
}
|
||||
}
|
||||
else if (Command.action == GLFW_RELEASE) {
|
||||
@@ -841,15 +838,9 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co
|
||||
if( ( Train->mvOccupied->BrakeCtrlPos == -1 )
|
||||
&& ( Train->mvOccupied->BrakeHandle == FVel6 )
|
||||
&& ( Train->DynamicObject->Controller != AIdriver )
|
||||
&& ( Global::iFeedbackMode != 4 ) ) {
|
||||
&& ( Global::iFeedbackMode < 3 ) ) {
|
||||
// Odskakiwanie hamulce EP
|
||||
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 );
|
||||
Train->keybrakecount = 0;
|
||||
if( ( Train->mvOccupied->TrainType == dt_EZT )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( Train->mvControlled->ActiveDir != 0 ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
Train->set_train_brake( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -858,29 +849,16 @@ void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Co
|
||||
|
||||
if( Command.action != GLFW_RELEASE ) {
|
||||
// press or hold
|
||||
// sound feedback
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( Train->mvOccupied->BrakeCtrlPos != -1 ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet( -1 );
|
||||
Train->set_train_brake( -1 );
|
||||
}
|
||||
else {
|
||||
// release
|
||||
if( ( Train->mvOccupied->BrakeCtrlPos == -1 )
|
||||
&& ( Train->mvOccupied->BrakeHandle == FVel6 )
|
||||
&& ( Train->DynamicObject->Controller != AIdriver )
|
||||
&& ( Global::iFeedbackMode != 4 ) ) {
|
||||
&& ( Global::iFeedbackMode < 3 ) ) {
|
||||
// Odskakiwanie hamulce EP
|
||||
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 );
|
||||
Train->keybrakecount = 0;
|
||||
if( ( Train->mvOccupied->TrainType == dt_EZT )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( Train->mvControlled->ActiveDir != 0 ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
Train->set_train_brake( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -889,14 +867,7 @@ void TTrain::OnCommand_trainbrakerelease( TTrain *Train, command_data const &Com
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
// sound feedback
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
||||
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet( 0 );
|
||||
Train->set_train_brake( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,14 +875,7 @@ void TTrain::OnCommand_trainbrakefirstservice( TTrain *Train, command_data const
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
// sound feedback
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( Train->mvOccupied->BrakeCtrlPos != 1 ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet( 1 );
|
||||
Train->set_train_brake( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -919,19 +883,11 @@ void TTrain::OnCommand_trainbrakeservice( TTrain *Train, command_data const &Com
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
// sound feedback
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
||||
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet(
|
||||
Train->set_train_brake( (
|
||||
Train->mvOccupied->BrakeCtrlPosNo / 2
|
||||
+ ( Train->mvOccupied->BrakeHandle == FV4a ?
|
||||
1 :
|
||||
0 ) );
|
||||
1 :
|
||||
0 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -939,14 +895,7 @@ void TTrain::OnCommand_trainbrakefullservice( TTrain *Train, command_data const
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
// sound feedback
|
||||
if( ( Train->is_eztoer() )
|
||||
&& ( Train->mvControlled->Mains )
|
||||
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
||||
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
||||
Train->dsbPneumaticSwitch.play();
|
||||
}
|
||||
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPosNo - 1 );
|
||||
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPosNo - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -954,7 +903,7 @@ void TTrain::OnCommand_trainbrakehandleoff( TTrain *Train, command_data const &C
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->Handle->GetPos( bh_NP ) );
|
||||
Train->set_train_brake( Train->mvOccupied->Handle->GetPos( bh_NP ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +911,7 @@ void TTrain::OnCommand_trainbrakeemergency( TTrain *Train, command_data const &C
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->Handle->GetPos( bh_EB ) );
|
||||
Train->set_train_brake( Train->mvOccupied->Handle->GetPos( bh_EB ) );
|
||||
/*
|
||||
if( Train->mvOccupied->BrakeCtrlPosNo <= 0.1 ) {
|
||||
// hamulec bezpieczeństwa dla wagonów
|
||||
@@ -3213,6 +3162,13 @@ void TTrain::OnCommand_radiochannelincrease( TTrain *Train, command_data const &
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
Train->iRadioChannel = clamp( Train->iRadioChannel + 1, 1, 10 );
|
||||
// visual feedback
|
||||
Train->ggRadioChannelSelector.UpdateValue( Train->iRadioChannel - 1 );
|
||||
Train->ggRadioChannelNext.UpdateValue( 1.0 );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// visual feedback
|
||||
Train->ggRadioChannelNext.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3220,6 +3176,13 @@ void TTrain::OnCommand_radiochanneldecrease( TTrain *Train, command_data const &
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
Train->iRadioChannel = clamp( Train->iRadioChannel - 1, 1, 10 );
|
||||
// visual feedback
|
||||
Train->ggRadioChannelSelector.UpdateValue( Train->iRadioChannel - 1 );
|
||||
Train->ggRadioChannelPrevious.UpdateValue( 1.0 );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// visual feedback
|
||||
Train->ggRadioChannelPrevious.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3417,9 +3380,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
|
||||
if (DynamicObject->mdKabina)
|
||||
{ // Ra: TODO: odczyty klawiatury/pulpitu nie
|
||||
// powinny być uzależnione od istnienia modelu
|
||||
// kabiny
|
||||
{ // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny
|
||||
tor = DynamicObject->GetTrack(); // McZapkie-180203
|
||||
// McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol
|
||||
float maxtacho = 3;
|
||||
@@ -3441,9 +3402,10 @@ bool TTrain::Update( double const Deltatime )
|
||||
if (fTachoCount < maxtacho)
|
||||
fTachoCount += Deltatime * 3; // szybciej zacznij stukac
|
||||
}
|
||||
else if (fTachoCount > 0)
|
||||
fTachoCount -= Deltatime * 0.66; // schodz powoli - niektore haslery to ze 4
|
||||
// sekundy potrafia stukac
|
||||
else if( fTachoCount > 0 ) {
|
||||
// schodz powoli - niektore haslery to ze 4 sekundy potrafia stukac
|
||||
fTachoCount -= Deltatime * 0.66;
|
||||
}
|
||||
|
||||
// Ra 2014-09: napięcia i prądy muszą być ustalone najpierw, bo wysyłane są ewentualnie na PoKeys
|
||||
if ((mvControlled->EngineType != DieselElectric)
|
||||
@@ -4056,6 +4018,9 @@ bool TTrain::Update( double const Deltatime )
|
||||
btLampkaForward.Turn(mvControlled->ActiveDir > 0); // jazda do przodu
|
||||
btLampkaBackward.Turn(mvControlled->ActiveDir < 0); // jazda do tyłu
|
||||
btLampkaED.Turn(mvControlled->DynamicBrakeFlag); // hamulec ED
|
||||
btLampkaBrakeProfileG.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_G ) );
|
||||
btLampkaBrakeProfileP.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_P ) );
|
||||
btLampkaBrakeProfileR.Turn( TestFlag( mvOccupied->BrakeDelayFlag, bdelay_R ) );
|
||||
// light indicators
|
||||
// NOTE: sides are hardcoded to deal with setups where single cab is equipped with all indicators
|
||||
btLampkaUpperLight.Turn( ( mvOccupied->iLights[ side::front ] & light::headlight_upper ) != 0 );
|
||||
@@ -4073,6 +4038,9 @@ bool TTrain::Update( double const Deltatime )
|
||||
{ // gdy bateria wyłączona
|
||||
btLampkaHamienie.Turn( false );
|
||||
btLampkaBrakingOff.Turn( false );
|
||||
btLampkaBrakeProfileG.Turn( false );
|
||||
btLampkaBrakeProfileP.Turn( false );
|
||||
btLampkaBrakeProfileR.Turn( false );
|
||||
btLampkaMaxSila.Turn( false );
|
||||
btLampkaPrzekrMaxSila.Turn( false );
|
||||
btLampkaRadio.Turn( false );
|
||||
@@ -4246,7 +4214,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
else // wylaczone
|
||||
{
|
||||
btLampkaCzuwaka.Turn( false );
|
||||
btLampkaSHP.Turn( true );
|
||||
btLampkaSHP.Turn( false );
|
||||
}
|
||||
// przelaczniki
|
||||
// ABu030405 obsluga lampki uniwersalnej:
|
||||
@@ -4280,6 +4248,9 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggConverterFuseButton.Update();
|
||||
ggStLinOffButton.Update();
|
||||
ggRadioButton.Update();
|
||||
ggRadioChannelSelector.Update();
|
||||
ggRadioChannelPrevious.Update();
|
||||
ggRadioChannelNext.Update();
|
||||
ggDepartureSignalButton.Update();
|
||||
|
||||
ggPantFrontButton.Update();
|
||||
@@ -4582,12 +4553,27 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
&& ( false == Global::CabWindowOpen )
|
||||
&& ( DynamicObject->GetVelocity() > 0.5 ) ) {
|
||||
|
||||
volume = rsRunningNoise.m_amplitudeoffset + rsRunningNoise.m_amplitudefactor * mvOccupied->Vel;
|
||||
auto frequency { rsRunningNoise.m_frequencyoffset + rsRunningNoise.m_frequencyfactor * mvOccupied->Vel };
|
||||
// frequency calculation
|
||||
auto const normalizer { (
|
||||
true == rsRunningNoise.is_combined() ?
|
||||
mvOccupied->Vmax * 0.01f :
|
||||
1.f ) };
|
||||
auto const frequency {
|
||||
rsRunningNoise.m_frequencyoffset
|
||||
+ rsRunningNoise.m_frequencyfactor * mvOccupied->Vel * normalizer };
|
||||
|
||||
// volume calculation
|
||||
volume =
|
||||
rsRunningNoise.m_amplitudeoffset
|
||||
+ rsRunningNoise.m_amplitudefactor * mvOccupied->Vel;
|
||||
if( std::abs( mvOccupied->nrot ) > 0.01 ) {
|
||||
// hamulce wzmagaja halas
|
||||
volume *= 1 + 0.25 * ( mvOccupied->UnitBrakeForce / ( 1 + mvOccupied->MaxBrakeForce ) );
|
||||
auto const brakeforceratio { (
|
||||
clamp(
|
||||
mvOccupied->UnitBrakeForce / std::max( 1.0, mvOccupied->BrakeForceR( 1.0, mvOccupied->Vel ) / ( mvOccupied->NAxles * std::max( 1, mvOccupied->NBpA ) ) ),
|
||||
0.0, 1.0 ) ) };
|
||||
|
||||
volume *= 1 + 0.125 * brakeforceratio;
|
||||
}
|
||||
// scale volume by track quality
|
||||
volume *= ( 20.0 + DynamicObject->MyTrack->iDamageFlag ) / 21;
|
||||
@@ -4599,10 +4585,16 @@ TTrain::update_sounds( double const Deltatime ) {
|
||||
clamp(
|
||||
mvOccupied->Vel / 40.0,
|
||||
0.0, 1.0 ) );
|
||||
rsRunningNoise
|
||||
.pitch( frequency )
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
|
||||
if( volume > 0.05 ) {
|
||||
rsRunningNoise
|
||||
.pitch( frequency )
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
rsRunningNoise.stop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// don't play the optional ending sound if the listener switches views
|
||||
@@ -5257,6 +5249,10 @@ void TTrain::clear_cab_controls()
|
||||
ggFuseButton.Clear();
|
||||
ggConverterFuseButton.Clear();
|
||||
ggStLinOffButton.Clear();
|
||||
ggRadioButton.Clear();
|
||||
ggRadioChannelSelector.Clear();
|
||||
ggRadioChannelPrevious.Clear();
|
||||
ggRadioChannelNext.Clear();
|
||||
ggDoorLeftButton.Clear();
|
||||
ggDoorRightButton.Clear();
|
||||
ggDepartureSignalButton.Clear();
|
||||
@@ -5335,6 +5331,9 @@ void TTrain::clear_cab_controls()
|
||||
btLampkaRadiotelefon.Clear();
|
||||
btLampkaHamienie.Clear();
|
||||
btLampkaBrakingOff.Clear();
|
||||
btLampkaBrakeProfileG.Clear();
|
||||
btLampkaBrakeProfileP.Clear();
|
||||
btLampkaBrakeProfileR.Clear();
|
||||
btLampkaSprezarka.Clear();
|
||||
btLampkaSprezarkaB.Clear();
|
||||
btLampkaSprezarkaOff.Clear();
|
||||
@@ -5391,6 +5390,7 @@ void TTrain::set_cab_controls() {
|
||||
if( true == mvOccupied->Radio ) {
|
||||
ggRadioButton.PutValue( 1.0 );
|
||||
}
|
||||
ggRadioChannelSelector.PutValue( iRadioChannel - 1 );
|
||||
// pantographs
|
||||
if( mvOccupied->PantSwitchType != "impulse" ) {
|
||||
ggPantFrontButton.PutValue(
|
||||
@@ -5612,6 +5612,9 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
|
||||
{ "i-braking:", btLampkaHamienie },
|
||||
{ "i-brakingoff:", btLampkaBrakingOff },
|
||||
{ "i-dynamicbrake:", btLampkaED },
|
||||
{ "i-brakeprofileg:", btLampkaBrakeProfileG },
|
||||
{ "i-brakeprofilep:", btLampkaBrakeProfileP },
|
||||
{ "i-brakeprofiler:", btLampkaBrakeProfileR },
|
||||
{ "i-braking-ezt:", btLampkaHamowanie1zes },
|
||||
{ "i-braking-ezt2:", btLampkaHamowanie2zes },
|
||||
{ "i-compressor:", btLampkaSprezarka },
|
||||
@@ -5719,6 +5722,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
||||
{ "converteroff_sw:", ggConverterOffButton },
|
||||
{ "main_sw:", ggMainButton },
|
||||
{ "radio_sw:", ggRadioButton },
|
||||
{ "radiochannel_sw:", ggRadioChannelSelector },
|
||||
{ "radiochannelprev_sw:", ggRadioChannelPrevious },
|
||||
{ "radiochannelnext_sw:", ggRadioChannelNext },
|
||||
{ "pantfront_sw:", ggPantFrontButton },
|
||||
{ "pantrear_sw:", ggPantRearButton },
|
||||
{ "pantfrontoff_sw:", ggPantFrontButtonOff },
|
||||
|
||||
13
Train.h
13
Train.h
@@ -90,7 +90,6 @@ class TTrain
|
||||
void UpdateMechPosition(double dt);
|
||||
vector3 GetWorldMechPosition();
|
||||
bool Update( double const Deltatime );
|
||||
void update_sounds( double const Deltatime );
|
||||
void MechStop();
|
||||
void SetLights();
|
||||
// McZapkie-310302: ladowanie parametrow z pliku
|
||||
@@ -115,6 +114,10 @@ class TTrain
|
||||
bool is_eztoer() const;
|
||||
// locates nearest vehicle belonging to the consist
|
||||
TDynamicObject *find_nearest_consist_vehicle() const;
|
||||
// moves train brake lever to specified position, potentially emits switch sound if conditions are met
|
||||
void set_train_brake( double const Position );
|
||||
// update function subroutines
|
||||
void update_sounds( double const Deltatime );
|
||||
|
||||
// command handlers
|
||||
// NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis
|
||||
@@ -269,6 +272,9 @@ public: // reszta może by?publiczna
|
||||
TGauge ggConverterFuseButton; // hunter-261211: przycisk odblokowania nadmiarowego przetwornic i ogrzewania
|
||||
TGauge ggStLinOffButton;
|
||||
TGauge ggRadioButton;
|
||||
TGauge ggRadioChannelSelector;
|
||||
TGauge ggRadioChannelPrevious;
|
||||
TGauge ggRadioChannelNext;
|
||||
TGauge ggUpperLightButton;
|
||||
TGauge ggLeftLightButton;
|
||||
TGauge ggRightLightButton;
|
||||
@@ -378,6 +384,10 @@ public: // reszta może by?publiczna
|
||||
TButton btLampkaHamienie;
|
||||
TButton btLampkaBrakingOff;
|
||||
TButton btLampkaED; // Stele 161228 hamowanie elektrodynamiczne
|
||||
TButton btLampkaBrakeProfileG; // cargo train brake acting speed
|
||||
TButton btLampkaBrakeProfileP; // passenger train brake acting speed
|
||||
TButton btLampkaBrakeProfileR; // rapid brake acting speed
|
||||
|
||||
// KURS90
|
||||
TButton btLampkaBoczniki;
|
||||
TButton btLampkaMaxSila;
|
||||
@@ -469,7 +479,6 @@ private:
|
||||
|
||||
double fPoslizgTimer;
|
||||
TTrack *tor;
|
||||
int keybrakecount;
|
||||
// McZapkie-240302 - przyda sie do tachometru
|
||||
float fTachoVelocity{ 0.0f };
|
||||
float fTachoVelocityJump{ 0.0f }; // ze skakaniem
|
||||
|
||||
16
World.cpp
16
World.cpp
@@ -1577,13 +1577,11 @@ TWorld::Update_UI() {
|
||||
"vel: " + to_string( vehicle->GetVelocity(), 2 ) + "/" + to_string( vehicle->MoverParameters->nrot* M_PI * vehicle->MoverParameters->WheelDiameter * 3.6, 2 )
|
||||
+ " km/h;" + ( vehicle->MoverParameters->SlippingWheels ? " (!)" : " " )
|
||||
+ " dist: " + to_string( vehicle->MoverParameters->DistCounter, 2 ) + " km"
|
||||
+ "; pos: ("
|
||||
+ to_string( vehicle->GetPosition().x, 2 ) + ", "
|
||||
+ to_string( vehicle->GetPosition().y, 2 ) + ", "
|
||||
+ to_string( vehicle->GetPosition().z, 2 ) + "), PM="
|
||||
+ to_string( vehicle->MoverParameters->WheelFlat, 1 ) + " mm; enrot="
|
||||
+ to_string( vehicle->MoverParameters->enrot * 60, 0 ) + " tmrot="
|
||||
+ to_string( std::abs( vehicle->MoverParameters->nrot ) * vehicle->MoverParameters->Transmision.Ratio * 60, 0 );
|
||||
+ "; pos: [" + to_string( vehicle->GetPosition().x, 2 ) + ", " + to_string( vehicle->GetPosition().y, 2 ) + ", " + to_string( vehicle->GetPosition().z, 2 ) + "]"
|
||||
+ ", PM=" + to_string( vehicle->MoverParameters->WheelFlat, 1 )
|
||||
+ " mm; enrot=" + to_string( vehicle->MoverParameters->enrot * 60, 0 )
|
||||
+ " tmrot=" + to_string( std::abs( vehicle->MoverParameters->nrot ) * vehicle->MoverParameters->Transmision.Ratio * 60, 0 )
|
||||
+ "; ventrot=" + to_string( vehicle->MoverParameters->RventRot, 1 );
|
||||
|
||||
uitextline2 =
|
||||
"HamZ=" + to_string( vehicle->MoverParameters->fBrakeCtrlPos, 2 )
|
||||
@@ -2207,14 +2205,14 @@ world_environment::update() {
|
||||
auto const skydomecolour = m_skydome.GetAverageColor();
|
||||
auto const skydomehsv = RGBtoHSV( skydomecolour );
|
||||
// sun strength is reduced by overcast level
|
||||
keylightintensity *= ( 1.0f - Global::Overcast * 0.65f );
|
||||
keylightintensity *= ( 1.0f - std::min( 1.f, Global::Overcast ) * 0.65f );
|
||||
|
||||
// intensity combines intensity of the sun and the light reflected by the sky dome
|
||||
// it'd be more technically correct to have just the intensity of the sun here,
|
||||
// but whether it'd _look_ better is something to be tested
|
||||
auto const intensity = std::min( 1.15f * ( 0.05f + keylightintensity + skydomehsv.z ), 1.25f );
|
||||
// the impact of sun component is reduced proportionally to overcast level, as overcast increases role of ambient light
|
||||
auto const diffuselevel = interpolate( keylightintensity, intensity * ( 1.0f - twilightfactor ), 1.0f - Global::Overcast * 0.75f );
|
||||
auto const diffuselevel = interpolate( keylightintensity, intensity * ( 1.0f - twilightfactor ), 1.0f - std::min( 1.f, Global::Overcast ) * 0.75f );
|
||||
// ...update light colours and intensity.
|
||||
keylightcolor = keylightcolor * diffuselevel;
|
||||
Global::DayLight.diffuse = glm::vec4( keylightcolor, Global::DayLight.diffuse.a );
|
||||
|
||||
@@ -342,6 +342,15 @@ mouse_input::default_bindings() {
|
||||
{ "radio_sw:", {
|
||||
user_command::radiotoggle,
|
||||
user_command::none } },
|
||||
{ "radiochannel_sw:", {
|
||||
user_command::radiochannelincrease,
|
||||
user_command::radiochanneldecrease } },
|
||||
{ "radiochannelprev_sw:", {
|
||||
user_command::radiochanneldecrease,
|
||||
user_command::none } },
|
||||
{ "radiochannelnext_sw:", {
|
||||
user_command::radiochannelincrease,
|
||||
user_command::none } },
|
||||
{ "pantfront_sw:", {
|
||||
user_command::pantographtogglefront,
|
||||
user_command::none } },
|
||||
|
||||
@@ -34,10 +34,6 @@ private:
|
||||
|
||||
user_command left;
|
||||
user_command right;
|
||||
|
||||
mouse_commands( user_command const Left, user_command const Right ):
|
||||
left(Left), right(Right)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::string, mouse_commands> controlcommands_map;
|
||||
|
||||
21
renderer.cpp
21
renderer.cpp
@@ -1325,6 +1325,10 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
// turn on moon shadows after nautical twilight, if the moon is actually up
|
||||
m_shadowcolor = glm::vec4{ 0.5f, 0.5f, 0.5f, 1.f };
|
||||
}
|
||||
// soften shadows depending on sky overcast factor
|
||||
m_shadowcolor = glm::min(
|
||||
colors::white,
|
||||
m_shadowcolor + glm::vec4{ glm::vec3{ 0.5f * Global::Overcast }, 1.f } );
|
||||
|
||||
if( Global::bWireFrame ) {
|
||||
// bez nieba w trybie rysowania linii
|
||||
@@ -1447,7 +1451,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
GL_LIGHT_MODEL_AMBIENT,
|
||||
glm::value_ptr(
|
||||
interpolate( Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f )
|
||||
* ( 1.0f - Global::Overcast * 0.5f ) // overcast darkens the clouds
|
||||
* interpolate( 1.f, 0.35f, Global::Overcast / 2.f ) // overcast darkens the clouds
|
||||
* 2.5f // arbitrary adjustment factor
|
||||
) );
|
||||
// render
|
||||
@@ -3129,11 +3133,17 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
static_cast<float>( TSubModel::fSquareDist / Submodel->fSquareMaxDist ) ); // pozycja punktu świecącego względem kamery
|
||||
Submodel->fCosViewAngle = glm::dot( glm::normalize( modelview * glm::vec4( 0.f, 0.f, -1.f, 1.f ) - lightcenter ), glm::normalize( -lightcenter ) );
|
||||
|
||||
float glarelevel = 0.6f; // luminosity at night is at level of ~0.1, so the overall resulting transparency is ~0.5 at full 'brightness'
|
||||
float glarelevel = 0.6f; // luminosity at night is at level of ~0.1, so the overall resulting transparency in clear conditions is ~0.5 at full 'brightness'
|
||||
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) {
|
||||
|
||||
// only bother if the viewer is inside the visibility cone
|
||||
if( Global::Overcast > 1.0 ) {
|
||||
// increase the glare in rainy/foggy conditions
|
||||
glarelevel += std::max( 0.f, 0.5f * ( Global::Overcast - 1.f ) );
|
||||
}
|
||||
// scale it down based on view angle
|
||||
glarelevel *= ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
|
||||
glarelevel = std::max( 0.0f, glarelevel - static_cast<float>(Global::fLuminance) );
|
||||
// reduce the glare in bright daylight
|
||||
glarelevel = clamp( glarelevel - static_cast<float>(Global::fLuminance), 0.f, 1.f );
|
||||
|
||||
if( glarelevel > 0.0f ) {
|
||||
// setup
|
||||
@@ -3360,7 +3370,8 @@ opengl_renderer::Update( double const Deltatime ) {
|
||||
::glEnable( GL_MULTISAMPLE );
|
||||
}
|
||||
|
||||
if( true == World.InitPerformed() ) {
|
||||
if( ( true == Global::ResourceSweep )
|
||||
&& ( true == World.InitPerformed() ) ) {
|
||||
// garbage collection
|
||||
m_geometry.update();
|
||||
m_textures.update();
|
||||
|
||||
@@ -20,7 +20,7 @@ inline bool strcend(std::string const &value, std::string const &ending)
|
||||
|
||||
gl_shader::gl_shader(std::string filename)
|
||||
{
|
||||
WriteLog("loading shader " + filename + " ..", false);
|
||||
WriteLog("loading shader " + filename + " ..");
|
||||
|
||||
std::stringstream stream;
|
||||
std::ifstream f;
|
||||
|
||||
@@ -166,7 +166,7 @@ state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad
|
||||
std::string token { Input.getToken<std::string>() };
|
||||
if( token != "endatmo" ) {
|
||||
// optional overcast parameter
|
||||
Global::Overcast = clamp( std::stof( token ), 0.f, 1.f );
|
||||
Global::Overcast = clamp( std::stof( token ), 0.f, 2.f );
|
||||
}
|
||||
while( ( false == token.empty() )
|
||||
&& ( token != "endatmo" ) ) {
|
||||
|
||||
@@ -274,8 +274,8 @@ void CSkyDome::RebuildColors() {
|
||||
float const y = PerezFunctionO2( perezy, icostheta, gamma, cosgamma2, zenithy );
|
||||
|
||||
// luminance(Y) for clear & overcast sky
|
||||
float const yclear = PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance );
|
||||
float const yover = zenithluminance * ( 1.0f + 2.0f * vertex.y ) / 3.0f;
|
||||
float const yclear = std::max( 0.01f, PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance ) );
|
||||
float const yover = std::max( 0.01f, zenithluminance * ( 1.0f + 2.0f * vertex.y ) / 3.0f );
|
||||
|
||||
float const Y = interpolate( yclear, yover, m_overcast );
|
||||
float const X = (x / y) * Y;
|
||||
|
||||
@@ -63,6 +63,9 @@ static std::unordered_map<std::string, std::string> m_cabcontrols = {
|
||||
{ "converteroff_sw:", "converter" },
|
||||
{ "main_sw:", "line breaker" },
|
||||
{ "radio_sw:", "radio" },
|
||||
{ "radiochannel_sw:", "radio channel" },
|
||||
{ "radiochannelprev_sw:", "radio channel" },
|
||||
{ "radiochannelnext_sw:", "radio channel" },
|
||||
{ "pantfront_sw:", "pantograph A" },
|
||||
{ "pantrear_sw:", "pantograph B" },
|
||||
{ "pantfrontoff_sw:", "pantograph A" },
|
||||
|
||||
Reference in New Issue
Block a user