OpenGL v C++ Builderu 5



Výpočet FPS a plynulé animace


Příklad a zdroják ke stažení (504k)

Tutorial na výpočet fps a plynulé animace, podle aktuálního fps.

Vše se počítá ve funkci CalcFPS()
//definice proměnných
float step;    //proměnná pomocí které plynule běhá animace
int  time2fps;    //druhý čas fps
int  time2synchro;    //druhý čas synchronizace
int  frame;    //hodnota snímku fps
int  synchro_frame=1;    //hodnota snímku synchronizace

//---------------------------------------------------------------------------

void CalcFPS()
{
    //definice proměnných
    __int64 counter;    //aktuálni počítadlo
    __int64 freq;    //frekvence procesoru (kolik je výpočtů za vteřinu)
    int time1fps;    //první čas fps
    int time1synchro;    //první čas synchronizace

    //kód
    bool perf=QueryPerformanceCounter((LARGE_INTEGER *)&counter);    //zkus načíst aktuální počítadlo
    if (perf)    //jestliže systém podporuje Performance tak
    {
        QueryPerformanceFrequency((LARGE_INTEGER *)&freq);    //načti výpočetní výkon za jednu sekundu
        time1fps = counter / freq;     //převeď na sekundy
        time1synchro = counter / (freq / 10);    //převeď na desetiny sekundy

        if (time1fps > time2fps)    //pokud je první čas pro výpočet FPS vyšší než druhý
        {
            Form1->Label1->Caption = " fps: " + IntToStr(frame);    //tak do editu vypiš hodnotu frame (FPS)
            frame = 0;    //vynuluj frame
        }
        if (time1synchro > time2synchro)    //pokud je prvni čas pro výpočet synchronizace vyšší než druhý
        {
            step = (8.0 / synchro_frame);    //vypočítej krok, podle kterého běží animace
            synchro_frame = 0;    //vynuluj synchronizační snímky
        }

        frame++;    //přičti snímek
        time2fps = time1fps;    //hoď první čas fps do druhého
        synchro_frame++;    //přičti synchonizační snímek
        time2synchro = time1synchro;    //hod první čas synchronizace do druhého
    }    //konec if (perf)
}    //konec void CalcFPS()
Princip je jednoduchý.
QueryPerformanceCounter((LARGE_INTEGER *)&counter); - nám vyhodí aktuální stav počítadla v milisekundách.
QueryPerformanceCounter((LARGE_INTEGER *)&counter); - nám vyhodí výpočetní výkon za jednu sekundu
Když vydělíme stav počítadla výpočetním výkonem time1fps = counter / freq; dostaneme hodnotu, která se bude každou sekundu zvyšovat o jedničku.
Pak budeme přičítat snímky frame++; , dokud nedojde ke zvýšení hodnoty if (time1fps > time2fps). Pokud ke zvýšení hodnoty dojde, tak vykreslíme aktuální stav snímků na Label1 Form1->Label1->Caption = " fps: " + IntToStr(frame); a snímky vynulujem frame = 0;

Výpočet plynulosti animace funguje na stejném principu s tim rozdílem, že budu hodnotu pro výpočet velikosti kroku animace počítat každou desetinu sekundy time1synchro = counter / (freq / 10);
Opět přičítám snímky synchro_frame++;, dokud nedojde ke zvýšení hodnoty if (time1synchro > time2synchro). Pokud ke zvýšení hodnoty dojde, tak vypočítám velikost kroku animace step = (8.0 / synchro_frame); a snímky vynuluju synchro_frame = 0;

Při výpočtu animace pak násobím hodnoty animace hodnotou step
void TranRotCube()    //vypočítej pohyb a rotaci
{
    //začátek výpočtu pohybu objektu
    if (start)    //jestliže probíhá první otočka cyklu
    {
      direction.x = 1;    //nastav směr pohybu objektu v X směru na 1
      direction.y = 1;    //nastav směr pohybu objektu v Y směru na 1
      direction.z = 1;    //nastav směr pohybu objektu v Z směru na 1
      translate.z = -8;   //nastav Z pozici objektu
      start = false;    //nastav start na false, aby při další otočce cyklu se základní hodnoty nenačítaly
    }

    if ((translate.x >= 3) || (translate.x <= -3))  //jetliže X pozice objektu přesáhne hodnoty 3 nebo -3
    {
        direction.x = -direction.x;    //otoč směr pohybu X
    }
    translate.x = translate.x + (0.01 * direction.x * (step));    //přičti 0.01 pozici X, podle směru pohybu X a velikosti kroku

    if ((translate.y >= 2) || (translate.y <= -2))    //jetliže Y pozice objektu přesáhne hodnoty 2 nebo -2
    {
        direction.y = -direction.y;    //otoč směr pohybu Y
    }
    translate.y = translate.y + (0.01 * direction.y * (step));    //přičti 0.01 pozici Y, podle směru pohybu Y a velikosti kroku

    if ((translate.z >= -6) || (translate.z <= -20))    //jetliže Z pozice objektu přesáhne hodnoty -6 nebo -20
    {
        direction.z = -direction.z;    //otoč směr pohybu Z
    }
    translate.z = translate.z + (0.01 * direction.z * (step));    //přičti 0.01 pozici Z, podle směru pohybu Z a velikosti kroku
    //konec výpočtu pohybu objektu

    //začátek výpočtu rotace objektu
    angle.x = angle.x + (0.5 * (step));    //přičti 0.5 úhlu X rotace podle velikosti kroku
    if (angle.x >= 360)    //jestliže je úhel větší, než 360 stupňů
    {
      angle.x = angle.x -360;    //odečti 360 stupňů
    }

    angle.y = angle.y + (1 * (step));    //přičti 1 úhlu Y rotace podle velikosti kroku
    if (angle.y >= 360)    //jestliže je úhel větší, než 360 stupňů
    {
      angle.y = angle.y -360;    //odečti 360 stupňů
    }

    angle.z = angle.z + (1.5 * (step));    //přičti 1.5 úhlu Z rotace podle velikosti kroku
    if (angle.z >= 360)    //jestliže je úhel větší, než 360 stupňů
    {
      angle.z = angle.z -360;    //odečti 360 stupňů
    }
    //konec výpočtu rotace objektu
}
Funkci CalcFPS() voláme v nekonečné smyčce
void __fastcall TForm1::RenderGLScene()
{
    DrawCube();    //vykresli krychli
    CalcFPS();    //vypočítej fps
}
Stejný tutorial pro Delphi najdete zde


Pohyb a rotace objektu

Home