6

私は iPad アプリを持っていて、openGL でメイン ビューを描画しています。デバイスが回転したときに自分の変更をアニメーション化したいと考えています。

このアプリはたまにしか描画しないことに注意してください。常にアニメーション化されているわけではありません。また、私のシーンは (非常に複雑な) 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 ビューの境界と一致しない場合、ピクセルの縦横比が正しくなく、描画の見栄えが悪いためです。

どんな助けでも大歓迎です。

4

2 に答える 2

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また、元の図面の歪んだバージョンがはっきりと見えるようになるまでに遅延があるため、画面をクリアする必要がありました。

これの欠点は、画面をクリアするとアニメーションの開始時にわずかなフラッシュが発生し、ストレッチ歪みはまだ存在しますが、古い外観から逸脱せずに正しい外観に収束し、その後にジャンプすることです。新しい外観なので、それほど悪くはありません。描画機能を使用して更新し、ビューのアニメーションのアスペクト比の変化を実際に追跡して正しい外観を継続的に維持しようとすると、実装が非常に複雑になり、将来的にAppleが変更する可能性が非常に高くなる可能性があります。

于 2013-02-28T21:52:53.677 に答える
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;
}

各 vSync で、preferredRotation に新しい値を渡すことができます。これにより、ビューが引き伸ばされずに回転します。

明らかに、ビデオの向きとその回転に応じて、matrix4 を 1 つだけ選択します。各 matrix4 は、ビデオ ウィンドウを反転します。回転はしません。回転の場合、最初に向きに基づいて matrix4 を選択し、次に、preferredRotation 変数を度数 (ラジアン単位、式も提供されています) に置き換える必要があります。

ビュー、レイヤー、オブジェクトなどを回転させる方法はたくさんあります。ただし、OpenGL 経由で画像をレンダリングする場合は、この方法を選択し、この方法のみを選択する必要があります。

于 2016-03-30T17:11:50.137 に答える