From 841e18f170ea798d1582f49b32201e62b2da95f7 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 16 Oct 2018 20:11:23 +0200 Subject: [PATCH] build 181016. freespot color override, vehicle start jolt sound, switch trackbed generation fixes --- AnimModel.cpp | 60 ++++++++++++++++++++++++++++++++++++--------------- AnimModel.h | 16 +++++++------- DynObj.cpp | 23 ++++++++++++++++++++ DynObj.h | 2 ++ Event.cpp | 8 +++---- Model3d.cpp | 19 ++++++++++++++++ Model3d.h | 3 +++ Track.cpp | 29 +++++++++++++++++-------- renderer.cpp | 35 +++++++++++++++++++----------- scene.cpp | 13 +++++++---- version.h | 4 ++-- 11 files changed, 155 insertions(+), 57 deletions(-) diff --git a/AnimModel.cpp b/AnimModel.cpp index 508f7ac8..edc00d0d 100644 --- a/AnimModel.cpp +++ b/AnimModel.cpp @@ -413,11 +413,9 @@ void TAnimContainer::EventAssign(basic_event *ev) //------------------------------------------------------------------------------ TAnimModel::TAnimModel( scene::node_data const &Nodedata ) : basic_node( Nodedata ) { - // TODO: wrap these in a tuple and move to underlying model - for( int index = 0; index < iMaxNumLights; ++index ) { - LightsOn[ index ] = LightsOff[ index ] = nullptr; // normalnie nie ma - lsLights[ index ] = ls_Off; // a jeśli są, to wyłączone - } + + m_lightcolors.fill( glm::vec3{ -1.f } ); + m_lightopacities.fill( 1.f ); } TAnimModel::~TAnimModel() @@ -498,20 +496,44 @@ bool TAnimModel::Load(cParser *parser, bool ter) if (LightsOn[i] || LightsOff[i]) // Ra: zlikwidowałem wymóg istnienia obu iNumLights = i + 1; - if ( parser->getToken() == "lights" ) - { - int i = 0; - std::string token = parser->getToken(); - while( ( token != "" ) - && ( token != "endmodel" ) ) { + std::string token; + do { + token = parser->getToken(); - LightSet( i, std::stof( token ) ); // stan światła jest liczbą z ułamkiem - ++i; + if( token == "lights" ) { + auto i{ 0 }; + while( ( false == ( token = parser->getToken() ).empty() ) + && ( token != "lightcolors" ) + && ( token != "endmodel" ) ) { + + if( i < iNumLights ) { + // stan światła jest liczbą z ułamkiem + LightSet( i, std::stof( token ) ); + } + ++i; + } + } + + if( token == "lightcolors" ) { + auto i{ 0 }; + while( ( false == ( token = parser->getToken() ).empty() ) + && ( token != "lights" ) + && ( token != "endmodel" ) ) { + + if( ( i < iNumLights ) + && ( token != "-1" ) ) { // -1 leaves the default color intact + auto const lightcolor { std::stoi( token, 0, 16 ) }; + m_lightcolors[i] = { + ( ( lightcolor >> 16 ) & 0xff ) / 255.f, + ( ( lightcolor >> 8 ) & 0xff ) / 255.f, + ( ( lightcolor ) & 0xff ) / 255.f }; + } + ++i; + } + } + } while( ( false == token.empty() ) + && ( token != "endmodel" ) ); - token = ""; - parser->getTokens(); *parser >> token; - } - } return true; } @@ -683,6 +705,10 @@ void TAnimModel::RaPrepare() if (LightsOff[i]) LightsOff[i]->iVisible = !state; } + // potentially modify freespot colors + if( LightsOn[i] ) { + LightsOn[i]->SetDiffuseOverride( m_lightcolors[i], true); + } } TSubModel::iInstance = reinterpret_cast( this ); //żeby nie robić cudzych animacji TSubModel::pasText = &asText; // przekazanie tekstu do wyświetlacza (!!!! do przemyślenia) diff --git a/AnimModel.h b/AnimModel.h index ac33e7b3..244d26f3 100644 --- a/AnimModel.h +++ b/AnimModel.h @@ -179,19 +179,19 @@ private: // members TAnimContainer *pRoot { nullptr }; // pojemniki sterujące, tylko dla aniomowanych submodeli TModel3d *pModel { nullptr }; -// double fBlinkTimer { 0.0 }; - int iNumLights { 0 }; - TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d - TSubModel *LightsOff[ iMaxNumLights ]; glm::vec3 vAngle; // bazowe obroty egzemplarza względem osi material_data m_materialdata; std::string asText; // tekst dla wyświetlacza znakowego TAnimAdvanced *pAdvanced { nullptr }; - // TODO: wrap into a light state struct - float lsLights[ iMaxNumLights ]; - std::array m_lighttimers { 0.f }; - std::array m_lightopacities { 1.f }; + // TODO: wrap into a light state struct, remove fixed element count + int iNumLights { 0 }; + std::array LightsOn {}; // Ra: te wskaźniki powinny być w ramach TModel3d + std::array LightsOff {}; + std::array lsLights {}; // ls_Off + std::array m_lightcolors; // -1 in constructor + std::array m_lighttimers {}; + std::array m_lightopacities; // {1} in constructor float fOnTime { 1.f / 2 };// { 60.f / 45.f / 2 }; float fOffTime { 1.f / 2 };// { 60.f / 45.f / 2 }; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza float fTransitionTime { fOnTime * 0.9f }; // time diff --git a/DynObj.cpp b/DynObj.cpp index 5bb6f25b..207a0dd1 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3932,6 +3932,13 @@ void TDynamicObject::RenderSounds() { if( Global.iPause != 0 ) { return; } + if( ( m_startjoltplayed ) + && ( ( MoverParameters->AccSVBased < 0.01 ) + || ( GetVelocity() < 0.01 ) ) ) { + // if the vehicle comes to a stop set the movement jolt to play when it starts moving again + m_startjoltplayed = false; + } + double const dt{ Timer::GetDeltaRenderTime() }; double volume{ 0.0 }; double frequency{ 1.0 }; @@ -4387,6 +4394,17 @@ void TDynamicObject::RenderSounds() { rscurve.stop(); } + // movement start jolt + if( false == m_startjoltplayed ) { + auto const velocity { GetVelocity() }; + if( ( MoverParameters->AccSVBased > 0.2 ) + && ( velocity > 2.5 ) + && ( velocity < 15.0 ) ) { + m_startjolt.play( sound_flags::exclusive ); + m_startjoltplayed = true; + } + } + // McZapkie! - to wazne - SoundFlag wystawiane jest przez moje moduly // gdy zachodza pewne wydarzenia komentowane dzwiekiem. if( TestFlag( MoverParameters->SoundFlag, sound::pneumatic ) ) { @@ -5799,6 +5817,11 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co couplersounds.dsbBufferClamp_loud = bufferclash; } } + else if( token == "startjolt:" ) { + // movement start jolt + m_startjolt.deserialize( parser, sound_type::single ); + m_startjolt.owner( this ); + } } while( token != "" ); diff --git a/DynObj.h b/DynObj.h index 698b347d..afca3fee 100644 --- a/DynObj.h +++ b/DynObj.h @@ -426,6 +426,8 @@ private: sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab sound_source sSand { sound_placement::external }; // moving part and other external sounds + sound_source m_startjolt { sound_placement::general }; // movement start jolt, played once on initial acceleration at slow enough speed + bool m_startjoltplayed { false }; std::array m_couplersounds; // always front and rear std::vector m_pantographsounds; // typically 2 but can be less (or more?) std::vector m_doorsounds; // can expect symmetrical arrangement, but don't count on it diff --git a/Event.cpp b/Event.cpp index 36c87cf3..108f97ef 100644 --- a/Event.cpp +++ b/Event.cpp @@ -1485,7 +1485,7 @@ lights_event::deserialize_( cParser &Input, scene::scratch_data &Scratchpad ) { } while( lightidx < lightcountlimit ) { // HACK: mark unspecified lights with magic value - m_lights[ lightidx++ ] = -2.f; + m_lights[ lightidx++ ] = std::numeric_limits::quiet_NaN(); } } @@ -1498,11 +1498,11 @@ lights_event::run_() { if( targetmodel == nullptr ) { continue; } // event effect code for( auto lightidx = 0; lightidx < iMaxNumLights; ++lightidx ) { - if( m_lights[ lightidx ] == -2.f ) { + if( m_lights[ lightidx ] == std::numeric_limits::quiet_NaN() ) { // processed all supplied values, bail out break; } - if( m_lights[ lightidx ] >= 0.f ) { + if( m_lights[ lightidx ] != -1.f ) { // -1 zostawia bez zmiany targetmodel->LightSet( lightidx, @@ -1518,7 +1518,7 @@ lights_event::export_as_text_( std::ostream &Output ) const { auto lightidx{ 0 }; while( ( lightidx < iMaxNumLights ) - && ( m_lights[ lightidx ] > -2.0 ) ) { + && ( m_lights[ lightidx ] != std::numeric_limits::quiet_NaN() ) ) { Output << m_lights[ lightidx ] << ' '; ++lightidx; } diff --git a/Model3d.cpp b/Model3d.cpp index 031f3a7c..92a40e31 100644 --- a/Model3d.cpp +++ b/Model3d.cpp @@ -71,6 +71,25 @@ void TSubModel::Name(std::string const &Name) pName = Name; }; +// sets rgb components of diffuse color override to specified value +void +TSubModel::SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren, bool const Includesiblings ) { + + if( eType == TP_FREESPOTLIGHT ) { + DiffuseOverride = Color; + } + if( true == Includesiblings ) { + auto sibling { this }; + while( ( sibling = sibling->Next ) != nullptr ) { + sibling->SetDiffuseOverride( Color, Includechildren, false ); // no need for all siblings to duplicate the work + } + } + if( ( true == Includechildren ) + && ( Child != nullptr ) ) { + Child->SetDiffuseOverride( Color, Includechildren, true ); // node's children include child's siblings and children + } +} + // sets visibility level (alpha component) to specified value void TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) { diff --git a/Model3d.h b/Model3d.h index 3c1d8a14..af52323b 100644 --- a/Model3d.h +++ b/Model3d.h @@ -104,6 +104,7 @@ private: f4Diffuse { 1.0f,1.0f,1.0f,1.0f }, f4Specular { 0.0f,0.0f,0.0f,1.0f }, f4Emision { 1.0f,1.0f,1.0f,1.0f }; + glm::vec3 DiffuseOverride { -1.f }; normalization m_normalizenormals { normalization::none }; // indicates vectors need to be normalized due to scaling etc float fWireSize { 0.0f }; // nie używane, ale wczytywane float fSquareMaxDist { 10000.0f * 10000.0f }; @@ -192,6 +193,8 @@ public: int Flags() const { return iFlags; }; void UnFlagNext() { iFlags &= 0x00FFFFFF; }; void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular ); + // sets rgb components of diffuse color override to specified value + void SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren = false, bool const Includesiblings = false ); // sets visibility level (alpha component) to specified value void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false ); // sets light level (alpha component of illumination color) to specified value diff --git a/Track.cpp b/Track.cpp index 3bce3419..7f9ae1d1 100644 --- a/Track.cpp +++ b/Track.cpp @@ -3074,7 +3074,7 @@ path_table::InitTracks() { auto const trackname { track->name() }; switch (track->eType) { - // TODO: re-enable + case tt_Table: { // obrotnicę też łączymy na starcie z innymi torami // szukamy modelu o tej samej nazwie @@ -3169,10 +3169,6 @@ path_table::InitTracks() { break; } } - if( Global.CreateSwitchTrackbeds ) { - // when autogenerating trackbeds, try to restore trackbeds for tracks neighbouring double slips - track->copy_adjacent_trackbed_material(); - } break; } case tt_Switch: { @@ -3180,10 +3176,6 @@ path_table::InitTracks() { track->AssignForcedEvents( simulation::Events.FindEvent( trackname + ":forced+" ), simulation::Events.FindEvent( trackname + ":forced-" ) ); - if( Global.CreateSwitchTrackbeds ) { - // when autogenerating trackbeds, try to restore trackbeds for tracks neighbouring double slips - track->copy_adjacent_trackbed_material(); - } break; } default: { @@ -3199,6 +3191,25 @@ path_table::InitTracks() { } } + if( Global.CreateSwitchTrackbeds ) { + // do this after all connections are established, otherwise missing switch connections + // may prevent us from obtaining texture data for basic track from 'across' a switch + for( auto *track : m_items ) { + // try to assign missing trackbed materials for switches and tracks neighbouring switches + switch( track->eType ) { + + case tt_Normal: + case tt_Switch: { + track->copy_adjacent_trackbed_material(); + break; + } + default: { + break; + } + } // switch + } + } + auto *isolated = TIsolated::Root(); while( isolated ) { diff --git a/renderer.cpp b/renderer.cpp index 02c2e817..73def98e 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -2579,6 +2579,11 @@ opengl_renderer::Render( TSubModel *Submodel ) { auto const unitstate = m_unitstate; switch_units( m_unitstate.diffuse, false, false ); + auto const *lightcolor { + Submodel->DiffuseOverride.r < 0.f ? // -1 indicates no override + glm::value_ptr( Submodel->f4Diffuse ) : + glm::value_ptr( Submodel->DiffuseOverride ) }; + // main draw call if( Global.Overcast > 1.f ) { // fake fog halo @@ -2587,11 +2592,12 @@ opengl_renderer::Render( TSubModel *Submodel ) { 2.f, 1.f, clamp( Global.fFogEnd / 2000, 0.f, 1.f ) ) * std::max( 1.f, Global.Overcast ) }; + ::glPointSize( pointsize * fogfactor ); ::glColor4f( - Submodel->f4Diffuse[ 0 ], - Submodel->f4Diffuse[ 1 ], - Submodel->f4Diffuse[ 2 ], + lightcolor[ 0 ], + lightcolor[ 1 ], + lightcolor[ 2 ], Submodel->fVisible * std::min( 1.f, lightlevel ) * 0.5f ); ::glDepthMask( GL_FALSE ); m_geometry.draw( Submodel->m_geometry ); @@ -2599,9 +2605,9 @@ opengl_renderer::Render( TSubModel *Submodel ) { } ::glPointSize( pointsize ); ::glColor4f( - Submodel->f4Diffuse[ 0 ], - Submodel->f4Diffuse[ 1 ], - Submodel->f4Diffuse[ 2 ], + lightcolor[ 0 ], + lightcolor[ 1 ], + lightcolor[ 2 ], Submodel->fVisible * std::min( 1.f, lightlevel ) ); m_geometry.draw( Submodel->m_geometry ); @@ -3507,7 +3513,6 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { ::glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT ); Bind_Texture( m_glaretexture ); - ::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], Submodel->fVisible * glarelevel ); ::glDisable( GL_LIGHTING ); ::glDisable( GL_FOG ); ::glDepthMask( GL_FALSE ); @@ -3518,12 +3523,19 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { ::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian ::glRotated( std::atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt // disable shadows so they don't obstruct self-lit items -/* - setup_shadow_color( colors::white ); -*/ auto const unitstate = m_unitstate; switch_units( unitstate.diffuse, false, false ); + auto const *lightcolor { + Submodel->DiffuseOverride.r < 0.f ? // -1 indicates no override + glm::value_ptr( Submodel->f4Diffuse ) : + glm::value_ptr( Submodel->DiffuseOverride ) }; + ::glColor4f( + lightcolor[ 0 ], + lightcolor[ 1 ], + lightcolor[ 2 ], + Submodel->fVisible * glarelevel ); + // main draw call m_geometry.draw( m_billboardgeometry ); /* @@ -3535,9 +3547,6 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) { // ...etc instead IF we had easy access to camera's forward and right vectors. TODO: check if Camera matrix is accessible */ // post-render cleanup -/* - setup_shadow_color( m_shadowcolor ); -*/ switch_units( unitstate.diffuse, unitstate.shadows, unitstate.reflections ); ::glPopMatrix(); diff --git a/scene.cpp b/scene.cpp index 5738d163..5d937723 100644 --- a/scene.cpp +++ b/scene.cpp @@ -1157,16 +1157,21 @@ basic_region::RadioStop( glm::dvec3 const &Location ) { } std::vector switchtrackbedtextures { + "rkpd34r190-tpd1", + "rkpd34r190-tpd2", + "rkpd34r190-tpd-oil2", "rozkrz8r150-1pods-new", "rozkrz8r150-2pods-new", "rozkrz34r150-tpbps-new2", "rozkrz34r150-tpd1", - "rkpd34r190-tpd1", - "rkpd34r190-tpd2", - "rkpd34r190-tpd-oil2", + "rz-1200-185", "zwr41r500", "zwrot-tpd-oil1", - "zwrot34r300pods-new" }; + "zwrot34r300pods", + "zwrot34r300pods-new", + "zwrot34r300pods-old", + "zwrotl65r1200pods-new", + "zwrotp65r1200pods-new" }; void basic_region::insert( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) { diff --git a/version.h b/version.h index 534a83d6..e0c28869 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 1011 -#define VERSION_REVISION 0 +#define VERSION_MINOR 1016 +#define VERSION_REVISION 1