OpenGL ESテンプレート(4)~GLFunViewControllerクラス(3)

2012. 02. 08
12)startAnimationメソッド

- (void)startAnimation
{
    if (!animating)
    {
        CADisplayLink *aDisplayLink = [[UIScreen mainScreen] displayLinkWithTarget:self
         selector:@selector(drawFrame)];
        [aDisplayLink setFrameInterval:animationFrameInterval];
        [aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop]
         forMode:NSDefaultRunLoopMode];
        self.displayLink = aDisplayLink;

        animating = TRUE;
    }
}

startAnimationメソッドは、ビューが表示される時やアプリケーションがアクティブになった時に呼び出される、アニメーションを開始するメソッドです。

フラグanimatingがFALSE(無効)な場合は以下の処理を行い、既にTRUE(有効)な場合は何もせず、現在行われているアニメーションが継続することになります。

最初に、ディスプレイのリフレッシュレートとアプリケーションの描画を同期させるタイマーオブジェクトである、仮のディスプレイリンクaDisplayLinkを生成します。
(詳細は『CADisplayLinkクラス』の概要を参照)

mainScreenメソッドでデバイスの画面を表す画面オブジェクトを取得し、その画面に対してdisplayLinkWithTarget:selector:メソッドで新しいディスプレイリンクを作成します。

アプリケーションの実行ループから画面が更新されたとの通知を受け取る度に、セレクタに設定しているdrawFrameメソッドが呼び出されます。

setFameIntervalはframeIntervalプロパティのセッタで、awakeFromNibメソッドで設定したフレームレート用の定数animationFrameIntervalを指定しています。

addToRunLoop:forMode:メソッドはアプリケーションの実行ループにディスプレイリンクを追加するもので、currentRunLoopメソッドで取得した現在の実行ループに登録します。

NSDefaultRunLoopModeは一般的に使用される実行ループモードです。

画面全体にOpenGL ESコンテンツを表示している場合は問題無いと思いますが、メニューを開いたり、ビューのスクロールをしているとタイマーが停止してしまうので、その場合はNSRunLoopCommonModesを使用すると良いようです。
(『(旧) Cocoaの日々/画面キャプチャその9 - タイマー取り込み(3)』、『Live2Dスタッフブログ/iPhone OpenGL ESメモ「スクロール中に描画されない」』、『Cocoa Foundationクラス勉強(2)』参照)

そしてdisplayLinkプロパティに仮のディスプレイリンクaDisplayLinkを設定し、最後にフラグanimatingを有効にします。

mainScreen

+ (UIScreen *)mainScreen

デバイスの画面を表す画面オブジェクトを返します。

戻り値はデバイスの画面オブジェクトです。

displayLinkWithTarget:selector:

+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel

新しいディスプレイリンクを返します。

戻り値は新たに構築されたディスプレイリンクになります。

ターゲット上で呼び出されるセレクタは、以下のシグネチャを持つメソッドにする必要があります。

- (void) selector:(CADisplayLink *)sender;

センダーは、このメソッドによって返されるディスプレイリンクです。

新たに構築されたディスプレイリンクはターゲットを保持します。

target:画面が更新された時にオブジェクトに通知するターゲットを指定します。

sel:ターゲット上で呼び出すメソッドを指定します。

frameInterval

@property(nonatomic) NSInteger frameInterval

ディスプレイリンクがターゲットを再度通知する前に経過する必要があるフレーム数です。

デフォルト値は1で、ディスプレイのリフレッシュレートで通知されるアプリケーション内の結果になります。

値が1より大きい値に設定されている場合、ディスプレイリンクはネイティブのリフレッシュレートの極僅かな時間でアプリケーションに通知します。

例えば間隔を2と設定すると、ディスプレイリンクが他の全てのフレームを発生させるのに、半分のフレームレートを提供します。

値が1より小さい値にに設定されている場合の動作は未定義で、プログラマのエラーになります。

addToRunLoop:forMode:

- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode

実行ループにディスプレイリンクを登録します。

複数の入力モードのディスプレイリンクに関連付けることができます。

実行ループが指定したモードで実行している間、ディスプレイリンクは新しいフレームが要求された時にターゲットを通知します。

実行ループはディスプレイリンクを保持します。

全ての実行ループからディスプレイリンクを削除するには、ディスプレイリンクにinvalidateメッセージを送信します。

runloop:ディスプレイリンクに関連付ける実行ループを指定します。

mode:実行ループに追加するディスプレイリンクのモードを指定します。
カスタムモードを指定するか、『NSRunLoop Class Reference』に記載されているモードの一つを使用することができます。

currentRunLoop

+ (NSRunLoop *)currentRunLoop

現在のスレッドのNSRunLoopオブジェクトを返します。

実行ループにまだスレッドが存在しない場合、生成されて返されます。

実行ループモード

NSRunLoopは以下の実行ループモードを定義します。

extern NSString* const NSDefaultRunLoopMode;
extern NSString* const NSRunLoopCommonModes;

NSDefaultRunLoopMode
NSConnectionオブジェクト以外の入力ソースを処理するモードです。
これは最も一般的に使用される実行ループモードです。

NSRunLoopCommonModes
オブジェクトは、『一般的な』モードのセットのメンバーとして宣言されている全ての実行ループモードによって監視されているものとして、この値を使用して実行ループに追加します。
詳細についてはCFRunLoopAddCommonModeを参照してください。

NSConnectionとNSApplicationによって以下の実行ループモードが追加で定義されています。

NSConnectionReplyMode 
NSModalPanelRunLoopMode 
NSEventTrackingRunLoopMode 


13)stopAnimationメソッド

- (void)stopAnimation
{
    if (animating)
    {
        [self.displayLink invalidate];
        self.displayLink = nil;
        animating = FALSE;
    }
}

stopAnimationメソッドは、ビューが非表示になる時やアプリケーションが非アクティブになる時に呼び出される、アニメーションを停止するメソッドです。

startAnimationメソッドとは逆に、フラグanimatingがTRUE(有効)な場合は以下の処理を行い、既にFALSE(無効)な場合は何もせず、アニメーションの停止状態が継続することになります。

最初にinvalidateメソッドで、実行ループからディスプレイリンクを削除し、その後ディスプレイリンクオブジェクトdisplayLinkをnilに設定して空にします。

最後にフラグanimatingを無効に設定します。

invalidate

- (void)invalidate

全ての実行ループのモードからディスプレイリンクを削除します。

全ての実行ループのモードからディスプレイリンクを削除すると、実行ループによって解放されます。

ディスプレイリンクもまたターゲットを解放します。


14)drawFrameメソッド

- (void)drawFrame
{
    [(EAGLView *)self.view setFramebuffer];

    // Replace the implementation of this method to do your own custom drawing.

    static const GLfloat squareVertices[] = {
        -0.5f, -0.33f,
        0.5f, -0.33f,
        -0.5f, 0.33f,
        0.5f, 0.33f,
    };

    static const GLubyte squareColors[] = {
        255, 255, 0, 255,
        0, 255, 255, 255,
        0, 0, 0, 0,
        255, 0, 255, 255,
    };

    static float transY = 0.0f;

    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    if ([context API] == kEAGLRenderingAPIOpenGLES2)
    {
        // Use shader program.
        glUseProgram(program);

        // Update uniform value.

        glUniform1f(uniforms[UNIFORM_TRANSLATE], (GLfloat)transY);
        transY += 0.075f;

        // Update attribute values.

        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, squareColors);
        glEnableVertexAttribArray(ATTRIB_COLOR);

        // Validate program before drawing. This is a good check, but only really necessary in a
        // debug build.
        // DEBUG macro must be defined in your debug configurations if that's not already the
        // case.

#if defined(DEBUG)
        if (![self validateProgram:program])
        {
            NSLog(@"Failed to validate program: %d", program);
            return;
        }
#endif
    }
    else
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
        transY += 0.075f;

        glVertexPointer(2, GL_FLOAT, 0, squareVertices);
        glEnableClientState(GL_VERTEX_ARRAY);
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
        glEnableClientState(GL_COLOR_ARRAY);
    }

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    [(EAGLView *)self.view presentFramebuffer];
}

drawFrameメソッドでは、以下の処理を行っています。

・setFramebufferメソッドによる、フレームバッファの生成とバインド、ビューポートの設定
・図形の頂点座標配列の設定
・図形の頂点色配列の設定
・図形が移動するアニメーション用の定数の設定
・背景色の設定とクリア(塗りつぶし)
・図形の頂点配列の設定と有効化(OpenGL ES 1.1と2.0用)
・図形の頂点配列の描画
・presentFramebufferメソッドによる、フレームバッファの表示

setFramebufferメソッドの呼び出し)

EAGLViewクラスのsetFramebufferメソッドを呼び出し、フレームバッファオブジェクトの生成とバインド、およびビューポートの設定を行っています。
(詳細は後述します)

頂点座標配列の設定)

コメント文で『独自のカスタム描画を行うには、このメソッドの実装を置換してください』とあるように、背景や描画するプリミティブの設定はここで行われています。

頂点座標配列squareVertices[ ]は、描画する四角形の頂点座標を設定しています。

(C)Y
(D)
 
(-0.5f, 0.33f) (0.5f, 0.33f)
   
(-0.5f, -0.33f) (0.5f, -0.33f)
→ X
(A) (B)

頂点色配列の設定)

頂点色配列squareColors[ ]は、各頂点の色を設定しています。

(C) (D)
 
Black
(0, 0, 0, 0)
 Magenta
(255, 0, 255, 255)
   
Yellow
(255, 255, 0, 255)
 Cyan
(0, 255, 255, 255)
 
(A) (B)

アニメーション用定数の設定)

図形が上下に反復移動するアニメーション用に、定数transYの初期値を0.0fに設定します。

詳細は後述しますが、transYはdrawFrameメソッドが呼び出されるごとにインクリメントされ、図形を描画する際の変換座標としてsin(transY)を与えることで上下の反復移動が実現されています。

背景色の設定と適用)

glClearColorでカラーバッファのクリア値(不透過の50%グレー)を設定し、glClearでカラーバッファ値でバッファをクリア(背景色の塗りつぶし)を行っています。

頂点配列の設定と有効化)

レンダリングコンテキストから、APIプロパティでサポートされているOpenGL ESのレンダリングAPIのバージョンを取得します。

取得したバージョンがkEAGLRenderingAPIOpenGLES2ならOpenGL ES 2.0、kEAGLRenderingAPIOpenGLES1ならOpenGL ES 1.1用のコンテキストとなるので、それに応じて頂点配列の設定と有効化を行います。

API

@property(readonly) EAGLRenderingAPI API

レシーバでサポートされているOpenGL ESのレンダリングAPIのバージョンを取得します。(読み込みのみ)



参考文献

iOS OpenGL ESプログラミングガイド

UIScreen Class Reference

CADisplayLink Class Reference

NSRunLoop Class Reference

EAGLContext Class Reference

(旧) Cocoaの日々/画面キャプチャその9 - タイマー取り込み(3)

Live2Dスタッフブログ/iPhone OpenGL ESメモ「スクロール中に描画されない」

Cocoa Foundationクラス勉強(2)






Bose QuietComfort 20
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
08 | 2017/09 | 10
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Bose QuietComfort 20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR