16
0
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:
tmj-fstate
2020-03-24 16:12:25 +01:00
parent e0c1f41474
commit c22f4c900f
17 changed files with 431 additions and 93 deletions

View File

@@ -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))

View File

@@ -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;
}
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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 |= (

View File

@@ -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 )

View File

@@ -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 );

View File

@@ -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 },

View File

@@ -146,6 +146,8 @@ enum class user_command {
carcouplingincrease,
carcouplingdisconnect,
carcoupleradapterattach,
carcoupleradapterremove,
doortoggleleft,
doortoggleright,
doorpermitleft,

View File

@@ -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 },

View File

@@ -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 );

View File

@@ -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:

View File

@@ -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();

View File

@@ -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: {

View File

@@ -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

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 20
#define VERSION_MINOR 222
#define VERSION_MINOR 322
#define VERSION_REVISION 0