From 10c5907c4d262b2e3503e17040d14b5ebac762d7 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 26 Dec 2017 17:17:06 +0100 Subject: [PATCH] diesel-powered vehicle startup ai tweaks, gfx renderer tweaks, crash fixes --- Driver.cpp | 241 ++++++++++++++++++++++--------------------- DynObj.cpp | 4 +- Gauge.h | 2 +- McZapkie/Mover.cpp | 7 +- McZapkie/hamulce.cpp | 6 -- World.cpp | 2 +- audiorenderer.h | 41 +++++--- renderer.cpp | 14 ++- 8 files changed, 167 insertions(+), 150 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 07342b5a..d541adbf 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1886,21 +1886,10 @@ bool TController::CheckVehicles(TOrders user) fMass += p->MoverParameters->TotalMass; // dodanie masy łącznie z ładunkiem if (fVelMax < 0 ? true : p->MoverParameters->Vmax < fVelMax) fVelMax = p->MoverParameters->Vmax; // ustalenie maksymalnej prędkości dla składu - /* //youBy: bez przesady, to jest proteza, napelniac mozna, a nawet trzeba, ale z umiarem! - //uwzględnić jeszcze wyłączenie hamulca - if - ((p->MoverParameters->BrakeSystem!=Pneumatic)&&(p->MoverParameters->BrakeSystem!=ElectroPneumatic)) - iDrivigFlags&=~moveOerlikons; //no jednak nie - else if (p->MoverParameters->BrakeSubsystem!=Oerlikon) - iDrivigFlags&=~moveOerlikons; //wtedy też nie */ p = p->Neightbour(dir); // pojazd podłączony od wskazanej strony } if (main) iDrivigFlags |= movePrimary; // nie znaleziono innego, można się porządzić - /* //tabelka z listą pojazdów jest na razie nie potrzebna - delete[] pVehicles; - pVehicles=new TDynamicObject*[iVehicles]; - */ ControllingSet(); // ustalenie członu do sterowania (może być inny niż zasiedziany) int pantmask = 1; if (iDrivigFlags & movePrimary) @@ -2187,42 +2176,19 @@ bool TController::PrepareEngine() LastReactionTime = 0.0; ReactionTime = PrepareTime; iDrivigFlags |= moveActive; // może skanować sygnały i reagować na komendy - // with Controlling do - if ( mvControlling->EnginePowerSource.SourceType == CurrentCollector ) -/* - || ( (mvOccupied->TrainType==dt_EZT) - && (mvControlling->GetTrainsetVoltage() > 0.0 ) ) ) // sprawdzanie, czy zasilanie jest może w innym członie -*/ - { + + if ( mvControlling->EnginePowerSource.SourceType == CurrentCollector ) { voltfront = true; voltrear = true; } - // begin - // if Couplers[0].Connected<>nil) - // begin - // if Couplers[0].Connected^.PantFrontVolt or Couplers[0].Connected^.PantRearVolt) - // voltfront:=true - // else - // voltfront:=false; - // end - // else - // voltfront:=false; - // if Couplers[1].Connected<>nil) - // begin - // if Couplers[1].Connected^.PantFrontVolt or Couplers[1].Connected^.PantRearVolt) - // voltrear:=true - // else - // voltrear:=false; - // end - // else - // voltrear:=false; - // end - else - // if EnginePowerSource.SourceType<>CurrentCollector) - if (mvOccupied->TrainType != dt_EZT) - voltfront = true; // Ra 2014-06: to jest wirtualny prąd dla spalinowych??? - if (AIControllFlag) // jeśli prowadzi komputer - { // część wykonawcza dla sterowania przez komputer + else { + if( mvOccupied->TrainType != dt_EZT ) { + // Ra 2014-06: to jest wirtualny prąd dla spalinowych??? + voltfront = true; + } + } + if (AIControllFlag) { + // część wykonawcza dla sterowania przez komputer mvOccupied->BatterySwitch(true); if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) { // jeśli silnikowy jest pantografującym @@ -2244,39 +2210,42 @@ bool TController::PrepareEngine() mvControlling->PantCompFlag = false; // sprężarkę pantografów można już wyłączyć } } - // if (mvOccupied->TrainType==dt_EZT) - //{//Ra 2014-12: po co to tutaj? - // mvControlling->PantFront(true); - // mvControlling->PantRear(true); - //} - // if (mvControlling->EngineType==DieselElectric) - // mvControlling->Battery=true; //Ra: to musi być tak? } + if (mvControlling->PantFrontVolt || mvControlling->PantRearVolt || voltfront || voltrear) { // najpierw ustalamy kierunek, jeśli nie został ustalony - if (!iDirection) // jeśli nie ma ustalonego kierunku - if (mvOccupied->V == 0) - { // ustalenie kierunku, gdy stoi + if( !iDirection ) { + // jeśli nie ma ustalonego kierunku + if( mvOccupied->V == 0 ) { // ustalenie kierunku, gdy stoi iDirection = mvOccupied->CabNo; // wg wybranej kabiny - if (!iDirection) // jeśli nie ma ustalonego kierunku - if ((mvControlling->PantFrontVolt != 0.0) || - (mvControlling->PantRearVolt != 0.0) || voltfront || voltrear) - { - if (mvOccupied->Couplers[1].CouplingFlag == - ctrain_virtual) // jeśli z tyłu nie ma nic + if( !iDirection ) { + // jeśli nie ma ustalonego kierunku + if( ( mvControlling->PantFrontVolt != 0.0 ) || ( mvControlling->PantRearVolt != 0.0 ) || voltfront || voltrear ) { + if( mvOccupied->Couplers[ 1 ].CouplingFlag == ctrain_virtual ) { + // jeśli z tyłu nie ma nic iDirection = -1; // jazda w kierunku sprzęgu 1 - if (mvOccupied->Couplers[0].CouplingFlag == - ctrain_virtual) // jeśli z przodu nie ma nic + } + if( mvOccupied->Couplers[ 0 ].CouplingFlag == ctrain_virtual ) { + // jeśli z przodu nie ma nic iDirection = 1; // jazda w kierunku sprzęgu 0 + } } + } } - else // ustalenie kierunku, gdy jedzie - if ((mvControlling->PantFrontVolt != 0.0) || (mvControlling->PantRearVolt != 0.0) || - voltfront || voltrear) - if (mvOccupied->V < 0) // jedzie do tyłu - iDirection = -1; // jazda w kierunku sprzęgu 1 - else // jak nie do tyłu, to do przodu - iDirection = 1; // jazda w kierunku sprzęgu 0 + else { + // ustalenie kierunku, gdy jedzie + if( ( mvControlling->PantFrontVolt != 0.0 ) || ( mvControlling->PantRearVolt != 0.0 ) || voltfront || voltrear ) { + if( mvOccupied->V < 0 ) { + // jedzie do tyłu + iDirection = -1; // jazda w kierunku sprzęgu 1 + } + else { + // jak nie do tyłu, to do przodu + iDirection = 1; // jazda w kierunku sprzęgu 0 + } + } + } + } if (AIControllFlag) // jeśli prowadzi komputer { // część wykonawcza dla sterowania przez komputer if (mvControlling->ConvOvldFlag) @@ -2285,38 +2254,48 @@ bool TController::PrepareEngine() ; // zerowanie napędu mvControlling->ConvOvldFlag = false; // reset nadmiarowego } - else if (!mvControlling->Mains) - { - // if TrainType=dt_SN61) - // begin - // OK:=(OrderDirectionChange(ChangeDir,Controlling)=-1); - // OK:=IncMainCtrl(1); - // end; + else if (false == mvControlling->Mains) { while (DecSpeed(true)) ; // zerowanie napędu - OK = mvControlling->MainSwitch(true); - if (mvControlling->EngineType == DieselEngine) - { // Ra 2014-06: dla SN61 trzeba wrzucić pierwszą pozycję - nie wiem, czy tutaj... - // kiedyś działało... - if (!mvControlling->MainCtrlPos) - { - if (mvControlling->RList[0].R == - 0.0) // gdy na pozycji 0 dawka paliwa jest zerowa, to zgaśnie - mvControlling->IncMainCtrl(1); // dlatego trzeba zwiększyć pozycję - if (!mvControlling->ScndCtrlPos) // jeśli bieg nie został ustawiony - if (!mvControlling->MotorParam[0].AutoSwitch) // gdy biegi ręczne - if (mvControlling->MotorParam[0].mIsat == 0.0) // bl,mIsat,fi,mfi - mvControlling->IncScndCtrl(1); // pierwszy bieg + + if( ( mvOccupied->EngineType == DieselEngine ) + || ( mvOccupied->EngineType == DieselElectric ) ) { + // start helper devices before spinning up the engine + // TODO: replace with dedicated diesel engine subsystems + mvOccupied->ConverterSwitch( true ); + mvOccupied->CompressorSwitch( true ); + } + if( mvOccupied->TrainType == dt_SN61 ) { + // specjalnie dla SN61 żeby nie zgasł + if( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) { + mvControlling->IncMainCtrl( 1 ); } } + OK = mvControlling->MainSwitch(true); +/* + if (mvControlling->EngineType == DieselEngine) { + // Ra 2014-06: dla SN61 trzeba wrzucić pierwszą pozycję - nie wiem, czy tutaj... + // kiedyś działało... + if (!mvControlling->MainCtrlPos) { + if( mvControlling->RList[ 0 ].R == 0.0 ) { + // gdy na pozycji 0 dawka paliwa jest zerowa, to zgaśnie dlatego trzeba zwiększyć pozycję + mvControlling->IncMainCtrl( 1 ); + } + if( ( !mvControlling->ScndCtrlPos ) // jeśli bieg nie został ustawiony + && ( !mvControlling->MotorParam[ 0 ].AutoSwitch ) // gdy biegi ręczne + && ( mvControlling->MotorParam[ 0 ].mIsat == 0.0 ) ) { // bl,mIsat,fi,mfi + // pierwszy bieg + mvControlling->IncScndCtrl( 1 ); + } + } + } +*/ } - else - { // Ra: iDirection określa, w którą stronę jedzie skład względem sprzęgów pojazdu z AI - OK = (OrderDirectionChange(iDirection, mvOccupied) == -1); + else { + OK = ( OrderDirectionChange( iDirection, mvOccupied ) == -1 ); + mvOccupied->ConverterSwitch( true ); // w EN57 sprężarka w ra jest zasilana z silnikowego - mvControlling->CompressorSwitch(true); - mvControlling->ConverterSwitch(true); - mvControlling->CompressorSwitch(true); + mvControlling->CompressorSwitch( true ); } } else @@ -2721,20 +2700,22 @@ bool TController::IncSpeed() break; case DieselEngine: if (mvControlling->ShuntModeAllow) - { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga - // zerowania kierunku) + { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku) // mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0); } - if ((mvControlling->Vel > mvControlling->dizel_minVelfullengage) && - (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0)) - OK = mvControlling->IncMainCtrl(1); - if (mvControlling->RList[mvControlling->MainCtrlPos].Mn == 0) - OK = mvControlling->IncMainCtrl(1); - if (!mvControlling->Mains) - { - mvControlling->MainSwitch(true); - mvControlling->ConverterSwitch(true); - mvControlling->CompressorSwitch(true); + if( true == Ready ) { + if( ( mvControlling->Vel > mvControlling->dizel_minVelfullengage ) + && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 ) ) { + OK = mvControlling->IncMainCtrl( 1 ); + } + if( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) { + OK = mvControlling->IncMainCtrl( 1 ); + } + } + if( false == mvControlling->Mains ) { + mvControlling->MainSwitch( true ); + mvControlling->ConverterSwitch( true ); + mvControlling->CompressorSwitch( true ); } break; } @@ -3194,12 +3175,11 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N vCommandLocation = *NewLocation; if ((NewValue1 != 0.0) && (OrderList[OrderPos] != Obey_train)) { // o ile jazda - if (!iEngineActive) - OrderNext(Prepare_engine); // trzeba odpalić silnik najpierw, światła ustawi - // JumpToNextOrder() - // if (OrderList[OrderPos]!=Obey_train) //jeśli nie pociągowa - OrderNext(Obey_train); // to uruchomić jazdę pociągową (od razu albo po odpaleniu - // silnika + if( iEngineActive == 0 ) { + // trzeba odpalić silnik najpierw, światła ustawi + OrderNext( Prepare_engine ); + } + OrderNext(Obey_train); // to uruchomić jazdę pociągową (od razu albo po odpaleniu silnika OrderCheck(); // jeśli jazda pociągowa teraz, to wykonać niezbędne operacje } if (NewValue1 != 0.0) // jeśli jechać @@ -3502,6 +3482,7 @@ TController::UpdateSituation(double dt) { index = std::min(BrakeAccTableSize, std::max(1, index)); fBrake_a0[0] = fBrake_a0[index]; fBrake_a1[0] = fBrake_a1[index]; + Ready = true; // wstępnie gotowy fReady = 0.0; // założenie, że odhamowany fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia @@ -3510,8 +3491,8 @@ TController::UpdateSituation(double dt) { TDynamicObject *p = pVehicles[0]; // pojazd na czole składu while (p) { // sprawdzenie odhamowania wszystkich połączonych pojazdów - if (Ready) // bo jak coś nie odhamowane, to dalej nie ma co sprawdzać - // if (p->MoverParameters->BrakePress>=0.03*p->MoverParameters->MaxBrakePress) + if (Ready) { + // bo jak coś nie odhamowane, to dalej nie ma co sprawdzać if (p->MoverParameters->BrakePress >= 0.4) // wg UIC określone sztywno na 0.04 { Ready = false; // nie gotowy @@ -3529,6 +3510,7 @@ TController::UpdateSituation(double dt) { Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego } } + } if (fReady < p->MoverParameters->BrakePress) fReady = p->MoverParameters->BrakePress; // szukanie najbardziej zahamowanego if( ( dy = p->VectorFront().y ) != 0.0 ) { @@ -3547,6 +3529,25 @@ TController::UpdateSituation(double dt) { // if (mvOccupied->BrakePress<0.08) //to wystarczy, że zadziałają liniowe (nie ma ich jeszcze!!!) if (fReady < 0.8) // delikatniejszy warunek, obejmuje wszystkie wagony Ready = true; //żeby uznać za odhamowany + // second pass, for diesel engines verify the engines are fully started + // TODO: cache presence of diesel engines in the consist, to skip this test if there isn't any + p = pVehicles[ 0 ]; // pojazd na czole składu + while( ( true == Ready ) + && ( p != nullptr ) ) { + + auto const *vehicle { p->MoverParameters }; + + if( ( vehicle->EngineType == DieselEngine ) + || ( vehicle->EngineType == DieselElectric ) ) { + + Ready = ( + vehicle->enrot > 0.9 * ( + vehicle->EngineType == DieselEngine ? + vehicle->dizel_nmin : + vehicle->DElist[ 0 ].RPM / 60.0 ) ); + } + p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła) + } // crude way to deal with automatic door opening on W4 preventing further ride // for human-controlled vehicles with no door control and dynamic brake auto-activating with door open @@ -5696,10 +5697,12 @@ void TController::DirectionForward(bool forward) else while (mvOccupied->ActiveDir >= 0) mvOccupied->DirectionBackward(); // do tyłu w obecnej kabinie - if (mvOccupied->EngineType == DieselEngine) // specjalnie dla SN61 - if (iDrivigFlags & moveActive) // jeśli był już odpalony - if (mvControlling->RList[mvControlling->MainCtrlPos].Mn == 0) - mvControlling->IncMainCtrl(1); //żeby nie zgasł + if( mvOccupied->TrainType == dt_SN61 ) { + // specjalnie dla SN61 żeby nie zgasł + if( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) { + mvControlling->IncMainCtrl( 1 ); + } + } }; std::string TController::Relation() diff --git a/DynObj.cpp b/DynObj.cpp index 1402faef..abbc3344 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3531,7 +3531,7 @@ void TDynamicObject::RenderSounds() { } m_lastbrakepressure = MoverParameters->BrakePress; // ensure some basic level of volume and scale it up depending on pressure in the cylinder; scale this by the leak rate - volume = 20 * m_brakepressurechange * ( 0.25 + 0.75 * ( std::max( MoverParameters->BrakePress, 0.0 ) / MoverParameters->MaxBrakePress[ 3 ] ) ); + volume = 20 * m_brakepressurechange * ( 0.25 + 0.75 * ( std::max( 0.0, MoverParameters->BrakePress ) / std::max( 1.0, MoverParameters->MaxBrakePress[ 3 ] ) ) ); if( volume > 0.075f ) { rsUnbrake .gain( volume ) @@ -3589,7 +3589,7 @@ void TDynamicObject::RenderSounds() { brakeforceratio = clamp( - MoverParameters->UnitBrakeForce / ( MoverParameters->BrakeForceR( 1.0, MoverParameters->Vel ) / ( MoverParameters->NAxles * std::max( 1, MoverParameters->NBpA ) ) ), + MoverParameters->UnitBrakeForce / std::max( 1.0, MoverParameters->BrakeForceR( 1.0, MoverParameters->Vel ) / ( MoverParameters->NAxles * std::max( 1, MoverParameters->NBpA ) ) ), 0.0, 1.0 ); rsBrake .pitch( rsBrake.m_frequencyoffset + MoverParameters->Vel * rsBrake.m_frequencyfactor ) diff --git a/Gauge.h b/Gauge.h index 9f76b335..8f454c3f 100644 --- a/Gauge.h +++ b/Gauge.h @@ -46,7 +46,7 @@ public: // returns offset of submodel associated with the button from the model centre glm::vec3 model_offset() const; // members - TSubModel *SubModel; // McZapkie-310302: zeby mozna bylo sprawdzac czy zainicjowany poprawnie + TSubModel *SubModel { nullptr }; // McZapkie-310302: zeby mozna bylo sprawdzac czy zainicjowany poprawnie private: // methods diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 2977f8e6..146685a9 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -8262,10 +8262,9 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C // end else if (Command == "CompressorSwitch") /*NBMX*/ { - if ((CValue1 == 1)) - CompressorAllow = true; - else if ((CValue1 == 0)) - CompressorAllow = false; + if( CompressorPower < 2 ) { + CompressorAllow = ( CValue1 == 1 ); + } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } else if (Command == "DoorOpen") /*NBMX*/ diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index fdfa2bbc..be9e1a01 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -247,10 +247,6 @@ TBrake::TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn NBpA = i_nbpa; BrakeDelays = i_BD; BrakeDelayFlag = bdelay_P; - DCV = false; - ASBP = 0.0; - BrakeStatus = b_hld; - SoundFlag = 0; // 210.88 // SizeBR:=i_bcn*i_bcr*i_bcr*i_bcd*40.17*MaxBP/(5-MaxBP); //objetosc ZP w stosunku do cylindra // 14" i cisnienia 4.2 atm @@ -258,7 +254,6 @@ TBrake::TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn SizeBC = i_bcn * i_bcr * i_bcr * i_bcd * 210.88 * MaxBP / 4.2; // objetosc CH w stosunku do cylindra 14" i cisnienia 4.2 atm - // BrakeCyl:=TReservoir.Create; BrakeCyl = std::make_shared(); BrakeRes = std::make_shared(); ValveRes = std::make_shared(); @@ -268,7 +263,6 @@ TBrake::TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn BrakeRes->CreateCap(i_brc); ValveRes->CreateCap(0.25); - // FM.Free; // materialy cierne i_mat = i_mat & (255 - bp_MHS); switch (i_mat) diff --git a/World.cpp b/World.cpp index 6721f7a6..e81860b5 100644 --- a/World.cpp +++ b/World.cpp @@ -1396,7 +1396,7 @@ TWorld::Update_UI() { uitextline2 += ( vehicle->MoverParameters->PantPressLockActive ? "!" : ( vehicle->MoverParameters->PantPressSwitchActive ? "*" : "." ) ); uitextline2 += ( false == vehicle->MoverParameters->ConverterAllowLocal ? "-" : ( vehicle->MoverParameters->ConverterAllow ? ( vehicle->MoverParameters->ConverterFlag ? "X" : "x" ) : "." ) ); uitextline2 += ( vehicle->MoverParameters->ConvOvldFlag ? "!" : "." ); - uitextline2 += ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( vehicle->MoverParameters->CompressorAllow ? ( vehicle->MoverParameters->CompressorFlag ? "C" : "c" ) : "." ) ); + uitextline2 += ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( ( vehicle->MoverParameters->CompressorAllow || vehicle->MoverParameters->CompressorPower > 1 ) ? ( vehicle->MoverParameters->CompressorFlag ? "C" : "c" ) : "." ) ); uitextline2 += ( vehicle->MoverParameters->CompressorGovernorLock ? "!" : "." ); /* uitextline2 += diff --git a/audiorenderer.h b/audiorenderer.h index a6864987..4ab63ec4 100644 --- a/audiorenderer.h +++ b/audiorenderer.h @@ -56,20 +56,7 @@ struct openal_source { // methods template openal_source & - bind( sound_source *Controller, uint32_sequence Sounds, Iterator_ First, Iterator_ Last ) { - controller = Controller; - sounds = Sounds; - // look up and queue assigned buffers - std::vector buffers; - std::for_each( - First, Last, - [&]( audio::buffer_handle const &buffer ) { - buffers.emplace_back( audio::renderer.buffer( buffer ).id ); } ); - if( id != audio::null_resource ) { - ::alSourceQueueBuffers( id, static_cast( buffers.size() ), buffers.data() ); - ::alSourceRewind( id ); } - is_multipart = ( buffers.size() > 1 ); - return *this; } + bind( sound_source *Controller, uint32_sequence Sounds, Iterator_ First, Iterator_ Last ); // starts playback of queued buffers void play(); @@ -163,6 +150,32 @@ private: extern openal_renderer renderer; + + +template +openal_source & +openal_source::bind( sound_source *Controller, uint32_sequence Sounds, Iterator_ First, Iterator_ Last ) { + + controller = Controller; + sounds = Sounds; + // look up and queue assigned buffers + std::vector buffers; + std::for_each( + First, Last, + [&]( audio::buffer_handle const &buffer ) { + buffers.emplace_back( audio::renderer.buffer( buffer ).id ); } ); + + if( id != audio::null_resource ) { + ::alSourceQueueBuffers( id, static_cast( buffers.size() ), buffers.data() ); + ::alSourceRewind( id ); + } + is_multipart = ( buffers.size() > 1 ); + + return *this; +} + + + inline float amplitude_to_db( float const Amplitude ) { diff --git a/renderer.cpp b/renderer.cpp index aa703f86..66d30c05 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -111,7 +111,7 @@ opengl_renderer::Init( GLFWwindow *Window ) { ::glDepthFunc( GL_LEQUAL ); glEnable( GL_DEPTH_TEST ); - glAlphaFunc( GL_GREATER, 0.04f ); + glAlphaFunc( GL_GREATER, 0.f ); glEnable( GL_ALPHA_TEST ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_BLEND ); @@ -828,11 +828,11 @@ opengl_renderer::setup_drawing( bool const Alpha ) { if( true == Alpha ) { ::glEnable( GL_BLEND ); - ::glAlphaFunc( GL_GREATER, 0.04f ); + ::glAlphaFunc( GL_GREATER, 0.f ); } else { ::glDisable( GL_BLEND ); - ::glAlphaFunc( GL_GREATER, 0.50f ); + ::glAlphaFunc( GL_GREATER, 0.5f ); } switch( m_renderpass.draw_mode ) { @@ -1807,6 +1807,10 @@ opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange void opengl_renderer::Render( TAnimModel *Instance ) { + if( false == Instance->m_visible ) { + return; + } + double distancesquared; switch( m_renderpass.draw_mode ) { case rendermode::shadows: { @@ -2634,6 +2638,10 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque void opengl_renderer::Render_Alpha( TAnimModel *Instance ) { + if( false == Instance->m_visible ) { + return; + } + double distancesquared; switch( m_renderpass.draw_mode ) { case rendermode::shadows: {