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
|
// 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 ) {
|
if( fVoltage < mvControlling->EnginePowerSource.CollectorParameters.MinV ) {
|
||||||
// gdy rozłączenie WS z powodu niskiego napięcia
|
// gdy rozłączenie WS z powodu niskiego napięcia
|
||||||
if( fActionTime >= 0 ) {
|
if( fActionTime >= 0 ) {
|
||||||
|
|||||||
@@ -4185,9 +4185,9 @@ void TDynamicObject::RenderSounds() {
|
|||||||
&& ( MoverParameters->Vel > 5.0 ) ) {
|
&& ( MoverParameters->Vel > 5.0 ) ) {
|
||||||
// scale volume with curve radius and vehicle speed
|
// scale volume with curve radius and vehicle speed
|
||||||
volume =
|
volume =
|
||||||
MoverParameters->AccN * MoverParameters->AccN
|
MoverParameters->AccN // * MoverParameters->AccN
|
||||||
* interpolate(
|
* interpolate(
|
||||||
0.0, 1.0,
|
0.5, 1.0,
|
||||||
clamp(
|
clamp(
|
||||||
MoverParameters->Vel / 40.0,
|
MoverParameters->Vel / 40.0,
|
||||||
0.0, 1.0 ) )
|
0.0, 1.0 ) )
|
||||||
|
|||||||
26
Globals.cpp
26
Globals.cpp
@@ -293,15 +293,23 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
Parser.getTokens(1, false);
|
Parser.getTokens(1, false);
|
||||||
int size;
|
int size;
|
||||||
Parser >> size;
|
Parser >> size;
|
||||||
if (size <= 64) { iMaxTextureSize = 64; }
|
auto p2size { 64 }; // start with 64px
|
||||||
else if (size <= 128) { iMaxTextureSize = 128; }
|
while( (p2size <= 16384 ) && ( p2size <= size ) ) {
|
||||||
else if (size <= 256) { iMaxTextureSize = 256; }
|
iMaxTextureSize = p2size;
|
||||||
else if (size <= 512) { iMaxTextureSize = 512; }
|
p2size = p2size << 1;
|
||||||
else if (size <= 1024) { iMaxTextureSize = 1024; }
|
}
|
||||||
else if (size <= 2048) { iMaxTextureSize = 2048; }
|
}
|
||||||
else if (size <= 4096) { iMaxTextureSize = 4096; }
|
else if (token == "maxcabtexturesize")
|
||||||
else if (size <= 8192) { iMaxTextureSize = 8192; }
|
{
|
||||||
else { iMaxTextureSize = 16384; }
|
// 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")
|
else if (token == "movelight")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ struct global_settings {
|
|||||||
std::string asCurrentSceneryPath{ "scenery/" };
|
std::string asCurrentSceneryPath{ "scenery/" };
|
||||||
std::string asCurrentTexturePath{ szTexturePath };
|
std::string asCurrentTexturePath{ szTexturePath };
|
||||||
std::string asCurrentDynamicPath;
|
std::string asCurrentDynamicPath;
|
||||||
|
int CurrentMaxTextureSize{ 4096 };
|
||||||
bool GfxFramebufferSRGB { true };
|
bool GfxFramebufferSRGB { true };
|
||||||
// settings
|
// settings
|
||||||
// filesystem
|
// filesystem
|
||||||
@@ -129,6 +130,7 @@ struct global_settings {
|
|||||||
float AnisotropicFiltering{ 8.f }; // requested level of anisotropic filtering. TODO: move it to renderer object
|
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
|
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
|
||||||
GLint iMaxTextureSize{ 4096 }; // maksymalny rozmiar tekstury
|
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
|
int iMultisampling{ 2 }; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||||
bool bSmoothTraction{ true }; // wygładzanie drutów starym sposobem
|
bool bSmoothTraction{ true }; // wygładzanie drutów starym sposobem
|
||||||
float SplineFidelity{ 1.f }; // determines segment size during conversion of splines to geometry
|
float SplineFidelity{ 1.f }; // determines segment size during conversion of splines to geometry
|
||||||
|
|||||||
@@ -1544,7 +1544,7 @@ public:
|
|||||||
bool RunInternalCommand();
|
bool RunInternalCommand();
|
||||||
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation);
|
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation);
|
||||||
bool CabActivisation(void);
|
bool CabActivisation(void);
|
||||||
bool CabDeactivisation(void);
|
bool CabDeactivisation( bool const Force = false );
|
||||||
|
|
||||||
/*! funkcje zwiekszajace/zmniejszajace nastawniki*/
|
/*! funkcje zwiekszajace/zmniejszajace nastawniki*/
|
||||||
/*! glowny nastawnik:*/
|
/*! glowny nastawnik:*/
|
||||||
|
|||||||
@@ -1728,7 +1728,7 @@ void TMoverParameters::HeatingCheck( double const Timestep ) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TPowerSource::Main: {
|
case TPowerSource::Main: {
|
||||||
voltage = ( true == Mains ? PantographVoltage : 0.0 );
|
voltage = ( true == Mains ? std::max( GetAnyTrainsetVoltage(), PantographVoltage ) : 0.0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -2355,11 +2355,11 @@ bool TMoverParameters::CabActivisation(void)
|
|||||||
// Q: 20160710
|
// Q: 20160710
|
||||||
// wyłączenie rozrządu
|
// wyłączenie rozrządu
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
bool TMoverParameters::CabDeactivisation(void)
|
bool TMoverParameters::CabDeactivisation( bool const Force )
|
||||||
{
|
{
|
||||||
bool OK = false;
|
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)
|
if (OK)
|
||||||
{
|
{
|
||||||
CabNo = 0;
|
CabNo = 0;
|
||||||
@@ -3736,7 +3736,7 @@ void TMoverParameters::CompressorCheck(double dt)
|
|||||||
if( CompressorPower == 2 ) {
|
if( CompressorPower == 2 ) {
|
||||||
CompressorAllow = ConverterAllow;
|
CompressorAllow = ConverterAllow;
|
||||||
}
|
}
|
||||||
|
// TODO: clean up compressor CompressorFlag state code, large parts are cloned and an utter mess
|
||||||
if (MaxCompressorF - MinCompressorF < 0.0001) {
|
if (MaxCompressorF - MinCompressorF < 0.0001) {
|
||||||
// TODO: investigate purpose of this branch and whether it can be removed as it duplicates later code
|
// TODO: investigate purpose of this branch and whether it can be removed as it duplicates later code
|
||||||
if( ( true == CompressorAllow )
|
if( ( true == CompressorAllow )
|
||||||
@@ -3802,10 +3802,9 @@ void TMoverParameters::CompressorCheck(double dt)
|
|||||||
CompressorFlag = (
|
CompressorFlag = (
|
||||||
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
||||||
&& ( CompressorAllowLocal )
|
&& ( CompressorAllowLocal )
|
||||||
&& ( Mains )
|
&& ( CompressorPower == 0 ? Mains :
|
||||||
&& ( ( ConverterFlag )
|
CompressorPower == 3 ? Mains :
|
||||||
|| ( CompressorPower == 0 )
|
ConverterFlag ) );
|
||||||
|| ( CompressorPower == 3 ) ) );
|
|
||||||
|
|
||||||
if( Compressor > MaxCompressorF ) {
|
if( Compressor > MaxCompressorF ) {
|
||||||
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
|
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
|
||||||
@@ -3876,12 +3875,11 @@ void TMoverParameters::CompressorCheck(double dt)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CompressorFlag = (
|
CompressorFlag = (
|
||||||
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
( ( CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
|
||||||
&& ( CompressorAllowLocal )
|
&& ( CompressorAllowLocal )
|
||||||
&& ( Mains )
|
&& ( CompressorPower == 0 ? Mains :
|
||||||
&& ( ( ConverterFlag )
|
CompressorPower == 3 ? Mains :
|
||||||
|| ( CompressorPower == 0 )
|
ConverterFlag ) );
|
||||||
|| ( CompressorPower == 3 ) ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: crude way to enforce simultaneous activation of compressors in multi-unit setups
|
// 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 blockSize = ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16 );
|
||||||
int offset = 0;
|
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
|
// pomijanie zbyt dużych mipmap, jeśli wymagane jest ograniczenie rozmiaru
|
||||||
offset += ( ( data_width + 3 ) / 4 ) * ( ( data_height + 3 ) / 4 ) * blockSize;
|
offset += ( ( data_width + 3 ) / 4 ) * ( ( data_height + 3 ) / 4 ) * blockSize;
|
||||||
data_width /= 2;
|
data_width /= 2;
|
||||||
@@ -714,7 +714,7 @@ opengl_texture::load_TGA() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
downsize( GL_BGRA );
|
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
|
// for non-square textures there's currently possibility the scaling routine will have to abort
|
||||||
// before it gets all work done
|
// before it gets all work done
|
||||||
data_state = resource_state::failed;
|
data_state = resource_state::failed;
|
||||||
@@ -1054,7 +1054,7 @@ opengl_texture::set_filtering() const {
|
|||||||
void
|
void
|
||||||
opengl_texture::downsize( GLuint const Format ) {
|
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
|
// 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
|
// 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
|
// TODO: replace with proper scaling function once we have image middleware in place
|
||||||
|
|||||||
47
Train.cpp
47
Train.cpp
@@ -439,8 +439,15 @@ TTrain::TTrain() {
|
|||||||
bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||||
{ // powiązanie ręcznego sterowania kabiną z pojazdem
|
{ // powiązanie ręcznego sterowania kabiną z pojazdem
|
||||||
if( NewDynamicObject->Mechanik == nullptr ) {
|
if( NewDynamicObject->Mechanik == nullptr ) {
|
||||||
|
/*
|
||||||
ErrorLog( "Bad config: can't take control of inactive vehicle \"" + NewDynamicObject->asName + "\"" );
|
ErrorLog( "Bad config: can't take control of inactive vehicle \"" + NewDynamicObject->asName + "\"" );
|
||||||
return false;
|
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);
|
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!
|
fMainRelayTimer = 0; // Hunter, do k...y nędzy, ustawiaj wartości początkowe zmiennych!
|
||||||
|
|
||||||
if( false == LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
|
iCabn = (
|
||||||
return false;
|
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
|
// Ra: taka proteza - przesłanie kierunku do członów connected
|
||||||
if (mvControlled->ActiveDir > 0)
|
if (mvControlled->ActiveDir > 0)
|
||||||
{ // było do przodu
|
{ // było do przodu
|
||||||
@@ -4434,14 +4450,33 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
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.GetDesiredValue() < 0.5 ) {
|
if( item.type() == TGaugeType::push ) {
|
||||||
|
// impulse switch
|
||||||
// turn on
|
// turn on
|
||||||
// visual feedback
|
// visual feedback
|
||||||
item.UpdateValue( 1.0 );
|
item.UpdateValue( 1.0 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// two-state switch
|
||||||
|
if( item.GetDesiredValue() < 0.5 ) {
|
||||||
|
// turn on
|
||||||
|
// visual feedback
|
||||||
|
item.UpdateValue( 1.0 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// turn off
|
||||||
|
// visual feedback
|
||||||
|
item.UpdateValue( 0.0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( Command.action == GLFW_RELEASE ) {
|
||||||
|
|
||||||
|
if( item.type() == TGaugeType::push ) {
|
||||||
|
// impulse switch
|
||||||
// turn off
|
// turn off
|
||||||
// visual feedback
|
// visual feedback
|
||||||
item.UpdateValue( 0.0 );
|
item.UpdateValue( 0.0 );
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
#include "simulation.h"
|
||||||
|
#include "Train.h"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
@@ -333,6 +335,7 @@ openal_renderer::update( double const Deltatime ) {
|
|||||||
::alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
|
::alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
|
||||||
// velocity
|
// velocity
|
||||||
if( Deltatime > 0 ) {
|
if( Deltatime > 0 ) {
|
||||||
|
/*
|
||||||
glm::dvec3 const listenerposition { Global.pCamera.Pos };
|
glm::dvec3 const listenerposition { Global.pCamera.Pos };
|
||||||
glm::dvec3 const listenermovement { listenerposition - m_listenerposition };
|
glm::dvec3 const listenermovement { listenerposition - m_listenerposition };
|
||||||
m_listenerposition = 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
|
glm::length( listenermovement ) < 1000.0 ? // large jumps are typically camera changes
|
||||||
limit_velocity( listenermovement / Deltatime ) :
|
limit_velocity( listenermovement / Deltatime ) :
|
||||||
glm::vec3() );
|
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 ) ) );
|
::alListenerfv( AL_VELOCITY, reinterpret_cast<ALfloat const *>( glm::value_ptr( m_listenervelocity ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,8 +147,16 @@ private:
|
|||||||
ALCdevice * m_device { nullptr };
|
ALCdevice * m_device { nullptr };
|
||||||
ALCcontext * m_context { nullptr };
|
ALCcontext * m_context { nullptr };
|
||||||
bool m_ready { false }; // renderer is initialized and functional
|
bool m_ready { false }; // renderer is initialized and functional
|
||||||
|
/*
|
||||||
glm::dvec3 m_listenerposition;
|
glm::dvec3 m_listenerposition;
|
||||||
|
*/
|
||||||
glm::vec3 m_listenervelocity;
|
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;
|
buffer_manager m_buffers;
|
||||||
// TBD: list of sources as vector, sorted by distance, for openal implementations with limited number of active sources?
|
// TBD: list of sources as vector, sorted by distance, for openal implementations with limited number of active sources?
|
||||||
|
|||||||
101
drivermode.cpp
101
drivermode.cpp
@@ -188,6 +188,14 @@ driver_mode::update() {
|
|||||||
if( Global.changeDynObj ) {
|
if( Global.changeDynObj ) {
|
||||||
// ABu zmiana pojazdu - przejście do innego
|
// ABu zmiana pojazdu - przejście do innego
|
||||||
ChangeDynamic();
|
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 ) {
|
if( simulation::Train != nullptr ) {
|
||||||
@@ -708,7 +716,6 @@ driver_mode::OnKeyDown(int cKey) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GLFW_KEY_F4: {
|
case GLFW_KEY_F4: {
|
||||||
|
|
||||||
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
||||||
@@ -722,46 +729,76 @@ driver_mode::OnKeyDown(int cKey) {
|
|||||||
break;
|
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 )
|
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
|
// 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 ) {
|
if( simulation::Train == nullptr ) {
|
||||||
simulation::Train = new TTrain(); // jeśli niczym jeszcze nie jeździlismy
|
simulation::Train = new TTrain(); // jeśli niczym jeszcze nie jeździlismy
|
||||||
}
|
}
|
||||||
if( simulation::Train->Init( tmp ) ) {
|
if( simulation::Train->Dynamic() != nullptr ) {
|
||||||
// przejmujemy sterowanie
|
// jeśli mielismy pojazd
|
||||||
if( true == Global.ctrlState ) {
|
if( simulation::Train->Dynamic()->Mechanik ) { // na skutek jakiegoś błędu może czasem zniknąć
|
||||||
// make sure we can take over the consist
|
auto const *currentvehicle { simulation::Train->Dynamic() };
|
||||||
// TODO: remove ctrl key mode once manual cab (de)activation is in place
|
auto const sameconsist {
|
||||||
simulation::Train->Dynamic()->Mechanik->primary( true );
|
( targetvehicle->ctOwner == currentvehicle->Mechanik )
|
||||||
simulation::Train->Dynamic()->MoverParameters->CabActivisation();
|
|| ( 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 );
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
simulation::Train->Dynamic()->Mechanik->TakeControl( false, true );
|
|
||||||
}
|
}
|
||||||
else {
|
if( simulation::Train->Dynamic() == nullptr ) {
|
||||||
SafeDelete( simulation::Train ); // i nie ma czym sterować
|
// jeśli niczym jeszcze nie jeździlismy
|
||||||
}
|
if( simulation::Train->Init( targetvehicle ) ) {
|
||||||
if( simulation::Train ) {
|
// przejmujemy sterowanie
|
||||||
InOutKey(); // do kabiny
|
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()->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ć
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
Render_cab(vehicle, vehicle->InteriorLightLevel, false);
|
Render_cab(vehicle, vehicle->InteriorLightLevel, false);
|
||||||
|
Render_interior( false );
|
||||||
setup_drawing(true);
|
setup_drawing(true);
|
||||||
|
Render_interior( true );
|
||||||
}
|
}
|
||||||
Render_cab(vehicle, vehicle->InteriorLightLevel, true);
|
Render_cab(vehicle, vehicle->InteriorLightLevel, true);
|
||||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
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
|
// creates dynamic environment cubemap
|
||||||
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
||||||
{
|
{
|
||||||
@@ -2301,24 +2401,8 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
// render
|
// render
|
||||||
if( Dynamic->mdLowPolyInt ) {
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
// low poly interior
|
// low poly interior
|
||||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
Render_lowpoly( Dynamic, squaredistance, false );
|
||||||
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 {
|
else {
|
||||||
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
||||||
if( Dynamic->mdLoad ) {
|
if( Dynamic->mdLoad ) {
|
||||||
@@ -4069,10 +4153,12 @@ bool opengl33_renderer::Init_caps()
|
|||||||
GLint texturesize;
|
GLint texturesize;
|
||||||
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texturesize);
|
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texturesize);
|
||||||
Global.iMaxTextureSize = std::min(Global.iMaxTextureSize, 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 );
|
||||||
m_shadowbuffersize = Global.shadowtune.map_size;
|
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);
|
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);
|
Global.DynamicLightCount = std::min(Global.DynamicLightCount, 8);
|
||||||
|
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ class opengl33_renderer : public gfx_renderer {
|
|||||||
void Render(TTrack *Track);
|
void Render(TTrack *Track);
|
||||||
void Render(scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last);
|
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_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(TMemCell *Memcell);
|
||||||
void Render_particles();
|
void Render_particles();
|
||||||
void Render_precipitation();
|
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
|
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||||
setup_drawing( false );
|
setup_drawing( false );
|
||||||
Render_cab( vehicle, vehicle->InteriorLightLevel, false );
|
Render_cab( vehicle, vehicle->InteriorLightLevel, false );
|
||||||
|
Render_interior( false);
|
||||||
setup_drawing( true );
|
setup_drawing( true );
|
||||||
|
Render_interior( true );
|
||||||
}
|
}
|
||||||
Render_cab( vehicle, vehicle->InteriorLightLevel, true );
|
Render_cab( vehicle, vehicle->InteriorLightLevel, true );
|
||||||
if( vehicle->InteriorLightLevel > 0.f ) {
|
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
|
// creates dynamic environment cubemap
|
||||||
bool
|
bool
|
||||||
opengl_renderer::Render_reflections() {
|
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
|
m_renderspecular = true; // vehicles are rendered with specular component. static models without, at least for the time being
|
||||||
// render
|
// render
|
||||||
if( Dynamic->mdLowPolyInt ) {
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
Render_lowpoly( Dynamic, squaredistance, false );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
// 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;
|
GLint texturesize;
|
||||||
::glGetIntegerv( GL_MAX_TEXTURE_SIZE, &texturesize );
|
::glGetIntegerv( GL_MAX_TEXTURE_SIZE, &texturesize );
|
||||||
Global.iMaxTextureSize = std::min( Global.iMaxTextureSize, texturesize );
|
Global.iMaxTextureSize = std::min(Global.iMaxTextureSize, texturesize);
|
||||||
WriteLog( "Texture sizes capped at " + std::to_string( Global.iMaxTextureSize ) + " pixels" );
|
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 = Global.shadowtune.map_size;
|
||||||
m_shadowbuffersize = std::min( m_shadowbuffersize, texturesize );
|
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
|
// 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 );
|
Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last );
|
||||||
bool
|
bool
|
||||||
Render_cab( TDynamicObject const *Dynamic, float const Lightlevel, bool const Alpha = false );
|
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
|
void
|
||||||
Render( TMemCell *Memcell );
|
Render( TMemCell *Memcell );
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ sound_source::play( int const Flags ) {
|
|||||||
|
|
||||||
// initialize emitter-specific pitch variation if it wasn't yet set
|
// initialize emitter-specific pitch variation if it wasn't yet set
|
||||||
if( m_pitchvariation == 0.f ) {
|
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 )
|
if( ( ( m_flags & sound_flags::exclusive ) != 0 )
|
||||||
|
|||||||
Reference in New Issue
Block a user