OpenGL v Delphi 5



Výpočet FPS a plynulé animace


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

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

Vše počítá proceduraCalcFPS
unit KTime;

interface

var
  step: single;   //proměnná pomocí které plynule běhá animace

procedure CalcFps;    //výpočet fps a plynulé animace



implementation

uses
  Windows, Sysutils, KRenderForm, Dialogs;


var
  time2fps: integer;    //druhý čas fps
  time2synchro: integer;    //druhý čas synchronizace
  frame: integer;    //hodnota snímku fps
  synchro_frame: integer=1;    //hodnota snímku synchronizace

procedure CalcFps;     //vypočítej fps a plynulou animaci
var
  counter: TLargeInteger;    //aktuální počítadlo
  freq: TLargeInteger;    //výpočetní výkon za jednu sekundu
  time1fps: integer;    //prvni čas fps
  time1synchro: integer;    //první čas synchronizace
begin
  if QueryPerformanceCounter(counter) then begin    //jestliže systém podporuje Performance tak načti aktuální počítadlo
    QueryPerformanceFrequency(freq);    //načti výpočetní výkon za jednu sekundu
    time1fps := counter div freq;     //převeď na sekundu
    time1synchro := counter div (freq div 10);    //převeď na desetiny sekundy
    if time1fps > time2fps  then begin    //pokud je první čas pro výpočet FPS vyšší než druhý
      Form1.Label1.Caption := ' fps: ' + IntToStr(frame);    //do editu vypiš hodnotu frame (FPS)
      frame := 0;    //vynuluj frame
    end;
    if time1synchro > time2synchro then begin    //pokud je první čas pro výpočet synchronizace vyšší než druhý
      step := 8 / synchro_frame;    //vypočítej last_frame, podle kterého běží animace
      synchro_frame := 0;    //vynuluj synchronizační snímky
    end;

    frame := frame + 1;    //jinak přičti snímek
    time2fps := time1fps;    //hoď první čas fps do druhého
    synchro_frame := synchro_frame + 1;    //přičti synchonizační snímek
    time2synchro := time1synchro;    //hoď první čas synchronizace do druhého
  end;
end;
Princip je jednoduchý.
QueryPerformanceCounter(counter) - nám vyhodí aktuální stav počítadla v milisekundách.
QueryPerformanceFrequency(freq); - 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 div freq; dostaneme hodnotu, která se bude každou sekundu zvyšovat o jedničku.
Pak budeme přičítat snímky frame := frame + 1; , 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 div (freq div 10);
Opět přičítám snímky synchro_frame := synchro_frame + 1;, dokud nedojde ke zvýšení hodnoty if time1synchro > time2synchro. Pokud ke zvýšení hodnoty dojde, tak vypočítám velikost kroku animace step := 8 / synchro_frame; a snímky vynuluju.synchro_frame := 0;

Při výpočtu animace pak násobím hodnoty animace hodnotou step
procedure TranRotCube;
begin
    //začátek výpočtu pohybu objektu
    if (start) then     //jestliže probíhá první otočka cyklu
    begin
      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
    end;

    if ((translate.x >= 3) or (translate.x <= -3)) then  //jetliže X pozice objektu přesáhne hodnoty 3 nebo -3
    begin
        direction.x := -direction.x;    //otoč směr pohybu X
    end;
    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) or (translate.y <= -2)) then    //jetlize Y pozice objektu přesáhne hodnoty 2 nebo -2
    begin
        direction.y := -direction.y;    //otoč směr pohybu Y
    end;
    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) or (translate.z <= -20)) then    //jetliže Z pozice objektu přesáhne hodnoty -6 nebo -20
    begin
        direction.z := -direction.z;    //otoč směr pohybu Z
    end;
    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) then    //jestliže je úhel větší, než 360 stupňů
    begin
      angle.x := angle.x -360;    //odečti 360 stupňů
    end;

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

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


Pohyb a rotace objektu

Home