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));
}
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 (fTranslateSpeed != 0.0)
@@ -236,7 +237,7 @@ void TAnimContainer::UpdateModel()
// zakończeniu
}
}
if (fRotateSpeed != 0)
if (fRotateSpeed != 0.0)
{
/*
@@ -303,8 +304,9 @@ void TAnimContainer::UpdateModel()
// zakończeniu
}
}
if (fAngleSpeed != 0.0)
{ // obrót kwaternionu (interpolacja)
if( fAngleSpeed != 0.f ) {
// 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)
{
fAngleCurrent +=
fAngleSpeed * Timer::GetDeltaTime(); // aktualny parametr interpolacji
if (fAngleCurrent >= 1.0f)
{ // interpolacja zakończona, ustawienie na pozycję końcową
qCurrent = qDesired;
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
if (evDone)
Global::AddToQuery(evDone,
NULL); // wykonanie eventu informującego o zakończeniu
if( evDone ) {
// wykonanie eventu informującego o zakończeniu
Global::AddToQuery( evDone, NULL );
}
}
else
{ // obliczanie pozycji pośredniej
@@ -412,9 +413,9 @@ TAnimModel::TAnimModel()
iNumLights = 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
}
vAngle.x = vAngle.y = vAngle.z = 0.0; // zerowanie obrotów egzemplarza
@@ -550,8 +551,15 @@ TAnimContainer * TAnimModel::GetContainer(char *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ść
TAnimContainer *pCurrent;
for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext)
@@ -560,15 +568,14 @@ void TAnimModel::RaAnimate()
// if () //tylko dla modeli z IK !!!!
for (pCurrent = pRoot; pCurrent != NULL; pCurrent = pCurrent->pNext) // albo osobny łańcuch
pCurrent->UpdateModelIK(); // przeliczenie odwrotnej kinematyki
m_framestamp = Framestamp;
};
void TAnimModel::RaPrepare()
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
fBlinkTimer -= Timer::GetDeltaTime();
if (fBlinkTimer <= 0)
fBlinkTimer = fOffTime;
bool state; // stan światła
for (int i = 0; i < iNumLights; i++)
for (int i = 0; i < iNumLights; ++i)
{
switch (lsLights[i])
{

View File

@@ -149,8 +149,9 @@ class TAnimModel {
TLightState lsLights[iMaxNumLights];
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
private:
void RaAnimate(); // przeliczenie animacji egzemplarza
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
private:
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
public:
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 ) {
// 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
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 )
&& ( v < fVelDes ) ) {
@@ -4059,17 +4059,13 @@ bool TController::UpdateSituation(double dt)
switch (comm)
{ // ustawienie VelSignal - trochę proteza = do przemyślenia
case cm_Ready: // W4 zezwolił na jazdę
TableCheck(
scanmax); // ewentualne doskanowanie trasy za W4, który zezwolił na jazdę
TableUpdate(VelDesired, ActualProximityDist, VelNext,
AccDesired); // aktualizacja po skanowaniu
// if (comm!=cm_SetVelocity) //jeśli dalej jest kolejny W4, to ma zwrócić
// cm_SetVelocity
// ewentualne doskanowanie trasy za W4, który zezwolił na jazdę
TableCheck( scanmax);
TableUpdate(VelDesired, ActualProximityDist, VelNext, AccDesired); // aktualizacja po skanowaniu
if (VelNext == 0.0)
break; // ale jak coś z przodu zamyka, to ma stać
if (iDrivigFlags & moveStopCloser)
VelSignal = -1.0; // niech jedzie, jak W4 puściło - nie, ma czekać na
// sygnał z sygnalizatora!
VelSignal = -1.0; // ma czekać na sygnał z sygnalizatora!
case cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy
if (!(OrderList[OrderPos] &
~(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...
}
void TSubRect::RaAnimate()
{ // wykonanie animacji
if( tTrackAnim == nullptr ) {
// wykonanie animacji
void TSubRect::RaAnimate( unsigned int const Framestamp ) {
if( ( tTrackAnim == nullptr )
|| ( Framestamp == m_framestamp ) ) {
// nie ma nic do animowania
return;
}
tTrackAnim = tTrackAnim->RaAnimate(); // przeliczenie animacji kolejnego
m_framestamp = Framestamp;
};
TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude)
@@ -431,8 +435,6 @@ void TSubRect::RenderSounds()
//---------------------------------------------------------------------------
//------------------ Kwadrat kilometrowy ------------------------------------
//---------------------------------------------------------------------------
int TGroundRect::iFrameNumber = 0; // licznik wyświetlanych klatek
TGroundRect::~TGroundRect()
{
SafeDeleteArray(pSubRects);

View File

@@ -171,6 +171,7 @@ class TSubRect : /*public Resource,*/ public CMesh
{ // sektor składowy kwadratu kilometrowego
public:
bounding_area m_area;
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
int iTracks = 0; // ilość torów w (tTracks)
TTrack **tTracks = nullptr; // tory do renderowania pojazdów
protected:
@@ -192,15 +193,12 @@ class TSubRect : /*public Resource,*/ public CMesh
void LoadNodes(); // utworzenie VBO sektora
public:
virtual ~TSubRect();
/*
virtual void Release(); // zwalnianie VBO sektora
*/
virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
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
};
@@ -221,7 +219,6 @@ class TGroundRect : public TSubRect
private:
TSubRect *pSubRects { nullptr };
int iLastDisplay; // numer klatki w której był ostatnio wyświetlany
void Init();
@@ -251,7 +248,6 @@ public:
// optymalizacja obiektów w sektorach
pSubRects[ i ].Sort(); } } };
static int iFrameNumber; // numer kolejny wyświetlanej klatki
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_debuginfo.clear();
++m_framestamp;
Render_pass( rendermode::color );
m_drawcount = m_drawqueue.size();
@@ -1330,8 +1331,6 @@ opengl_renderer::Texture( texture_handle const Texture ) const {
bool
opengl_renderer::Render( TGround *Ground ) {
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
m_drawqueue.clear();
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
if( Groundcell->iLastDisplay != Groundcell->iFrameNumber ) {
// tylko jezeli dany kwadrat nie był jeszcze renderowany
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// non-interactive scenery elements get neutral colour
::glColor3fv( glm::value_ptr( colors::none ) );
}
case rendermode::color:
case rendermode::reflections: {
if( Groundcell->nRenderRect != nullptr ) {
// nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
Render( node );
}
switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: {
// non-interactive scenery elements get neutral colour
::glColor3fv( glm::value_ptr( colors::none ) );
}
case rendermode::color:
case rendermode::reflections: {
if( Groundcell->nRenderRect != nullptr ) {
// nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
Render( node );
}
break;
result = true;
}
case rendermode::shadows: {
if( Groundcell->nRenderRect != nullptr ) {
// experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips'
::glDisable( GL_CULL_FACE );
// nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
Render( node );
}
::glEnable( GL_CULL_FACE );
break;
}
case rendermode::shadows: {
if( Groundcell->nRenderRect != nullptr ) {
// experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips'
::glDisable( GL_CULL_FACE );
// nieprzezroczyste trójkąty kwadratu kilometrowego
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
Render( node );
}
}
case rendermode::pickcontrols:
default: {
break;
result = true;
::glEnable( GL_CULL_FACE );
}
}
case rendermode::pickcontrols:
default: {
break;
}
}
#ifdef EU07_USE_OLD_TERRAINCODE
if( Groundcell->nTerrain ) {
if( Groundcell->nTerrain ) {
Render( Groundcell->nTerrain );
}
Render( Groundcell->nTerrain );
}
#endif
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
result = true;
// add the subcells of the cell to the draw queue
switch( m_renderpass.draw_mode ) {
case rendermode::color:
case rendermode::shadows:
case rendermode::pickscenery: {
if( Groundcell->pSubRects != nullptr ) {
for( std::size_t subcellindex = 0; subcellindex < iNumSubRects * iNumSubRects; ++subcellindex ) {
auto subcell = Groundcell->pSubRects + subcellindex;
if( subcell->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
m_drawqueue.emplace_back(
glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ),
subcell );
}
// add the subcells of the cell to the draw queue
switch( m_renderpass.draw_mode ) {
case rendermode::color:
case rendermode::shadows:
case rendermode::pickscenery: {
if( Groundcell->pSubRects != nullptr ) {
for( std::size_t subcellindex = 0; subcellindex < iNumSubRects * iNumSubRects; ++subcellindex ) {
auto subcell = Groundcell->pSubRects + subcellindex;
if( subcell->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
m_drawqueue.emplace_back(
glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ),
subcell );
}
}
break;
}
case rendermode::reflections:
case rendermode::pickcontrols:
default: {
break;
}
break;
}
case rendermode::reflections:
case rendermode::pickcontrols:
default: {
break;
}
}
return result;
@@ -1518,7 +1514,8 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
// oznaczanie aktywnych sektorów
Groundsubcell->LoadNodes();
Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze
// przeliczenia animacji torów w sektorze
Groundsubcell->RaAnimate( m_framestamp );
TGroundNode *node;
@@ -1667,7 +1664,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
break;
}
}
Node->Model->RaAnimate(); // jednorazowe przeliczenie animacji
Node->Model->RaAnimate( m_framestamp ); // jednorazowe przeliczenie animacji
Node->Model->RaPrepare();
if( Node->Model->pModel ) {
// renderowanie rekurencyjne submodeli

View File

@@ -350,6 +350,7 @@ private:
int m_diffusetextureunit{ GL_TEXTURE3 };
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
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
float m_framerate;