Cubism SDK‎ > ‎プラットフォーム‎ > ‎Cocos2d-x‎ > ‎

5. Live2Dを描画するコード

Last update: 2014/08/22

ここでは、 Cocos2d-xでLive2Dを描画するためのコードを紹介します。

コードを追加・編集
最終的な構成は以下のようになります。

ページ内リンク
・AppDelegate.h は編集しません。
・HelloWorldScene.h は編集しません。
・HelloWorldScene.cpp
・SampleLive2DSprite.h は新規で作成します。
・SampleLive2DSprite.cpp は新規で作成します。


AppDelegate.cpp
AppDelegate.cppに追加を記述します
Live2Dをインクルードしてlive2dをネームスペースとして宣言します。
  1. #include "Live2D.h"
  2.  
  3. using namespace live2d;


AppDelegateにLive2D::dispose();を追加します。
applicationDidFinishLaunching()にLive2D::init();を追加します。

コードは最終的に以下のようになります。
  1. /**
  2.  *
  3.  *  You can modify and use this source freely
  4.  *  only for the development of application related Live2D.
  5.  *
  6.  *  (c) Live2D Inc. All rights reserved.
  7.  */
  8. #include "AppDelegate.h"
  9. #include "HelloWorldScene.h"
  10. #include "Live2D.h"
  11.  
  12. using namespace live2d;
  13. USING_NS_CC;
  14.  
  15. AppDelegate::AppDelegate() {
  16.  
  17. }
  18.  
  19. AppDelegate::~AppDelegate()
  20. {
  21.         Live2D::dispose();
  22. }
  23.  
  24. bool AppDelegate::applicationDidFinishLaunching() {
  25.     // initialize director
  26.     auto director = Director::getInstance();
  27.     auto glview = director->getOpenGLView();
  28.     if(!glview) {
  29.         glview = GLView::create("Live2D Simple");
  30.         director->setOpenGLView(glview);
  31.     }
  32.  
  33.     // turn on display FPS
  34.     director->setDisplayStats(true);
  35.  
  36.     // set FPS. the default value is 1.0/60 if you don't call this
  37.     director->setAnimationInterval(1.0 / 60);
  38.  
  39.         //Live2D
  40.         Live2D::init();
  41.  
  42.     // create a scene. it's an autorelease object
  43.     auto scene = HelloWorld::createScene();
  44.  
  45.     // run
  46.     director->runWithScene(scene);
  47.  
  48.     return true;
  49. }
  50.  
  51. // This function will be called when the app is inactive. When comes a phone call,it's be invoked too
  52. void AppDelegate::applicationDidEnterBackground() {
  53.     Director::getInstance()->stopAnimation();
  54.  
  55.     // if you use SimpleAudioEngine, it must be pause
  56.     // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
  57. }
  58.  
  59. // this function will be called when the app is active again
  60. void AppDelegate::applicationWillEnterForeground() {
  61.     Director::getInstance()->startAnimation();
  62.  
  63.     // if you use SimpleAudioEngine, it must resume here
  64.     // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
  65. }
  66.  


HelloWorldScene.cpp
HelloWorldScene.cppに追加を記述します。
SampleLive2DSpriteをインクルードします。
  1. #include "SampleLive2DSprite.h"


SampleLive2DSpriteのインスタンスを生成、それをアドチャイルドします。
  1. Sprite* pLive2DSprite = new SampleLive2DSprite();
  2. this->addChild(pLive2DSprite);


コードは最終的に以下のようになります。
  1. #include "HelloWorldScene.h"
  2. #include "SampleLive2DSprite.h"
  3.  
  4. USING_NS_CC;
  5.  
  6. Scene* HelloWorld::createScene()
  7. {
  8.     // 'scene' is an autorelease object
  9.     auto scene = Scene::create();
  10.    
  11.     // 'layer' is an autorelease object
  12.     auto layer = HelloWorld::create();
  13.  
  14.     // add layer as a child to scene
  15.     scene->addChild(layer);
  16.  
  17.     // return the scene
  18.     return scene;
  19. }
  20.  
  21. // on "init" you need to initialize your instance
  22. bool HelloWorld::init()
  23. {
  24.     //////////////////////////////
  25.     // 1. super init first
  26.     if ( !Layer::init() )
  27.     {
  28.         return false;
  29.     }
  30.    
  31.     Size visibleSize = Director::getInstance()->getVisibleSize();
  32.     Point origin = Director::getInstance()->getVisibleOrigin();
  33.  
  34.     /////////////////////////////
  35.     // 2. add a menu item with "X" image, which is clicked to quit the program
  36.     //    you may modify it.
  37.  
  38.     // add a "close" icon to exit the progress. it's an autorelease object
  39.     auto closeItem = MenuItemImage::create(
  40.                                            "CloseNormal.png",
  41.                                            "CloseSelected.png",
  42.                                            CC_CALLBACK_1(HelloWorld::menuCloseCallbackthis));
  43.    
  44.         closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
  45.                                 origin.y + closeItem->getContentSize().height/2));
  46.  
  47.     // create menu, it's an autorelease object
  48.     auto menu = Menu::create(closeItem, NULL);
  49.     menu->setPosition(Point::ZERO);
  50.     this->addChild(menu, 1);
  51.  
  52.     /////////////////////////////
  53.     // 3. add your codes below...
  54.  
  55.     // add a label shows "Hello World"
  56.     // create and initialize a label
  57.    
  58.     auto label = LabelTTF::create("Hello World""Arial"24);
  59.    
  60.     // position the label on the center of the screen
  61.     label->setPosition(Point(origin.x + visibleSize.width/2,
  62.                             origin.y + visibleSize.height - label->getContentSize().height));
  63.  
  64.     // add the label as a child to this layer
  65.     this->addChild(label, 1);
  66.  
  67.     // add "HelloWorld" splash screen"
  68.     auto sprite = Sprite::create("HelloWorld.png");
  69.  
  70.     // position the sprite on the center of the screen
  71.     sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
  72.  
  73.     // add the sprite as a child to this layer
  74.     this->addChild(sprite, 0);
  75.    
  76.         Sprite* pLive2DSprite = new SampleLive2DSprite();
  77.         this->addChild(pLive2DSprite);
  78.  
  79.     return true;
  80. }
  81.  
  82.  
  83. void HelloWorld::menuCloseCallback(Ref* pSender)
  84. {
  85. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  86.         MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
  87.     return;
  88. #endif
  89.  
  90.     Director::getInstance()->end();
  91.  
  92. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  93.     exit(0);
  94. #endif
  95. }
  96.  


SampleLive2DSprite.h
SampleLive2DSprite.hを記述します。
  1. /**
  2.  *
  3.  *  You can modify and use this source freely
  4.  *  only for the development of application related Live2D.
  5.  *
  6.  *  (c) Live2D Inc. All rights reserved.
  7.  */
  8. #ifndef __sampleCocos2dx__SampleLive2DSprite__
  9. #define __sampleCocos2dx__SampleLive2DSprite__
  10.  
  11. #include "cocos2d.h"
  12. #include "2d/CCSprite.h"
  13. #include <vector>
  14. #include "Live2DModelOpenGL.h"
  15.  
  16.  
  17. class SampleLive2DSprite :public cocos2d::Sprite {
  18.        
  19.         live2d::Live2DModelOpenGL* live2DModel ;
  20.         std::vector<cocos2d::Texture2D*> textures ;
  21.         cocos2d::Texture2D* texture1;
  22.  
  23. public:
  24.         SampleLive2DSprite();
  25.         virtual ~SampleLive2DSprite();
  26.  
  27.         virtual void draw(cocos2d::Renderer *renderer, const kmMat4 &transform, bool transformUpdated) override;
  28.         void onDraw(const kmMat4 &transform, bool transformUpdated);
  29.  
  30. protected:
  31.         cocos2d::CustomCommand _customCommand;
  32. };
  33.  
  34. #endif /* defined(__sampleCocos2dx__SampleLive2DSprite__) */


SampleLive2DSprite.cpp
SampleLive2DSprite.cppを記述します。
コンストラクタで、モデルとテクスチャの読み込み、テクスチャの設定、描画位置の設定をします。
  1. SampleLive2DSprite::SampleLive2DSprite()
  2. {
  3.         //Live2D Sample
  4.         const char* MODEL = "haru.moc" ;
  5.         const char* TEXTURES[] ={
  6.                 "texture_00.png" ,
  7.                 "texture_01.png" ,
  8.                 "texture_02.png" ,
  9.                 NULL
  10.         } ;
  11.         unsigned char* buf;
  12.         ssize_t bufSize;
  13.         buf = FileUtils::getInstance()->getFileData(MODEL,"rb"&bufSize);
  14.        
  15.         live2DModel = Live2DModelOpenGL::loadModel( buf,bufSize ) ;
  16.        
  17.         for( int i = 0 ; TEXTURES[i] != NULL ; i++ ){
  18.                 Texture2D *texture = new Texture2D();
  19.                 Image *img = new Image();
  20.  
  21.                 img->initWithImageFile(TEXTURES[i]);
  22.                 texture->initWithImage(img);
  23.  
  24.                
  25.                 Texture2D::TexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
  26.                 texture->setTexParameters(texParams);
  27.                 texture->generateMipmap();
  28.  
  29.                 int glTexNo = texture->getName() ;
  30.  
  31.                 live2DModel->setTexture( i , glTexNo ) ;// テクスチャとモデルを結びつける
  32.                 textures.push_back( texture ) ;
  33.         }
  34.  
  35.         // Live2Dモデルはローカル座標で左上を原点にして(CanvasWidth、CanvasWidth)
  36.         // のサイズになるため、以下のようにして調整してください。
  37.         float w = Director::getInstance()->getWinSize().width;
  38.         float h = Director::getInstance()->getWinSize().height;
  39.         float scx = 2.0 / live2DModel->getCanvasWidth() ;
  40.         float scy = -2.0 / live2DModel->getCanvasWidth() * (w/h);
  41.         float x = -1 ;
  42.         float y = 1 ;
  43.         float matrix []= {
  44.                 scx , 0 , 0 , 0 ,
  45.                 0 , scy ,0 , 0 ,
  46.                 0 , 0 , 1 , 0 ,
  47.                 x , y , 0 , 1
  48.         } ;
  49.        
  50.         live2DModel->setMatrix(matrix) ;// 位置を設定
  51.        
  52.         live2DModel->setPremultipliedAlpha( false );
  53. }


デストラクタで、モデルとテクスチャ解放します。
  1. SampleLive2DSprite::~SampleLive2DSprite()
  2. {
  3.         delete live2DModel;
  4.         // テクスチャを解放
  5.         for (int i=0; i<textures.size(); i++)
  6.         {
  7.                 textures[i]->release();
  8.         }
  9. }
  10.  


drawをオーバーライドします。
  1. void SampleLive2DSprite::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
  2. {
  3.         Sprite::draw(renderer, transform, transformUpdated);
  4.  
  5.        
  6.         _customCommand.init(_globalZOrder);
  7.         _customCommand.func = CC_CALLBACK_0(SampleLive2DSprite::onDrawthis, transform, transformUpdated);
  8.         renderer->addCommand(&_customCommand);
  9. }
  10.  


onDrawを用意します。
  1. void SampleLive2DSprite::onDraw(const kmMat4 &transform, bool transformUpdated)
  2. {
  3.         kmGLPushMatrix();
  4.     kmGLLoadMatrix(&transform);
  5.  
  6.          
  7.         // モデルのパラメータを変更。動作確認用です。
  8.         double t = (UtSystem::getUserTimeMSec()/1000.0) * 2 * M_PI  ;// 1秒ごとに2π(1周期)増える
  9.         double cycle=3.0;// パラメータが一周する時間(秒)
  10.         double value=sin( t/cycle );// -1から1の間を周期ごとに変化する
  11.         live2DModel->setParamFloat( "PARAM_ANGLE_X" , (float) (30 * value) ) ;// PARAM_ANGLE_Xのパラメータが[cycle]秒ごとに-30から30まで変化する
  12.  
  13.        
  14.         // Live2Dの描画前と描画後に以下の関数を呼んでください
  15.         // live2d::DrawProfileCocos2D::preDraw() ;
  16.         // live2d::DrawProfileCocos2D::postDraw() ;
  17.         // これはOpenGLの状態をもとに戻すための処理です。
  18.         // これを行わない場合、Cocos2DかLive2Dどちらかで状態の不整合が起こります。
  19.         live2d::DrawProfileCocos2D::preDraw();
  20.        
  21.         live2DModel->update() ;
  22.         live2DModel->draw() ;
  23.        
  24.         live2d::DrawProfileCocos2D::postDraw() ;
  25.  
  26.         kmGLPopMatrix();
  27. }


コードは最終的に以下のようになります。
  1. /**
  2.  *
  3.  *  You can modify and use this source freely
  4.  *  only for the development of application related Live2D.
  5.  *
  6.  *  (c) Live2D Inc. All rights reserved.
  7.  */
  8. #include "SampleLive2DSprite.h"
  9. #include "CCDirector.h"
  10. #include "util/UtSystem.h"
  11.  
  12. #include "graphics/DrawProfileCocos2D.h"
  13. #include "platform/CCFileUtils.h"
  14.  
  15. using namespace live2d;
  16. USING_NS_CC;
  17.  
  18. SampleLive2DSprite::SampleLive2DSprite()
  19. {
  20.         //Live2D Sample
  21.         const char* MODEL = "haru.moc" ;
  22.         const char* TEXTURES[] ={
  23.                 "texture_00.png" ,
  24.                 "texture_01.png" ,
  25.                 "texture_02.png" ,
  26.                 NULL
  27.         } ;
  28.         unsigned char* buf;
  29.         ssize_t bufSize;
  30.         buf = FileUtils::getInstance()->getFileData(MODEL,"rb"&bufSize);
  31.        
  32.         live2DModel = Live2DModelOpenGL::loadModel( buf,bufSize ) ;
  33.        
  34.         for( int i = 0 ; TEXTURES[i] != NULL ; i++ ){
  35.                 Texture2D *texture = new Texture2D();
  36.                 Image *img = new Image();
  37.  
  38.                 img->initWithImageFile(TEXTURES[i]);
  39.                 texture->initWithImage(img);
  40.  
  41.                
  42.                 Texture2D::TexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
  43.                 texture->setTexParameters(texParams);
  44.                 texture->generateMipmap();
  45.  
  46.                 int glTexNo = texture->getName() ;
  47.  
  48.                 live2DModel->setTexture( i , glTexNo ) ;// テクスチャとモデルを結びつける
  49.                 textures.push_back( texture ) ;
  50.         }
  51.  
  52.         // Live2Dモデルはローカル座標で左上を原点にして(CanvasWidth、CanvasWidth)
  53.         // のサイズになるため、以下のようにして調整してください。
  54.         float w = Director::getInstance()->getWinSize().width;
  55.         float h = Director::getInstance()->getWinSize().height;
  56.         float scx = 2.0 / live2DModel->getCanvasWidth() ;
  57.         float scy = -2.0 / live2DModel->getCanvasWidth() * (w/h);
  58.         float x = -1 ;
  59.         float y = 1 ;
  60.         float matrix []= {
  61.                 scx , 0 , 0 , 0 ,
  62.                 0 , scy ,0 , 0 ,
  63.                 0 , 0 , 1 , 0 ,
  64.                 x , y , 0 , 1
  65.         } ;
  66.        
  67.         live2DModel->setMatrix(matrix) ;// 位置を設定
  68.        
  69.         live2DModel->setPremultipliedAlpha( false );
  70. }
  71.  
  72. SampleLive2DSprite::~SampleLive2DSprite()
  73. {
  74.         delete live2DModel;
  75.         // テクスチャを解放
  76.         for (int i=0; i<textures.size(); i++)
  77.         {
  78.                 textures[i]->release();
  79.         }
  80. }
  81.  
  82.  
  83. void SampleLive2DSprite::draw(Renderer *renderer, const kmMat4 &transform, bool transformUpdated)
  84. {
  85.         Sprite::draw(renderer, transform, transformUpdated);
  86.  
  87.        
  88.         _customCommand.init(_globalZOrder);
  89.         _customCommand.func = CC_CALLBACK_0(SampleLive2DSprite::onDrawthis, transform, transformUpdated);
  90.         renderer->addCommand(&_customCommand);
  91. }
  92.  
  93. void SampleLive2DSprite::onDraw(const kmMat4 &transform, bool transformUpdated)
  94. {
  95.         kmGLPushMatrix();
  96.     kmGLLoadMatrix(&transform);
  97.  
  98.          
  99.         // モデルのパラメータを変更。動作確認用です。
  100.         double t = (UtSystem::getUserTimeMSec()/1000.0) * 2 * M_PI  ;// 1秒ごとに2π(1周期)増える
  101.         double cycle=3.0;// パラメータが一周する時間(秒)
  102.         double value=sin( t/cycle );// -1から1の間を周期ごとに変化する
  103.         live2DModel->setParamFloat( "PARAM_ANGLE_X" , (float) (30 * value) ) ;// PARAM_ANGLE_Xのパラメータが[cycle]秒ごとに-30から30まで変化する
  104.  
  105.        
  106.         // Live2Dの描画前と描画後に以下の関数を呼んでください
  107.         // live2d::DrawProfileCocos2D::preDraw() ;
  108.         // live2d::DrawProfileCocos2D::postDraw() ;
  109.         // これはOpenGLの状態をもとに戻すための処理です。
  110.         // これを行わない場合、Cocos2DかLive2Dどちらかで状態の不整合が起こります。
  111.         live2d::DrawProfileCocos2D::preDraw();
  112.        
  113.         live2DModel->update() ;
  114.         live2DModel->draw() ;
  115.        
  116.         live2d::DrawProfileCocos2D::postDraw() ;
  117.  
  118.         kmGLPopMatrix();
  119. }
  120.  




Comments