Custom animation of iOS interface orientation changes with OpenGL

I have an iPad app and paint the main view using openGL, and I want to animate my own change when the device is rotated.

Please note that this application only draws from time to time, it is not constantly animated. Also my scene is a (very complex) 2D drawing, not 3D. I just want it to simply rotate around the center of the display while changing the orientation of the device, while maintaining the correct aspect ratio.

Currently, I only have the following code:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { // nothing yet } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { IMMainView *mv = (IMMainView *)self.view; [mv createRenderbuffer]; [mv drawView]; } 

I just re-create the OpenGL rendering buffer to match the new width and height after the rotation is complete.

The default behavior of iOS seems to rotate the view, but it also changes strangely as the aspect ratio changes.

I can animate the drawing options so that something is better displayed during the transition, but I do not understand (1) how to stop the iOS animation of my level and (2) how to set up the animation loop from these method calls that corresponds to the iOS animation.

For example, does the actual width and height of the view change during the animation?

There may also be a question about when you need to recreate the visualization buffer, because if the OpenGL buffer does not meet the iOS viewing restrictions, then the pixel proportions are not correct, and the picture looks bad.

Any help would be appreciated.

+6
source share
2 answers

I spent some time on sensible ways to do it right and thus ended the simplest route, which should simply clear the screen from willRotateToInterfaceOrientation , and then display the new content in the right place in didRotateFromInterfaceOrientation , It just doesnโ€™t look so bad, and there is too much complexity for something better not worth IMHO.

Alternatively, although I did not go for this solution, the best result with the animation that I achieved with not too much work was something like this:

 - (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]; } 

The change in origin is intended to re-center the graph after the turn in the same place in which it was before the turn.

I found that willAnimateToInterfaceOrientation is called once after calculating the new ratings. Therefore, I set up a new rendering at this point, because the distortion associated with the change in aspect is not as noticeable as my original case. I also had to clear the screen in willRotateToInterfaceOrientation because there is a delay during which a distorted version of the original drawing is clearly visible.

The disadvantage of this is that cleaning the screen causes a slight flash at the beginning of the animation, as well as stretching distortions are still present, but converge on the correct appearance, without departing from the old look, followed by a new look, so it doesnโ€™t look so bad. I suspect that any attempt to actually track changes in the proportions of the animation of the view with the update using my drawing function to constantly maintain the correct appearance will be quite difficult to implement and will probably be very vulnerable to Apple, which will change the situation in the future.

+3
source

You can rotate the OpenGL output in the vertex shader as follows:

 #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; } 

With each vSync, you can pass a new value to preferredRotation, which will rotate the view without stretching.

Obviously, you select only one matrix4, depending on the orientation of the video, and then its rotation. Each matrix 4 flips the video window - does not rotate it. To rotate, you must first select the matrix4 based on the orientation, and then replace the preferredRotation variable with the number of degrees (in radians, a formula for which is also provided).

There are many ways to rotate a view, layer, object, etc .; but if you create an image through OpenGL, then you should choose this method and only this method.

0
source

All Articles