0

我的 OpenGL ES 类和代码源自 Apple 的GLES2Sample 代码示例。我使用它们来显示 3D 对象围绕一个轴平滑旋转,我期望的旋转速度是恒定的。目前,应用程序使用的帧间隔为 1,每次绘制 OpenGL 视图(在 EAGLView 的drawView方法中),我都会将模型旋转一定角度。

在实践中,这给出了不错的结果,但并不完美:在旋转过程中,当物体的大部分消失时,渲染变得更快,因此旋转没有恒定的角速度。我的问题是:如何使它更平滑?

尽管我欢迎所有建议,但我已经有了一个想法:每半秒测量一次渲染 FPS,并在此基础上调整每次重绘时的旋转角度。但是,这听起来不太好,所以:您对此有何看法,您将如何处理这个问题?

4

2 回答 2

3

我倾向于使用 CADisplayLink 来触发新帧,并在帧请求中进行简单的时间计算,以确定我的逻辑可以推进多远。

假设您有一个 NSTimeInterval 类型的成员变量 timeOfLastDraw。你希望你的逻辑以每秒 60 次的速度打勾。然后(使用一大堆变量使代码更清晰):

- (void)displayLinkDidTick
{
    // get the time now
    NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];

    // work out how many quantums (rounded down to the nearest integer) of
    // time have elapsed since last we drew
    NSTimeInterval timeSinceLastDraw = timeNow - timeOfLastDraw;
    NSTimeInterval desiredBeatsPerSecond = 60.0;
    NSTimeInterval desiredTimeInterval = 1.0 / desiredBeatsPerSecond;

    NSUInteger numberOfTicks = (NSUInteger)(timeSinceLastDraw / desiredTimeInterval);

    if(numberOfTicks > 8)
    {
        // if we're more than 8 ticks behind then just do 8 and catch up
        // instantly to the correct time
        numberOfTicks = 8;
        timeOfLastDraw = timeNow;
    }
    else
    {
        // otherwise, advance timeOfLastDraw according to the number of quantums
        // we're about to apply. Don't update it all the way to now, or we'll lose
        // part quantums
        timeOfLastDraw += numberOfTicks * desiredTimeInterval;
    }

    // do the number of updates
    while(numberOfTicks--)
        [self updateLogic];

    // and draw
    [self draw];
}

在您的情况下, updateLogic 将应用固定数量的旋转。如果你真的想要恒定旋转,那么你可以将旋转常数乘以 numberOfTicks,或者甚至跳过整个方法并执行以下操作:

glRotatef([NSDate timeIntervalSinceReferenceData] * rotationsPerSecond, 0, 0, 1);

而不是保留自己的变量。但是,除了最微不足道的情况外,您通常希望在每个时间量子上做一大堆复杂的事情。

于 2010-11-07T22:46:56.853 回答
1

如果您不希望渲染速度发生变化,并且您不希望使用 CADisplayLink 或其他动画计时器运行开环(即完全倾斜),您可以做两件事:

1) 优化您的代码,使其永远不会低于 60 FPS - 设备在任何情况下与您的模型的最大帧速率。

2) 在运行时,通过几个完整的周期测量您的应用程序的帧速率,并设置绘制速率,使其永远不会超过您测量的最低绘制性能。

我相信调整你的旋转角度不是解决这个问题的正确方法,因为你现在正试图保持两个参数相互调整(绘制速率和旋转速率),而不是简单地固定一个参数:绘制速率。

干杯。

于 2010-11-07T22:00:06.753 回答