Unit KambiTimeUtils

DescriptionUsesClasses, Interfaces, Objects and RecordsFunctions and ProceduresTypesConstantsVariables

Description

Things working with time

Uses

Overview

Functions and Procedures

procedure Delay(MiliSec: Word);
function TimeTickSecondLater(firstTime, secondTime, timeDelay: TMilisecTime): boolean;
function TimeTickDiff(firstTime, secondTime: TMilisecTime): TMilisecTime;
function MilisecTimesAdd(t1, t2: TMilisecTime): TMilisecTime;
function MilisecTimesSubtract(t1, t2: TMilisecTime): TMilisecTime;
function GetTickCount: TMilisecTime;
function DateTimeToAtStr(DateTime: TDateTime): string;
function ProcessTimerNow: TProcessTimerResult;
function ProcessTimerDiff(a, b: TProcessTimerResult): TProcessTimerResult;
procedure ProcessTimerBegin;
function ProcessTimerEnd: Double;
function KamTimer: TKamTimerResult;

Types

TKamTime = Double;
TMilisecTime = LongWord;
TProcessTimerResult = clock_t ;
TKamTimerResult = Int64;
TKamTimerFrequency = LongWord;

Constants

MinDateTime: TDateTime = MinDouble;
ProcessTimersPerSec = 128 ;
KamTimerFrequency: TKamTimerFrequency = 1000000;

Description

Functions and Procedures

procedure Delay(MiliSec: Word);
 
function TimeTickSecondLater(firstTime, secondTime, timeDelay: TMilisecTime): boolean;

zwraca czy secondTime jest pozniejsze o co najmniej timeDelay od firstTime. first i second Time sa time'ami branymi z GetTickCount, tzn. czas jest w zakresie Dword i moze sie przewinac. Tzn. kazdy czas jest rozumiany jako Later - natomiast sprawdzane jest czy czas jest pozniejszy o timeDelay. TimeTickSecond(x, x, 0) = true (czas x jest pozniejszy od x o 0 = true).

function TimeTickDiff(firstTime, secondTime: TMilisecTime): TMilisecTime;

zwraca roznice czasow secondTime-firstTime. Czasy sa brane z GetTickCount czyli sa Dwordami i moga sie przewinac.

function MilisecTimesAdd(t1, t2: TMilisecTime): TMilisecTime;

dodawanie i odejmowanie dwoch czasow. Zwroc uwage na brak precyzji : czy TMilisecTime to punkt w czasie czy okres czasu ? Nie jest to zdefiniowane, bo moze byc dowolnie. Mozesz dodac punkt czasu do okresu czasu albo dwa okresy czasu, albo dwa punkty czasu i nawet jesli to ostatnie jest bez sensu - z punktu widzenia ponizszych funkcji nie istnieje rozroznienie miedzy tymi operacjami. Przy okazji mozna zauwazyc ze skoro wynik odejmowania tez jest TMilisecTime to jesli odejmujesz dwa czasy od siebie na pewno otrzymasz wynik dodatni (innymi slowy, jezeli chcesz odjac czas mniejszy od wiekszego to funkcja ponizej zachowa sie jakby uznala ze czas sie musial "przewinac".

function MilisecTimesSubtract(t1, t2: TMilisecTime): TMilisecTime;
 
function GetTickCount: TMilisecTime;

czas od uruchomienia systemu w milisekundach (przewija sie co 49 dni)

function DateTimeToAtStr(DateTime: TDateTime): string;

zamien DateTime na "at" string czyli string w postaci "data at time". Czesto uzywam takiego formatu.

function ProcessTimerNow: TProcessTimerResult;

Values below were choosen experimentally for Linux and FreeBSD (and I know that on most UNIXes it should be 128, that's a traditional value)

function ProcessTimerDiff(a, b: TProcessTimerResult): TProcessTimerResult;
 
procedure ProcessTimerBegin;
 
function ProcessTimerEnd: Double;
 
function KamTimer: TKamTimerResult;

KamTimer is used to measure passed "real time". "Real" as opposed to e.g. process time (see ProcessTimerNow and friends above). Call KamTimer twice, calculate the difference, and you get time passed — with frequency in KamTimerFrequency.

KamTimerFrequency says how much KamTimer gets larger during 1 second (how many "ticks" are during one second).

Implementation details: Under Unix this uses gettimeofday. Under Windows this uses QueryPerformanceCounter/Frequency, unless WinAPI "performance timer" is not available, then standard GetTickCount is used.

Types

TKamTime = Double;

Time in seconds. This is used throughout my engine to represent time as a floating-point value with good accuracy in seconds. In particular, for VRML / X3D time-dependent nodes.

Implementation notes, about the choice of precision:

  • "Single" precision is sometimes not enough for this. Proof: open rotate.kanim (from kambi_vrml_test_suite). Change "on display" time pass to 1000, wait a couple seconds (world time will reach a couple of thousands), change "on display" time pass back to 1. Result: with time as Single, animation becomes jagged. Reason: the precision loss of Single time, and the fact that Draw is not called all the time (because AutoRedisplay is false, and model is in Examine mode and is still (not rotating)), so incrementation steps of AnimationTime are very very small.

    Setting AutoRedisplay to true workarounds the problem too, but that's 1. unacceptable to eat 100% CPU without a reason for utility like view3dscene 2. that's asking for trouble, after all even with AutoRedisplay = true the precision loss is there, it's just not noticeable... using better precision feels much safer.

  • For X3D, SFTime has "Double" precision. Also "The Castle" and "The Rift" prooved it's enough in practice.

    I could have choosen Extended here, but for X3D sake (to avoid unnecessary floating-point convertions all around), let's stick to Double for now.

TMilisecTime = LongWord;

nie robiac Process messages

TProcessTimerResult = clock_t ;
 
TKamTimerResult = Int64;
 
TKamTimerFrequency = LongWord;
 

Constants

MinDateTime: TDateTime = MinDouble;
 
ProcessTimersPerSec = 128 ;
 
KamTimerFrequency: TKamTimerFrequency = 1000000;
 

Generated by PasDoc 0.11.0 on 2008-09-12 11:58:28