プロジェクトの作成

Last update: 2014/06/04

ここでは、iOSアプリのプロジェクト作成から Live2D モデルを表示するまでの手順を説明します。

用意するもの
  • Xcode (ここではXcode 5.1.1を使用します)
  • Live2D ライブラリ
    (ダウンロードしたLive2D SDK の「lib」フォルダにある「Debug-iphoneos」、「Debug-iphonesimulator」、「Release-iphoneos」、「Release-iphonesimulator」フォルダ。
     ここでは、1.0.02のバージョンを使用します
  • Live2D のリソース
本来は、Live2Dのリソースは作成するモデルに応じてそれぞれ準備します。
ここではサンプルプロジェクトの「ハル」のリソースを使って説明をしていきます。

/sample/simple/res/haru/
  • haru.moc
  • haru.1024/haru.1024/texture_00.png
  • haru.1024/haru.1024/texture_01.png
  • haru.1024/haru.1024/texture_02.png



◆プロジェクトの作成と下準備

新規プロジェクトを作成して、必要なファイルをインポートしていきます。

Xcodeを起動して、メニューバーの「File」 > 「New」 > 「Project...」をクリックします。



作成するプロジェクトを聞かれるので、「Single View Application」を選択して「Next」をクリックします。



プロジェクト名などを設定して「Next」をクリックし、保存場所を指定して「Create」をクリックします。
ここでは、Product Nameを「Live2DSample」とします。




次に、必要なファイルをプロジェクトに追加していきましょう。

まずはライブラリやモデルファイルなどを入れるグループを作成します。
Xcode上でプロジェクトのルートで右クリックし、「New Group」をクリックします。



ここでは、グループ名は「Resources」とします。



Live2D SDKの、/sample/simple/res の中にある、モデルファイルとテクスチャを、
先ほど作成した Resources グループにドラッグアンドドロップします。


追加時の設定では、ここでは以下のようにします。



SDKの/lib内のライブラリ、/include内のヘッダファイルも同様に追加します。



追加したら以下のようになります。



ライブラリなどの追加が終わったら、追加したライブラリを使えるように設定しましょう。

プロジェクトから、「Build Settings」 > 「Linking」 > 「Other Linker Flags」 に、-lLive2D と記述します。
※-lLive2D の "l" は小文字のLです。大文字の I (アイ)や | (バーティカルバー)ではありませんので注意してください。





プロジェクトから「Build Settings」 > 「Search Paths」 > 「Library Search Paths」 には、ライブラリまでのパスを、
「Build Settings」 > 「Search Paths」 > 「User Header Search Paths」には、
ライブラリのヘッダファイル(上で追加した「include」フォルダ内のファイル)までのパスを設定します。

ここでは、「Library Search Paths」に $(SRCROOT)/$(CONFIGURATION)-$(PLATFORM_NAME) 、
「User Header Search Paths」に $(SRCROOT)/include と設定します。
    $(SRCROOT) : プロジェクトまでのフルパス
    $(CONFIGURATION) : デバッグとリリースのどちらでビルドされるか(Debug、Release)
    ・$(PLATFORM_NAME) : プラットフォームの名前(iPhoneosなど)




最後に、「Build Settings」 > 「Apple LLVM 5.0 - Preprocessing」 > 「Preprocessor Macros」に、
L2D_TARGET_IPHONE を追加すれば、ライブラリを使用する準備は完了です。




OpenGLの設定

次はLive2Dモデルを表示させるための、OpenGLの設定を行います。

プロジェクト内の Live2DSample グループを右クリックして、「New File...」をクリック。
Objective-C class を選択して「Next」をクリック、クラス名を設定して「Next」をクリック、
ファイルの保存場所を指定して「Create」をクリックします。
ここでは、クラス名を「EAGLView」とし、SubclassはUIViewとします。





また、プロジェクト作成時に自動生成されたAppDelegate.m、ViewController.m、上で作成したEAGLView.m
の拡張子を、 ".m" から ".mm" に変えます。
Live2Dのライブラリは、C++で記述されているため、iPhoneで利用するには
拡張子が .cpp (C++用拡張子)もしくは .mm ( Objective-CとC++を混在できる拡張子)
である必要があります。





それではOpenGLの設定をしていきます。
作成した EAGLView.h を開き、以下のように書き換えます。

  1. #import <UIKit/UIKit.h>
  2. #import <QuartzCore/QuartzCore.h>
  3. #import <OpenGLES/EAGL.h>
  4. #import <OpenGLES/ES1/gl.h>
  5. #import <OpenGLES/ES1/glext.h>
  6.  
  7. @interface EAGLView : UIView
  8. {
  9. @private
  10.     EAGLContextcontext;
  11.    
  12.     GLint deviceWidth, deviceHeight;
  13.    
  14.     GLuint defaultFramebuffer, colorRenderbuffer;
  15. }
  16. - (id)initWithFrame:(CGRect)frame;
  17. - (void) drawView:(id)sender;
  18. - (void) dealloc;
  19.  
  20. @end




EAGLView.mm を開き、initWithFrame 関数を以下のように書き換え、OpenGLを初期化します。

  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3.     if ((self = [super initWithFrame:frame]))
  4.     {
  5.         CAEAGLLayereaglLayer = (CAEAGLLayer*)self.layer;
  6.         self.contentScaleFactor = [UIScreen mainScreen].scale ;
  7.         eaglLayer.opaque = TRUE;
  8.        
  9.         context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
  10.        
  11.         if (!context || ![EAGLContext setCurrentContext:context])
  12.         {
  13.             [self release];
  14.             return nil;
  15.         }
  16.         glGenFramebuffersOES(1&defaultFramebuffer);
  17.         glGenRenderbuffersOES(1&colorRenderbuffer);
  18.         glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
  19.         glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
  20.         glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
  21.     }
  22.     return self;
  23. }



同じく EAGLView.mm に、 layoutSubViews 関数を追加し、以下のように書き換えます。

  1. - (void) layoutSubviews
  2. {
  3.     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
  4.     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &deviceWidth);
  5.     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &deviceHeight);
  6.        
  7.    
  8.     glViewport(00, deviceWidth, deviceHeight);
  9.     
  10.     glMatrixMode(GL_PROJECTION);
  11.     glLoadIdentity();
  12.        
  13.     float modelWidth = live2DModel->getCanvasWidth();
  14.    
  15.     glOrthof(
  16.          0,
  17.          modelWidth,
  18.          modelWidth * deviceHeight / deviceWidth,
  19.          0,
  20.          0.5f, -0.5f
  21.          );
  22. }



次に、モデルの初期化を行います。
EAGLView.h に、Live2Dモデルとテクスチャの変数、テクスチャ作成用の関数の宣言を、
EAGLView.mm に、その実装を追加します。

  1. @interface EAGLView : UIView
  2. {
  3. @private
  4.     live2d::Live2DModelIPhone* live2DModel;// Live2Dモデル
  5.     NSMutableArray* textures;// テクスチャ
  6.    
  7.     EAGLContextcontext;
  8.    
  9.     GLint deviceWidth, deviceHeight;
  10.    
  11.     GLuint defaultFramebuffer, colorRenderbuffer;
  12. }
  13. - (id)initWithFrame:(CGRect)frame;
  14. - (void) drawView:(id)sender;
  15. - (void) dealloc;
  16. - (GLuint)loadTexture:(NSString*)fileNamel;// OpenGL用のテクスチャを作成する関数 
  17. @end



EAGLView.mm の initWithFrame 関数で、Live2Dのモデルを初期化します。

  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3.     if ((self = [super initWithFrame:frame])) 
  4.     {
  5.                
  6.         CAEAGLLayereaglLayer = (CAEAGLLayer*)self.layer;
  7.         self.contentScaleFactor = [UIScreen mainScreen].scale ;
  8.         eaglLayer.opaque = TRUE;
  9.        
  10.         context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
  11.        
  12.         if (!context || ![EAGLContext setCurrentContext:context])
  13.         {
  14.             [self release];
  15.             return nil;
  16.         }
  17.         glGenFramebuffersOES(1&defaultFramebuffer);
  18.         glGenRenderbuffersOES(1&colorRenderbuffer);
  19.         glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
  20.         glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
  21.         glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
  22.        
  23.         // Live2Dモデルの初期化
  24.         Live2D::init() ;
  25.        
  26.         NSStringmodelpath = [[NSBundle mainBundle] pathForResource:MODEL_PATH ofType:@"moc"];
  27.         live2DModel = Live2DModelIPhone::loadModel( [modelpath UTF8String] ) ;
  28.        
  29.         for( int i = 0 ; TEXTURE_PATH[i] != NULL ; i++ )
  30.         {
  31.             int texNo = [self loadTexture:(TEXTURE_PATH[i])] ;
  32.             live2DModel->setTexture( i , texNo ) ;
  33.             [textures addObject:[NSNumber numberWithInt:texNo]];// 解放するために設定
  34.         }
  35.     }
  36.     return self;
  37. }



EAGLView.mmに、画像からOpenGL用のテクスチャを作成する関数を追加します。

  1. - (GLuint)loadTexture:(NSString*)fileName
  2. {
  3.     GLuint texture;
  4.    
  5.     UIImage* uiImage = [UIImage imageNamed:fileName];
  6.    
  7.     CGImageRef image = uiImage.CGImage ;
  8.    
  9.     size_t width = CGImageGetWidth(image);
  10.     size_t height = CGImageGetHeight(image);
  11.    
  12.     GLubyte* imageData = (GLubyte*) calloc(width * height * 4 , 1);
  13.     CGContextRef imageContext = CGBitmapContextCreate(imageData,width,height,8,width * 4,CGImageGetColorSpace(image),
  14.         kCGImageAlphaPremultipliedLast);
  15.     CGContextDrawImage(imageContext, CGRectMake(00(CGFloat)width, (CGFloat)height), image);
  16.     CGContextRelease(imageContext);
  17.    
  18.     glGenTextures(1&texture);
  19.     glBindTexture(GL_TEXTURE_2D, texture);
  20.     glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  21.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  22.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  23.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  24.    
  25.     free(imageData);
  26.    
  27.     return texture;
  28. }



毎フレームの描画を行う関数を作成します。
EAGLView.mm に drawView 関数を追加し、以下のようにします。

  1. - (void) drawView:(id)sender
  2. {
  3.     [EAGLContext setCurrentContext:context];
  4.    
  5.     glMatrixMode(GL_MODELVIEW);
  6.     glLoadIdentity();
  7.     glClear(GL_COLOR_BUFFER_BIT);
  8.     glEnable(GL_BLEND);
  9.     glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA );
  10.     glDisable(GL_DEPTH_TEST) ;
  11.     glDisable(GL_CULL_FACE) ;
  12.    
  13.     live2DModel->update();
  14.     live2DModel->draw();
  15.        
  16.     [context presentRenderbuffer:GL_RENDERBUFFER_OES];
  17. }



layoutSubViews 関数の一番最後に以下のように記述し、 drawView 関数が毎フレーム呼び出されるよう設定します。

  1.     [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(1/60)
  2.                                      target:self
  3.                                    selector:@selector(drawView:)
  4.                                    userInfo:nil repeats:TRUE];



最後に、ビューコントローラーの awakeFromNib 関数を以下のように書き換えて完了です!

ViewController.h
  1. @interface ViewController : UIViewController{
  2.     UIView* glView;
  3. }

ViewController.m
  1. - (void)awakeFromNib
  2. {
  3.     CGRect rect = CGRectMake(
  4.         0,
  5.         0,
  6.         [[UIScreen mainScreen] bounds].size.width,
  7.         [[UIScreen mainScreen] bounds].size.height ) ;
  8.     glView = [[EAGLView alloc] initWithFrame:rect] ;
  9.     
  10.     [self.view addSubview:glView] ;
  11. }





最終的なコードは以下のようになります。
以下のもの以外は、自動生成された状態から手を加えていません。

ViewController.h
  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface ViewController : UIViewController{
  4.     UIView* glView;
  5. }
  6.  
  7. @end


ViewController.m
  1. #import "ViewController.h"
  2. #import "EAGLView.h"
  3.  
  4. @implementation ViewController
  5.  
  6. - (void)awakeFromNib
  7. {
  8.     CGRect rect = CGRectMake(
  9.         0,
  10.         0,
  11.         [[UIScreen mainScreen] bounds].size.width,
  12.         [[UIScreen mainScreen] bounds].size.height ) ;
  13.     glView = [[EAGLView alloc] initWithFrame:rect] ;
  14.     
  15.     [self.view addSubview:glView] ;
  16. }
  17.  
  18. - (void)viewDidLoad
  19. {
  20.     [super viewDidLoad];
  21. }
  22.  
  23. - (void)didReceiveMemoryWarning
  24. {
  25.     [super didReceiveMemoryWarning];
  26. }
  27.  
  28. @end


EAGLView.h
  1. #import <UIKit/UIKit.h>
  2. #import <QuartzCore/QuartzCore.h>
  3. #import <OpenGLES/EAGL.h>
  4. #import <OpenGLES/ES1/gl.h>
  5. #import <OpenGLES/ES1/glext.h>
  6. #import "Live2DModelIPhone.h"
  7.  
  8. @interface EAGLView : UIView
  9. {
  10. @private
  11.     live2d::Live2DModelIPhone* live2DModel;
  12.     NSMutableArray* textures;
  13.    
  14.     EAGLContextcontext;
  15.    
  16.     GLint deviceWidth, deviceHeight;
  17.    
  18.     GLuint defaultFramebuffer, colorRenderbuffer;
  19. }
  20. - (id)initWithFrame:(CGRect)frame;
  21. - (void)drawView:(id)sender;
  22. - (GLuint)loadTexture:(NSString*)fileNamel;
  23.  
  24. @end


EAGLView.mm
  1. #import "EAGLView.h"
  2.  
  3. #import "Live2D.h"
  4. #import "UtSystem.h"
  5. using namespace live2d ;
  6.  
  7. @implementation EAGLView
  8.  
  9. NSString* MODEL_PATH = @"haru" ;
  10. NSString* TEXTURE_PATH[] = {
  11.     @"texture_00.png" ,
  12.     @"texture_01.png" ,
  13.     @"texture_02.png" ,
  14.     NULL
  15. } ;
  16.  
  17.  
  18. + (Class) layerClass
  19. {
  20.     return [CAEAGLLayer class];
  21. }
  22.  
  23. - (id)initWithFrame:(CGRect)frame
  24. {
  25.     if ((self = [super initWithFrame:frame])) 
  26.     {
  27.                
  28.         CAEAGLLayereaglLayer = (CAEAGLLayer*)self.layer;
  29.         self.contentScaleFactor = [UIScreen mainScreen].scale ;
  30.         eaglLayer.opaque = TRUE;
  31.        
  32.         context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
  33.        
  34.         if (!context || ![EAGLContext setCurrentContext:context])
  35.         {
  36.             return nil;
  37.         }
  38.         glGenFramebuffersOES(1&defaultFramebuffer);
  39.         glGenRenderbuffersOES(1&colorRenderbuffer);
  40.         glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
  41.         glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
  42.         glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
  43.        
  44.        
  45.         Live2D::init() ;
  46.        
  47.         NSStringmodelpath = [[NSBundle mainBundle] pathForResource:MODEL_PATH ofType:@"moc"];
  48.         live2DModel = Live2DModelIPhone::loadModel( [modelpath UTF8String] ) ;
  49.        
  50.         for( int i = 0 ; TEXTURE_PATH[i] != NULL ; i++ )
  51.         {
  52.             int texNo = [self loadTexture:(TEXTURE_PATH[i])] ;
  53.             live2DModel->setTexture( i , texNo ) ;// テクスチャとモデルを結びつける
  54.             [textures addObject:[NSNumber numberWithInt:texNo]];// 解放するために設定
  55.         }
  56.     }
  57.     return self;
  58. }
  59.  
  60. - (void) drawView:(id)sender
  61. {
  62.     [EAGLContext setCurrentContext:context];
  63.    
  64.     //  モデル用のOpenGLの描画関係を設定
  65.     glMatrixMode(GL_MODELVIEW);
  66.     glLoadIdentity();
  67.     glClear(GL_COLOR_BUFFER_BIT);
  68.     glEnable(GL_BLEND);
  69.     glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA );
  70.     glDisable(GL_DEPTH_TEST) ;
  71.     glDisable(GL_CULL_FACE) ;
  72.    
  73.     live2DModel->update();
  74.     live2DModel->draw();
  75.        
  76.     [context presentRenderbuffer:GL_RENDERBUFFER_OES];
  77. }
  78.  
  79. - (void) layoutSubviews
  80. {
  81.     [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
  82.     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &deviceWidth);
  83.     glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &deviceHeight);
  84.        
  85.    
  86.     //  ビューポートはデバイスの幅と合わせる。画面全体に表示される。
  87.     glViewport(00, deviceWidth, deviceHeight);
  88.        
  89.     //  簡易的にプロジェクション行列一つですべての変換を行う。
  90.     glMatrixMode(GL_PROJECTION);
  91.     glLoadIdentity();
  92.        
  93.     float modelWidth = live2DModel->getCanvasWidth()//  モデラーで設定したキャンバス幅
  94.    
  95.     //  描画範囲の設定。引数はleft, right, bottom, top の順。
  96.     glOrthof(
  97.          0,
  98.          modelWidth,
  99.          modelWidth * deviceHeight / deviceWidth,
  100.          0,
  101.          0.5f, -0.5f
  102.          );
  103.        
  104.     [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(1/60)
  105.                                      target:self
  106.                                    selector:@selector(drawView:)
  107.                                    userInfo:nil repeats:TRUE];
  108. }
  109.  
  110.  
  111. // 画像ファイルからテクスチャを作成
  112. - (GLuint)loadTexture:(NSString*)fileName
  113. {
  114.     GLuint texture;
  115.     
  116.     // 画像ファイルを展開しCGImageRefを生成
  117.     UIImage* uiImage = [UIImage imageNamed:fileName];
  118.     
  119.     CGImageRef image = uiImage.CGImage ;
  120.        
  121.     // 画像の大きさを取得
  122.     size_t width = CGImageGetWidth(image);
  123.     size_t height = CGImageGetHeight(image);
  124.        
  125.     // ビットマップデータを用意
  126.     GLubyte* imageData = (GLubyte*) calloc(width * height * 4 , 1);
  127.     CGContextRef imageContext = CGBitmapContextCreate(imageData,width,height,8,width * 4,CGImageGetColorSpace(image),
  128.         kCGImageAlphaPremultipliedLast);
  129.     CGContextDrawImage(imageContext, CGRectMake(00(CGFloat)width, (CGFloat)height), image);
  130.     CGContextRelease(imageContext);
  131.    
  132.     // OpenGL用のテクスチャを生成
  133.     glGenTextures(1&texture);
  134.     glBindTexture(GL_TEXTURE_2D, texture);
  135.     glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  136.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  137.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  138.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  139.    
  140.     free(imageData);
  141.        
  142.     // 作成したテクスチャを返す
  143.     return texture;
  144. }
  145.  
  146. @end
  147.  



Comments