2013-02-28 46 views
6

我有一个iPad应用程序,并使用openGL绘制主视图,并且我想在设备旋转时为我自己的更改制作动画。使用OpenGL自定义iOS界面方向更改动画

请注意,这个应用程序只偶尔画,它不是不断的动画。另外我的场景是一个(非常复杂的)2D绘图,而不是3D。我只是希望它在设备方向更改期间围绕显示中心旋转,并保持正确的宽高比。

此刻,我只是有下面的代码:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    // nothing yet 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 
    IMMainView *mv = (IMMainView *)self.view; 
    [mv createRenderbuffer]; 
    [mv drawView]; 
} 

我刚刚重新创建的OpenGL渲染缓冲区一旦旋转完成以匹配新的宽度和高度。

默认的iOS行为似乎旋转了视图,但也随着宽高比的变化而变得很奇怪。

我可以对绘图参数进行动画处理,以便在转换过程中更好地显示某些内容,但我不明白(1)如何停止iOS动画处理图层,以及(2)如何从这些方法调用中设置动画循环与iOS动画相匹配。

例如,在动画过程中,实际视图的宽度和高度是否逐渐变化?

另外一个可能的问题是什么时候重新创建渲染缓冲区的问题,因为如果OpenGL缓冲区与iOS视图边界不匹配,那么像素纵横比不正确,并且图形看起来很糟糕。

任何帮助,将不胜感激。

+0

OK我想我理解我的问题的答案的一部分,即我需要在方向更改期间继续呈现呈现缓冲区,以覆盖默认情况下显示的内容。目前,只有在需要根据用户界面更改更改视图内容时,才会显示它。 – Robotbugs 2013-02-28 00:48:22

回答

3

我花了一些时间寻找合理的方法来正确地做到这一点,并最终走了最简单的路线,只是清除willRotateToInterfaceOrientation上的屏幕,然后在didRotateFromInterfaceOrientation的正确位置呈现新内容。它看起来不那么糟糕,更好的东西的额外复杂性是不值得的恕我直言。

另外,虽然我没有去这个解决方案,与我没有太多的工作取得了动画最好的结果是这样的:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    IMMainView *mv = (IMMainView *)self.view; 
    [mv drawBlankScreen]; 

    m_oldviewsize = self.view.bounds.size; 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 
{ 
    IMMainView *mv = (IMMainView *)self.view; 

    CGPoint neworigin = mv.origin; 

    neworigin.x += 0.5f*(self.view.bounds.size.width - m_oldviewsize.width); 
    neworigin.y += 0.5f*(self.view.bounds.size.height - m_oldviewsize.height); 

    mv.origin = neworigin; 

    [mv createRenderbuffer]; 
    [mv drawView]; 
} 

来源的变化是为了重新将旋转后的绘图居中在旋转之前的相同位置。

我发现willAnimateToInterfaceOrientation在新的视图边界被计算后被调用一次。因此,我在这一点上设置了新的渲染缓冲区,因为与方面变化相关的变形不像我原来的情况那么明显。我还必须清除willRotateToInterfaceOrientation中的屏幕,因为延迟期间原始图形的变形版本清晰可见。

这样做的缺点是屏幕的清除会在动画开始时引起轻微的闪光,并且拉伸失真仍然存在但会聚在正确的外观上,不会与旧的外观发生分离跳到新的外观,所以它看起来不那么糟糕。我怀疑,任何试图通过使用绘图函数进行更新来实际跟踪视图的动画宽高比变化以持续保持正确的外观将非常复杂,并且很可能在未来对苹果公司的变化非常脆弱。

0

如下您可以旋转的顶点着色器OpenGL的输出:

#version 300 es 


in vec4 position; 
in mediump vec4 texturecoordinate; 

in vec4 color; 

uniform float preferredRotation; 

out mediump vec2 coordinate; 

void main() 
{ 
    //const float pi = 4.0 * atan(1.0); 
    //float radians = ((-90.0)/180.0 * pi); 

    // Preferred rotation of video acquired, for example, by: 
    // AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; 
    // CGAffineTransform preferredTransform = [videoTrack preferredTransform]; 
    // self.glKitView.preferredRotation = -1 * atan2(preferredTransform.b, preferredTransform.a); 

    // Preferred rotation for both portrait and landscape   
    mat4 rotationMatrix = mat4(cos(preferredRotation), -sin(preferredRotation), 0.0, 0.0, 
           sin(preferredRotation), cos(preferredRotation), 0.0, 0.0, 
           0.0,      0.0,     1.0, 0.0, 
           0.0,      0.0,     0.0, 1.0); 

    // Mirror vertical (portrait only) 
    mat4 rotationMatrix = mat4(cos(preferredRotation), sin(preferredRotation), 0.0, 0.0, 
           -sin(preferredRotation), cos(preferredRotation), 0.0, 0.0, 
           0.0,   0.0,   1.0, 0.0, 
           0.0,   0.0,   0.0, 1.0); 

    // Mirror horizontal (landscape only) 
    mat4 rotationMatrix = mat4(1.0, 0.0,      0.0,     0.0, 
           0.0, cos(preferredRotation), -sin(preferredRotation), 0.0, 
           0.0, sin(preferredRotation), cos(preferredRotation), 0.0, 
           0.0, 0.0,      0.0,     1.0); 

    // Mirror vertical (landscape only) 
    mat4 rotationMatrix = mat4(cos(preferredRotation), 0.0, sin(preferredRotation), 0.0, 
           0.0,     1.0, 0.0,     0.0, 
           -sin(preferredRotation), 0.0, cos(preferredRotation), 0.0, 
           0.0,     0.0, 0.0,     1.0); 

    gl_Position = position * rotationMatrix; 
    coordinate = texturecoordinate.xy; 
} 

对于每个垂直同步,你可以通过对preferredRotation一个新值,这将旋转视图不拉伸。

显然,您只选择一个矩阵4,具体取决于视频的方向,然后根据视频的旋转方向。每个矩阵4翻转视频窗口 - 不旋转它。对于旋转,您必须首先根据方向选择矩阵4,然后将preferredRotation变量替换为度数(以弧度表示,也提供了公式)。

有很多方法可以旋转视图,图层,对象等;但是,如果你通过OpenGL渲染图像,那么你应该选择这种方法,并且只能使用这种方法。