我正在用perl编写一个面向对象的OpenGL框架,当我测量每帧之间的DeltaTime时,我遇到了一个奇怪的问题。增量时间似乎每隔一段时间就会消失(每隔约0.5秒)。 我不确定这是否是gettimeofday的问题,或者它是否是GLUT如何调用我的回调的问题,但它非常烦人,因为它使我的精灵的运动每半秒跳一次。
这是我的主要循环功能:
# This is called everytime in the main glut loop
sub Tick
{
my $this = shift;
my ($now, $dt);
$now = gettimeofday;
$dt = $now - $this->{_oldTime};
if ($dt < 0)
{
my $dterr;
$dterr = $now - $this->{_oldErrorTime};
print "WTF! We just encountered a time paradox! " .
"This function was last called $dt seconds ago...\n" .
"Current time: $now, Last call: $this->{_oldTime}\n" .
"We already encountered this error $dterr seconds ago.\n\n";
$this->{_oldErrorTime} = $now;
}
$this->{_oldTime} = $now;
$this->{FPS} = 1.0 / $dt;
$this->Update($dt);
$this->DrawFrame($dt);
}
这是输出:
WTF!我们刚遇到一个时间悖论!最后调用此函数 -0.017144 9184417725秒前...当前时间:1340196716.27624,最后来号:1340196716.29339我们已经遇到过这个错误 0.482785940170288秒前。
WTF!我们刚遇到一个时间悖论!最后调用此函数 -0.013265 84815979秒前...当前时间:1340196716.74632,最后得到:1340196716.75959我们已经碰到过这个错误 0.470081090927124秒前。
WTF!我们刚遇到一个时间悖论!最后调用此函数 -0.011317 9683685303秒前...当前时间:1340196717.21836,最后得到的号码:1340196717.22968我们已经碰到过这个错误 0.472035884857178秒前。
WTF!我们刚遇到一个时间悖论!最后调用此函数 -0.015201 0917663574秒前...当前时间:1340196717.68649,最后来电日:1340196717.70169我们已经遇到这个错误 0.468127012252808秒前。
答案 0 :(得分:4)
您需要CLOCK_MONOTONIC,请参阅Time::HiRes。
答案 1 :(得分:1)
感谢你们的回答,我想出了这种跨平台的单调秒表功能:
use constant WIN32 => $^O eq "MSWin32";
our $QueryPerformanceCounter = undef;
our $QueryPerformanceFrequency = undef;
our $qpf = undef;
sub GetTime
{
# Windows
if (WIN32)
{
my ($count, @unpacked_count);
require Win32::API;
Win32::API->import();
if (!$QueryPerformanceCounter || !$QueryPerformanceFrequency || !$qpf)
{
my ($freq, @unpacked_freq);
$QueryPerformanceCounter = new Win32::API(
"Kernel32", "QueryPerformanceCounter", [qw(P)], 'I')
or Carp::croak("GLPerl::Utils::GetTime(): Failed to get QueryPerformanceCounter: " .
Win32::FormatMessage(Win32::GetLastError()));
$QueryPerformanceFrequency = new Win32::API(
"Kernel32", "QueryPerformanceFrequency", [qw(P)], 'I')
or Carp::croak("GLPerl::Utils::GetTime(): Failed to get QueryPerformanceFrequency: " .
Win32::FormatMessage(Win32::GetLastError()));
$freq = pack 'I2', 0;
Carp::croak("GLPerl::Utils::GetTime(): QueryPerformanceFrequency call failed: " .
Win32::FormatMessage(Win32::GetLastError()))
unless ($QueryPerformanceFrequency->Call($freq));
@unpacked_freq = reverse unpack 'I2', $freq;
$qpf = $unpacked_freq[0] * 2**32 + $unpacked_freq[1];
}
$count = pack 'I2', 0;
Carp::croak("GLPerl::Utils::GetTime(): QueryPerformanceCounter call failed: " .
Win32::FormatMessage(Win32::GetLastError()))
unless ($QueryPerformanceCounter->Call($count));
@unpacked_count = reverse unpack 'I2', $count;
return ($unpacked_count[0] * 2**32 + $unpacked_count[1]) / $qpf;
}
# Linux
require Time::HiRes;
Time::HiRes->import(qw(clock_gettime));
eval "return clock_gettime(CLOCK_MONOTONIC);";
}