build 181216. increased coupler disconnection working range, guaranteed freespot visibility range, optional alternate rotation event mode, ai vehicle startup logic enhancement, minor bug fixes

This commit is contained in:
tmj-fstate
2018-12-17 01:41:38 +01:00
parent f56a2b67be
commit 14c1e89209
11 changed files with 161 additions and 142 deletions

View File

@@ -243,24 +243,10 @@ void TAnimContainer::UpdateModel() {
}
if (fRotateSpeed != 0.0)
{
/*
double dif= fDesiredAngle-fAngle;
double s= fRotateSpeed*sign(dif)*Timer::GetDeltaTime();
if ((abs(s)-abs(dif))>0)
fAngle= fDesiredAngle;
else
fAngle+= s;
while (fAngle>360) fAngle-= 360;
while (fAngle<-360) fAngle+= 360;
pSubModel->SetRotate(vRotateAxis,fAngle);
*/
bool anim = false;
auto dif = vDesiredAngles - vRotateAngles;
double s;
s = fRotateSpeed * sign(dif.x) * Timer::GetDeltaTime();
s = std::abs( fRotateSpeed ) * sign(dif.x) * Timer::GetDeltaTime();
if (fabs(s) >= fabs(dif.x))
vRotateAngles.x = vDesiredAngles.x;
else
@@ -268,7 +254,7 @@ void TAnimContainer::UpdateModel() {
vRotateAngles.x += s;
anim = true;
}
s = fRotateSpeed * sign(dif.y) * Timer::GetDeltaTime();
s = std::abs( fRotateSpeed ) * sign(dif.y) * Timer::GetDeltaTime();
if (fabs(s) >= fabs(dif.y))
vRotateAngles.y = vDesiredAngles.y;
else
@@ -276,7 +262,7 @@ void TAnimContainer::UpdateModel() {
vRotateAngles.y += s;
anim = true;
}
s = fRotateSpeed * sign(dif.z) * Timer::GetDeltaTime();
s = std::abs( fRotateSpeed ) * sign(dif.z) * Timer::GetDeltaTime();
if (fabs(s) >= fabs(dif.z))
vRotateAngles.z = vDesiredAngles.z;
else
@@ -284,22 +270,27 @@ void TAnimContainer::UpdateModel() {
vRotateAngles.z += s;
anim = true;
}
while (vRotateAngles.x >= 360)
vRotateAngles.x -= 360;
while (vRotateAngles.x <= -360)
vRotateAngles.x += 360;
while (vRotateAngles.y >= 360)
vRotateAngles.y -= 360;
while (vRotateAngles.y <= -360)
vRotateAngles.y += 360;
while (vRotateAngles.z >= 360)
vRotateAngles.z -= 360;
while (vRotateAngles.z <= -360)
vRotateAngles.z += 360;
if (vRotateAngles.x == 0.0)
if (vRotateAngles.y == 0.0)
if (vRotateAngles.z == 0.0)
iAnim &= ~1; // kąty są zerowe
// HACK: negative speed allows to work around legacy behaviour, where desired angle > 360 meant permanent rotation
if( fRotateSpeed > 0.0 ) {
while( vRotateAngles.x >= 360 )
vRotateAngles.x -= 360;
while( vRotateAngles.x <= -360 )
vRotateAngles.x += 360;
while( vRotateAngles.y >= 360 )
vRotateAngles.y -= 360;
while( vRotateAngles.y <= -360 )
vRotateAngles.y += 360;
while( vRotateAngles.z >= 360 )
vRotateAngles.z -= 360;
while( vRotateAngles.z <= -360 )
vRotateAngles.z += 360;
}
if( ( vRotateAngles.x == 0.0 )
&& ( vRotateAngles.y == 0.0 )
&& ( vRotateAngles.z == 0.0 ) ) {
iAnim &= ~1; // kąty są zerowe
}
if (!anim)
{ // nie potrzeba przeliczać już
fRotateSpeed = 0.0;

View File

@@ -2430,7 +2430,7 @@ bool TController::PrepareEngine()
; // zerowanie napędu
mvControlling->ConvOvldFlag = false; // reset nadmiarowego
}
else if (false == mvControlling->Mains) {
else if (false == IsLineBreakerClosed) {
while (DecSpeed(true))
; // zerowanie napędu
if( mvOccupied->TrainType == dt_SN61 ) {
@@ -3206,8 +3206,8 @@ void TController::SpeedCntrl(double DesiredSpeed)
else if (mvControlling->ScndCtrlPosNo > 1)
{
int DesiredPos = 1 + mvControlling->ScndCtrlPosNo * ((DesiredSpeed - 1.0) / mvControlling->Vmax);
while (mvControlling->ScndCtrlPos > DesiredPos) mvControlling->DecScndCtrl(1);
while (mvControlling->ScndCtrlPos < DesiredPos) mvControlling->IncScndCtrl(1);
while( ( mvControlling->ScndCtrlPos > DesiredPos ) && ( true == mvControlling->DecScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop
while( ( mvControlling->ScndCtrlPos < DesiredPos ) && ( true == mvControlling->IncScndCtrl( 1 ) ) ) { ; } // all work is done in the condition loop
}
};
@@ -3826,37 +3826,47 @@ TController::UpdateSituation(double dt) {
fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia
double dy; // składowa styczna grawitacji, w przedziale <0,1>
double AbsAccS = 0;
IsLineBreakerClosed = true; // presume things are in working order
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
while (p)
{ // sprawdzenie odhamowania wszystkich połączonych pojazdów
auto *vehicle { p->MoverParameters };
if (Ready) {
// bo jak coś nie odhamowane, to dalej nie ma co sprawdzać
if (p->MoverParameters->BrakePress >= 0.4) // wg UIC określone sztywno na 0.04
if (vehicle->BrakePress >= 0.4) // wg UIC określone sztywno na 0.04
{
Ready = false; // nie gotowy
// Ra: odluźnianie przeładowanych lokomotyw, ciągniętych na zimno - prowizorka...
if (AIControllFlag) // skład jak dotąd był wyluzowany
{
if( ( mvOccupied->BrakeCtrlPos == 0 ) // jest pozycja jazdy
&& ( ( p->MoverParameters->Hamulec->GetBrakeStatus() & b_dmg ) == 0 ) // brake isn't broken
&& ( p->MoverParameters->PipePress - 5.0 > -0.1 ) // jeśli ciśnienie jak dla jazdy
&& ( p->MoverParameters->Hamulec->GetCRP() > p->MoverParameters->PipePress + 0.12 ) ) { // za dużo w zbiorniku
&& ( ( vehicle->Hamulec->GetBrakeStatus() & b_dmg ) == 0 ) // brake isn't broken
&& ( vehicle->PipePress - 5.0 > -0.1 ) // jeśli ciśnienie jak dla jazdy
&& ( vehicle->Hamulec->GetCRP() > vehicle->PipePress + 0.12 ) ) { // za dużo w zbiorniku
// indywidualne luzowanko
p->MoverParameters->BrakeReleaser( 1 );
vehicle->BrakeReleaser( 1 );
}
if( ( vehicle->Power > 0.01 ) // jeśli ma silnik
&& ( vehicle->FuseFlag ) ) { // wywalony nadmiarowy
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
}
if (p->MoverParameters->Power > 0.01) // jeśli ma silnik
if (p->MoverParameters->FuseFlag) // wywalony nadmiarowy
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
}
}
}
if (fReady < p->MoverParameters->BrakePress)
fReady = p->MoverParameters->BrakePress; // szukanie najbardziej zahamowanego
if (fReady < vehicle->BrakePress)
fReady = vehicle->BrakePress; // szukanie najbardziej zahamowanego
if( ( dy = p->VectorFront().y ) != 0.0 ) {
// istotne tylko dla pojazdów na pochyleniu
// ciężar razy składowa styczna grawitacji
fAccGravity -= p->MoverParameters->TotalMassxg * dy * ( p->DirectionGet() == iDirection ? 1 : -1 );
fAccGravity -= vehicle->TotalMassxg * dy * ( p->DirectionGet() == iDirection ? 1 : -1 );
}
// test state of main switch in all powered vehicles under control
if( ( vehicle->Power > 0.01 )
&& ( ( vehicle == mvControlling )
|| ( p->PrevC( coupling::control ) != nullptr ) ) ) {
IsLineBreakerClosed = ( IsLineBreakerClosed && vehicle->Mains );
}
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
}
if( iDirection ) {
@@ -5221,10 +5231,10 @@ TController::UpdateSituation(double dt) {
return; // ...and don't touch any other controls
}
if (mvControlling->ConvOvldFlag ||
!mvControlling->Mains) // WS może wywalić z powodu błędu w drutach
{ // wywalił bezpiecznik nadmiarowy przetwornicy
PrepareEngine(); // próba ponownego załączenia
if( ( true == mvControlling->ConvOvldFlag ) // wywalił bezpiecznik nadmiarowy przetwornicy
|| ( false == IsLineBreakerClosed ) ) { // WS może wywalić z powodu błędu w drutach
// próba ponownego załączenia
PrepareEngine();
}
// włączanie bezpiecznika
if ((mvControlling->EngineType == TEngineType::ElectricSeriesMotor) ||

View File

@@ -222,6 +222,7 @@ public:
double BrakingLevelIncrease{ 0.25 };
bool IsCargoTrain{ false };
bool IsHeavyCargoTrain{ false };
bool IsLineBreakerClosed{ false }; // state of line breaker in all powered vehicles under control
double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca

View File

@@ -620,8 +620,12 @@ void
TDynamicObject::toggle_lights() {
if( true == SectionLightsActive ) {
// switch all lights off
// switch all lights off...
for( auto &section : Sections ) {
// ... but skip cab sections, their lighting ignores battery state
auto const sectionname { section.compartment->pName };
if( sectionname.find( "cab" ) == 0 ) { continue; }
section.light_level = 0.0f;
}
SectionLightsActive = false;

View File

@@ -1370,6 +1370,7 @@ public:
bool MotorBlowersSwitch( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
bool MotorBlowersSwitchOff( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/
void MainSwitch_( bool const State );
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/

View File

@@ -490,7 +490,7 @@ int TMoverParameters::DettachStatus(int ConnectNo)
// if (CouplerType==Articulated) return false; //sprzęg nie do rozpięcia - może być tylko urwany
// Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim);
CouplerDist(ConnectNo);
if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Couplers[ConnectNo].CoupleDist < 0.0 : true)
if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Couplers[ConnectNo].CoupleDist < 0.01 : true)
return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty
return (Couplers[ConnectNo].CoupleDist > 0.2) ? -Couplers[ConnectNo].CouplingFlag :
Couplers[ConnectNo].CouplingFlag;
@@ -2729,66 +2729,75 @@ bool TMoverParameters::MotorBlowersSwitchOff( bool State, side const Side, range
// Q: 20160713
// włączenie / wyłączenie obwodu głownego
// *************************************************************************************************
bool TMoverParameters::MainSwitch( bool const State, range_t const Notify )
{
bool TMoverParameters::MainSwitch( bool const State, range_t const Notify ) {
bool const initialstate { Mains || dizel_startup };
if( ( Mains != State )
&& ( MainCtrlPosNo > 0 ) ) {
MainSwitch_( State );
if( ( false == State )
|| ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) )
&& ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) )
&& ( true == NoVoltRelay )
&& ( true == OvervoltageRelay )
&& ( LastSwitchingTime > CtrlDelay )
&& ( false == TestFlag( DamageFlag, dtrain_out ) )
&& ( false == TestFlag( EngDmgFlag, 1 ) ) ) ) {
if( true == State ) {
// switch on
if( ( EngineType == TEngineType::DieselEngine )
|| ( EngineType == TEngineType::DieselElectric ) ) {
// launch diesel engine startup procedure
dizel_startup = true;
}
else {
Mains = true;
}
}
else {
Mains = false;
// potentially knock out the pumps if their switch doesn't force them on
WaterPump.is_active &= WaterPump.is_enabled;
FuelPump.is_active &= FuelPump.is_enabled;
}
if( ( TrainType == dt_EZT )
&& ( false == State ) ) {
ConvOvldFlag = true;
}
if( Mains != initialstate ) {
LastSwitchingTime = 0;
}
if( Notify != range_t::local ) {
// pass the command to other vehicles
SendCtrlToNext(
"MainSwitch",
( State ? 1 : 0 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
}
if( Notify != range_t::local ) {
// pass the command to other vehicles
SendCtrlToNext(
"MainSwitch",
( State ? 1 : 0 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return ( ( Mains || dizel_startup ) != initialstate );
}
void TMoverParameters::MainSwitch_( bool const State ) {
if( ( Mains == State )
|| ( MainCtrlPosNo == 0 ) ) {
// nothing to do
return;
}
bool const initialstate { Mains || dizel_startup };
if( ( false == State )
|| ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) )
&& ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) )
&& ( true == NoVoltRelay )
&& ( true == OvervoltageRelay )
&& ( LastSwitchingTime > CtrlDelay )
&& ( false == TestFlag( DamageFlag, dtrain_out ) )
&& ( false == TestFlag( EngDmgFlag, 1 ) ) ) ) {
if( true == State ) {
// switch on
if( ( EngineType == TEngineType::DieselEngine )
|| ( EngineType == TEngineType::DieselElectric ) ) {
// launch diesel engine startup procedure
dizel_startup = true;
}
else {
Mains = true;
}
}
else {
Mains = false;
// potentially knock out the pumps if their switch doesn't force them on
WaterPump.is_active &= WaterPump.is_enabled;
FuelPump.is_active &= FuelPump.is_enabled;
}
if( ( TrainType == dt_EZT )
&& ( false == State ) ) {
ConvOvldFlag = true;
}
if( Mains != initialstate ) {
LastSwitchingTime = 0;
}
}
}
// *************************************************************************************************
// Q: 20160713
// włączenie / wyłączenie przetwornicy
@@ -9446,22 +9455,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
}
else if (Command == "MainSwitch")
{
if (CValue1 == 1) {
if( ( EngineType == TEngineType::DieselEngine )
|| ( EngineType == TEngineType::DieselElectric ) ) {
dizel_startup = true;
}
else {
Mains = true;
}
}
else {
Mains = false;
// potentially knock out the pumps if their switch doesn't force them on
WaterPump.is_active &= WaterPump.is_enabled;
FuelPump.is_active &= FuelPump.is_enabled;
}
MainSwitch_( CValue1 > 0.0 );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if (Command == "Direction")

View File

@@ -808,11 +808,14 @@ void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data con
if( Command.action != GLFW_RELEASE ) {
// on press or hold
if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric )
&& ( true == Train->mvControlled->ShuntMode ) ) {
&& ( true == Train->mvControlled->ShuntMode ) ) {
Train->mvControlled->AnPos = clamp(
Train->mvControlled->AnPos + 0.025,
0.0, 1.0 );
}
else {
Train->mvControlled->IncScndCtrl( 1 );
}
}
}
@@ -900,16 +903,19 @@ void TTrain::OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data
void TTrain::OnCommand_secondcontrollerset( TTrain *Train, command_data const &Command ) {
auto const targetposition { std::min<int>( Command.param1, Train->mvControlled->ScndCtrlPosNo ) };
while( ( targetposition < Train->mvControlled->ScndCtrlPos )
&& ( true == Train->mvControlled->DecScndCtrl( 1 ) ) ) {
// all work is done in the header
;
}
while( ( targetposition > Train->mvControlled->ScndCtrlPos )
&& ( true == Train->mvControlled->IncScndCtrl( 1 ) ) ) {
// all work is done in the header
;
if( Command.action != GLFW_RELEASE ) {
// on press or hold
auto const targetposition{ std::min<int>( Command.param1, Train->mvControlled->ScndCtrlPosNo ) };
while( ( targetposition < Train->mvControlled->ScndCtrlPos )
&& ( true == Train->mvControlled->DecScndCtrl( 1 ) ) ) {
// all work is done in the header
;
}
while( ( targetposition > Train->mvControlled->ScndCtrlPos )
&& ( true == Train->mvControlled->IncScndCtrl( 1 ) ) ) {
// all work is done in the header
;
}
}
}
@@ -961,10 +967,13 @@ void TTrain::OnCommand_independentbrakedecreasefast( TTrain *Train, command_data
void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &Command ) {
Train->mvControlled->LocalBrakePosA = (
clamp(
Command.param1,
0.0, 1.0 ) );
if( Command.action != GLFW_RELEASE ) {
Train->mvControlled->LocalBrakePosA = (
clamp(
Command.param1,
0.0, 1.0 ) );
}
/*
Train->mvControlled->LocalBrakePos = (
std::round(

View File

@@ -190,11 +190,13 @@ opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream
m_buffercapacity = datasize;
}
// actual draw procedure starts here
auto &chunkrecord { m_chunkrecords[ Geometry.chunk - 1 ] };
// sanity check; shouldn't be needed but, eh
if( chunkrecord.size == 0 ) { return; }
// setup...
if( m_activebuffer != m_buffer ) {
bind_buffer();
}
auto &chunkrecord = m_chunkrecords[ Geometry.chunk - 1 ];
auto const &chunk = gfx::geometry_bank::chunk( Geometry );
if( false == chunkrecord.is_good ) {
// we may potentially need to upload new buffer data before we can draw it

View File

@@ -2588,7 +2588,8 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// material configuration:
Bind_Material( null_handle );
// limit impact of dense fog on the lights
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / std::min<float>( Global.fFogEnd, m_fogrange * 2 ) ) );
auto const lightrange { std::max<float>( 500, m_fogrange * 2 ) }; // arbitrary, visibility at least 750m
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / lightrange ) );
::glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT );
::glDisable( GL_LIGHTING );
@@ -3123,7 +3124,8 @@ opengl_renderer::Render_Alpha( TAnimModel *Instance ) {
void
opengl_renderer::Render_Alpha( TTraction *Traction ) {
/*
// NOTE: test disabled as this call is only executed as part of the colour pass
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
@@ -3136,6 +3138,8 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
break;
}
}
*/
auto const distancesquared { glm::length2( ( Traction->location() - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
if( ( distancesquared < Traction->m_rangesquaredmin )
|| ( distancesquared >= Traction->m_rangesquaredmax ) ) {
return;
@@ -3184,7 +3188,8 @@ void
opengl_renderer::Render_Alpha( scene::lines_node const &Lines ) {
auto const &data { Lines.data() };
/*
// NOTE: test disabled as this call is only executed as part of the colour pass
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
@@ -3197,6 +3202,8 @@ opengl_renderer::Render_Alpha( scene::lines_node const &Lines ) {
break;
}
}
*/
auto const distancesquared { glm::length2( ( data.area.center - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
if( ( distancesquared < data.rangesquared_min )
|| ( distancesquared >= data.rangesquared_max ) ) {
return;

View File

@@ -25,7 +25,7 @@ http://mozilla.org/MPL/2.0/.
//#define EU07_USE_DEBUG_CABSHADOWMAP
//#define EU07_USE_DEBUG_CAMERA
//#define EU07_USE_DEBUG_SOUNDEMITTERS
#define EU07_USEIMGUIIMPLOPENGL2
//#define EU07_USEIMGUIIMPLOPENGL2
struct opengl_light : public basic_light {

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 18
#define VERSION_MINOR 1128
#define VERSION_MINOR 1216
#define VERSION_REVISION 0