16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 05:49:19 +02:00

fixed animation rate of scene elements

This commit is contained in:
tmj-fstate
2017-08-23 16:56:56 +02:00
parent 3a63d1d346
commit a41a666184
7 changed files with 98 additions and 98 deletions

View File

@@ -205,8 +205,9 @@ void TAnimContainer::AnimSetVMD(double fNewSpeed)
// "+AnsiString(pMovementData->f3Vector.y)+" "+AnsiString(pMovementData->f3Vector.z)); // "+AnsiString(pMovementData->f3Vector.y)+" "+AnsiString(pMovementData->f3Vector.z));
} }
void TAnimContainer::UpdateModel() // przeliczanie animacji wykonać tylko raz na model
{ // przeliczanie animacji wykonać tylko raz na model void TAnimContainer::UpdateModel() {
if (pSubModel) // pozbyć się tego - sprawdzać wcześniej if (pSubModel) // pozbyć się tego - sprawdzać wcześniej
{ {
if (fTranslateSpeed != 0.0) if (fTranslateSpeed != 0.0)
@@ -236,7 +237,7 @@ void TAnimContainer::UpdateModel()
// zakończeniu // zakończeniu
} }
} }
if (fRotateSpeed != 0) if (fRotateSpeed != 0.0)
{ {
/* /*
@@ -303,8 +304,9 @@ void TAnimContainer::UpdateModel()
// zakończeniu // zakończeniu
} }
} }
if (fAngleSpeed != 0.0) if( fAngleSpeed != 0.f ) {
{ // obrót kwaternionu (interpolacja) // NOTE: this is angle- not quaternion-based rotation TBD, TODO: switch to quaternion rotations?
fAngleCurrent += fAngleSpeed * Timer::GetDeltaTime(); // aktualny parametr interpolacji
} }
} }
}; };
@@ -322,15 +324,14 @@ void TAnimContainer::PrepareModel()
{ {
if (fAngleSpeed > 0.0f) if (fAngleSpeed > 0.0f)
{ {
fAngleCurrent +=
fAngleSpeed * Timer::GetDeltaTime(); // aktualny parametr interpolacji
if (fAngleCurrent >= 1.0f) if (fAngleCurrent >= 1.0f)
{ // interpolacja zakończona, ustawienie na pozycję końcową { // interpolacja zakończona, ustawienie na pozycję końcową
qCurrent = qDesired; qCurrent = qDesired;
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
if (evDone) if( evDone ) {
Global::AddToQuery(evDone, // wykonanie eventu informującego o zakończeniu
NULL); // wykonanie eventu informującego o zakończeniu Global::AddToQuery( evDone, NULL );
}
} }
else else
{ // obliczanie pozycji pośredniej { // obliczanie pozycji pośredniej
@@ -412,9 +413,9 @@ TAnimModel::TAnimModel()
iNumLights = 0; iNumLights = 0;
fBlinkTimer = 0; fBlinkTimer = 0;
for (int i = 0; i < iMaxNumLights; i++) for (int i = 0; i < iMaxNumLights; ++i)
{ {
LightsOn[i] = LightsOff[i] = NULL; // normalnie nie ma LightsOn[i] = LightsOff[i] = nullptr; // normalnie nie ma
lsLights[i] = ls_Off; // a jeśli są, to wyłączone lsLights[i] = ls_Off; // a jeśli są, to wyłączone
} }
vAngle.x = vAngle.y = vAngle.z = 0.0; // zerowanie obrotów egzemplarza vAngle.x = vAngle.y = vAngle.z = 0.0; // zerowanie obrotów egzemplarza
@@ -550,8 +551,15 @@ TAnimContainer * TAnimModel::GetContainer(char *pName)
return AddContainer(pName); return AddContainer(pName);
} }
void TAnimModel::RaAnimate() // przeliczenie animacji - jednorazowo na klatkę
{ // przeliczenie animacji - jednorazowo na klatkę void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
if( Framestamp == m_framestamp ) { return; }
fBlinkTimer -= Timer::GetDeltaTime();
if( fBlinkTimer <= 0 )
fBlinkTimer += fOffTime;
// Ra 2F1I: to by można pomijać dla modeli bez animacji, których jest większość // Ra 2F1I: to by można pomijać dla modeli bez animacji, których jest większość
TAnimContainer *pCurrent; TAnimContainer *pCurrent;
for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext) for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext)
@@ -560,15 +568,14 @@ void TAnimModel::RaAnimate()
// if () //tylko dla modeli z IK !!!! // if () //tylko dla modeli z IK !!!!
for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext) // albo osobny łańcuch for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext) // albo osobny łańcuch
pCurrent->UpdateModelIK(); // przeliczenie odwrotnej kinematyki pCurrent->UpdateModelIK(); // przeliczenie odwrotnej kinematyki
m_framestamp = Framestamp;
}; };
void TAnimModel::RaPrepare() void TAnimModel::RaPrepare()
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza { // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
fBlinkTimer -= Timer::GetDeltaTime();
if (fBlinkTimer <= 0)
fBlinkTimer = fOffTime;
bool state; // stan światła bool state; // stan światła
for (int i = 0; i < iNumLights; i++) for (int i = 0; i < iNumLights; ++i)
{ {
switch (lsLights[i]) switch (lsLights[i])
{ {

View File

@@ -149,8 +149,9 @@ class TAnimModel {
TLightState lsLights[iMaxNumLights]; TLightState lsLights[iMaxNumLights];
float fDark; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?) float fDark; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
float fOnTime, fOffTime; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza float fOnTime, fOffTime; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
private: unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
void RaAnimate(); // przeliczenie animacji egzemplarza private:
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
public: public:
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania

View File

@@ -1253,7 +1253,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( fBrakeDist > 0.0 ) { if( fBrakeDist > 0.0 ) {
// maintain desired acc while we have enough room to brake safely, when close enough start paying attention // maintain desired acc while we have enough room to brake safely, when close enough start paying attention
// try to make a smooth transition instead of sharp change // try to make a smooth transition instead of sharp change
a = interpolate( a, fAcc, clamp( ( d - fBrakeDist ) / fBrakeDist, 0.0, 1.0 ) ); a = interpolate( a, AccPreferred, clamp( ( d - fBrakeDist ) / fBrakeDist, 0.0, 1.0 ) );
} }
if( ( d < fMinProximityDist ) if( ( d < fMinProximityDist )
&& ( v < fVelDes ) ) { && ( v < fVelDes ) ) {
@@ -4059,17 +4059,13 @@ bool TController::UpdateSituation(double dt)
switch (comm) switch (comm)
{ // ustawienie VelSignal - trochę proteza = do przemyślenia { // ustawienie VelSignal - trochę proteza = do przemyślenia
case cm_Ready: // W4 zezwolił na jazdę case cm_Ready: // W4 zezwolił na jazdę
TableCheck( // ewentualne doskanowanie trasy za W4, który zezwolił na jazdę
scanmax); // ewentualne doskanowanie trasy za W4, który zezwolił na jazdę TableCheck( scanmax);
TableUpdate(VelDesired, ActualProximityDist, VelNext, TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired); // aktualizacja po skanowaniu
AccDesired); // aktualizacja po skanowaniu
// if (comm!=cm_SetVelocity) //jeśli dalej jest kolejny W4, to ma zwrócić
// cm_SetVelocity
if (VelNext == 0.0) if (VelNext == 0.0)
break; // ale jak coś z przodu zamyka, to ma stać break; // ale jak coś z przodu zamyka, to ma stać
if (iDrivigFlags & moveStopCloser) if (iDrivigFlags & moveStopCloser)
VelSignal = -1.0; // niech jedzie, jak W4 puściło - nie, ma czekać na VelSignal = -1.0; // ma czekać na sygnał z sygnalizatora!
// sygnał z sygnalizatora!
case cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy case cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy
if (!(OrderList[OrderPos] & if (!(OrderList[OrderPos] &
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders ~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders

View File

@@ -356,13 +356,17 @@ bool TSubRect::RaTrackAnimAdd(TTrack *t)
return false; // będzie animowane... return false; // będzie animowane...
} }
void TSubRect::RaAnimate() // wykonanie animacji
{ // wykonanie animacji void TSubRect::RaAnimate( unsigned int const Framestamp ) {
if( tTrackAnim == nullptr ) {
if( ( tTrackAnim == nullptr )
|| ( Framestamp == m_framestamp ) ) {
// nie ma nic do animowania // nie ma nic do animowania
return; return;
} }
tTrackAnim = tTrackAnim->RaAnimate(); // przeliczenie animacji kolejnego tTrackAnim = tTrackAnim->RaAnimate(); // przeliczenie animacji kolejnego
m_framestamp = Framestamp;
}; };
TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude) TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude)
@@ -431,8 +435,6 @@ void TSubRect::RenderSounds()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//------------------ Kwadrat kilometrowy ------------------------------------ //------------------ Kwadrat kilometrowy ------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int TGroundRect::iFrameNumber = 0; // licznik wyświetlanych klatek
TGroundRect::~TGroundRect() TGroundRect::~TGroundRect()
{ {
SafeDeleteArray(pSubRects); SafeDeleteArray(pSubRects);

View File

@@ -171,6 +171,7 @@ class TSubRect : /*public Resource,*/ public CMesh
{ // sektor składowy kwadratu kilometrowego { // sektor składowy kwadratu kilometrowego
public: public:
bounding_area m_area; bounding_area m_area;
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
int iTracks = 0; // ilość torów w (tTracks) int iTracks = 0; // ilość torów w (tTracks)
TTrack **tTracks = nullptr; // tory do renderowania pojazdów TTrack **tTracks = nullptr; // tory do renderowania pojazdów
protected: protected:
@@ -192,15 +193,12 @@ class TSubRect : /*public Resource,*/ public CMesh
void LoadNodes(); // utworzenie VBO sektora void LoadNodes(); // utworzenie VBO sektora
public: public:
virtual ~TSubRect(); virtual ~TSubRect();
/*
virtual void Release(); // zwalnianie VBO sektora
*/
virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur) void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude); TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude); TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
void RaAnimate(); // przeliczenie animacji torów void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
}; };
@@ -221,7 +219,6 @@ class TGroundRect : public TSubRect
private: private:
TSubRect *pSubRects { nullptr }; TSubRect *pSubRects { nullptr };
int iLastDisplay; // numer klatki w której był ostatnio wyświetlany
void Init(); void Init();
@@ -251,7 +248,6 @@ public:
// optymalizacja obiektów w sektorach // optymalizacja obiektów w sektorach
pSubRects[ i ].Sort(); } } }; pSubRects[ i ].Sort(); } } };
static int iFrameNumber; // numer kolejny wyświetlanej klatki
TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh? TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh?
}; };

View File

@@ -320,6 +320,7 @@ opengl_renderer::Render() {
m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_mode = rendermode::none; // force setup anew
m_debuginfo.clear(); m_debuginfo.clear();
++m_framestamp;
Render_pass( rendermode::color ); Render_pass( rendermode::color );
m_drawcount = m_drawqueue.size(); m_drawcount = m_drawqueue.size();
@@ -1330,8 +1331,6 @@ opengl_renderer::Texture( texture_handle const Texture ) const {
bool bool
opengl_renderer::Render( TGround *Ground ) { opengl_renderer::Render( TGround *Ground ) {
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
m_drawqueue.clear(); m_drawqueue.clear();
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
@@ -1440,73 +1439,70 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
bool result { false }; // will be true if we do any rendering bool result { false }; // will be true if we do any rendering
if( Groundcell->iLastDisplay != Groundcell->iFrameNumber ) { Groundcell->LoadNodes(); // ewentualne tworzenie siatek
// tylko jezeli dany kwadrat nie był jeszcze renderowany
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: { case rendermode::pickscenery: {
// non-interactive scenery elements get neutral colour // non-interactive scenery elements get neutral colour
::glColor3fv( glm::value_ptr( colors::none ) ); ::glColor3fv( glm::value_ptr( colors::none ) );
} }
case rendermode::color: case rendermode::color:
case rendermode::reflections: { case rendermode::reflections: {
if( Groundcell->nRenderRect != nullptr ) { if( Groundcell->nRenderRect != nullptr ) {
// nieprzezroczyste trójkąty kwadratu kilometrowego // nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) { for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
Render( node ); Render( node );
}
} }
break; result = true;
} }
case rendermode::shadows: { break;
if( Groundcell->nRenderRect != nullptr ) { }
// experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips' case rendermode::shadows: {
::glDisable( GL_CULL_FACE ); if( Groundcell->nRenderRect != nullptr ) {
// nieprzezroczyste trójkąty kwadratu kilometrowego // experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips'
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) { ::glDisable( GL_CULL_FACE );
Render( node ); // nieprzezroczyste trójkąty kwadratu kilometrowego
} for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
::glEnable( GL_CULL_FACE ); Render( node );
} }
} result = true;
case rendermode::pickcontrols: ::glEnable( GL_CULL_FACE );
default: {
break;
} }
} }
case rendermode::pickcontrols:
default: {
break;
}
}
#ifdef EU07_USE_OLD_TERRAINCODE #ifdef EU07_USE_OLD_TERRAINCODE
if( Groundcell->nTerrain ) { if( Groundcell->nTerrain ) {
Render( Groundcell->nTerrain ); Render( Groundcell->nTerrain );
} }
#endif #endif
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
result = true;
// add the subcells of the cell to the draw queue // add the subcells of the cell to the draw queue
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::color: case rendermode::color:
case rendermode::shadows: case rendermode::shadows:
case rendermode::pickscenery: { case rendermode::pickscenery: {
if( Groundcell->pSubRects != nullptr ) { if( Groundcell->pSubRects != nullptr ) {
for( std::size_t subcellindex = 0; subcellindex < iNumSubRects * iNumSubRects; ++subcellindex ) { for( std::size_t subcellindex = 0; subcellindex < iNumSubRects * iNumSubRects; ++subcellindex ) {
auto subcell = Groundcell->pSubRects + subcellindex; auto subcell = Groundcell->pSubRects + subcellindex;
if( subcell->iNodeCount ) { if( subcell->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać // o ile są jakieś obiekty, bo po co puste sektory przelatywać
m_drawqueue.emplace_back( m_drawqueue.emplace_back(
glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ), glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ),
subcell ); subcell );
}
} }
} }
break;
}
case rendermode::reflections:
case rendermode::pickcontrols:
default: {
break;
} }
break;
}
case rendermode::reflections:
case rendermode::pickcontrols:
default: {
break;
} }
} }
return result; return result;
@@ -1518,7 +1514,8 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
// oznaczanie aktywnych sektorów // oznaczanie aktywnych sektorów
Groundsubcell->LoadNodes(); Groundsubcell->LoadNodes();
Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze // przeliczenia animacji torów w sektorze
Groundsubcell->RaAnimate( m_framestamp );
TGroundNode *node; TGroundNode *node;
@@ -1667,7 +1664,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
break; break;
} }
} }
Node->Model->RaAnimate(); // jednorazowe przeliczenie animacji Node->Model->RaAnimate( m_framestamp ); // jednorazowe przeliczenie animacji
Node->Model->RaPrepare(); Node->Model->RaPrepare();
if( Node->Model->pModel ) { if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli // renderowanie rekurencyjne submodeli

View File

@@ -350,6 +350,7 @@ private:
int m_diffusetextureunit{ GL_TEXTURE3 }; int m_diffusetextureunit{ GL_TEXTURE3 };
units_state m_unitstate; units_state m_unitstate;
unsigned int m_framestamp; // id of currently rendered gfx frame
float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
float m_framerate; float m_framerate;