mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 01:39:19 +02:00
cab textures size limit, generic cab controls return type support, minor bug fixes
This commit is contained in:
@@ -4592,7 +4592,7 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
|
||||
// uśrednione napięcie sieci: przy spadku poniżej wartości minimalnej opóźnić rozruch o losowy czas
|
||||
fVoltage = 0.5 * (fVoltage + mvControlling->PantographVoltage);
|
||||
fVoltage = 0.5 * (fVoltage + std::max( mvControlling->GetAnyTrainsetVoltage(), mvControlling->PantographVoltage ) );
|
||||
if( fVoltage < mvControlling->EnginePowerSource.CollectorParameters.MinV ) {
|
||||
// gdy rozłączenie WS z powodu niskiego napięcia
|
||||
if( fActionTime >= 0 ) {
|
||||
|
||||
@@ -4185,9 +4185,9 @@ void TDynamicObject::RenderSounds() {
|
||||
&& ( MoverParameters->Vel > 5.0 ) ) {
|
||||
// scale volume with curve radius and vehicle speed
|
||||
volume =
|
||||
MoverParameters->AccN * MoverParameters->AccN
|
||||
MoverParameters->AccN // * MoverParameters->AccN
|
||||
* interpolate(
|
||||
0.0, 1.0,
|
||||
0.5, 1.0,
|
||||
clamp(
|
||||
MoverParameters->Vel / 40.0,
|
||||
0.0, 1.0 ) )
|
||||
|
||||
26
Globals.cpp
26
Globals.cpp
@@ -293,15 +293,23 @@ global_settings::ConfigParse(cParser &Parser) {
|
||||
Parser.getTokens(1, false);
|
||||
int size;
|
||||
Parser >> size;
|
||||
if (size <= 64) { iMaxTextureSize = 64; }
|
||||
else if (size <= 128) { iMaxTextureSize = 128; }
|
||||
else if (size <= 256) { iMaxTextureSize = 256; }
|
||||
else if (size <= 512) { iMaxTextureSize = 512; }
|
||||
else if (size <= 1024) { iMaxTextureSize = 1024; }
|
||||
else if (size <= 2048) { iMaxTextureSize = 2048; }
|
||||
else if (size <= 4096) { iMaxTextureSize = 4096; }
|
||||
else if (size <= 8192) { iMaxTextureSize = 8192; }
|
||||
else { iMaxTextureSize = 16384; }
|
||||
auto p2size { 64 }; // start with 64px
|
||||
while( (p2size <= 16384 ) && ( p2size <= size ) ) {
|
||||
iMaxTextureSize = p2size;
|
||||
p2size = p2size << 1;
|
||||
}
|
||||
}
|
||||
else if (token == "maxcabtexturesize")
|
||||
{
|
||||
// wymuszenie przeskalowania tekstur
|
||||
Parser.getTokens( 1, false );
|
||||
int size;
|
||||
Parser >> size;
|
||||
auto p2size { 64 }; // start with 64px
|
||||
while( ( p2size <= 16384 ) && ( p2size <= size ) ) {
|
||||
iMaxCabTextureSize = p2size;
|
||||
p2size = p2size << 1;
|
||||
}
|
||||
}
|
||||
else if (token == "movelight")
|
||||
{
|
||||
|
||||
@@ -53,6 +53,7 @@ struct global_settings {
|
||||
std::string asCurrentSceneryPath{ "scenery/" };
|
||||
std::string asCurrentTexturePath{ szTexturePath };
|
||||
std::string asCurrentDynamicPath;
|
||||
int CurrentMaxTextureSize{ 4096 };
|
||||
bool GfxFramebufferSRGB { true };
|
||||
// settings
|
||||
// filesystem
|
||||
@@ -129,6 +130,7 @@ struct global_settings {
|
||||
float AnisotropicFiltering{ 8.f }; // requested level of anisotropic filtering. TODO: move it to renderer object
|
||||
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
|
||||
GLint iMaxTextureSize{ 4096 }; // maksymalny rozmiar tekstury
|
||||
GLint iMaxCabTextureSize{ 4096 }; // largest allowed texture in vehicle cab
|
||||
int iMultisampling{ 2 }; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||
bool bSmoothTraction{ true }; // wygładzanie drutów starym sposobem
|
||||
float SplineFidelity{ 1.f }; // determines segment size during conversion of splines to geometry
|
||||
|
||||
@@ -1544,7 +1544,7 @@ public:
|
||||
bool RunInternalCommand();
|
||||
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation);
|
||||
bool CabActivisation(void);
|
||||
bool CabDeactivisation(void);
|
||||
bool CabDeactivisation( bool const Force = false );
|
||||
|
||||
/*! funkcje zwiekszajace/zmniejszajace nastawniki*/
|
||||
/*! glowny nastawnik:*/
|
||||
|
||||
@@ -1728,7 +1728,7 @@ void TMoverParameters::HeatingCheck( double const Timestep ) {
|
||||
break;
|
||||
}
|
||||
case TPowerSource::Main: {
|
||||
voltage = ( true == Mains ? PantographVoltage : 0.0 );
|
||||
voltage = ( true == Mains ? std::max( GetAnyTrainsetVoltage(), PantographVoltage ) : 0.0 );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -2355,11 +2355,11 @@ bool TMoverParameters::CabActivisation(void)
|
||||
// Q: 20160710
|
||||
// wyłączenie rozrządu
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::CabDeactivisation(void)
|
||||
bool TMoverParameters::CabDeactivisation( bool const Force )
|
||||
{
|
||||
bool OK = false;
|
||||
|
||||
OK = (CabNo == ActiveCab); // o ile obsada jest w kabinie ze sterowaniem
|
||||
OK = Force || (CabNo == ActiveCab); // o ile obsada jest w kabinie ze sterowaniem
|
||||
if (OK)
|
||||
{
|
||||
CabNo = 0;
|
||||
@@ -3736,7 +3736,7 @@ void TMoverParameters::CompressorCheck(double dt)
|
||||
if( CompressorPower == 2 ) {
|
||||
CompressorAllow = ConverterAllow;
|
||||
}
|
||||
|
||||
// TODO: clean up compressor CompressorFlag state code, large parts are cloned and an utter mess
|
||||
if (MaxCompressorF - MinCompressorF < 0.0001) {
|
||||
// TODO: investigate purpose of this branch and whether it can be removed as it duplicates later code
|
||||
if( ( true == CompressorAllow )
|
||||
@@ -3802,10 +3802,9 @@ void TMoverParameters::CompressorCheck(double dt)
|
||||
CompressorFlag = (
|
||||
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
||||
&& ( CompressorAllowLocal )
|
||||
&& ( Mains )
|
||||
&& ( ( ConverterFlag )
|
||||
|| ( CompressorPower == 0 )
|
||||
|| ( CompressorPower == 3 ) ) );
|
||||
&& ( CompressorPower == 0 ? Mains :
|
||||
CompressorPower == 3 ? Mains :
|
||||
ConverterFlag ) );
|
||||
|
||||
if( Compressor > MaxCompressorF ) {
|
||||
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
|
||||
@@ -3878,10 +3877,9 @@ void TMoverParameters::CompressorCheck(double dt)
|
||||
CompressorFlag = (
|
||||
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
||||
&& ( CompressorAllowLocal )
|
||||
&& ( Mains )
|
||||
&& ( ( ConverterFlag )
|
||||
|| ( CompressorPower == 0 )
|
||||
|| ( CompressorPower == 3 ) ) );
|
||||
&& ( CompressorPower == 0 ? Mains :
|
||||
CompressorPower == 3 ? Mains :
|
||||
ConverterFlag ) );
|
||||
}
|
||||
|
||||
// NOTE: crude way to enforce simultaneous activation of compressors in multi-unit setups
|
||||
|
||||
@@ -473,7 +473,7 @@ opengl_texture::load_DDS() {
|
||||
int blockSize = ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16 );
|
||||
int offset = 0;
|
||||
|
||||
while( ( data_width > Global.iMaxTextureSize ) || ( data_height > Global.iMaxTextureSize ) ) {
|
||||
while( ( data_width > Global.CurrentMaxTextureSize ) || ( data_height > Global.CurrentMaxTextureSize ) ) {
|
||||
// pomijanie zbyt dużych mipmap, jeśli wymagane jest ograniczenie rozmiaru
|
||||
offset += ( ( data_width + 3 ) / 4 ) * ( ( data_height + 3 ) / 4 ) * blockSize;
|
||||
data_width /= 2;
|
||||
@@ -714,7 +714,7 @@ opengl_texture::load_TGA() {
|
||||
}
|
||||
|
||||
downsize( GL_BGRA );
|
||||
if( ( data_width > Global.iMaxTextureSize ) || ( data_height > Global.iMaxTextureSize ) ) {
|
||||
if( ( data_width > Global.CurrentMaxTextureSize ) || ( data_height > Global.CurrentMaxTextureSize ) ) {
|
||||
// for non-square textures there's currently possibility the scaling routine will have to abort
|
||||
// before it gets all work done
|
||||
data_state = resource_state::failed;
|
||||
@@ -1054,7 +1054,7 @@ opengl_texture::set_filtering() const {
|
||||
void
|
||||
opengl_texture::downsize( GLuint const Format ) {
|
||||
|
||||
while( ( data_width > Global.iMaxTextureSize ) || ( data_height > Global.iMaxTextureSize ) ) {
|
||||
while( ( data_width > Global.CurrentMaxTextureSize ) || ( data_height > Global.CurrentMaxTextureSize ) ) {
|
||||
// scale down the base texture, if it's larger than allowed maximum
|
||||
// NOTE: scaling is uniform along both axes, meaning non-square textures can drop below the maximum
|
||||
// TODO: replace with proper scaling function once we have image middleware in place
|
||||
|
||||
41
Train.cpp
41
Train.cpp
@@ -439,8 +439,15 @@ TTrain::TTrain() {
|
||||
bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||
{ // powiązanie ręcznego sterowania kabiną z pojazdem
|
||||
if( NewDynamicObject->Mechanik == nullptr ) {
|
||||
/*
|
||||
ErrorLog( "Bad config: can't take control of inactive vehicle \"" + NewDynamicObject->asName + "\"" );
|
||||
return false;
|
||||
*/
|
||||
auto const activecab { (
|
||||
NewDynamicObject->MoverParameters->ActiveCab > 0 ? "1" :
|
||||
NewDynamicObject->MoverParameters->ActiveCab < 0 ? "2" :
|
||||
"p" ) };
|
||||
NewDynamicObject->create_controller( activecab, NewDynamicObject->ctOwner != nullptr );
|
||||
}
|
||||
|
||||
DynamicSet(NewDynamicObject);
|
||||
@@ -452,11 +459,20 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||
|
||||
fMainRelayTimer = 0; // Hunter, do k...y nędzy, ustawiaj wartości początkowe zmiennych!
|
||||
|
||||
if( false == LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
|
||||
iCabn = (
|
||||
mvOccupied->ActiveCab < 0 ? 0 :
|
||||
mvOccupied->ActiveCab > 0 ? 1 :
|
||||
2 );
|
||||
|
||||
{
|
||||
Global.CurrentMaxTextureSize = Global.iMaxCabTextureSize;
|
||||
auto const result{ LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) };
|
||||
Global.CurrentMaxTextureSize = Global.iMaxTextureSize;
|
||||
if( false == result ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
iCabn = 0;
|
||||
// Ra: taka proteza - przesłanie kierunku do członów connected
|
||||
if (mvControlled->ActiveDir > 0)
|
||||
{ // było do przodu
|
||||
@@ -4434,8 +4450,17 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||
|
||||
if( item.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// turn on
|
||||
// visual feedback
|
||||
item.UpdateValue( 1.0 );
|
||||
}
|
||||
else {
|
||||
// two-state switch
|
||||
if( item.GetDesiredValue() < 0.5 ) {
|
||||
// turn on
|
||||
// visual feedback
|
||||
@@ -4447,6 +4472,16 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
|
||||
item.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
|
||||
if( item.type() == TGaugeType::push ) {
|
||||
// impulse switch
|
||||
// turn off
|
||||
// visual feedback
|
||||
item.UpdateValue( 0.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_springbraketoggle(TTrain *Train, command_data const &Command) {
|
||||
|
||||
@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Camera.h"
|
||||
#include "Logs.h"
|
||||
#include "utilities.h"
|
||||
#include "simulation.h"
|
||||
#include "Train.h"
|
||||
|
||||
namespace audio {
|
||||
|
||||
@@ -333,6 +335,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
::alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
|
||||
// velocity
|
||||
if( Deltatime > 0 ) {
|
||||
/*
|
||||
glm::dvec3 const listenerposition { Global.pCamera.Pos };
|
||||
glm::dvec3 const listenermovement { listenerposition - m_listenerposition };
|
||||
m_listenerposition = listenerposition;
|
||||
@@ -340,6 +343,40 @@ openal_renderer::update( double const Deltatime ) {
|
||||
glm::length( listenermovement ) < 1000.0 ? // large jumps are typically camera changes
|
||||
limit_velocity( listenermovement / Deltatime ) :
|
||||
glm::vec3() );
|
||||
*/
|
||||
auto cameramove{ glm::dvec3{ Global.pCamera.Pos - m_camerapos} };
|
||||
// intercept sudden user-induced camera jumps...
|
||||
// ...from free fly mode change
|
||||
if( m_freeflymode != FreeFlyModeFlag ) {
|
||||
m_freeflymode = FreeFlyModeFlag;
|
||||
if( true == m_freeflymode ) {
|
||||
// cache last precipitation vector in the cab
|
||||
m_cabcameramove = m_cameramove;
|
||||
// don't carry previous precipitation vector to a new unrelated location
|
||||
m_cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
else {
|
||||
// restore last cached precipitation vector
|
||||
m_cameramove = m_cabcameramove;
|
||||
}
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
// ...from jump between cab and window/mirror view
|
||||
if( m_windowopen != Global.CabWindowOpen ) {
|
||||
m_windowopen = Global.CabWindowOpen;
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
// ... from cab change
|
||||
if( ( simulation::Train != nullptr ) && ( simulation::Train->iCabn != m_activecab ) ) {
|
||||
m_activecab = simulation::Train->iCabn;
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
// ... from camera jump to another location
|
||||
if( glm::length( cameramove ) > 100.0 ) {
|
||||
cameramove = glm::dvec3{ 0.0 };
|
||||
}
|
||||
m_listenervelocity = limit_velocity( cameramove / Deltatime );
|
||||
|
||||
::alListenerfv( AL_VELOCITY, reinterpret_cast<ALfloat const *>( glm::value_ptr( m_listenervelocity ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -147,8 +147,16 @@ private:
|
||||
ALCdevice * m_device { nullptr };
|
||||
ALCcontext * m_context { nullptr };
|
||||
bool m_ready { false }; // renderer is initialized and functional
|
||||
/*
|
||||
glm::dvec3 m_listenerposition;
|
||||
*/
|
||||
glm::vec3 m_listenervelocity;
|
||||
glm::dvec3 m_camerapos{ 0.0 };
|
||||
glm::dvec3 m_cameramove{ 0.0 };
|
||||
glm::dvec3 m_cabcameramove{ 0.0 };
|
||||
bool m_freeflymode{ true };
|
||||
bool m_windowopen{ true };
|
||||
int m_activecab{ 0 };
|
||||
|
||||
buffer_manager m_buffers;
|
||||
// TBD: list of sources as vector, sorted by distance, for openal implementations with limited number of active sources?
|
||||
|
||||
@@ -188,6 +188,14 @@ driver_mode::update() {
|
||||
if( Global.changeDynObj ) {
|
||||
// ABu zmiana pojazdu - przejście do innego
|
||||
ChangeDynamic();
|
||||
// move inside, but only if the human is in charge (otherwise we'll get pulled in when ai switches cabs)
|
||||
if( ( simulation::Train != nullptr )
|
||||
&& ( simulation::Train->Dynamic() != nullptr )
|
||||
&& ( simulation::Train->Dynamic()->Mechanik != nullptr )
|
||||
&& ( simulation::Train->Dynamic()->Mechanik->AIControllFlag == false )
|
||||
&& ( true == FreeFlyModeFlag ) ) {
|
||||
InOutKey();
|
||||
}
|
||||
}
|
||||
|
||||
if( simulation::Train != nullptr ) {
|
||||
@@ -708,7 +716,6 @@ driver_mode::OnKeyDown(int cKey) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GLFW_KEY_F4: {
|
||||
|
||||
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
||||
@@ -722,46 +729,76 @@ driver_mode::OnKeyDown(int cKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
TDynamicObject *tmp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 50, true, false ) );
|
||||
TDynamicObject *targetvehicle = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global.pCamera.Pos, 50, false, false ) );
|
||||
|
||||
if( tmp != nullptr ) {
|
||||
if( targetvehicle != nullptr ) {
|
||||
|
||||
if( ( true == DebugModeFlag )
|
||||
|| ( tmp->MoverParameters->Vel <= 5.0 ) ) {
|
||||
|| ( targetvehicle->MoverParameters->Vel <= 5.0 ) ) {
|
||||
// works always in debug mode, or for stopped/slow moving vehicles otherwise
|
||||
if( simulation::Train ) { // jeśli mielismy pojazd
|
||||
if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć
|
||||
if( ( tmp->ctOwner == simulation::Train->Dynamic()->Mechanik )
|
||||
&& ( true == Global.ctrlState ) ) {
|
||||
// if the vehicle we left to the ai controlled the vehicle we're about to take over
|
||||
// put the ai we left in charge of our old vehicle to sleep
|
||||
// TODO: remove ctrl key mode once manual cab (de)activation is in place
|
||||
simulation::Train->Dynamic()->Mechanik->primary( false );
|
||||
simulation::Train->Dynamic()->Mechanik->action() = TAction::actSleep;
|
||||
simulation::Train->Dynamic()->MoverParameters->CabDeactivisation();
|
||||
}
|
||||
simulation::Train->Dynamic()->Mechanik->TakeControl( true ); // oddajemy dotychczasowy AI
|
||||
}
|
||||
}
|
||||
|
||||
if( simulation::Train == nullptr ) {
|
||||
simulation::Train = new TTrain(); // jeśli niczym jeszcze nie jeździlismy
|
||||
}
|
||||
if( simulation::Train->Init( tmp ) ) {
|
||||
if( simulation::Train->Dynamic() != nullptr ) {
|
||||
// jeśli mielismy pojazd
|
||||
if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć
|
||||
auto const *currentvehicle { simulation::Train->Dynamic() };
|
||||
auto const sameconsist {
|
||||
( targetvehicle->ctOwner == currentvehicle->Mechanik )
|
||||
|| ( targetvehicle->ctOwner == currentvehicle->ctOwner ) };
|
||||
auto const isincharge { currentvehicle->Mechanik->primary() };
|
||||
auto const aidriveractive { currentvehicle->Mechanik->AIControllFlag };
|
||||
|
||||
if( !sameconsist && isincharge ) {
|
||||
// oddajemy dotychczasowy AI
|
||||
simulation::Train->Dynamic()->Mechanik->TakeControl( true );
|
||||
}
|
||||
|
||||
if( ( !sameconsist ) // we leave behind an ai driver which should be preserved
|
||||
|| ( aidriveractive ) // we want to preserve existing ai driver
|
||||
|| ( targetvehicle->Mechanik != nullptr ) ) { // .changedynobj swaps drivers but we want a takeover not a swap
|
||||
|
||||
if( sameconsist && !aidriveractive ) {
|
||||
// we will be taking over controller in the target vehicle, so get rid of the old one
|
||||
// unless it's an active ai in which case leave it running
|
||||
SafeDelete( simulation::Train->Dynamic()->Mechanik );
|
||||
}
|
||||
// HACK: by resetting owned vehicle we can reuse dynamic==nullptr code branch below
|
||||
// TODO: refactor into utility method
|
||||
simulation::Train->DynamicSet( nullptr );
|
||||
}
|
||||
else {
|
||||
// we can simply move the 'human' controller to the new vehicle
|
||||
Global.changeDynObj = targetvehicle;
|
||||
// TODO: choose active cab based on camera's location relative to vehicle's location
|
||||
/*
|
||||
Global.changeDynObj->MoverParameters->ActiveCab = (
|
||||
Train->DynamicObject->MoverParameters->Neighbours[ exitdirection ].vehicle_end ?
|
||||
-1 :
|
||||
1 );
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
if( simulation::Train->Dynamic() == nullptr ) {
|
||||
// jeśli niczym jeszcze nie jeździlismy
|
||||
if( simulation::Train->Init( targetvehicle ) ) {
|
||||
// przejmujemy sterowanie
|
||||
if( true == Global.ctrlState ) {
|
||||
// make sure we can take over the consist
|
||||
// TODO: remove ctrl key mode once manual cab (de)activation is in place
|
||||
simulation::Train->Dynamic()->Mechanik->primary( true );
|
||||
simulation::Train->Dynamic()->MoverParameters->CabActivisation();
|
||||
}
|
||||
simulation::Train->Dynamic()->Mechanik->TakeControl( false, true );
|
||||
if( true == simulation::Train->Dynamic()->Mechanik->primary() ) {
|
||||
simulation::Train->Dynamic()->MoverParameters->CabDeactivisation( true ); // potentially left active
|
||||
simulation::Train->Dynamic()->MoverParameters->CabActivisation();
|
||||
}
|
||||
InOutKey(); // do kabiny
|
||||
}
|
||||
else {
|
||||
SafeDelete( simulation::Train ); // i nie ma czym sterować
|
||||
}
|
||||
if( simulation::Train ) {
|
||||
InOutKey(); // do kabiny
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +708,9 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
||||
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||
setup_drawing(false);
|
||||
Render_cab(vehicle, vehicle->InteriorLightLevel, false);
|
||||
Render_interior( false );
|
||||
setup_drawing(true);
|
||||
Render_interior( true );
|
||||
}
|
||||
Render_cab(vehicle, vehicle->InteriorLightLevel, true);
|
||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||
@@ -931,6 +933,104 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool opengl33_renderer::Render_interior( bool const Alpha ) {
|
||||
// TODO: early frustum based cull, camera might be pointing elsewhere
|
||||
std::vector< std::pair<float, TDynamicObject *> > dynamics;
|
||||
auto *dynamic { simulation::Train->Dynamic() };
|
||||
// draw interiors of the occupied vehicle, and all vehicles behind it with permanent coupling, in case they're open-ended
|
||||
while( dynamic != nullptr ) {
|
||||
|
||||
glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.pass_camera.position() };
|
||||
float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||
dynamics.emplace_back( squaredistance, dynamic );
|
||||
dynamic = dynamic->NextC( coupling::permanent );
|
||||
}
|
||||
// draw also interiors of permanently coupled vehicles in front, if there's any
|
||||
dynamic = simulation::Train->Dynamic()->PrevC( coupling::permanent );
|
||||
while( dynamic != nullptr ) {
|
||||
|
||||
glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.pass_camera.position() };
|
||||
float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||
dynamics.emplace_back( squaredistance, dynamic );
|
||||
dynamic = dynamic->PrevC( coupling::permanent );
|
||||
}
|
||||
if( Alpha ) {
|
||||
std::sort(
|
||||
std::begin( dynamics ), std::end( dynamics ),
|
||||
[]( std::pair<float, TDynamicObject *> const &Left, std::pair<float, TDynamicObject *> const &Right ) {
|
||||
return ( Left.first ) > ( Right.first ); } );
|
||||
}
|
||||
for( auto &dynamic : dynamics ) {
|
||||
Render_lowpoly( dynamic.second, dynamic.first, true, Alpha );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool opengl33_renderer::Render_lowpoly( TDynamicObject *Dynamic, float const Squaredistance, bool const Setup, bool const Alpha ) {
|
||||
|
||||
if( Dynamic->mdLowPolyInt == nullptr ) { return false; }
|
||||
|
||||
// low poly interior
|
||||
if( Setup ) {
|
||||
|
||||
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>( Dynamic ); //żeby nie robić cudzych animacji
|
||||
glm::dvec3 const originoffset{ Dynamic->vPosition - m_renderpass.pass_camera.position() };
|
||||
|
||||
Dynamic->ABuLittleUpdate( Squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
|
||||
|
||||
glm::mat4 mv = OpenGLMatrices.data( GL_MODELVIEW );
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
::glMultMatrixd( Dynamic->mMatrix.readArray() );
|
||||
}
|
||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||
if( false == Alpha ) {
|
||||
auto const luminance{ static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||
setup_sunlight_intensity(
|
||||
clamp( (
|
||||
Dynamic->fShade > 0.f ?
|
||||
Dynamic->fShade :
|
||||
1.f )
|
||||
- luminance,
|
||||
0.f, 1.f ) );
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), Squaredistance );
|
||||
// HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), Squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
}
|
||||
setup_sunlight_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||
}
|
||||
else {
|
||||
// Render_Alpha( Dynamic->mdLowPolyInt, Dynamic->Material(), Squaredistance );
|
||||
// HACK: some models have windows included as part of the main model instead of lowpoly
|
||||
if( Dynamic->mdModel ) {
|
||||
// main model
|
||||
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), Squaredistance );
|
||||
}
|
||||
}
|
||||
|
||||
if( Setup ) {
|
||||
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
// restore regular light level
|
||||
setup_sunlight_intensity();
|
||||
}
|
||||
|
||||
::glPopMatrix();
|
||||
|
||||
// TODO: check if this reset is needed. In theory each object should render all parts based on its own instance data anyway?
|
||||
if( Dynamic->btnOn ) {
|
||||
Dynamic->TurnOff(); // przywrócenie domyślnych pozycji submodeli
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// creates dynamic environment cubemap
|
||||
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
||||
{
|
||||
@@ -2301,23 +2401,7 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
||||
// render
|
||||
if( Dynamic->mdLowPolyInt ) {
|
||||
// low poly interior
|
||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||
auto const luminance { static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||
setup_sunlight_intensity(
|
||||
clamp( (
|
||||
Dynamic->fShade > 0.f ?
|
||||
Dynamic->fShade :
|
||||
1.f )
|
||||
- luminance,
|
||||
0.f, 1.f ) );
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||
// HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
}
|
||||
|
||||
setup_sunlight_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||
Render_lowpoly( Dynamic, squaredistance, false );
|
||||
}
|
||||
else {
|
||||
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
||||
@@ -4069,10 +4153,12 @@ bool opengl33_renderer::Init_caps()
|
||||
GLint texturesize;
|
||||
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texturesize);
|
||||
Global.iMaxTextureSize = std::min(Global.iMaxTextureSize, texturesize);
|
||||
WriteLog("texture sizes capped at " + std::to_string(Global.iMaxTextureSize) + "px");
|
||||
Global.iMaxCabTextureSize = std::min( Global.iMaxCabTextureSize, texturesize );
|
||||
WriteLog( "texture sizes capped at " + std::to_string(Global.iMaxTextureSize) + "p (" + std::to_string( Global.iMaxCabTextureSize ) + "p for cab textures)" );
|
||||
Global.CurrentMaxTextureSize = Global.iMaxTextureSize;
|
||||
m_shadowbuffersize = Global.shadowtune.map_size;
|
||||
m_shadowbuffersize = std::min(m_shadowbuffersize, texturesize);
|
||||
WriteLog("shadows map size capped at " + std::to_string(m_shadowbuffersize) + "px");
|
||||
WriteLog("shadows map size capped at " + std::to_string(m_shadowbuffersize) + "p");
|
||||
}
|
||||
Global.DynamicLightCount = std::min(Global.DynamicLightCount, 8);
|
||||
|
||||
|
||||
@@ -225,6 +225,8 @@ class opengl33_renderer : public gfx_renderer {
|
||||
void Render(TTrack *Track);
|
||||
void Render(scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last);
|
||||
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 );
|
||||
void Render(TMemCell *Memcell);
|
||||
void Render_particles();
|
||||
void Render_precipitation();
|
||||
|
||||
@@ -525,7 +525,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||
setup_drawing( false );
|
||||
Render_cab( vehicle, vehicle->InteriorLightLevel, false );
|
||||
Render_interior( false);
|
||||
setup_drawing( true );
|
||||
Render_interior( true );
|
||||
}
|
||||
Render_cab( vehicle, vehicle->InteriorLightLevel, true );
|
||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||
@@ -723,6 +725,107 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
}
|
||||
}
|
||||
|
||||
bool opengl_renderer::Render_interior( bool const Alpha ) {
|
||||
// NOTE: legacy renderer doesn't need to repaint translucent parts
|
||||
// TODO: investigate reasons (depth writing?) and duplicate in opengl33 branch
|
||||
if( Alpha ) { return false; }
|
||||
// TODO: early frustum based cull, camera might be pointing elsewhere
|
||||
std::vector< std::pair<float, TDynamicObject *> > dynamics;
|
||||
auto *dynamic { simulation::Train->Dynamic() };
|
||||
// draw interiors of the occupied vehicle, and all vehicles behind it with permanent coupling, in case they're open-ended
|
||||
while( dynamic != nullptr ) {
|
||||
|
||||
glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.camera.position() };
|
||||
float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||
dynamics.emplace_back( squaredistance, dynamic );
|
||||
dynamic = dynamic->NextC( coupling::permanent );
|
||||
}
|
||||
// draw also interiors of permanently coupled vehicles in front, if there's any
|
||||
dynamic = simulation::Train->Dynamic()->PrevC( coupling::permanent );
|
||||
while( dynamic != nullptr ) {
|
||||
|
||||
glm::dvec3 const originoffset { dynamic->vPosition - m_renderpass.camera.position() };
|
||||
float const squaredistance{ glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||
dynamics.emplace_back( squaredistance, dynamic );
|
||||
dynamic = dynamic->PrevC( coupling::permanent );
|
||||
}
|
||||
if( Alpha ) {
|
||||
std::sort(
|
||||
std::begin( dynamics ), std::end( dynamics ),
|
||||
[]( std::pair<float, TDynamicObject *> const &Left, std::pair<float, TDynamicObject *> const &Right ) {
|
||||
return ( Left.first ) > ( Right.first ); } );
|
||||
}
|
||||
for( auto &dynamic : dynamics ) {
|
||||
Render_lowpoly( dynamic.second, dynamic.first, true, Alpha );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool opengl_renderer::Render_lowpoly( TDynamicObject *Dynamic, float const Squaredistance, bool const Setup, bool const Alpha ) {
|
||||
|
||||
if( Dynamic->mdLowPolyInt == nullptr ) { return false; }
|
||||
|
||||
// low poly interior
|
||||
glm::dvec3 const originoffset { Dynamic->vPosition - m_renderpass.camera.position() };
|
||||
|
||||
if( Setup ) {
|
||||
|
||||
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>( Dynamic ); //żeby nie robić cudzych animacji
|
||||
Dynamic->ABuLittleUpdate( Squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
|
||||
::glPushMatrix();
|
||||
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
::glMultMatrixd( Dynamic->mMatrix.getArray() );
|
||||
|
||||
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
|
||||
}
|
||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||
if( false == Alpha ) {
|
||||
auto const luminance{ static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||
m_sunlight.apply_intensity(
|
||||
clamp( (
|
||||
Dynamic->fShade > 0.f ?
|
||||
Dynamic->fShade :
|
||||
1.f )
|
||||
- luminance,
|
||||
0.f, 1.f ) );
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), Squaredistance );
|
||||
// HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), Squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
}
|
||||
m_sunlight.apply_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||
}
|
||||
else {
|
||||
// Render_Alpha( Dynamic->mdLowPolyInt, Dynamic->Material(), Squaredistance );
|
||||
// HACK: some models have windows included as part of the main model instead of lowpoly
|
||||
if( Dynamic->mdModel ) {
|
||||
// main model
|
||||
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), Squaredistance );
|
||||
}
|
||||
}
|
||||
|
||||
if( Setup ) {
|
||||
|
||||
m_renderspecular = false;
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
// restore regular light level
|
||||
m_sunlight.apply_intensity();
|
||||
}
|
||||
|
||||
::glPopMatrix();
|
||||
|
||||
// TODO: check if this reset is needed. In theory each object should render all parts based on its own instance data anyway?
|
||||
if( Dynamic->btnOn ) {
|
||||
Dynamic->TurnOff(); // przywrócenie domyślnych pozycji submodeli
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// creates dynamic environment cubemap
|
||||
bool
|
||||
opengl_renderer::Render_reflections() {
|
||||
@@ -2182,25 +2285,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
|
||||
// render
|
||||
if( Dynamic->mdLowPolyInt ) {
|
||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||
auto const luminance { static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||
m_sunlight.apply_intensity(
|
||||
clamp( (
|
||||
Dynamic->fShade > 0.f ?
|
||||
Dynamic->fShade :
|
||||
1.f )
|
||||
- luminance,
|
||||
0.f, 1.f ) );
|
||||
|
||||
// low poly interior
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||
// HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
|
||||
if( Dynamic->mdLoad ) {
|
||||
// renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||
}
|
||||
|
||||
m_sunlight.apply_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||
Render_lowpoly( Dynamic, squaredistance, false );
|
||||
}
|
||||
else {
|
||||
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
||||
@@ -4078,11 +4163,13 @@ opengl_renderer::Init_caps() {
|
||||
{
|
||||
GLint texturesize;
|
||||
::glGetIntegerv( GL_MAX_TEXTURE_SIZE, &texturesize );
|
||||
Global.iMaxTextureSize = std::min( Global.iMaxTextureSize, texturesize );
|
||||
WriteLog( "Texture sizes capped at " + std::to_string( Global.iMaxTextureSize ) + " pixels" );
|
||||
Global.iMaxTextureSize = std::min(Global.iMaxTextureSize, texturesize);
|
||||
Global.iMaxCabTextureSize = std::min( Global.iMaxCabTextureSize, texturesize );
|
||||
WriteLog( "texture sizes capped at " + std::to_string(Global.iMaxTextureSize) + "p (" + std::to_string( Global.iMaxCabTextureSize ) + "p for cab textures)" );
|
||||
Global.CurrentMaxTextureSize = Global.iMaxTextureSize;
|
||||
m_shadowbuffersize = Global.shadowtune.map_size;
|
||||
m_shadowbuffersize = std::min( m_shadowbuffersize, texturesize );
|
||||
WriteLog( "Shadows map size capped at " + std::to_string( m_shadowbuffersize ) + " pixels" );
|
||||
WriteLog( "Shadows map size capped at " + std::to_string( m_shadowbuffersize ) + "p" );
|
||||
}
|
||||
// cap the number of supported lights based on hardware
|
||||
{
|
||||
|
||||
@@ -218,6 +218,10 @@ private:
|
||||
Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last );
|
||||
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 );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
void
|
||||
|
||||
@@ -333,7 +333,7 @@ sound_source::play( int const Flags ) {
|
||||
|
||||
// initialize emitter-specific pitch variation if it wasn't yet set
|
||||
if( m_pitchvariation == 0.f ) {
|
||||
m_pitchvariation = 0.01f * static_cast<float>( Random( 97.5, 102.5 ) );
|
||||
m_pitchvariation = 1.f; // 0.01f * static_cast<float>( Random( 97.5, 102.5 ) );
|
||||
}
|
||||
/*
|
||||
if( ( ( m_flags & sound_flags::exclusive ) != 0 )
|
||||
|
||||
Reference in New Issue
Block a user