16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 01:59:19 +02:00

external cargo included in the vehicle load visualization system, cargo model offset parameter

This commit is contained in:
tmj-fstate
2018-09-08 19:55:13 +02:00
parent e4789db1d5
commit 397628242c
7 changed files with 100 additions and 60 deletions

View File

@@ -621,26 +621,26 @@ TDynamicObject::toggle_lights() {
if( true == SectionLightsActive ) {
// switch all lights off
for( auto &sectionlight : SectionLightLevels ) {
sectionlight.level = 0.0f;
for( auto &section : Sections ) {
section.light_level = 0.0f;
}
SectionLightsActive = false;
}
else {
// set lights with probability depending on the compartment type. TODO: expose this in .mmd file
for( auto &sectionlight : SectionLightLevels ) {
for( auto &section : Sections ) {
std::string const &compartmentname = sectionlight.compartment->pName;
if( ( compartmentname.find( "corridor" ) == 0 )
|| ( compartmentname.find( "korytarz" ) == 0 ) ) {
auto const sectionname { section.compartment->pName };
if( ( sectionname.find( "corridor" ) == 0 )
|| ( sectionname.find( "korytarz" ) == 0 ) ) {
// corridors are lit 100% of time
sectionlight.level = 0.75f;
section.light_level = 0.75f;
}
else if(
( compartmentname.find( "compartment" ) == 0 )
|| ( compartmentname.find( "przedzial" ) == 0 ) ) {
( sectionname.find( "compartment" ) == 0 )
|| ( sectionname.find( "przedzial" ) == 0 ) ) {
// compartments are lit with 75% probability
sectionlight.level = ( Random() < 0.75 ? 0.75f : 0.15f );
section.light_level = ( Random() < 0.75 ? 0.75f : 0.15f );
}
}
SectionLightsActive = true;
@@ -1024,10 +1024,10 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
// else btHeadSignals23.TurnOff();
}
// interior light levels
for( auto const &section : SectionLightLevels ) {
section.compartment->SetLightLevel( section.level, true );
for( auto const &section : Sections ) {
section.compartment->SetLightLevel( section.light_level, true );
if( section.load != nullptr ) {
section.load->SetLightLevel( section.level, true );
section.load->SetLightLevel( section.light_level, true );
}
}
// load chunks visibility
@@ -2161,35 +2161,21 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
// check the low poly interior for potential compartments of interest, ie ones which can be individually lit
// TODO: definition of relevant compartments in the .mmd file
TSubModel *submodel { nullptr };
if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); }
if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); }
if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { Sections.push_back( { submodel, nullptr, 0.0f } ); }
// passenger car compartments
std::vector<std::string> nameprefixes = { "corridor", "korytarz", "compartment", "przedzial" };
int compartmentindex;
std::string compartmentname;
for( auto const &nameprefix : nameprefixes ) {
compartmentindex = 0;
do {
compartmentname =
nameprefix + (
compartmentindex < 10 ?
"0" + std::to_string( compartmentindex ) :
std::to_string( compartmentindex ) );
submodel = mdLowPolyInt->GetFromName( compartmentname );
if( submodel != nullptr ) {
SectionLightLevels.push_back( {
submodel,
nullptr, // pointers to load sections are generated afterwards
0.0f } );
}
++compartmentindex;
} while( ( submodel != nullptr )
|| ( compartmentindex < 2 ) ); // chain can start from prefix00 or prefix01
init_sections( mdLowPolyInt, nameprefix );
}
update_load_sections();
update_load_visibility();
}
// 'external_load' is an optional special section in the main model, pointing to submodel of external load
if( mdModel ) {
init_sections( mdModel, "external_load" );
}
update_load_sections();
update_load_visibility();
// wyszukiwanie zderzakow
if( mdModel ) {
// jeśli ma w czym szukać
@@ -2277,6 +2263,35 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
return MoverParameters->Dim.L;
}
int
TDynamicObject::init_sections( TModel3d const *Model, std::string const &Nameprefix ) {
std::string sectionname;
auto sectioncount = 0;
auto sectionindex = 0;
TSubModel *sectionsubmodel { nullptr };
do {
sectionname =
Nameprefix + (
sectionindex < 10 ?
"0" + std::to_string( sectionindex ) :
std::to_string( sectionindex ) );
sectionsubmodel = Model->GetFromName( sectionname );
if( sectionsubmodel != nullptr ) {
Sections.push_back( {
sectionsubmodel,
nullptr, // pointers to load sections are generated afterwards
0.0f } );
++sectioncount;
}
++sectionindex;
} while( ( sectionsubmodel != nullptr )
|| ( sectionindex < 2 ) ); // chain can start from prefix00 or prefix01
return sectioncount;
}
void
TDynamicObject::create_controller( std::string const Type, bool const Trainset ) {
@@ -2580,6 +2595,9 @@ void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int co
// update state of load exchange operation
void TDynamicObject::update_exchange( double const Deltatime ) {
// TODO: move offset calculation after initial check, when the loading system is all unified
update_load_offset();
if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return; }
if( ( MoverParameters->Vel < 2.0 )
@@ -2686,7 +2704,7 @@ TDynamicObject::update_load_sections() {
SectionLoadVisibility.clear();
for( auto &section : SectionLightLevels ) {
for( auto &section : Sections ) {
section.load = (
mdLoad != nullptr ?
@@ -2737,6 +2755,19 @@ TDynamicObject::update_load_visibility() {
} } );
}
void
TDynamicObject::update_load_offset() {
if( MoverParameters->LoadMinOffset == 0.f ) { return; }
auto const loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
0.0 :
100.0 * MoverParameters->Load / MoverParameters->MaxLoad ) };
LoadOffset = interpolate( MoverParameters->LoadMinOffset, 0.f, clamp( 0.0, 1.0, loadpercentage * 0.01 ) );
}
void
TDynamicObject::shuffle_load_sections() {
@@ -2748,6 +2779,8 @@ TDynamicObject::shuffle_load_sections() {
return (
( section.submodel->pName.find( "compartment" ) == 0 )
|| ( section.submodel->pName.find( "przedzial" ) == 0 ) ); } );
// NOTE: potentially we're left with a mix of corridor and external section loads
// but that's not necessarily a wrong outcome, so we leave it this way for the time being
}
/*
@@ -3807,10 +3840,11 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->DerailReason = 0; //żeby tylko raz
}
update_exchange( dt );
if (MoverParameters->LoadStatus)
if( MoverParameters->LoadStatus ) {
LoadUpdate(); // zmiana modelu ładunku
}
update_exchange( dt );
return true; // Ra: chyba tak?
}
@@ -3848,9 +3882,11 @@ bool TDynamicObject::FastUpdate(double dt)
// ResetdMoveLen();
FastMove(dDOMoveLen);
update_exchange( dt );
if (MoverParameters->LoadStatus)
if( MoverParameters->LoadStatus ) {
LoadUpdate(); // zmiana modelu ładunku
}
update_exchange( dt );
return true; // Ra: chyba tak?
}

View File

@@ -196,16 +196,17 @@ public:
TModel3d *mdLoad; // model zmiennego ładunku
TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
float LoadOffset { 0.f };
glm::vec3 InteriorLight { 0.9f * 255.f / 255.f, 0.9f * 216.f / 255.f, 0.9f * 176.f / 255.f }; // tungsten light. TODO: allow definition of light type?
float InteriorLightLevel { 0.0f }; // current level of interior lighting
struct section_light {
struct vehicle_section {
TSubModel *compartment;
TSubModel *load;
float level;
float light_level;
};
std::vector<section_light> SectionLightLevels; // table of light levels for specific compartments of associated 3d model
std::vector<vehicle_section> Sections; // table of recognized vehicle sections
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
struct section_visibility {
TSubModel *submodel;
bool visible;
@@ -517,6 +518,7 @@ private:
std::string Name, std::string BaseDir, std::string asReplacableSkin, std::string Type_Name,
TTrack *Track, double fDist, std::string DriverType, double fVel, std::string TrainName,
float Load, std::string LoadType, bool Reversed, std::string);
int init_sections( TModel3d const *Model, std::string const &Nameprefix );
void create_controller( std::string const Type, bool const Trainset );
void AttachPrev(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt, double dt1, bool FullVer);
@@ -525,6 +527,7 @@ private:
void LoadUpdate();
void update_load_sections();
void update_load_visibility();
void update_load_offset();
void shuffle_load_sections();
bool Update(double dt, double dt1);
bool FastUpdate(double dt);

View File

@@ -947,6 +947,7 @@ public:
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
float LoadMinOffset { 0.f }; // offset applied to cargo model when load amount is 0
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/

View File

@@ -6624,12 +6624,9 @@ TMoverParameters::signal_departure( bool const State, range_t const Notify ) {
void
TMoverParameters::update_autonomous_doors( double const Deltatime ) {
if( ( DoorCloseCtrl != control_t::autonomous )
|| ( ( false == DoorLeftOpened )
&& ( false == DoorRightOpened ) ) ) {
// nothing to do
return;
}
if( DoorCloseCtrl != control_t::autonomous ) { return; }
if( ( false == DoorLeftOpened )
&& ( false == DoorRightOpened ) ) { return; }
if( DoorStayOpen > 0.0 ) {
// update door timers if the door close after defined time
@@ -6641,18 +6638,19 @@ TMoverParameters::update_autonomous_doors( double const Deltatime ) {
if( true == DoorLeftOpened ) { DoorLeftOpenTimer = DoorStayOpen; }
if( true == DoorRightOpened ) { DoorRightOpenTimer = DoorStayOpen; }
}
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 5 km/h
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 10 km/h
auto const closingspeed { 10.0 };
// NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving
if( true == DoorLeftOpened ) {
if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) )
|| ( Vel > 5.0 ) ) {
|| ( Vel > closingspeed ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorLeft( false, range_t::local );
}
}
if( true == DoorRightOpened ) {
if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) )
|| ( Vel > 5.0 ) ) {
|| ( Vel > closingspeed ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorRight( false, range_t::local );
}
@@ -7576,6 +7574,8 @@ void TMoverParameters::LoadFIZ_Load( std::string const &line ) {
extract_value( OverLoadFactor, "OverLoadFactor", line, "" );
extract_value( LoadSpeed, "LoadSpeed", line, "" );
extract_value( UnLoadSpeed, "UnLoadSpeed", line, "" );
extract_value( LoadMinOffset, "LoadMinOffset", line, "" );
}
void TMoverParameters::LoadFIZ_Dimensions( std::string const &line ) {

View File

@@ -1154,7 +1154,7 @@ void TModel3d::AddTo(TSubModel *tmp, TSubModel *SubModel) {
iFlags |= 0x0200; // submodele są oddzielne
};
TSubModel *TModel3d::GetFromName(std::string const &Name)
TSubModel *TModel3d::GetFromName(std::string const &Name) const
{ // wyszukanie submodelu po nazwie
if (Name.empty())
return Root; // potrzebne do terenu z E3D

View File

@@ -241,7 +241,7 @@ public:
Root->m_boundingradius :
0.f ); }
inline TSubModel * GetSMRoot() { return (Root); };
TSubModel * GetFromName(std::string const &Name);
TSubModel * GetFromName(std::string const &Name) const;
TSubModel * AddToNamed(const char *Name, TSubModel *SubModel);
void AddTo(TSubModel *tmp, TSubModel *SubModel);
void LoadFromTextFile(std::string const &FileName, bool dynamic);

View File

@@ -2151,7 +2151,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
// post-render cleanup
m_renderspecular = false;
@@ -3096,7 +3096,7 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
// post-render cleanup
m_renderspecular = false;