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

vehicle visualization config file parameters, vehicle attachments support, axle clatter fix, disabled vehicles smoke fix

This commit is contained in:
tmj-fstate
2019-09-25 18:18:33 +02:00
parent 4e0975f387
commit 41834c4d4c
10 changed files with 167 additions and 92 deletions

View File

@@ -1784,8 +1784,7 @@ void TController::OrdersClear()
void TController::Activation() void TController::Activation()
{ // umieszczenie obsady w odpowiednim członie, wykonywane wyłącznie gdy steruje AI { // umieszczenie obsady w odpowiednim członie, wykonywane wyłącznie gdy steruje AI
iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został ustalony (zmieniony)
// ustalony (zmieniony)
if (iDirection) if (iDirection)
{ // jeśli jest ustalony kierunek { // jeśli jest ustalony kierunek
TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI
@@ -1794,7 +1793,7 @@ void TController::Activation()
ZeroSpeed(); ZeroSpeed();
ZeroDirection(); ZeroDirection();
mvOccupied->SpringBrakeActivate(true); mvOccupied->SpringBrakeActivate(true);
if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? 1 : 0].CouplingFlag, ctrain_controll)) { if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, ctrain_controll)) {
mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe
// mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na // mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na
@@ -1806,20 +1805,17 @@ void TController::Activation()
mvOccupied->ActiveCab = mvOccupied->CabNo; // użytkownik moze zmienić ActiveCab wychodząc mvOccupied->ActiveCab = mvOccupied->CabNo; // użytkownik moze zmienić ActiveCab wychodząc
mvOccupied->CabDeactivisation(); // tak jest w Train.cpp mvOccupied->CabDeactivisation(); // tak jest w Train.cpp
// przejście AI na drugą stronę EN57, ET41 itp. // przejście AI na drugą stronę EN57, ET41 itp.
while (TestFlag(d->MoverParameters->Couplers[iDirection < 0 ? 1 : 0].CouplingFlag, ctrain_controll)) while (TestFlag(d->MoverParameters->Couplers[iDirection < 0 ? end::rear : end::front].CouplingFlag, ctrain_controll))
{ // jeśli pojazd z przodu jest ukrotniony, to przechodzimy do niego { // jeśli pojazd z przodu jest ukrotniony, to przechodzimy do niego
d = iDirection * d->DirectionGet() < 0 ? d->Next() : d = iDirection * d->DirectionGet() < 0 ? d->Next() :
d->Prev(); // przechodzimy do następnego członu d->Prev(); // przechodzimy do następnego członu
if (d) if (d)
{ {
drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami
// dwóch zamienić miejscami
d->Mechanik = this; // na razie bilokacja d->Mechanik = this; // na razie bilokacja
d->MoverParameters->SetInternalCommand( d->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
"", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
if (d->DirectionGet() != pVehicle->DirectionGet()) // jeśli są przeciwne do siebie if (d->DirectionGet() != pVehicle->DirectionGet()) // jeśli są przeciwne do siebie
iDirection = -iDirection; // to będziemy jechać w drugą stronę względem iDirection = -iDirection; // to będziemy jechać w drugą stronę względem zasiedzianego pojazdu
// zasiedzianego pojazdu
pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja) pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja)
pVehicle->MoverParameters->CabNo = 0; // wyłączanie kabin po drodze pVehicle->MoverParameters->CabNo = 0; // wyłączanie kabin po drodze
pVehicle->MoverParameters->ActiveCab = 0; // i zaznaczenie, że nie ma tam nikogo pVehicle->MoverParameters->ActiveCab = 0; // i zaznaczenie, że nie ma tam nikogo

View File

@@ -2009,12 +2009,18 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
smBuforPrawy[ i ]->WillBeAnimated(); smBuforPrawy[ i ]->WillBeAnimated();
} }
} }
if( Track->fSoundDistance > 0.f ) {
for( auto &axle : m_axlesounds ) { for( auto &axle : m_axlesounds ) {
// wyszukiwanie osi (0 jest na końcu, dlatego dodajemy długość?) // wyszukiwanie osi (0 jest na końcu, dlatego dodajemy długość?)
axle.distance = ( axle.distance =
Reversed ? clamp_circular<double>(
( Reversed ?
-axle.offset : -axle.offset :
( axle.offset + MoverParameters->Dim.L ) ) + fDist; axle.offset )
- 0.5 * MoverParameters->Dim.L
+ fDist,
Track->fSoundDistance );
}
} }
// McZapkie-250202 end. // McZapkie-250202 end.
Track->AddDynamicObject(this); // wstawiamy do toru na pozycję 0, a potem przesuniemy Track->AddDynamicObject(this); // wstawiamy do toru na pozycję 0, a potem przesuniemy
@@ -3155,12 +3161,19 @@ bool TDynamicObject::Update(double dt, double dt1)
if( MyTrack->fSoundDistance != -1 ) { if( MyTrack->fSoundDistance != -1 ) {
if( MyTrack->fSoundDistance != dRailLength ) { if( MyTrack->fSoundDistance != dRailLength ) {
dRailLength = MyTrack->fSoundDistance; if( dRailLength > 0.0 ) {
for( auto &axle : m_axlesounds ) { for( auto &axle : m_axlesounds ) {
axle.distance = axle.offset + MoverParameters->Dim.L; axle.distance =
clamp_circular<double>(
axle.distance - dRailLength
+ axle.offset
/* - 0.5 * MoverParameters->Dim.L */,
MyTrack->fSoundDistance );
} }
} }
if( dRailLength != -1 ) { dRailLength = MyTrack->fSoundDistance;
}
if( dRailLength > 0.0 ) {
if( MoverParameters->Vel > 0 ) { if( MoverParameters->Vel > 0 ) {
// TODO: track quality and/or environment factors as separate subroutine // TODO: track quality and/or environment factors as separate subroutine
auto volume = auto volume =
@@ -3182,13 +3195,14 @@ bool TDynamicObject::Update(double dt, double dt1)
break; break;
} }
} }
if( dRailLength > 0.0 ) {
auto axleindex { 0 }; auto axleindex { 0 };
for( auto &axle : m_axlesounds ) { for( auto &axle : m_axlesounds ) {
axle.distance -= dDOMoveLen * Sign( dDOMoveLen ); axle.distance += dDOMoveLen * DirectionGet();
if( axle.distance < 0 ) { if( ( axle.distance < 0 )
axle.distance += dRailLength; || ( axle.distance > dRailLength ) ) {
if( MoverParameters->Vel > 2.5 ) { axle.distance = clamp_circular( axle.distance, dRailLength );
if( MoverParameters->Vel > 0.1 ) {
// NOTE: for combined clatter sound we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range // NOTE: for combined clatter sound we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range
auto const frequency = ( auto const frequency = (
true == axle.clatter.is_combined() ? true == axle.clatter.is_combined() ?
@@ -3215,6 +3229,7 @@ bool TDynamicObject::Update(double dt, double dt1)
} }
} }
} }
}
// McZapkie-260202 end // McZapkie-260202 end
// fragment z EXE Kursa // fragment z EXE Kursa
@@ -4268,11 +4283,24 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
std::string asAnimName; std::string asAnimName;
bool Stop_InternalData = false; bool Stop_InternalData = false;
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
{
// preliminary check whether the file exists
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir ); cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir );
if( false == parser.ok() ) { if( false == parser.ok() ) {
ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name ); ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name );
return; return;
} }
}
// use #include wrapper to access the appearance data file
// this allows us to provide the file content with user-defined parameters
cParser parser(
"include " + TypeName + ".mmd"
+ " " + asName // (p1)
+ " " + TypeName // (p2)
+ " " + ReplacableSkin // (p3)
+ " end",
cParser::buffer_TEXT,
asBaseDir );
std::string token; std::string token;
do { do {
token = ""; token = "";
@@ -4430,15 +4458,30 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
parser.getTokens(); parser.getTokens();
parser >> asModel; parser >> asModel;
replace_slashes( asModel ); replace_slashes( asModel );
if( asModel[ 0 ] == '/' ) { erase_leading_slashes( asModel );
// filename can potentially begin with a slash, and we don't need it
asModel.erase( 0, 1 );
}
asModel = asBaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir asModel = asBaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/... Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
mdLowPolyInt = TModelsManager::GetModel(asModel, true); mdLowPolyInt = TModelsManager::GetModel(asModel, true);
} }
else if(token == "attachments:") {
// additional 3d models attached to main body
// content provided as a series of values together enclosed in "{}"
// each value is a name of additional 3d model
// value can be optionally set of values enclosed in "[]" in which case one value will be picked randomly
// TBD: reconsider something more yaml-compliant and/or ability to define offset and rotation
while( ( ( token = parser.getToken<std::string>() ) != "" )
&& ( token != "}" ) ) {
auto attachmentmodelname { deserialize_random_set( parser ) };
replace_slashes( attachmentmodelname );
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
auto *attachmentmodel { TModelsManager::GetModel( asBaseDir + attachmentmodelname, true ) };
if( attachmentmodel != nullptr ) {
mdAttachments.emplace_back( attachmentmodel );
}
}
}
else if(token == "loads:") { else if(token == "loads:") {
// default load visualization models overrides // default load visualization models overrides
// content provided as "key: value" pairs together enclosed in "{}" // content provided as "key: value" pairs together enclosed in "{}"
@@ -4982,18 +5025,18 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
// add another axle entry to the list // add another axle entry to the list
axle_sounds axle { axle_sounds axle {
0, 0,
std::atof( token.c_str() ), std::atof( token.c_str() ) * -1.0, // for axle locations negative value means ahead of centre but vehicle faces +Z in 'its' space
{ sound_placement::external, static_cast<float>( dSDist ) } }; { sound_placement::external, static_cast<float>( dSDist ) } };
axle.clatter.deserialize( parser, sound_type::single ); axle.clatter.deserialize( parser, sound_type::single );
axle.clatter.owner( this ); axle.clatter.owner( this );
axle.clatter.offset( { 0, 0, -axle.offset } ); // vehicle faces +Z in 'its' space, for axle locations negative value means ahead of centre axle.clatter.offset( { 0, 0, axle.offset } );
m_axlesounds.emplace_back( axle ); m_axlesounds.emplace_back( axle );
} }
// arrange the axles in case they're listed out of order // arrange the axles in case they're listed out of order
std::sort( std::sort(
std::begin( m_axlesounds ), std::end( m_axlesounds ), std::begin( m_axlesounds ), std::end( m_axlesounds ),
[]( axle_sounds const &Left, axle_sounds const &Right ) { []( axle_sounds const &Left, axle_sounds const &Right ) {
return ( Left.offset < Right.offset ); } ); return ( Left.offset > Right.offset ); } );
} }
else if( ( token == "engine:" ) else if( ( token == "engine:" )

View File

@@ -200,6 +200,7 @@ public:
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs
bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s) bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s)
std::vector<TModel3d *> mdAttachments; // additional models attached to main body
struct destination_data { struct destination_data {
TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4 TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4
bool has_light { false }; // the submodel was originally configured with self-illumination attribute bool has_light { false }; // the submodel was originally configured with self-illumination attribute

View File

@@ -78,25 +78,6 @@ bool TEventLauncher::Load(cParser *parser)
} }
parser->getTokens(); parser->getTokens();
*parser >> DeltaTime; *parser >> DeltaTime;
if (DeltaTime < 0)
DeltaTime = -DeltaTime; // dla ujemnego zmieniamy na dodatni
else if (DeltaTime > 0)
{ // wartość dodatnia oznacza wyzwalanie o określonej godzinie
iMinute = int(DeltaTime) % 100; // minuty są najmłodszymi cyframi dziesietnymi
iHour = int(DeltaTime - iMinute) / 100; // godzina to setki
DeltaTime = 0; // bez powtórzeń
// potentially shift the provided time by requested offset
auto const timeoffset { static_cast<int>( Global.ScenarioTimeOffset * 60 ) };
if( timeoffset != 0 ) {
auto const adjustedtime { clamp_circular( iHour * 60 + iMinute + timeoffset, 24 * 60 ) };
iHour = ( adjustedtime / 60 ) % 24;
iMinute = adjustedtime % 60;
}
WriteLog(
"EventLauncher at "
+ std::to_string( iHour ) + ":"
+ ( iMinute < 10 ? "0" : "" ) + to_string( iMinute ) ); // wyświetlenie czasu
}
parser->getTokens(); parser->getTokens();
*parser >> token; *parser >> token;
asEvent1Name = token; // pierwszy event asEvent1Name = token; // pierwszy event
@@ -145,6 +126,29 @@ bool TEventLauncher::Load(cParser *parser)
parser->getTokens(); // słowo zamykające parser->getTokens(); // słowo zamykające
*parser >> token; *parser >> token;
} }
if( DeltaTime < 0 )
DeltaTime = -DeltaTime; // dla ujemnego zmieniamy na dodatni
else if( DeltaTime > 0 ) { // wartość dodatnia oznacza wyzwalanie o określonej godzinie
iMinute = int( DeltaTime ) % 100; // minuty są najmłodszymi cyframi dziesietnymi
iHour = int( DeltaTime - iMinute ) / 100; // godzina to setki
DeltaTime = 0; // bez powtórzeń
// potentially shift the provided time by requested offset
auto const timeoffset{ static_cast<int>( Global.ScenarioTimeOffset * 60 ) };
if( timeoffset != 0 ) {
auto const adjustedtime{ clamp_circular( iHour * 60 + iMinute + timeoffset, 24 * 60 ) };
iHour = ( adjustedtime / 60 ) % 24;
iMinute = adjustedtime % 60;
}
WriteLog(
"EventLauncher at "
+ std::to_string( iHour ) + ":"
+ ( iMinute < 10 ? "0" : "" ) + to_string( iMinute )
+ " (" + asEvent1Name
+ ( asEvent2Name != "none" ? " / " + asEvent2Name : "" )
+ ")" ); // wyświetlenie czasu
}
return true; return true;
} }

View File

@@ -244,7 +244,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
{ // gdy zostaje na tym samym torze (przesuwanie już nie zmienia toru) { // gdy zostaje na tym samym torze (przesuwanie już nie zmienia toru)
if (bPrimary) if (bPrimary)
{ // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki { // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki
if (Owner->MoverParameters->CabNo != 0) { if (Owner->MoverParameters->ActiveCab != 0) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 ); pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 );
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 ); pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 );

View File

@@ -44,6 +44,7 @@ drivingaid_panel::update() {
auto const *mover = controlled->MoverParameters; auto const *mover = controlled->MoverParameters;
auto const *driver = controlled->Mechanik; auto const *driver = controlled->Mechanik;
auto const *owner = ( controlled->ctOwner != nullptr ? controlled->ctOwner : controlled->Mechanik );
{ // throttle, velocity, speed limits and grade { // throttle, velocity, speed limits and grade
std::string expandedtext; std::string expandedtext;
@@ -60,8 +61,8 @@ drivingaid_panel::update() {
gradetext = m_buffer.data(); gradetext = m_buffer.data();
} }
// next speed limit // next speed limit
auto const speedlimit { static_cast<int>( std::floor( driver->VelDesired ) ) }; auto const speedlimit { static_cast<int>( std::floor( owner->VelDesired ) ) };
auto const nextspeedlimit { static_cast<int>( std::floor( driver->VelNext ) ) }; auto const nextspeedlimit { static_cast<int>( std::floor( owner->VelNext ) ) };
std::string nextspeedlimittext; std::string nextspeedlimittext;
if( nextspeedlimit != speedlimit ) { if( nextspeedlimit != speedlimit ) {
std::snprintf( std::snprintf(
@@ -117,7 +118,7 @@ drivingaid_panel::update() {
{ // alerter, hints { // alerter, hints
std::string expandedtext; std::string expandedtext;
if( is_expanded ) { if( is_expanded ) {
auto const stoptime { static_cast<int>( std::ceil( -1.0 * controlled->Mechanik->fStopTime ) ) }; auto const stoptime { static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) };
if( stoptime > 0 ) { if( stoptime > 0 ) {
std::snprintf( std::snprintf(
m_buffer.data(), m_buffer.size(), m_buffer.data(), m_buffer.size(),
@@ -126,7 +127,7 @@ drivingaid_panel::update() {
expandedtext = m_buffer.data(); expandedtext = m_buffer.data();
} }
else { else {
auto const trackblockdistance{ std::abs( controlled->Mechanik->TrackBlock() ) }; auto const trackblockdistance{ std::abs( owner->TrackBlock() ) };
if( trackblockdistance <= 75.0 ) { if( trackblockdistance <= 75.0 ) {
std::snprintf( std::snprintf(
m_buffer.data(), m_buffer.size(), m_buffer.data(), m_buffer.size(),

View File

@@ -50,20 +50,24 @@ class cParser //: public std::stringstream
bool bool
expectToken( std::string const &Value ) { expectToken( std::string const &Value ) {
return readToken() == Value; }; return readToken() == Value; };
inline
bool bool
eof() { eof() {
return mStream->eof(); }; return mStream->eof(); };
inline
bool bool
ok() { ok() {
return !mStream->fail(); }; return ( !mStream->fail() ); };
cParser & cParser &
autoclear( bool const Autoclear ); autoclear( bool const Autoclear );
inline
bool bool
autoclear() const { autoclear() const {
return m_autoclear; } return m_autoclear; }
bool bool
getTokens( unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;" ); getTokens( unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;" );
// returns next incoming token, if any, without removing it from the set // returns next incoming token, if any, without removing it from the set
inline
std::string std::string
peek() const { peek() const {
return ( return (

View File

@@ -167,11 +167,17 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
std::min<float>( std::min<float>(
m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ), m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ),
m_max_particles ) ); m_max_particles ) );
// consider special spawn rate cases
if( m_ownertype == owner_type::vehicle ) {
// HACK: don't spawn particles in tunnels, to prevent smoke clipping through 'terrain' outside // HACK: don't spawn particles in tunnels, to prevent smoke clipping through 'terrain' outside
if( ( m_ownertype == owner_type::vehicle ) if( m_owner.vehicle->RaTrackGet()->eEnvironment == e_tunnel ) {
&& ( m_owner.vehicle->RaTrackGet()->eEnvironment == e_tunnel ) ) {
m_spawncount = 0.f; m_spawncount = 0.f;
} }
if( false == m_owner.vehicle->bEnabled ) {
// don't spawn particles for vehicles which left the scenario
m_spawncount = 0.f;
}
}
// update spawned particles // update spawned particles
for( auto particleiterator { std::begin( m_particles ) }; particleiterator != std::end( m_particles ); ++particleiterator ) { for( auto particleiterator { std::begin( m_particles ) }; particleiterator != std::end( m_particles ); ++particleiterator ) {

View File

@@ -2393,8 +2393,13 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
} }
} }
if( Dynamic->mdModel ) { if( Dynamic->mdModel ) {
// main model
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
} }
// optional attached models
for( auto *attachment : Dynamic->mdAttachments ) {
Render( attachment, Dynamic->Material(), squaredistance );
}
// post-render cleanup // post-render cleanup
m_renderspecular = false; m_renderspecular = false;
if( Dynamic->fShade > 0.0f ) { if( Dynamic->fShade > 0.0f ) {
@@ -2411,10 +2416,18 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance ); Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
// } // }
} }
if( Dynamic->mdModel ) if( Dynamic->mdModel ) {
// main model
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance ); Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku }
// optional attached models
for( auto *attachment : Dynamic->mdAttachments ) {
Render( attachment, Dynamic->Material(), squaredistance );
}
if( Dynamic->mdLoad ) {
// renderowanie nieprzezroczystego ładunku
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} ); Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
}
// post-render cleanup // post-render cleanup
break; break;
} }
@@ -3523,11 +3536,18 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
// } // }
} }
if( Dynamic->mdModel ) if( Dynamic->mdModel ) {
// main model
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance ); Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
}
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku // optional attached models
for( auto *attachment : Dynamic->mdAttachments ) {
Render_Alpha( attachment, Dynamic->Material(), squaredistance );
}
if( Dynamic->mdLoad ) {
// renderowanie nieprzezroczystego ładunku
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} ); Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
}
// post-render cleanup // post-render cleanup
m_renderspecular = false; m_renderspecular = false;

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 19 #define VERSION_MAJOR 19
#define VERSION_MINOR 916 #define VERSION_MINOR 925
#define VERSION_REVISION 0 #define VERSION_REVISION 0