iPhone 3D 円盤

GLKitを使って円盤を表示するiPhoneアプリを書いてみます。モデルデータは、Photoshopの3Dを使ってobjファイルをエクスポート、「obj2opengl.pl」をターミナルで実行してplate.hというファイルを作成しました。


動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。

サンプルコード

// ————————-

// ViewController.h

// ————————-

#import <GLKit/GLKit.h>

@interface ViewController : GLKViewController

@end

// ————————-

// ViewController.m

// ————————-

#import “ViewController.h”

#import “plate.h”

@interface ViewController () {

    GLuint v;

    GLuint nv;

    BOOL toss;

    float angle;

    float height;

}

@property (strong, nonatomic) GLKBaseEffect *baseEffect;

@property (strong, nonatomic) GLKView *gv;

@end

@implementation ViewController

@synthesize baseEffect, gv;

– (void)loadView

{

    self.view = [[GLKView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) context:[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]];

}

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    gv = (GLKView*)self.view;

    gv.drawableDepthFormat = GLKViewDrawableDepthFormat16;

    gv.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    [EAGLContext setCurrentContext:gv.context];

    

    self.baseEffect = [[GLKBaseEffect alloc] init];

    self.baseEffect.light0.enabled = GL_TRUE;

    self.baseEffect.light0.diffuseColor = GLKVector4Make(0.9f,0.9f,0.4f,1.0f);

    self.baseEffect.light0.position = GLKVector4Make(-0.8f,-0.8f,-3.0f,0.8f);

    self.baseEffect.light0.ambientColor = GLKVector4Make(0.7f, 0.7f, 0.7f, 1.0f);

    

    glClearColor(.4f, .4f, .6f, 1.0f);

    

    glGenBuffers(1, &v);

    glBindBuffer(GL_ARRAY_BUFFER, v);

    glBufferData(GL_ARRAY_BUFFER, sizeof(plateVerts), plateVerts, GL_STATIC_DRAW);

    

    glGenBuffers(1, &nv);

    glBindBuffer(GL_ARRAY_BUFFER, nv);

    glBufferData(GL_ARRAY_BUFFER, sizeof(plateNormals), plateNormals, GL_STATIC_DRAW);

    

    glEnable(GL_DEPTH_TEST);

    

    self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeRotation(0.4, 1, 0, 0);

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    toss = !toss;

}

– (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

{

    [self.baseEffect prepareToDraw];

    

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    

    glBindBuffer(GL_ARRAY_BUFFER, v);

    glEnableVertexAttribArray(GLKVertexAttribPosition);

    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL + 0);

    

    glBindBuffer(GL_ARRAY_BUFFER, nv);

    glEnableVertexAttribArray(GLKVertexAttribNormal);

    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 3* sizeof(GLfloat), NULL + 0);

    

    const GLfloat  aspectRatio = (GLfloat)view.drawableWidth / (GLfloat)view.drawableHeight;

    self.baseEffect.transform.projectionMatrix = GLKMatrix4MakeScale(0.5f, 0.5 * aspectRatio, 0.5f);

    self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeRotation(0.4, 1, 0, 0);

    

    // coin toss

    if (toss) {

        GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;

        if (height < 3) {

            height += 0.05;

            angle += 15;

            modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0, height, 0);

            modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix,GLKMathDegreesToRadians(angle), 1.0f, 0.0f, 0.0f);

        } else {

            toss = NO;

            height = 0;

        }

        self.baseEffect.transform.modelviewMatrix = modelViewMatrix;

    }

    

    glDrawArrays(GL_TRIANGLES, 0, plateNumVerts);

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end