mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 15:39:19 +02:00
build 200322. coupler adapter, automatic coupling vehicle setting, parked vehicle manual brake activation, ai braking logic enhancement, opengl 3.3 renderer diffuse color visualization fix, minor cab control logic bug fixes
This commit is contained in:
113
Driver.cpp
113
Driver.cpp
@@ -1988,6 +1988,8 @@ void TController::AutoRewident()
|
||||
break;
|
||||
}
|
||||
}
|
||||
// potentially release manual brake
|
||||
d->MoverParameters->DecManualBrakeLevel( ManualBrakePosNo );
|
||||
}
|
||||
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
|
||||
}
|
||||
@@ -2347,6 +2349,10 @@ bool TController::CheckVehicles(TOrders user)
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) {
|
||||
// nastawianie hamulca do jazdy pociągowej
|
||||
AutoRewident();
|
||||
}
|
||||
}
|
||||
// Ra 2014-09: tymczasowo prymitywne ustawienie warunku pod kątem SN61
|
||||
if( ( mvOccupied->TrainType == dt_EZT )
|
||||
@@ -2767,7 +2773,14 @@ bool TController::ReleaseEngine() {
|
||||
}
|
||||
// gasimy światła
|
||||
Lights( 0, 0 );
|
||||
// activate parking brake
|
||||
// TBD: do it earlier?
|
||||
mvOccupied->SpringBrakeActivate(true);
|
||||
if( ( mvOccupied->LocalBrake == TLocalBrake::ManualBrake )
|
||||
|| ( mvOccupied->MBrake == true ) ) {
|
||||
mvOccupied->IncManualBrakeLevel( ManualBrakePosNo );
|
||||
}
|
||||
// switch off remaining power
|
||||
mvOccupied->BatterySwitch( false );
|
||||
}
|
||||
}
|
||||
@@ -2959,7 +2972,14 @@ bool TController::IncBrakeEIM()
|
||||
switch (mvOccupied->EIMCtrlType)
|
||||
{
|
||||
case 0: {
|
||||
OK = mvOccupied->IncLocalBrakeLevel( 1 );
|
||||
if( mvOccupied->MED_amax != 9.81 ) {
|
||||
auto const brakeposition{ clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * AccDesired / mvOccupied->MED_amax, 0.0, 1.0 ) };
|
||||
OK = ( brakeposition != mvOccupied->LocalBrakePosA );
|
||||
mvOccupied->LocalBrakePosA = brakeposition;
|
||||
}
|
||||
else {
|
||||
OK = mvOccupied->IncLocalBrakeLevel( 1 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
@@ -3067,24 +3087,35 @@ bool TController::DecBrakeEIM()
|
||||
bool OK = false;
|
||||
switch (mvOccupied->EIMCtrlType)
|
||||
{
|
||||
case 0:
|
||||
OK = mvOccupied->DecLocalBrakeLevel(1);
|
||||
break;
|
||||
case 1:
|
||||
OK = mvOccupied->MainCtrlPos < 2;
|
||||
if (OK)
|
||||
mvOccupied->MainCtrlPos = 2;
|
||||
break;
|
||||
case 2:
|
||||
OK = mvOccupied->MainCtrlPos < 3;
|
||||
if (OK)
|
||||
mvOccupied->MainCtrlPos = 3;
|
||||
break;
|
||||
case 3:
|
||||
OK = mvOccupied->MainCtrlPos < mvOccupied->MainCtrlMaxDirChangePos;
|
||||
if( OK )
|
||||
mvOccupied->MainCtrlPos = mvOccupied->MainCtrlMaxDirChangePos;
|
||||
break;
|
||||
case 0: {
|
||||
if( mvOccupied->MED_amax != 9.81 ) {
|
||||
auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * AccDesired / mvOccupied->MED_amax, 0.0, 1.0 ) };
|
||||
OK = ( brakeposition != mvOccupied->LocalBrakePosA );
|
||||
mvOccupied->LocalBrakePosA = brakeposition;
|
||||
}
|
||||
else {
|
||||
OK = mvOccupied->DecLocalBrakeLevel( 1 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
OK = mvOccupied->MainCtrlPos < 2;
|
||||
if( OK )
|
||||
mvOccupied->MainCtrlPos = 2;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
OK = mvOccupied->MainCtrlPos < 3;
|
||||
if( OK )
|
||||
mvOccupied->MainCtrlPos = 3;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
OK = mvOccupied->MainCtrlPos < mvOccupied->MainCtrlMaxDirChangePos;
|
||||
if( OK )
|
||||
mvOccupied->MainCtrlPos = mvOccupied->MainCtrlMaxDirChangePos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -4468,6 +4499,7 @@ void TController::PhysicsLog()
|
||||
void
|
||||
TController::UpdateSituation(double dt) {
|
||||
// uruchamiać przynajmniej raz na sekundę
|
||||
if( false == simulation::is_ready ) { return; }
|
||||
if( ( iDrivigFlags & movePrimary ) == 0 ) { return; } // pasywny nic nie robi
|
||||
|
||||
// update timers
|
||||
@@ -5068,18 +5100,30 @@ TController::UpdateSituation(double dt) {
|
||||
int const end { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
|
||||
auto const &neighbour { vehicleparameters->Neighbours[ end ] };
|
||||
if( neighbour.vehicle != nullptr ) {
|
||||
// próba podczepienia
|
||||
vehicleparameters->Attach(
|
||||
end, neighbour.vehicle_end,
|
||||
neighbour.vehicle->MoverParameters,
|
||||
iCoupler );
|
||||
if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) {
|
||||
// jeżeli został podłączony
|
||||
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
|
||||
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
|
||||
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
|
||||
CheckVehicles( Connect ); // sprawdzić światła nowego składu
|
||||
JumpToNextOrder(); // wykonanie następnej komendy
|
||||
if( neighbour.distance < 10 ) {
|
||||
// check whether we don't need to attach coupler adapter
|
||||
auto &coupler{ vehicleparameters->Couplers[ end ] };
|
||||
if( coupler.type() != TCouplerType::Automatic ) {
|
||||
auto &othercoupler = neighbour.vehicle->MoverParameters->Couplers[ ( neighbour.vehicle_end != 2 ? neighbour.vehicle_end : coupler.ConnectedNr ) ];
|
||||
if( othercoupler.type() == TCouplerType::Automatic ) {
|
||||
vehicle->attach_coupler_adapter( end );
|
||||
}
|
||||
}
|
||||
if( neighbour.distance < 2 ) {
|
||||
// próba podczepienia
|
||||
vehicleparameters->Attach(
|
||||
end, neighbour.vehicle_end,
|
||||
neighbour.vehicle->MoverParameters,
|
||||
iCoupler );
|
||||
if( vehicleparameters->Couplers[ end ].CouplingFlag == iCoupler ) {
|
||||
// jeżeli został podłączony
|
||||
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
|
||||
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
|
||||
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
|
||||
CheckVehicles( Connect ); // sprawdzić światła nowego składu
|
||||
JumpToNextOrder(); // wykonanie następnej komendy
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
|
||||
@@ -5463,7 +5507,12 @@ TController::UpdateSituation(double dt) {
|
||||
// tylko jeśli odepnie
|
||||
WriteLog( mvOccupied->Name + " odczepiony." );
|
||||
iVehicleCount = -2;
|
||||
CheckVehicles( Disconnect ); // update trainset state
|
||||
// potentially remove coupler adapter
|
||||
if( p->MoverParameters->Couplers[ d ].has_adapter() ) {
|
||||
p->remove_coupler_adapter( d );
|
||||
}
|
||||
// update trainset state
|
||||
CheckVehicles( Disconnect );
|
||||
} // a jak nie, to dociskać dalej
|
||||
}
|
||||
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
|
||||
|
||||
119
DynObj.cpp
119
DynObj.cpp
@@ -747,14 +747,16 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
||||
// ABu-240105: Dodatkowy warunek: if (...).Render, zeby rysowal tylko
|
||||
// jeden
|
||||
// z polaczonych sprzegow
|
||||
if ((TestFlag(MoverParameters->Couplers[end::front].CouplingFlag, ctrain_coupler)) &&
|
||||
if ((false == MoverParameters->Couplers[ end::front ].has_adapter()) &&
|
||||
(TestFlag(MoverParameters->Couplers[end::front].CouplingFlag, ctrain_coupler)) &&
|
||||
(MoverParameters->Couplers[end::front].Render))
|
||||
{
|
||||
btCoupler1.Turn( true );
|
||||
btnOn = true;
|
||||
}
|
||||
// else btCoupler1.TurnOff();
|
||||
if ((TestFlag(MoverParameters->Couplers[end::rear].CouplingFlag, ctrain_coupler)) &&
|
||||
if ((false == MoverParameters->Couplers[ end::rear ].has_adapter()) &&
|
||||
(TestFlag(MoverParameters->Couplers[end::rear].CouplingFlag, ctrain_coupler)) &&
|
||||
(MoverParameters->Couplers[end::rear].Render))
|
||||
{
|
||||
btCoupler2.Turn( true );
|
||||
@@ -903,6 +905,12 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
||||
// uginanie zderzakow
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
if( MoverParameters->Couplers[ i ].has_adapter() ) {
|
||||
// HACK: if there's coupler adapter on this side, we presume there's additional distance put between vehicles
|
||||
// which prevents buffers from clashing against each other (or the other vehicle doesn't have buffers to begin with)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const dist { clamp( MoverParameters->Couplers[ i ].Dist / 2.0, -MoverParameters->Couplers[ i ].DmaxB, 0.0 ) };
|
||||
|
||||
if( dist >= 0.0 ) { continue; }
|
||||
@@ -1539,6 +1547,64 @@ TDynamicObject::uncouple( int const Side ) {
|
||||
return couplingflag;
|
||||
}
|
||||
|
||||
bool
|
||||
TDynamicObject::attach_coupler_adapter( int const Side ) {
|
||||
|
||||
auto &coupler { MoverParameters->Couplers[ Side ] };
|
||||
// sanity check(s)
|
||||
if( coupler.type() == TCouplerType::Automatic ) { return false; }
|
||||
auto const *neighbour { MoverParameters->Neighbours[ Side ].vehicle };
|
||||
if( ( neighbour == nullptr )
|
||||
|| ( MoverParameters->Neighbours[ Side ].distance > 25.0 ) ) {
|
||||
// can only acquire the adapter from a nearby enough vehicle
|
||||
return false;
|
||||
}
|
||||
// TBD: empty struct instead of fallback defaults, to allow vehicles without adapter?
|
||||
auto adapterdata {
|
||||
coupleradapter_data {
|
||||
{ 0.085f, 0.95f },
|
||||
"tabor/polsprzeg" } };
|
||||
if( false == neighbour->m_coupleradapter.model.empty() ) {
|
||||
// explicit coupler adapter definition overrides default parameters
|
||||
adapterdata = neighbour->m_coupleradapter;
|
||||
}
|
||||
if( MoverParameters->Neighbours[ Side ].distance - adapterdata.position.x < 0.5 ) {
|
||||
// arbitrary amount of free room required to install the adapter
|
||||
// NOTE: this also covers cases with established physical connection
|
||||
return false;
|
||||
}
|
||||
|
||||
coupler.adapter_type = TCouplerType::Automatic;
|
||||
coupler.adapter_length = adapterdata.position.x;
|
||||
coupler.adapter_height = adapterdata.position.y;
|
||||
// audio flag, visuals update
|
||||
coupler.sounds |= sound::attachadapter;
|
||||
m_coupleradapters[ Side ] = TModelsManager::GetModel( adapterdata.model );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TDynamicObject::remove_coupler_adapter( int const Side ) {
|
||||
|
||||
auto &coupler{ MoverParameters->Couplers[ Side ] };
|
||||
|
||||
if( coupler.adapter_type == TCouplerType::NoCoupler ) { return false; }
|
||||
// TODO: sanity check(s)
|
||||
if( coupler.Connected != nullptr ) {
|
||||
// TBD: disallow instead adapter removal if it's coupled with another vehicle?
|
||||
uncouple( Side );
|
||||
}
|
||||
coupler.adapter_type = TCouplerType::NoCoupler;
|
||||
coupler.adapter_length = 0.0;
|
||||
coupler.adapter_height = 0.0;
|
||||
// audio flag, visuals update
|
||||
coupler.sounds |= sound::removeadapter;
|
||||
m_coupleradapters[ Side ] = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TDynamicObject::TDynamicObject() {
|
||||
modelShake = Math3D::vector3(0, 0, 0);
|
||||
// fTrackBlock = 10000.0; // brak przeszkody na drodze
|
||||
@@ -3367,7 +3433,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
double fCurrent = (
|
||||
( MoverParameters->DynamicBrakeFlag && MoverParameters->ResistorsFlag ) ?
|
||||
0 :
|
||||
std::abs( MoverParameters->Itot ) )
|
||||
std::abs( MoverParameters->Itot ) * MoverParameters->IsVehicleEIMBrakingFactor() )
|
||||
+ MoverParameters->TotalCurrent; // prąd pobierany przez pojazd - bez sensu z tym (TotalCurrent)
|
||||
// TotalCurrent to bedzie prad nietrakcyjny (niezwiazany z napedem)
|
||||
// fCurrent+=fabs(MoverParameters->Voltage)*1e-6; //prąd płynący przez woltomierz, rozładowuje kondensator orgromowy 4µF
|
||||
@@ -4394,6 +4460,12 @@ void TDynamicObject::RenderSounds() {
|
||||
m_couplersounds[ couplerindex ].dsbCouplerAttach.play();
|
||||
m_couplersounds[ couplerindex ].dsbCouplerDetach.play();
|
||||
}
|
||||
if( true == TestFlag( coupler.sounds, sound::attachadapter ) ) {
|
||||
m_couplersounds[ couplerindex ].dsbAdapterAttach.play();
|
||||
}
|
||||
if( true == TestFlag( coupler.sounds, sound::removeadapter ) ) {
|
||||
m_couplersounds[ couplerindex ].dsbAdapterRemove.play();
|
||||
}
|
||||
|
||||
++couplerindex;
|
||||
coupler.sounds = 0;
|
||||
@@ -4566,6 +4638,17 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
mdLowPolyInt = TModelsManager::GetModel(asModel, true);
|
||||
}
|
||||
|
||||
else if(token == "coupleradapter:") {
|
||||
// coupling adapter data
|
||||
parser.getTokens( 3 );
|
||||
parser
|
||||
>> m_coupleradapter.model
|
||||
>> m_coupleradapter.position.x
|
||||
>> m_coupleradapter.position.y;
|
||||
replace_slashes( m_coupleradapter.model );
|
||||
erase_leading_slashes( m_coupleradapter.model );
|
||||
}
|
||||
|
||||
else if(token == "attachments:") {
|
||||
// additional 3d models attached to main body
|
||||
// content provided as a series of values together enclosed in "{}"
|
||||
@@ -5784,6 +5867,24 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
couplersounds.dsbBufferClamp_loud = bufferclash;
|
||||
}
|
||||
}
|
||||
else if( token == "coupleradapterattach:" ) {
|
||||
// laczenie:
|
||||
sound_source adapterattach { sound_placement::external };
|
||||
adapterattach.deserialize( parser, sound_type::single );
|
||||
adapterattach.owner( this );
|
||||
for( auto &couplersounds : m_couplersounds ) {
|
||||
couplersounds.dsbAdapterAttach = adapterattach;
|
||||
}
|
||||
}
|
||||
else if( token == "coupleradapterremove:" ) {
|
||||
// rozlaczanie:
|
||||
sound_source adapterremove { sound_placement::external };
|
||||
adapterremove.deserialize( parser, sound_type::single );
|
||||
adapterremove.owner( this );
|
||||
for( auto &couplersounds : m_couplersounds ) {
|
||||
couplersounds.dsbAdapterRemove = adapterremove;
|
||||
}
|
||||
}
|
||||
else if( token == "startjolt:" ) {
|
||||
// movement start jolt
|
||||
m_startjolt.deserialize( parser, sound_type::single );
|
||||
@@ -5972,6 +6073,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
m_couplersounds[ end::front ].dsbCouplerStretch_loud.offset( frontcoupleroffset );
|
||||
m_couplersounds[ end::front ].dsbBufferClamp.offset( frontcoupleroffset );
|
||||
m_couplersounds[ end::front ].dsbBufferClamp_loud.offset( frontcoupleroffset );
|
||||
m_couplersounds[ end::front ].dsbAdapterAttach.offset( frontcoupleroffset );
|
||||
m_couplersounds[ end::front ].dsbAdapterRemove.offset( frontcoupleroffset );
|
||||
auto const rearcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * -0.5f } };
|
||||
m_couplersounds[ end::rear ].dsbCouplerAttach.offset( rearcoupleroffset );
|
||||
m_couplersounds[ end::rear ].dsbCouplerDetach.offset( rearcoupleroffset );
|
||||
@@ -5979,6 +6082,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
m_couplersounds[ end::rear ].dsbCouplerStretch_loud.offset( rearcoupleroffset );
|
||||
m_couplersounds[ end::rear ].dsbBufferClamp.offset( rearcoupleroffset );
|
||||
m_couplersounds[ end::rear ].dsbBufferClamp_loud.offset( rearcoupleroffset );
|
||||
m_couplersounds[ end::rear ].dsbAdapterAttach.offset( rearcoupleroffset );
|
||||
m_couplersounds[ end::rear ].dsbAdapterRemove.offset( rearcoupleroffset );
|
||||
}
|
||||
|
||||
TModel3d *
|
||||
@@ -6258,6 +6363,10 @@ TDynamicObject::update_neighbours() {
|
||||
// neighbour.vehicle = coupler.Connected;
|
||||
// neighbour.vehicle_end = coupler.ConnectedNr;
|
||||
neighbour.distance = TMoverParameters::CouplerDist( MoverParameters, coupler.Connected );
|
||||
// take into account potential adapters attached to the couplers
|
||||
auto const &othercoupler { neighbour.vehicle->MoverParameters->Couplers[ neighbour.vehicle_end ] };
|
||||
neighbour.distance -= coupler.adapter_length;
|
||||
neighbour.distance -= othercoupler.adapter_length;
|
||||
}
|
||||
else {
|
||||
// if there's no connected vehicle check for potential collision sources in the vicinity
|
||||
@@ -6276,6 +6385,10 @@ TDynamicObject::update_neighbours() {
|
||||
if( neighbour.distance < ( neighbour.vehicle->MoverParameters->CategoryFlag == 2 ? 50 : 100 ) ) {
|
||||
// at short distances (re)calculate range between couplers directly
|
||||
neighbour.distance = TMoverParameters::CouplerDist( MoverParameters, neighbour.vehicle->MoverParameters );
|
||||
// take into account potential adapters attached to the couplers
|
||||
auto const &othercoupler { neighbour.vehicle->MoverParameters->Couplers[ neighbour.vehicle_end ] };
|
||||
neighbour.distance -= coupler.adapter_length;
|
||||
neighbour.distance -= othercoupler.adapter_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
DynObj.h
16
DynObj.h
@@ -311,6 +311,11 @@ private:
|
||||
float time { 0.f }; // time spent on the operation
|
||||
};
|
||||
|
||||
struct coupleradapter_data {
|
||||
glm::vec2 position; // adapter placement; offset from vehicle end and height
|
||||
std::string model; // 3d model of the adapter
|
||||
};
|
||||
|
||||
struct coupler_sounds {
|
||||
sound_source dsbCouplerAttach { sound_placement::external }; // moved from cab
|
||||
sound_source dsbCouplerDetach { sound_placement::external }; // moved from cab
|
||||
@@ -318,6 +323,8 @@ private:
|
||||
sound_source dsbCouplerStretch_loud { sound_placement::external };
|
||||
sound_source dsbBufferClamp { sound_placement::external }; // moved from cab
|
||||
sound_source dsbBufferClamp_loud { sound_placement::external };
|
||||
sound_source dsbAdapterAttach { sound_placement::external };
|
||||
sound_source dsbAdapterRemove { sound_placement::external };
|
||||
};
|
||||
|
||||
struct pantograph_sounds {
|
||||
@@ -394,6 +401,7 @@ private:
|
||||
// members
|
||||
TButton btCoupler1; // sprzegi
|
||||
TButton btCoupler2;
|
||||
std::array<TModel3d *, 2> m_coupleradapters = { nullptr, nullptr };
|
||||
TAirCoupler btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
|
||||
TAirCoupler btCPneumatic2;
|
||||
TAirCoupler btCPneumatic1r; // ABu: to zeby nie bylo problemow przy laczeniu wagonow,
|
||||
@@ -469,12 +477,14 @@ private:
|
||||
sound_source m_outernoise { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
||||
#endif
|
||||
sound_source m_wheelflat { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
||||
sound_source rscurve { sound_placement::external, 2 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
|
||||
sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
|
||||
sound_source rsDerailment { sound_placement::external, 2 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // McZapkie-051202
|
||||
|
||||
exchange_data m_exchange; // state of active load exchange procedure, if any
|
||||
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
||||
|
||||
coupleradapter_data m_coupleradapter;
|
||||
|
||||
bool renderme; // yB - czy renderowac
|
||||
float ModCamRot;
|
||||
int iInventory[ 2 ] { 0, 0 }; // flagi bitowe posiadanych submodeli (np. świateł)
|
||||
@@ -583,6 +593,8 @@ private:
|
||||
// pobranie współrzędnych tyłu
|
||||
inline Math3D::vector3 RearPosition() {
|
||||
return vCoulpler[iDirection]; };
|
||||
inline Math3D::vector3 CouplerPosition( end const End ) const {
|
||||
return vCoulpler[ End ]; }
|
||||
inline Math3D::vector3 AxlePositionGet() {
|
||||
return iAxleFirst ?
|
||||
Axle1.pPosition :
|
||||
@@ -647,6 +659,8 @@ private:
|
||||
|
||||
void couple( int const Side );
|
||||
int uncouple( int const Side );
|
||||
bool attach_coupler_adapter( int const Side );
|
||||
bool remove_coupler_adapter( int const Side );
|
||||
void RadioStop();
|
||||
void Damage(char flag);
|
||||
void RaLightsSet(int head, int rear);
|
||||
|
||||
@@ -240,7 +240,9 @@ enum sound {
|
||||
attachmainhose = 1 << 10,
|
||||
attachcontrol = 1 << 11,
|
||||
attachgangway = 1 << 12,
|
||||
attachheating = 1 << 13
|
||||
attachheating = 1 << 13,
|
||||
attachadapter = 1 << 14,
|
||||
removeadapter = 1 << 15,
|
||||
};
|
||||
|
||||
//szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType
|
||||
@@ -673,7 +675,8 @@ struct TCoupling {
|
||||
double FmaxC = 1000.0;
|
||||
double beta = 0.0;
|
||||
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
|
||||
int AllowedFlag = 3; //Ra: maska dostępnych
|
||||
int AutomaticCouplingFlag = coupling::coupler;
|
||||
int AllowedFlag = coupling::coupler | coupling::brakehose; //Ra: maska dostępnych
|
||||
/*zmienne*/
|
||||
int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/
|
||||
class TMoverParameters *Connected = nullptr; /*co jest podlaczone*/
|
||||
@@ -682,12 +685,26 @@ struct TCoupling {
|
||||
double Dist = 0.0; /*strzalka ugiecia zderzaków*/
|
||||
bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/
|
||||
float stretch_duration { 0.f }; // seconds, elapsed time with excessive force applied to the coupler
|
||||
// optional adapter piece
|
||||
double adapter_length { 0.0 }; // meters, value added on the given end to standard vehicle (half)length
|
||||
double adapter_height { 0.0 }; // meters, distance from rail level
|
||||
TCouplerType adapter_type = TCouplerType::NoCoupler; // CouplerType override if other than NoCoupler
|
||||
|
||||
power_coupling power_high;
|
||||
// power_coupling power_low; // TODO: implement this
|
||||
|
||||
int sounds { 0 }; // sounds emitted by the coupling devices
|
||||
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
|
||||
|
||||
inline bool
|
||||
has_adapter() const {
|
||||
return ( adapter_type != TCouplerType::NoCoupler ); }
|
||||
inline TCouplerType const
|
||||
type() const {
|
||||
return (
|
||||
adapter_type == TCouplerType::NoCoupler ?
|
||||
CouplerType :
|
||||
adapter_type ); }
|
||||
};
|
||||
|
||||
struct neighbour_data {
|
||||
@@ -1543,6 +1560,7 @@ public:
|
||||
int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu
|
||||
|
||||
int AIHintPantstate{ 0 }; // suggested pantograph setup
|
||||
double AIHintLocalBrakeAccFactor{ 1.05 }; // suggested acceleration weight for local brake operation
|
||||
|
||||
public:
|
||||
TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab);
|
||||
@@ -1557,6 +1575,8 @@ public:
|
||||
bool DirectionForward();
|
||||
bool DirectionBackward( void );/*! kierunek ruchu*/
|
||||
bool EIMDirectionChangeAllow( void ) const;
|
||||
inline double IsVehicleEIMBrakingFactor() {
|
||||
return eimv[ eimv_Ipoj ] < 0 ? -1.0 : 1.0; }
|
||||
void BrakeLevelSet(double b);
|
||||
bool BrakeLevelAdd(double b);
|
||||
bool IncBrakeLevel(); // wersja na użytek AI
|
||||
|
||||
@@ -22,7 +22,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
// Jeśli jakieś zmienne nie są używane w mover.pas, też można je przenosić.
|
||||
// Przeniesienie wszystkiego na raz zrobiło by zbyt wielki chaos do ogarnięcia.
|
||||
|
||||
const double dEpsilon = 0.01; // 1cm (zależy od typu sprzęgu...)
|
||||
const double dEpsilon = 0.025; // 1cm (zależy od typu sprzęgu...)
|
||||
const double CouplerTune = 0.1; // skalowanie tlumiennosci
|
||||
|
||||
int ConversionError = 0;
|
||||
@@ -438,13 +438,13 @@ bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *
|
||||
|
||||
auto &coupler { Couplers[ ConnectNo ] };
|
||||
auto &othercoupler = ConnectTo->Couplers[ ( ConnectToNr != 2 ? ConnectToNr : coupler.ConnectedNr ) ];
|
||||
auto const distance { CouplerDist( this, ConnectTo ) };
|
||||
auto const distance { CouplerDist( this, ConnectTo ) - ( coupler.adapter_length + othercoupler.adapter_length ) };
|
||||
|
||||
auto const couplercheck {
|
||||
( Forced )
|
||||
|| ( ( distance <= dEpsilon )
|
||||
&& ( coupler.CouplerType != TCouplerType::NoCoupler )
|
||||
&& ( coupler.CouplerType == othercoupler.CouplerType ) ) };
|
||||
&& ( coupler.type() != TCouplerType::NoCoupler )
|
||||
&& ( coupler.type() == othercoupler.type() ) ) };
|
||||
|
||||
if( false == couplercheck ) { return false; }
|
||||
|
||||
@@ -495,7 +495,7 @@ int TMoverParameters::DettachStatus(int ConnectNo)
|
||||
if (TestFlag(DamageFlag, dtrain_coupling))
|
||||
return -Couplers[ConnectNo].CouplingFlag; // hak urwany - rozłączanie jest OK
|
||||
// CouplerDist(ConnectNo);
|
||||
if (Couplers[ConnectNo].CouplerType == TCouplerType::Screw ? Neighbours[ConnectNo].distance < 0.01 : true)
|
||||
if ( (Couplers[ConnectNo].type() != TCouplerType::Screw) || (Neighbours[ConnectNo].distance < 0.01) )
|
||||
return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty
|
||||
return (Neighbours[ConnectNo].distance > 0.2) ? -Couplers[ConnectNo].CouplingFlag :
|
||||
Couplers[ConnectNo].CouplingFlag;
|
||||
@@ -1102,7 +1102,7 @@ TMoverParameters::damage_coupler( int const End ) {
|
||||
|
||||
auto &coupler{ Couplers[ End ] };
|
||||
|
||||
if( coupler.CouplerType == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what
|
||||
if( coupler.type() == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what
|
||||
|
||||
if( SetFlag( DamageFlag, dtrain_coupling ) )
|
||||
EventFlag = true;
|
||||
@@ -1595,7 +1595,7 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime ) {
|
||||
// bez napiecia...
|
||||
if( couplervoltage != 0.0 ) {
|
||||
// ...ale jest cos na sprzegach:
|
||||
coupler.power_high.current = ( std::abs( Itot ) + TotalCurrent ) * coupler.power_high.voltage / couplervoltage; // obciążenie rozkladane stosownie do napiec
|
||||
coupler.power_high.current = ( std::abs( Itot ) * IsVehicleEIMBrakingFactor() + TotalCurrent ) * coupler.power_high.voltage / couplervoltage; // obciążenie rozkladane stosownie do napiec
|
||||
if( true == coupler.power_high.is_live ) {
|
||||
coupler.power_high.current += connectedothercoupler.power_high.current;
|
||||
}
|
||||
@@ -4837,7 +4837,8 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
|
||||
// potentially generate sounds on clash or stretch
|
||||
if( ( newdistance < 0.0 )
|
||||
&& ( coupler.Dist > newdistance )
|
||||
&& ( dV < -0.1 ) ) {
|
||||
&& ( dV < -0.1 )
|
||||
&& ( false == coupler.has_adapter() ) ) { // HACK: with adapter present we presume buffers won't clash
|
||||
// 090503: dzwieki pracy zderzakow
|
||||
SetFlag(
|
||||
coupler.sounds,
|
||||
@@ -4866,7 +4867,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
|
||||
if( ( coupler.CouplingFlag != coupling::faux )
|
||||
|| ( initialdistance < 0 ) ) {
|
||||
|
||||
coupler.Dist = clamp( newdistance, -coupler.DmaxB, coupler.DmaxC );
|
||||
coupler.Dist = clamp( newdistance, ( coupler.has_adapter() ? 0 : -coupler.DmaxB ), coupler.DmaxC );
|
||||
|
||||
double BetaAvg = 0;
|
||||
double Fmax = 0;
|
||||
@@ -4923,16 +4924,19 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
|
||||
- Fmax * dV * BetaAvg;
|
||||
}
|
||||
// liczenie sily ze sprezystosci zderzaka
|
||||
if( -newdistance > ( coupler.DmaxB + othercoupler.DmaxB ) ) {
|
||||
auto const collisiondistance { (
|
||||
( coupler.has_adapter() || othercoupler.has_adapter() ) ?
|
||||
std::min( coupler.DmaxB, othercoupler.DmaxB ) : // HACK: only take into account buffering ability of automatic coupler
|
||||
coupler.DmaxB + othercoupler.DmaxB
|
||||
) };
|
||||
if( -newdistance > collisiondistance ) {
|
||||
// zderzenie
|
||||
coupler.CheckCollision = true;
|
||||
if( ( coupler.CouplerType == TCouplerType::Automatic )
|
||||
&& ( coupler.CouplerType == othercoupler.CouplerType )
|
||||
if( ( coupler.type() == TCouplerType::Automatic )
|
||||
&& ( coupler.type() == othercoupler.type() )
|
||||
&& ( coupler.CouplingFlag == coupling::faux ) ) {
|
||||
// sprzeganie wagonow z samoczynnymi sprzegami
|
||||
// EN57
|
||||
// TBD, TODO: configurable flag for automatic coupling
|
||||
coupler.CouplingFlag = coupling::coupler /*| coupling::brakehose | coupling::mainhose | coupling::control*/;
|
||||
coupler.CouplingFlag = ( coupler.AutomaticCouplingFlag & othercoupler.AutomaticCouplingFlag );
|
||||
SetFlag( coupler.sounds, sound::attachcoupler );
|
||||
}
|
||||
}
|
||||
@@ -5898,10 +5902,10 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
else if ((std::abs(EngineVoltage) < EnginePowerSource.CollectorParameters.MaxV))
|
||||
Vadd *= (1.0 - dt);
|
||||
else
|
||||
Vadd = Max0R(
|
||||
Vadd = std::max(
|
||||
Vadd * (1.0 - 0.2 * dt),
|
||||
0.007 * (std::abs(EngineVoltage) - (EnginePowerSource.CollectorParameters.MaxV - 100)));
|
||||
Itot = eimv[eimv_Ipoj] * (0.01 + Min0R(0.99, 0.99 - Vadd));
|
||||
Itot = eimv[eimv_Ipoj] * (0.01 + std::min(0.99, 0.99 - Vadd));
|
||||
|
||||
EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000;
|
||||
// power inverters
|
||||
@@ -9498,8 +9502,8 @@ void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Ind
|
||||
auto lookup = couplertypes.find( extract_value( "CType", line ) );
|
||||
coupler->CouplerType = (
|
||||
lookup != couplertypes.end() ?
|
||||
lookup->second :
|
||||
TCouplerType::NoCoupler );
|
||||
lookup->second :
|
||||
TCouplerType::NoCoupler );
|
||||
|
||||
extract_value( coupler->SpringKC, "kC", line, "" );
|
||||
extract_value( coupler->DmaxC, "DmaxC", line, "" );
|
||||
@@ -9508,6 +9512,7 @@ void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Ind
|
||||
extract_value( coupler->DmaxB, "DmaxB", line, "" );
|
||||
extract_value( coupler->FmaxB, "FmaxB", line, "" );
|
||||
extract_value( coupler->beta, "beta", line, "" );
|
||||
extract_value( coupler->AutomaticCouplingFlag, "AutomaticFlag", line, "" );
|
||||
extract_value( coupler->AllowedFlag, "AllowedFlag", line, "" );
|
||||
|
||||
if( coupler->AllowedFlag < 0 ) {
|
||||
@@ -10255,6 +10260,8 @@ void TMoverParameters::LoadFIZ_Circuit( std::string const &Input ) {
|
||||
void TMoverParameters::LoadFIZ_AI( std::string const &Input ) {
|
||||
|
||||
extract_value( AIHintPantstate, "Pantstate", Input, "" );
|
||||
extract_value( AIHintLocalBrakeAccFactor, "LocalBrakeAccFactor", Input, "" );
|
||||
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_RList( std::string const &Input ) {
|
||||
@@ -10763,6 +10770,13 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
|
||||
LocalBrakePosA = 0.0;
|
||||
BrakeCtrlPos = static_cast<int>( Handle->GetPos( bh_NP ) );
|
||||
LimPipePress = LowPipePress;
|
||||
if( ( LocalBrake == TLocalBrake::ManualBrake )
|
||||
|| ( MBrake == true ) ) {
|
||||
IncManualBrakeLevel( ManualBrakePosNo );
|
||||
}
|
||||
if( SpringBrake.MaxBrakeForce > 0.0 ) {
|
||||
SpringBrake.Activate = true;
|
||||
}
|
||||
}
|
||||
|
||||
ActFlowSpeed = 0.0;
|
||||
|
||||
@@ -448,9 +448,13 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
*/
|
||||
{
|
||||
// if material has opacity set, replace submodel opacity with it
|
||||
// NOTE: reverted to use base opacity, this allows to define opacity threshold in material
|
||||
// without it causing the translucent models to become opaque
|
||||
auto const opacity { (
|
||||
/*
|
||||
false == std::isnan( mat.opacity ) ?
|
||||
mat.opacity :
|
||||
*/
|
||||
Opacity ) };
|
||||
iFlags &= ~0x30;
|
||||
iFlags |= (
|
||||
|
||||
59
Train.cpp
59
Train.cpp
@@ -360,6 +360,8 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
|
||||
{ user_command::doormodetoggle, &TTrain::OnCommand_doormodetoggle },
|
||||
{ user_command::carcouplingincrease, &TTrain::OnCommand_carcouplingincrease },
|
||||
{ user_command::carcouplingdisconnect, &TTrain::OnCommand_carcouplingdisconnect },
|
||||
{ user_command::carcoupleradapterattach, &TTrain::OnCommand_carcoupleradapterattach },
|
||||
{ user_command::carcoupleradapterremove, &TTrain::OnCommand_carcoupleradapterremove },
|
||||
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce },
|
||||
{ user_command::hornlowactivate, &TTrain::OnCommand_hornlowactivate },
|
||||
{ user_command::hornhighactivate, &TTrain::OnCommand_hornhighactivate },
|
||||
@@ -2430,22 +2432,20 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( Train->mvControlled->PantPress > 4.8 )
|
||||
|| ( false == Train->mvControlled->Battery ) ) {
|
||||
// needs live power source and low enough pressure to work
|
||||
return;
|
||||
}
|
||||
|
||||
if( Command.action != GLFW_RELEASE ) {
|
||||
// press or hold to activate
|
||||
Train->mvControlled->PantCompFlag = true;
|
||||
// visual feedback:
|
||||
if( ( Train->mvControlled->PantPress < 4.8 )
|
||||
&& ( true == Train->mvControlled->Battery ) ) {
|
||||
// needs live power source and low enough pressure to work
|
||||
Train->mvControlled->PantCompFlag = true;
|
||||
}
|
||||
// visual feedback
|
||||
Train->ggPantCompressorButton.UpdateValue( 1.0 );
|
||||
}
|
||||
else {
|
||||
// release to disable
|
||||
Train->mvControlled->PantCompFlag = false;
|
||||
// visual feedback:
|
||||
// visual feedback
|
||||
Train->ggPantCompressorButton.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
@@ -2480,6 +2480,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
|
||||
OnCommand_linebreakerclose( Train, Command );
|
||||
}
|
||||
}
|
||||
// HACK: ignition key ignores lack of submodel, so we can start vehicles without any modeled controls
|
||||
Train->ggIgnitionKey.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2543,6 +2545,8 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm
|
||||
}
|
||||
else {
|
||||
// no switch capable of doing the job
|
||||
// HACK: ignition key ignores lack of submodel, so we can start vehicles without any modeled controls
|
||||
Train->ggIgnitionKey.UpdateValue( 1.0 );
|
||||
return;
|
||||
}
|
||||
// the actual closing of the line breaker is handled in the train update routine
|
||||
@@ -5400,6 +5404,40 @@ void TTrain::OnCommand_carcouplingdisconnect( TTrain *Train, command_data const
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_carcoupleradapterattach( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( ( true == FreeFlyModeFlag )
|
||||
&& ( Command.action == GLFW_PRESS ) ) {
|
||||
// tryb freefly, press only
|
||||
auto *vehicle { std::get<TDynamicObject *>( simulation::Region->find_vehicle( Command.location, 50, false, true ) ) };
|
||||
if( vehicle == nullptr ) { return; }
|
||||
|
||||
auto const coupler = (
|
||||
glm::length2( glm::vec3 { vehicle->CouplerPosition( end::front ) } - Command.location ) < glm::length2( glm::vec3 { vehicle->CouplerPosition( end::rear ) } - Command.location ) ?
|
||||
end::front :
|
||||
end::rear );
|
||||
|
||||
vehicle->attach_coupler_adapter( coupler );
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_carcoupleradapterremove( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( ( true == FreeFlyModeFlag )
|
||||
&& ( Command.action == GLFW_PRESS ) ) {
|
||||
// tryb freefly, press only
|
||||
auto *vehicle { std::get<TDynamicObject *>( simulation::Region->find_vehicle( Command.location, 50, false, true ) ) };
|
||||
if( vehicle == nullptr ) { return; }
|
||||
|
||||
auto const coupler = (
|
||||
glm::length2( glm::vec3 { vehicle->CouplerPosition( end::front ) } - Command.location ) < glm::length2( glm::vec3 { vehicle->CouplerPosition( end::rear ) } - Command.location ) ?
|
||||
end::front :
|
||||
end::rear );
|
||||
|
||||
vehicle->remove_coupler_adapter( coupler );
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_departureannounce( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Train->ggDepartureSignalButton.SubModel == nullptr ) {
|
||||
@@ -5797,7 +5835,8 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
|
||||
if( ( ( ggMainButton.SubModel != nullptr ) && ( ggMainButton.GetDesiredValue() > 0.95 ) )
|
||||
|| ( ( ggMainOnButton.SubModel != nullptr ) && ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) ) {
|
||||
|| ( ( ggMainOnButton.SubModel != nullptr ) && ( ggMainOnButton.GetDesiredValue() > 0.95 )
|
||||
|| ( ggIgnitionKey.GetDesiredValue() > 0.95 ) ) ) { // HACK: fallback
|
||||
// keep track of period the line breaker button is held down, to determine when/if circuit closes
|
||||
if( ( mvControlled->MainsInitTimeCountdown <= 0.0 )
|
||||
&& ( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage )
|
||||
|
||||
2
Train.h
2
Train.h
@@ -386,6 +386,8 @@ class TTrain {
|
||||
static void OnCommand_doormodetoggle( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcoupleradapterattach( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_carcoupleradapterremove( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_departureannounce( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_hornlowactivate( TTrain *Train, command_data const &Command );
|
||||
static void OnCommand_hornhighactivate( TTrain *Train, command_data const &Command );
|
||||
|
||||
@@ -155,6 +155,8 @@ commanddescription_sequence Commands_descriptions = {
|
||||
// TBD, TODO: make coupling controls entity-centric
|
||||
{ "carcouplingincrease", command_target::vehicle },
|
||||
{ "carcouplingdisconnect", command_target::vehicle },
|
||||
{ "carcoupleradapterattach", command_target::vehicle },
|
||||
{ "carcoupleradapterremove", command_target::vehicle },
|
||||
{ "doortoggleleft", command_target::vehicle },
|
||||
{ "doortoggleright", command_target::vehicle },
|
||||
{ "doorpermitleft", command_target::vehicle },
|
||||
|
||||
@@ -146,6 +146,8 @@ enum class user_command {
|
||||
|
||||
carcouplingincrease,
|
||||
carcouplingdisconnect,
|
||||
carcoupleradapterattach,
|
||||
carcoupleradapterremove,
|
||||
doortoggleleft,
|
||||
doortoggleright,
|
||||
doorpermitleft,
|
||||
|
||||
@@ -155,6 +155,8 @@ driverkeyboard_input::default_bindings() {
|
||||
{ user_command::movedown, GLFW_KEY_PAGE_DOWN },
|
||||
{ user_command::carcouplingincrease, GLFW_KEY_INSERT },
|
||||
{ user_command::carcouplingdisconnect, GLFW_KEY_DELETE },
|
||||
{ user_command::carcoupleradapterattach, GLFW_KEY_INSERT | keymodifier::control },
|
||||
{ user_command::carcoupleradapterremove, GLFW_KEY_DELETE | keymodifier::control },
|
||||
{ user_command::doortoggleleft, GLFW_KEY_COMMA },
|
||||
{ user_command::doortoggleright, GLFW_KEY_PERIOD },
|
||||
{ user_command::doorpermitleft, GLFW_KEY_COMMA | keymodifier::shift },
|
||||
|
||||
@@ -797,18 +797,23 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
|
||||
std::string
|
||||
debug_panel::update_vehicle_coupler( int const Side ) {
|
||||
// NOTE: mover and vehicle are guaranteed to be valid by the caller
|
||||
auto const &mover { *( m_input.mover ) };
|
||||
|
||||
std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] };
|
||||
std::string const adapterstatus { ( mover.Couplers[ Side ].adapter_type == TCouplerType::NoCoupler ? "" : "[A]" ) };
|
||||
|
||||
auto const *connected { m_input.vehicle->MoverParameters->Neighbours[ Side ].vehicle };
|
||||
|
||||
if( connected == nullptr ) { return couplerstatus; }
|
||||
if( connected == nullptr ) {
|
||||
|
||||
auto const &mover { *( m_input.mover ) };
|
||||
return couplerstatus + " " + adapterstatus;
|
||||
}
|
||||
|
||||
std::snprintf(
|
||||
m_buffer.data(), m_buffer.size(),
|
||||
"%s [%d] (%.1f m)",
|
||||
"%s %s[%d] (%.1f m)",
|
||||
connected->name().c_str(),
|
||||
adapterstatus.c_str(),
|
||||
mover.Couplers[ Side ].CouplingFlag,
|
||||
mover.Neighbours[ Side ].distance );
|
||||
|
||||
|
||||
@@ -1083,6 +1083,30 @@ bool opengl33_renderer::Render_lowpoly( TDynamicObject *Dynamic, float const Squ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool opengl33_renderer::Render_coupler_adapter( TDynamicObject *Dynamic, float const Squaredistance, int const End, bool const Alpha ) {
|
||||
|
||||
if( Dynamic->m_coupleradapters[ End ] == nullptr ) { return false; }
|
||||
|
||||
auto const position { Math3D::vector3 {
|
||||
0.f,
|
||||
Dynamic->MoverParameters->Couplers[ End ].adapter_height,
|
||||
( Dynamic->MoverParameters->Couplers[ End ].adapter_length + Dynamic->MoverParameters->Dim.L * 0.5 ) * ( End == end::front ? 1 : -1 ) } };
|
||||
|
||||
auto const angle { glm::vec3{
|
||||
0,
|
||||
( End == end::front ? 0 : 180 ),
|
||||
0 } };
|
||||
|
||||
if( Alpha ) {
|
||||
Render_Alpha( Dynamic->m_coupleradapters[ End ], Dynamic->Material(), Squaredistance, position, angle );
|
||||
}
|
||||
else {
|
||||
Render( Dynamic->m_coupleradapters[ End ], Dynamic->Material(), Squaredistance, position, angle );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// creates dynamic environment cubemap
|
||||
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
||||
{
|
||||
@@ -1813,13 +1837,17 @@ void opengl33_renderer::Bind_Material( material_handle const Material, TSubModel
|
||||
// material-based parameters
|
||||
switch( entry.defaultparam ) {
|
||||
case gl::shader::defaultparam_e::glossiness: {
|
||||
src = glm::vec4( material.glossiness );
|
||||
src = glm::vec4 { material.glossiness };
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( entry.size == 1 ) {
|
||||
// HACK: convert color to luminosity, if it's passed as single value
|
||||
src == glm::vec4 { colors::RGBtoHSV( glm::vec3 { src } ).s };
|
||||
}
|
||||
for (size_t j = 0; j < entry.size; j++)
|
||||
model_ubs.param[entry.location][entry.offset + j] = src[j];
|
||||
}
|
||||
@@ -2487,8 +2515,11 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear );
|
||||
|
||||
// post-render cleanup
|
||||
// post-render cleanup
|
||||
if (Dynamic->fShade > 0.0f)
|
||||
{
|
||||
// restore regular light level
|
||||
@@ -2510,6 +2541,9 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear );
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
@@ -2687,11 +2721,6 @@ void opengl33_renderer::Render(TSubModel *Submodel)
|
||||
|
||||
if ((Submodel->iVisible) && (TSubModel::fSquareDist >= Submodel->fSquareMinDist) && (TSubModel::fSquareDist < Submodel->fSquareMaxDist))
|
||||
{
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
glm::mat4 future_stack = model_ubs.future;
|
||||
|
||||
if (Submodel->iFlags & 0xC000)
|
||||
@@ -2714,6 +2743,11 @@ void opengl33_renderer::Render(TSubModel *Submodel)
|
||||
if (Submodel->iAlpha & Submodel->iFlags & 0x1F)
|
||||
{
|
||||
// rysuj gdy element nieprzezroczysty
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
switch (m_renderpass.draw_mode)
|
||||
{
|
||||
case rendermode::color:
|
||||
@@ -3440,6 +3474,9 @@ bool opengl33_renderer::Render_Alpha(TDynamicObject *Dynamic)
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render_Alpha( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front, true );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear, true );
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
@@ -3512,11 +3549,6 @@ void opengl33_renderer::Render_Alpha(TSubModel *Submodel)
|
||||
// renderowanie przezroczystych przez DL
|
||||
if ((Submodel->iVisible) && (TSubModel::fSquareDist >= Submodel->fSquareMinDist) && (TSubModel::fSquareDist < Submodel->fSquareMaxDist))
|
||||
{
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
glm::mat4 future_stack = model_ubs.future;
|
||||
|
||||
if (Submodel->iFlags & 0xC000)
|
||||
@@ -3538,7 +3570,12 @@ void opengl33_renderer::Render_Alpha(TSubModel *Submodel)
|
||||
// renderowanie obiektów OpenGL
|
||||
if (Submodel->iAlpha & Submodel->iFlags & 0x2F)
|
||||
{
|
||||
// rysuj gdy element przezroczysty
|
||||
// rysuj gdy element przezroczysty
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
switch (m_renderpass.draw_mode)
|
||||
{
|
||||
case rendermode::color:
|
||||
|
||||
@@ -242,6 +242,7 @@ class opengl33_renderer : public gfx_renderer {
|
||||
bool Render_cab(TDynamicObject const *Dynamic, float const Lightlevel, bool const Alpha = false);
|
||||
bool Render_interior( bool const Alpha = false );
|
||||
bool Render_lowpoly( TDynamicObject *Dynamic, float const Squaredistance, bool const Setup, bool const Alpha = false );
|
||||
bool Render_coupler_adapter( TDynamicObject *Dynamic, float const Squaredistance, int const End, bool const Alpha = false );
|
||||
void Render(TMemCell *Memcell);
|
||||
void Render_particles();
|
||||
void Render_precipitation();
|
||||
|
||||
@@ -845,6 +845,27 @@ bool opengl_renderer::Render_lowpoly( TDynamicObject *Dynamic, float const Squar
|
||||
return true;
|
||||
}
|
||||
|
||||
bool opengl_renderer::Render_coupler_adapter( TDynamicObject *Dynamic, float const Squaredistance, int const End, bool const Alpha ) {
|
||||
|
||||
if( Dynamic->m_coupleradapters[ End ] == nullptr ) { return false; }
|
||||
|
||||
auto const position { Math3D::vector3 {
|
||||
0.f,
|
||||
Dynamic->MoverParameters->Couplers[ End ].adapter_height,
|
||||
( Dynamic->MoverParameters->Couplers[ End ].adapter_length + Dynamic->MoverParameters->Dim.L * 0.5 ) * ( End == end::front ? 1 : -1 ) } };
|
||||
|
||||
auto const angle{ glm::vec3{ 0, ( End == end::front ? 0 : 180 ), 0 } };
|
||||
|
||||
if( Alpha ) {
|
||||
Render_Alpha( Dynamic->m_coupleradapters[ End ], Dynamic->Material(), Squaredistance, position, angle );
|
||||
}
|
||||
else {
|
||||
Render( Dynamic->m_coupleradapters[ End ], Dynamic->Material(), Squaredistance, position, angle );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// creates dynamic environment cubemap
|
||||
bool
|
||||
opengl_renderer::Render_reflections() {
|
||||
@@ -2318,6 +2339,9 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear );
|
||||
// post-render cleanup
|
||||
m_renderspecular = false;
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
@@ -2342,6 +2366,9 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear );
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
@@ -2524,10 +2551,6 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
&& ( TSubModel::fSquareDist >= Submodel->fSquareMinDist )
|
||||
&& ( TSubModel::fSquareDist < Submodel->fSquareMaxDist ) ) {
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
if( Submodel->iFlags & 0xC000 ) {
|
||||
::glPushMatrix();
|
||||
if( Submodel->fMatrix )
|
||||
@@ -2540,6 +2563,11 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
// renderowanie obiektów OpenGL
|
||||
if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) {
|
||||
// rysuj gdy element nieprzezroczysty
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color:
|
||||
case rendermode::reflections: {
|
||||
@@ -3491,6 +3519,9 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||
Render_Alpha( attachment, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
// optional coupling adapters
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::front, true );
|
||||
Render_coupler_adapter( Dynamic, squaredistance, end::rear, true );
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
@@ -3569,10 +3600,6 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
&& ( TSubModel::fSquareDist >= Submodel->fSquareMinDist )
|
||||
&& ( TSubModel::fSquareDist < Submodel->fSquareMaxDist ) ) {
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
if( Submodel->iFlags & 0xC000 ) {
|
||||
::glPushMatrix();
|
||||
if( Submodel->fMatrix )
|
||||
@@ -3585,6 +3612,11 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
// renderowanie obiektów OpenGL
|
||||
if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) {
|
||||
// rysuj gdy element przezroczysty
|
||||
|
||||
// debug data
|
||||
++m_renderpass.draw_stats.submodels;
|
||||
++m_renderpass.draw_stats.drawcalls;
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color: {
|
||||
|
||||
|
||||
@@ -223,6 +223,8 @@ private:
|
||||
Render_interior( bool const Alpha = false );
|
||||
bool
|
||||
Render_lowpoly( TDynamicObject *Dynamic, float const Squaredistance, bool const Setup, bool const Alpha = false );
|
||||
bool
|
||||
Render_coupler_adapter( TDynamicObject *Dynamic, float const Squaredistance, int const End, bool const Alpha = false );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user