diff --git a/Driver.cpp b/Driver.cpp index 1aecbc0e..5c8b7a10 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2665,12 +2665,14 @@ bool TController::PrepareEngine() bool TController::ReleaseEngine() { if( mvOccupied->Vel > 0.01 ) { - // TBD, TODO: make a dedicated braking procedure out of it for potential reuse VelDesired = 0.0; AccDesired = std::min( AccDesired, -1.25 ); // hamuj solidnie - ReactionTime = 0.1; - ZeroSpeed(); - IncBrake(); + if( true == AIControllFlag ) { + // TBD, TODO: make a dedicated braking procedure out of it for potential reuse + ZeroSpeed(); + IncBrake(); + ReactionTime = 0.1; + } // don't bother with the rest until we're standing still return false; } @@ -2936,19 +2938,36 @@ bool TController::IncBrakeEIM() bool OK = false; switch (mvOccupied->EIMCtrlType) { - case 0: - OK = mvOccupied->IncLocalBrakeLevel(1); - break; - case 1: - OK = mvOccupied->MainCtrlPos > 0; - if (OK) - mvOccupied->MainCtrlPos = 0; - break; - case 2: - OK = mvOccupied->MainCtrlPos > 1; - if (OK) - mvOccupied->MainCtrlPos = 1; - break; + case 0: { + OK = mvOccupied->IncLocalBrakeLevel( 1 ); + break; + } + case 1: { + OK = mvOccupied->MainCtrlPos > 0; + if( OK ) + mvOccupied->MainCtrlPos = 0; + break; + } + case 2: { + OK = mvOccupied->MainCtrlPos > 1; + if( OK ) + mvOccupied->MainCtrlPos = 1; + break; + } + case 3: { + if( mvOccupied->UniCtrlIntegratedLocalBrakeCtrl ) { + OK = mvOccupied->MainCtrlPos > 0; + if( OK ) + mvOccupied->MainCtrlPos = 0; + } + else { + OK = mvOccupied->IncLocalBrakeLevel( 1 ); + } + break; + } + default: { + break; + } } return OK; } @@ -3041,7 +3060,12 @@ bool TController::DecBrakeEIM() if (OK) mvOccupied->MainCtrlPos = 3; break; - } + case 3: + OK = mvOccupied->MainCtrlPos < mvOccupied->MaxMainCtrlPosNoDirChange; + if( OK ) + mvOccupied->MainCtrlPos = mvOccupied->MaxMainCtrlPosNoDirChange; + break; + } return OK; } @@ -3188,7 +3212,9 @@ bool TController::IncSpeed() if (!mvControlling->FuseFlag) if (Ready || (iDrivigFlags & movePress)) //{(BrakePress<=0.01*MaxBrakePress)} { - OK = mvControlling->IncMainCtrl(1); + OK = IncSpeedEIM(); + if( !OK ) + OK = mvControlling->IncMainCtrl(1); if (!OK) OK = mvControlling->IncScndCtrl(1); } diff --git a/DynObj.cpp b/DynObj.cpp index 2a91b271..e35b3a4a 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3801,12 +3801,14 @@ void TDynamicObject::RenderSounds() { // NBMX dzwiek przetwornicy if( MoverParameters->ConverterFlag ) { frequency = ( - MoverParameters->EngineType == TEngineType::ElectricSeriesMotor ? - ( MoverParameters->PantographVoltage / MoverParameters->NominalVoltage ) * MoverParameters->RList[ MoverParameters->RlistSize ].Mn : - 1.0 ); + MoverParameters->EngineType != TEngineType::ElectricSeriesMotor ? + 1.0 : + MoverParameters->PantographVoltage > 0.0 ? + MoverParameters->PantographVoltage / ( MoverParameters->NominalVoltage * MoverParameters->RList[ MoverParameters->RlistSize ].Mn ) : + 1.0 ); frequency = sConverter.m_frequencyoffset + sConverter.m_frequencyfactor * frequency; sConverter - .pitch( clamp( frequency, 0.5, 1.25 ) ) // arbitrary limits ) + .pitch( clamp( frequency, 0.75, 1.25 ) ) // arbitrary limits ) .play( sound_flags::exclusive | sound_flags::looping ); } else { @@ -4208,13 +4210,13 @@ void TDynamicObject::RenderSounds() { && ( MoverParameters->Vel > 5.0 ) ) { // scale volume with curve radius and vehicle speed volume = - MoverParameters->AccN // * MoverParameters->AccN + std::abs( MoverParameters->AccN ) // * MoverParameters->AccN * interpolate( 0.5, 1.0, clamp( MoverParameters->Vel / 40.0, 0.0, 1.0 ) ) - * ( MyTrack->eType == tt_Switch ? 100.0 : 1.0 ); + * ( ( ( MyTrack->eType == tt_Switch ) && ( std::abs( ts.R ) < 1500.0 ) ) ? 100.0 : 1.0 ); } else { volume = 0; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index b1207669..1ea00f90 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2189,6 +2189,7 @@ int TMoverParameters::MainCtrlNoPowerPos() const { switch( EIMCtrlType ) { case 1: { return 3; } case 2: { return 3; } + case 3: { return 3; } default: { return 0; } } } @@ -10775,14 +10776,24 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C if (Command == "MainCtrl") { - if (MainCtrlPosNo >= floor(CValue1)) - MainCtrlPos = static_cast(floor(CValue1)); + if( MainCtrlPosNo >= floor( CValue1 ) ) { + MainCtrlPos = static_cast( floor( CValue1 ) ); + if( DelayCtrlFlag ) { + if( ( LastRelayTime >= InitialCtrlDelay ) && ( MainCtrlPos == 1 ) ) + LastRelayTime = 0; + } + else if( LastRelayTime > CtrlDelay ) + LastRelayTime = 0; + } OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "ScndCtrl") { - if (ScndCtrlPosNo >= floor(CValue1)) - ScndCtrlPos = static_cast(floor(CValue1)); + if( ScndCtrlPosNo >= floor( CValue1 ) ) { + ScndCtrlPos = static_cast( floor( CValue1 ) ); + if( LastRelayTime > CtrlDelay ) + LastRelayTime = 0; + } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } /* else if command='BrakeCtrl' then diff --git a/geometrybank.cpp b/geometrybank.cpp index 3cc68cbd..ac8448a6 100644 --- a/geometrybank.cpp +++ b/geometrybank.cpp @@ -212,10 +212,10 @@ geometry_bank::append( gfx::vertex_array &Vertices, gfx::geometry_handle const & } // draws geometry stored in specified chunk -void +std::size_t geometry_bank::draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { // template method implementation - draw_( Geometry, Units, Streams ); + return draw_( Geometry, Units, Streams ); } // frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time @@ -283,7 +283,7 @@ geometrybank_manager::draw( gfx::geometry_handle const &Geometry, unsigned int c auto &bankrecord = bank( Geometry ); bankrecord.second = m_garbagecollector.timestamp(); - bankrecord.first->draw( Geometry, m_units, Streams ); + m_primitivecount += bankrecord.first->draw( Geometry, m_units, Streams ); } // provides direct access to vertex data of specfied chunk diff --git a/geometrybank.h b/geometrybank.h index d3c14007..1bfd982d 100644 --- a/geometrybank.h +++ b/geometrybank.h @@ -97,12 +97,14 @@ public: // adds supplied vertex data at the end of specified chunk auto append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) -> bool; // draws geometry stored in specified chunk - void draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ); + auto draw( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) -> std::size_t; // draws geometry stored in supplied list of chunks template - void draw( Iterator_ First, Iterator_ Last, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) { + auto draw( Iterator_ First, Iterator_ Last, gfx::stream_units const &Units, unsigned int const Streams = basic_streams ) ->std::size_t { + std::size_t count { 0 }; while( First != Last ) { - draw( *First, Units, Streams ); ++First; } } + count += draw( *First, Units, Streams ); ++First; } + return count; } // frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time void release(); // provides direct access to vertex data of specfied chunk @@ -141,7 +143,7 @@ private: // replace() subclass details virtual void replace_( gfx::geometry_handle const &Geometry ) = 0; // draw() subclass details - virtual void draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) = 0; + virtual auto draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) -> std::size_t = 0; // resource release subclass details virtual void release_() = 0; }; @@ -177,6 +179,9 @@ public: auto vertices( gfx::geometry_handle const &Geometry ) const -> gfx::vertex_array const &; // sets target texture unit for the texture data stream auto units() -> gfx::stream_units & { return m_units; } + // provides access to primitives count + auto primitives_count() const -> std::size_t const & { return m_primitivecount; } + auto primitives_count() -> std::size_t & { return m_primitivecount; } private: // types: @@ -200,6 +205,8 @@ private: auto bank( gfx::geometry_handle const Geometry ) const -> geometrybanktimepointpair_sequence::value_type const & { return m_geometrybanks[ Geometry.bank - 1 ]; } +// members: + std::size_t m_primitivecount { 0 }; // number of drawn primitives }; } // namespace gfx \ No newline at end of file diff --git a/material.cpp b/material.cpp index 2b2fae30..ca1ee332 100644 --- a/material.cpp +++ b/material.cpp @@ -49,6 +49,8 @@ std::map texture_bindings { void opengl_material::finalize(bool Loadnow) { + is_good = true; + if (parse_info) { for (auto it : parse_info->tex_mapping) @@ -59,10 +61,13 @@ void opengl_material::finalize(bool Loadnow) if (key.size() > 0 && key[0] != '_') { size_t num = std::stoi(key) - 1; - if (num < gl::MAX_TEXTURES) + if (num < gl::MAX_TEXTURES) { textures[num] = GfxRenderer->Fetch_Texture(value, Loadnow); - else + } + else { log_error("invalid texture binding: " + std::to_string(num)); + is_good = false; + } } else if (key.size() > 2) { @@ -78,10 +83,13 @@ void opengl_material::finalize(bool Loadnow) } else { log_error( "unknown texture binding: " + key ); + is_good = false; } } - else + else { log_error("unrecognized texture binding: " + key); + is_good = false; + } } if (!shader) @@ -103,8 +111,10 @@ void opengl_material::finalize(bool Loadnow) } } - if (!shader) + if( !shader ) { + is_good = false; return; + } for (auto it : parse_info->param_mapping) { @@ -114,10 +124,13 @@ void opengl_material::finalize(bool Loadnow) if (key.size() > 1 && key[0] != '_') { size_t num = std::stoi(key) - 1; - if (num < gl::MAX_PARAMS) + if (num < gl::MAX_PARAMS) { params[num] = value; - else + } + else { log_error("invalid param binding: " + std::to_string(num)); + is_good = false; + } } else if (key.size() > 2) { @@ -129,18 +142,24 @@ void opengl_material::finalize(bool Loadnow) for (size_t i = 0; i < entry.size; i++) params[entry.location][entry.offset + i] = value[i]; } - else + else { log_error("unknown param binding: " + key); + is_good = false; + } } - else + else { log_error("unrecognized param binding: " + key); + is_good = false; + } } parse_info.reset(); } - if (!shader) - return; + if( !shader ) { + is_good = false; + return; + } for (auto it : shader->param_conf) { @@ -169,10 +188,13 @@ void opengl_material::finalize(bool Loadnow) { gl::shader::texture_entry &entry = it.second; texture_handle handle = textures[entry.id]; - if (handle) + if (handle) { GfxRenderer->Texture(handle).set_components_hint((GLint)entry.components); - else + } + else { log_error("missing texture: " + it.first); + is_good = false; + } } } diff --git a/material.h b/material.h index cf6a44ce..3b447fdc 100644 --- a/material.h +++ b/material.h @@ -40,6 +40,8 @@ struct opengl_material { void finalize(bool Loadnow); float get_or_guess_opacity() const; bool is_translucent() const; +// members + bool is_good { false }; // indicates material was compiled without failure private: // methods diff --git a/opengl33geometrybank.cpp b/opengl33geometrybank.cpp index 78324703..07b3adad 100644 --- a/opengl33geometrybank.cpp +++ b/opengl33geometrybank.cpp @@ -93,7 +93,7 @@ void opengl33_vaogeometrybank::setup_buffer() // draw() subclass details // NOTE: units and stream parameters are unused, but they're part of (legacy) interface // TBD: specialized bank/manager pair without the cruft? -void +std::size_t opengl33_vaogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { setup_buffer(); @@ -101,7 +101,7 @@ opengl33_vaogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stre auto &chunkrecord = m_chunkrecords.at(Geometry.chunk - 1); // sanity check; shouldn't be needed but, eh if( chunkrecord.size == 0 ) - return; + return 0; auto const &chunk = gfx::geometry_bank::chunk( Geometry ); if( false == chunkrecord.is_good ) { // we may potentially need to upload new buffer data before we can draw it @@ -113,6 +113,12 @@ opengl33_vaogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stre // render m_vao->bind(); ::glDrawArrays( chunk.type, chunkrecord.offset, chunkrecord.size ); + + switch( chunk.type ) { + case GL_TRIANGLES: { return chunkrecord.size / 3; } + case GL_TRIANGLE_STRIP: { return chunkrecord.size - 2; } + default: { return 0; } + } } // release () subclass details diff --git a/opengl33geometrybank.h b/opengl33geometrybank.h index 6ea4ed43..53432198 100644 --- a/opengl33geometrybank.h +++ b/opengl33geometrybank.h @@ -48,8 +48,8 @@ private: void replace_( gfx::geometry_handle const &Geometry ) override; // draw() subclass details - void - draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override; + auto + draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) -> std::size_t override; // release() subclass details void release_() override; diff --git a/opengl33renderer.cpp b/opengl33renderer.cpp index aeac2497..31ef48ef 100644 --- a/opengl33renderer.cpp +++ b/opengl33renderer.cpp @@ -438,6 +438,7 @@ bool opengl33_renderer::Render() m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_stats = debug_stats(); + m_geometry.primitives_count() = 0; for (auto &viewport : m_viewports) { Render_pass(*viewport, rendermode::color); @@ -468,7 +469,8 @@ bool opengl33_renderer::Render() shadowstats += shadowpass.draw_stats; } m_debugstatstext = - "vehicles: " + to_string( m_colorpass.draw_stats.dynamics, 7 ) + " +" + to_string( shadowstats.dynamics, 7 ) + "triangles: " + to_string( static_cast(m_geometry.primitives_count()), 7 ) + "\n" + + "vehicles: " + to_string( m_colorpass.draw_stats.dynamics, 7 ) + " +" + to_string( shadowstats.dynamics, 7 ) + " =" + to_string( m_colorpass.draw_stats.dynamics + shadowstats.dynamics, 7 ) + "\n" + "models: " + to_string( m_colorpass.draw_stats.models, 7 ) + " +" + to_string( shadowstats.models, 7 ) + " =" + to_string( m_colorpass.draw_stats.models + shadowstats.models, 7 ) + "\n" @@ -1692,6 +1694,14 @@ void opengl33_renderer::Bind_Material(material_handle const Material, TSubModel { auto &material = m_materials.material(Material); + if( false == material.is_good ) { + // use failure indicator instead + if( Material != m_invalid_material ) { + Bind_Material( m_invalid_material ); + } + return; + } + memcpy(&model_ubs.param[0], &material.params[0], sizeof(model_ubs.param)); for (size_t i = 0; i < material.params_state.size(); i++) diff --git a/opengl33renderer.h b/opengl33renderer.h index e5fea87e..755cd8dd 100644 --- a/opengl33renderer.h +++ b/opengl33renderer.h @@ -155,6 +155,7 @@ class opengl33_renderer : public gfx_renderer { int lines{0}; int particles{0}; int drawcalls{0}; + int triangles{0}; debug_stats& operator+=( const debug_stats& Right ) { dynamics += Right.dynamics; diff --git a/openglgeometrybank.cpp b/openglgeometrybank.cpp index ad58db98..53052c6e 100644 --- a/openglgeometrybank.cpp +++ b/openglgeometrybank.cpp @@ -46,14 +46,14 @@ opengl_vbogeometrybank::replace_( gfx::geometry_handle const &Geometry ) { } // draw() subclass details -void +std::size_t opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { setup_buffer(); auto &chunkrecord { m_chunkrecords[ Geometry.chunk - 1 ] }; // sanity check; shouldn't be needed but, eh - if( chunkrecord.size == 0 ) { return; } + if( chunkrecord.size == 0 ) { return 0; } // setup... if( m_activebuffer != m_buffer ) { bind_buffer(); @@ -80,6 +80,11 @@ opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream ::glDisableClientState( GL_TEXTURE_COORD_ARRAY ); ::glBindBuffer( GL_ARRAY_BUFFER, 0 ); m_activebuffer = 0; */ + switch( chunk.type ) { + case GL_TRIANGLES: { return chunkrecord.size / 3; } + case GL_TRIANGLE_STRIP: { return chunkrecord.size - 2; } + default: { return 0; } + } } // release () subclass details @@ -231,12 +236,13 @@ opengl_dlgeometrybank::replace_( gfx::geometry_handle const &Geometry ) { } // draw() subclass details -void +std::size_t opengl_dlgeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { auto &chunkrecord = m_chunkrecords[ Geometry.chunk - 1 ]; if( chunkrecord.streams != Streams ) { delete_list( Geometry ); + chunkrecord.primitive_count = 0; } if( chunkrecord.list == 0 ) { // we don't have a list ready, so compile one @@ -254,9 +260,16 @@ opengl_dlgeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_ } ::glEnd(); ::glEndList(); + + switch( chunk.type ) { + case GL_TRIANGLES: { chunkrecord.primitive_count += chunk.vertices.size() / 3; break; } + case GL_TRIANGLE_STRIP: { chunkrecord.primitive_count += chunk.vertices.size() - 2; break; } + default: { break; } + } } // with the list done we can just play it ::glCallList( chunkrecord.list ); + return chunkrecord.primitive_count; } // release () subclass details diff --git a/openglgeometrybank.h b/openglgeometrybank.h index 2f0fae1e..31dde3c2 100644 --- a/openglgeometrybank.h +++ b/openglgeometrybank.h @@ -48,8 +48,8 @@ private: void replace_( gfx::geometry_handle const &Geometry ) override; // draw() subclass details - void - draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override; + auto + draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) -> std::size_t override; // release() subclass details void release_() override; @@ -93,6 +93,7 @@ private: struct chunk_record { GLuint list { 0 }; // display list associated with the chunk unsigned int streams { 0 }; // stream combination used to generate the display list + std::size_t primitive_count { 0 }; }; using chunkrecord_sequence = std::vector; @@ -105,8 +106,8 @@ private: void replace_( gfx::geometry_handle const &Geometry ) override; // draw() subclass details - void - draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override; + auto + draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) -> std::size_t override; // release () subclass details void release_() override; diff --git a/openglrenderer.cpp b/openglrenderer.cpp index 84134dd9..2315f290 100644 --- a/openglrenderer.cpp +++ b/openglrenderer.cpp @@ -331,6 +331,7 @@ opengl_renderer::Render() { opengl_texture::reset_unit_cache(); m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_stats = debug_stats(); + m_geometry.primitives_count() = 0; m_debugtimestext.clear(); Render_pass( rendermode::color ); Timer::subsystem.gfx_color.stop(); @@ -361,7 +362,8 @@ opengl_renderer::Render() { m_debugtimestext += "uilayer: " + to_string( Timer::subsystem.gfx_gui.average(), 2 ) + " ms\n"; m_debugstatstext = - "vehicles: " + to_string( m_colorpass.draw_stats.dynamics, 7 ) + " +" + to_string( m_shadowpass.draw_stats.dynamics, 7 ) + "triangles: " + to_string( static_cast(m_geometry.primitives_count()), 7 ) + "\n" + + "vehicles: " + to_string( m_colorpass.draw_stats.dynamics, 7 ) + " +" + to_string( m_shadowpass.draw_stats.dynamics, 7 ) + " =" + to_string( m_colorpass.draw_stats.dynamics + m_shadowpass.draw_stats.dynamics, 7 ) + "\n" + "models: " + to_string( m_colorpass.draw_stats.models, 7 ) + " +" + to_string( m_shadowpass.draw_stats.models, 7 ) + " =" + to_string( m_colorpass.draw_stats.models + m_shadowpass.draw_stats.models, 7 ) + "\n" diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index aca525e0..730dc820 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -120,7 +120,7 @@ state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad ) } timenow = std::chrono::steady_clock::now(); - if( std::chrono::duration_cast( timenow - timelast ).count() >= 75 ) { + if( std::chrono::duration_cast( timenow - timelast ).count() >= 100 ) { timelast = timenow; glfwPollEvents(); Application.set_progress( Input.getProgress(), Input.getFullProgress() ); diff --git a/version.h b/version.h index f8f8f692..0e5f4a0e 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 20 -#define VERSION_MINOR 101 +#define VERSION_MINOR 104 #define VERSION_REVISION 0