Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.11.07;
Скачать: CL | DM;

Вниз

Движение объектов в OpenGL или как замерять время   Найти похожие ветки 

 
ПсихЪ_копия   (2004-07-11 10:47) [0]

Столкнулся с такой проблемой:
Делаю:

step := Speed*( GetTickCount()-LastTime )/1000;
// step - шаг, на который изменится координата за текущий кадр (для плавного движения объекта)
// Speed - количество пикселей, которые проходит объект за секунду
// LastTime - последнее значение GetTickCount(), считаю в конце цикла отрисовки

В этоге движение осуществляется не плавно, а какими-то рывками, как буд-то step вычисляется в отдельной функции вызываемой через рендомные промежутки времени. Видимо вся проблема в глючности GetTickCount т.к. считаемый с её помощью FPS тоже невероятно прыгает и глючит (тема на счёт прыгающего FPS"а еыт на http://GameDev.ru/Forum/).

Так вот, сосбственно, вопрос - Как нормально замерять время в милличсекундах?


 
miek ©   (2004-07-11 12:19) [1]

QueryPerformanceCounter
queryperformancefrequency


 
Zeqfreed ©   (2004-07-11 12:21) [2]

Помоему нужно сначала разделить скорость на 1000 а потом только умножить на разницу во времени. т.е.:
step := (GetTickCount - LastTime) * (Speed/1000);


 
Zeqfreed ©   (2004-07-11 12:22) [3]

Хотя извиняюсь, сморозил тупость, никакой разницы вроде и нет =)


 
ПсихЪ_копия   (2004-07-11 13:30) [4]

Решение нашёл. Хотя скорее всего оно и кривое. Теперь делаю так.

Нахожу плавный, не скачущий FPS:

NowTickCount := GetTickCount();
 FPSDelta := FPSDelta + NowTickCount - FPSTickCount;
 if NowTickCount <> FPSTickCount then
   inc( FPSCnt );
 FPSTickCount := NowTickCount;
 if FPSDelta >= 500 then
 begin
   FPSCount := FPSCnt*2;
   FPSDelta := 0;
   FPSCnt := 0;
 end;


Далее, основываясь на этом FPS вычисляю шаг для изменения координат:

step := FPSCount/1000*Speed;


Единственная проблема - первые пол-секунды FPS равен 0 и ничего не движется... Если снижвать с пол-секунды до, скажем, 100 миллисекунд, тогда сильно снижается точность...

Но юзать можно.


 
Zer0 ©   (2004-07-12 02:25) [5]

GetTickCount() выдает время с точностью ~17мс
при большом fps будут проблемы


 
NailMan ©   (2004-07-12 11:14) [6]

Совет дня: не используй в играх GetTickCount - это бяка низкого разрешения.

Пользуй для синхро QueryPerformanceCounter как посоветовал miek ©, а вот как использовать расскажу я...

делаем структуру:

TSyncronize = packed record
LastHPC : Int64;
TimeOffset : Cardinal;
CorrMultiplier : Extended;
End;


Объявляем глобальные переменные:

TimerResolution : Int64;     //Разрешение одной секунды в HighPerfomance тиках
TimerMSecResolution : Cardinal;   //Разрешение одной миллисекунды


И объявляем процедуры/функции:

Procedure SetTimerResolution;
var z,z2:int64;
begin
QueryPerformanceCounter(z);
Sleep(1000);
QueryPerformanceCounter(z2);
TimerResolution:=z2 - z;
TimerMSecResolution:= round(TimerResolution / 1000);
end;

Процедура определяет разрешение HighPerfoance счетчика на конкретной машине и вычисляет разрешение 1-й миллисекунды.
Скажем на большинстве тачер очень разной конфигурации разрешение счетчика было в районе 3.5 млн тиков в секунду.

Function SetSync(msecs:Cardinal):TSyncronize;
begin
QueryPerformanceCounter(result.LastHPC);
result.TimeOffset:=TimerMSecResolution * msecs;
Result.CorrMultiplier:=1;
end;

Функция устанавливает стартовое значение синхро и задает время ожидания в миллисекундах.

Function CheckSync(Var Sync:TSyncronize):boolean;
var tickcount,subtraction:int64;
begin
result:=false;
QueryPerformanceCounter(Tickcount);
subtraction:=tickcount - Sync.LastHPC;
If subtraction>=Sync.TimeOffset then
 begin
  If Sync.TimeOffset=0 then  Sync.CorrMultiplier:=1 else
  Sync.CorrMultiplier:=subtraction / (Sync.TimeOffset);
  result:=true;
 end;
end;

Функция определяет свершилось ли событие(прошедшее время с момента установки синхро[SetSync-ом]) превысило или равно велечине времени ожидания для этого синхро) и создает коэффициент поправки.
Последний нужен для масштабирования како-го либо процесса, в т.ч. анимаци  и движений.

Пример использования:

- У каждого Актера есть свой синхро Sync:TSyncronize;
- При инициализации Актера на сцене ему задается начальное значение синхро. Скажем Actor.Sync:=SetSync(20);

- Когда должны делать обработку процессов Актера(двигаем его или че-то еще с ним творим), то делаем это так:

Procedure TActor.Processing;
begin
if CheckSync(Sync) then
BEGIN
 ...
 ...
 //roll Rotation
    If not RollActive then
      MoveCaps.RollAngularVelocity:=MoveCaps.RollAngularVelocity * 0.98
      else
        MoveCaps.RollAngularVelocity:=MoveCaps.RollAngularVelocity +
                                      MoveCaps.RollAngularAcceleration * Sync.CorrMultiplier * 0.05;

    if (MoveCaps.RollAngularVelocity<>0) then
     begin
      if (MoveCaps.RollAngularVelocity<=-MoveCaps.MaxAngularVelocity) then
          MoveCaps.RollAngularVelocity:=-MoveCaps.MaxAngularVelocity;
      if (MoveCaps.RollAngularVelocity>=MoveCaps.MaxAngularVelocity) then
         MoveCaps.RollAngularVelocity:=MoveCaps.MaxAngularVelocity;
     end;
     ...
     ...

 Sync:=SetSync(20);
END;  

Итого получаем полностью синхронизированные с производительностью машины движения. На убогих тачках коэффициент будет больше единицы и движение будет более "растянутым" по значению, а на нормальной тачке коэффициент будет близок к единице.

---
WBR, NailMan aka 2:5020/3337.13


 
Колбасьев ©   (2004-07-12 11:52) [7]

>> Единственная проблема - первые пол-секунды FPS равен 0 и
>> ничего не движется... Если снижвать с пол-секунды до, скажем,
>> 100 миллисекунд, тогда сильно снижается точность...

Надо первые пол-секунды выводить черный экран ;-)
И все будет смотрется нормально.


 
ПсихЪ_просто   (2004-07-13 13:15) [8]


> NailMan ©   (12.07.04 11:14) [6]

Огромное спасибо. Тема закрыта.


 
NailMan ©   (2004-07-13 15:57) [9]

Да кстате насчет подсчета фпс:

предпочитаю мерять фактический ФПС, а не теоретически-"реальный", т.е.

создаю мастдайный счетчик(функцией WinAPI) в котором создается строчка(создавать надо ее именно там так как в Render не должно быть лишний операций таких тяжелых как строковые) с ФПСом на основе глобальной переменной-счетчика. Там же и обнуляется. Время срабатывания 1000мс. Фактически это аналог TTimer, но без формы и рочего батута.

Счетчик инкрементируется в методе движка Render.

Таким образом считается фактическое число кадров отрендеренных за прошедшую секунду.

Что касаемо "быстрых" счетчиков ФПС(показывают хоть робные значения), то имхо это неточное число или так сказать "вероятное", потому что считается за небольшой отрезок секунды и множится на число отрезков в секунде.
Да не спорю - эффектно, но не точно. На сцене за оставшийся промежуток времени может все что угодно и заметно снизить результат. К тому же увеличение числа строковых операций(создание строки с ФПСом будет только хуже для скорости).

Вот так...

---
WBR, NailMan aka 2:5020/3337.13


 
ПсихЪ_копия   (2004-07-13 23:38) [10]


> NailMan ©   (13.07.04 15:57) [9]

Хм... А как ты выводишь ФПС на экран, не переводя его в строку или там Window.PAnsiChar?


 
NailMan ©   (2004-07-14 09:19) [11]

ПсихЪ_копия
Да не, я перевожу в строчку, но в обработчике таймера, которая выполняется раз в секунду, а в рендере только используется уже подготовленная String. Тоже самое с стокой информации(скажем можно выводить для дебага координаты чего-то), готовая строчка рендерится, а подготавливается(заполняется) когда игрок поменяет координаты.

---
WBR, NailMan aka 2:5020/3337.13


 
__?!__   (2004-07-14 10:39) [12]

Юзай GLScene, там есть Cadencer.


 
ПсихЪ_злобный_АПИшник   (2004-07-14 15:21) [13]


> __?!__   (14.07.04 10:39) [12]

Приколист... GLScene must die!!! API rulezzz!!!



Страницы: 1 вся ветка

Текущий архив: 2004.11.07;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.048 c
3-1097061190
Its
2004-10-06 15:13
2004.11.07
SQL - запрос


10-1053161214
From_X
2003-05-17 12:07
2004.11.07
Можно ли организовать двухстороннюю связь в корбе?


3-1097271774
Sid
2004-10-09 01:42
2004.11.07
IBase не находит файл *.gdb на сетевом диске


1-1098428606
Arnold
2004-10-22 11:03
2004.11.07
Как программно выделить нужную ячейку в StringGride?


14-1098027153
olookin
2004-10-17 19:32
2004.11.07
Универсализация или прагматичность?