在 iPhone 上使用 CADisplayLink 在 OpenGL ES 视图中进行等速旋转
Posted
技术标签:
【中文标题】在 iPhone 上使用 CADisplayLink 在 OpenGL ES 视图中进行等速旋转【英文标题】:Constant-velocity rotation in OpenGL ES view using CADisplayLink on iPhone 【发布时间】:2010-11-06 20:05:34 【问题描述】:我的 OpenGL ES 类和代码源自 Apple 的 GLES2Sample code sample。我用它们来展示 3D 对象围绕一个轴平滑旋转,我期望的旋转速度是恒定的。目前app使用1帧间隔,每次绘制OpenGL视图(在EAGLView的drawView
方法中),我将模型旋转一定角度。
在实践中,这给出了不错的结果,但并不完美:在旋转过程中,当物体的大部分看不见时,渲染变得更快,因此旋转没有恒定的角速度。我的问题是:如何让它更流畅?
虽然我欢迎所有建议,但我已经有了一个想法:每半秒测量一次渲染 FPS,并在此基础上调整每次重绘时的旋转角度。然而,这听起来不太好,所以:您如何看待这个问题,您将如何处理这个问题?
【问题讨论】:
【参考方案1】:我倾向于使用 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);
而不是保留自己的变量。但是,除了最微不足道的情况外,您通常希望每个时间片做一大堆复杂的事情。
【讨论】:
【参考方案2】:如果您不希望渲染速度发生变化,并且您不希望使用 CADisplayLink 或其他动画计时器运行开环(即完全倾斜),您可以做两件事:
1) 优化您的代码,使其永远不会低于 60 FPS - 在任何情况下使用您的型号的设备的最大帧速率。
2) 在运行时,通过几个完整的周期测量应用程序的帧速率,并设置绘制速率,使其永远不会超过您测量的最低绘制性能。
我认为调整旋转角度不是解决此问题的正确方法,因为您现在正试图保持两个参数(绘制速率和旋转速率)相互调整,而不是简单地固定一个参数:绘制速率.
干杯。
【讨论】:
以上是关于在 iPhone 上使用 CADisplayLink 在 OpenGL ES 视图中进行等速旋转的主要内容,如果未能解决你的问题,请参考以下文章
仅在 iphone 11 上显示 UI 图像在其他 iphone 版本上隐藏
无法使用 JavaScript 在 iPhone 上播放声音,但可以在 Android 上播放
在 iPhone 上使用 UISplitViewController 时如何实现推送导航?
苹果 mapkit 在中国可以在 iPhone 设备上使用吗