Help us understand the problem. What is going on with this article?

cocos2dでLive2Dモーション再生

More than 3 years have passed since last update.

フォーラムでLive2Dのcocos2dでつまづいていた人がいたので、シンプルなモーション再生させてみました。
Live2Dコミュニティ - cocos2dx 3.9 mtnファイルの読み込みでエラー

開発環境

Live2D Cocos2d-x 3.5のSimpleプロジェクトをカスタム
・Xcode ver 6.4 (Mac 10.10.5 - Yosemite)

修正手順

1)モーションファイルをResoucesフォルダ配下におく
screenshoto.png

2)SampleLive2DSprite.hのコードを修正
モーションマネージャーを追加(コメントのADD参照)

SampleLive2DSprite.h
#ifndef __sampleCocos2dx__SampleLive2DSprite__
#define __sampleCocos2dx__SampleLive2DSprite__

#include "cocos2d.h"
#include "2d/CCSprite.h"
#include <vector>
#include "Live2DModelOpenGL.h"
#include "motion/Live2DMotion.h"         // ADD
#include "motion/MotionQueueManager.h"   // ADD


class SampleLive2DSprite :public cocos2d::DrawNode {

    live2d::Live2DModelOpenGL* live2DModel ;
    live2d::MotionQueueManager* motionManager;  // ADD
    std::vector<cocos2d::Texture2D*> textures ;

public:
    SampleLive2DSprite();
    virtual ~SampleLive2DSprite();

    virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
    void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);
    static SampleLive2DSprite* createDrawNode();
protected:
    cocos2d::CustomCommand _customCommand;
};

#endif /* defined(__sampleCocos2dx__SampleLive2DSprite__) */

3)SampleLive2DSprite.cppのコードを修正
モーションロードと再生処理を追加(コメントのADD参照)

SampleLive2DSprite.cpp
#include "SampleLive2DSprite.h"
#include "base/CCDirector.h"
#include "util/UtSystem.h"

#include "graphics/DrawProfileCocos2D.h"
#include "platform/CCFileUtils.h"

using namespace live2d;
USING_NS_CC;
const char* TEXTURES[] ={
    "haru/haru_02.1024/texture_00.png" ,
    "haru/haru_02.1024/texture_01.png" ,
    "haru/haru_02.1024/texture_02.png" ,
    NULL
};

AMotion* motion; // モーション ADD

SampleLive2DSprite::SampleLive2DSprite()
{
    //Live2D Sample
    const char* MODEL = "haru/haru_02.moc" ;
    unsigned char* buf;
    ssize_t bufSize;
    buf = FileUtils::getInstance()->getFileData(MODEL,"rb", &bufSize);
    // mocロード
    live2DModel = Live2DModelOpenGL::loadModel( buf,bufSize ) ;
    free(buf);

    // Textureロード
    for( int i = 0 ; TEXTURES[i] != NULL ; i++ ){
        auto texture =Director::getInstance()->getTextureCache()->addImage(std::string(TEXTURES[i]));       
        Texture2D::TexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
        texture->setTexParameters(texParams);
        texture->generateMipmap();

        int glTexNo = texture->getName() ;

        live2DModel->setTexture( i , glTexNo ) ;// テクスチャとモデルを結びつける
        textures.push_back( texture ) ;
    }

    // Motionロード ADD Start
    const char* MOTION = "haru/motions/tapBody_00.mtn";
    unsigned char* motionbuf;
    ssize_t MotionSize;
    motionbuf = FileUtils::getInstance()->getFileData(MOTION,"rb", &MotionSize);
    // モーションロード
    motion=Live2DMotion::loadMotion(motionbuf,(int)MotionSize);
    // モーションマネージャー生成
    motionManager = new MotionQueueManager();
    // Motionロード ADD End

    // Live2Dモデルはローカル座標で左上を原点にして(CanvasWidth、CanvasWidth)
    // のサイズになるため、以下のようにして調整してください。
    float w = Director::getInstance()->getWinSize().width;
    float h = Director::getInstance()->getWinSize().height;
    float scx = 2.0 / live2DModel->getCanvasWidth() ;
    float scy = -2.0 / live2DModel->getCanvasWidth() * (w/h);
    float x = -1 ;
    float y = 1 ;
    float matrix []= {
        scx , 0 , 0 , 0 ,
        0 , scy ,0 , 0 ,
        0 , 0 , 1 , 0 ,
        x , y , 0 , 1
    } ;

    live2DModel->setMatrix(matrix) ;// 位置を設定

}

SampleLive2DSprite::~SampleLive2DSprite()
{
    delete live2DModel;
    // テクスチャを解放
    Director::getInstance()->getTextureCache()->removeTextureForKey(std::string(TEXTURES[0]));
    Director::getInstance()->getTextureCache()->removeTextureForKey(std::string(TEXTURES[1]));
    Director::getInstance()->getTextureCache()->removeTextureForKey(std::string(TEXTURES[2]));

}


void SampleLive2DSprite::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
    DrawNode::draw(renderer, transform, flags);

    _customCommand.init(_globalZOrder);
    _customCommand.func = CC_CALLBACK_0(SampleLive2DSprite::onDraw, this, transform, flags);
    renderer->addCommand(&_customCommand);
}

void SampleLive2DSprite::onDraw(const cocos2d::Mat4 &transform, uint32_t flags)
{
    kmGLPushMatrix();
    kmGLLoadMatrix(&transform);

    // モデルのパラメータを変更。動作確認用です。
    double t = (UtSystem::getUserTimeMSec()/1000.0) * 2 * M_PI  ;// 1秒ごとに2π(1周期)増える
//  double cycle=3.0;// パラメータが一周する時間(秒)
//  double value=sin( t/cycle );// -1から1の間を周期ごとに変化する
//  live2DModel->setParamFloat( "PARAM_ANGLE_X" , (float) (30 * value) ) ;// PARAM_ANGLE_Xのパラメータが[cycle]秒ごとに-30から30まで変化する

    // Motion再生 ADD Start
    if(motionManager->isFinished())
    {
        motionManager->startMotion(motion, false);
    }
    motionManager->updateParam(live2DModel);
    // Motion再生 ADD End

    // Live2Dの描画前と描画後に以下の関数を呼んでください
    // live2d::DrawProfileCocos2D::preDraw() ;
    // live2d::DrawProfileCocos2D::postDraw() ;
    // これはOpenGLの状態をもとに戻すための処理です。
    // これを行わない場合、Cocos2DかLive2Dどちらかで状態の不整合が起こります。
    live2d::DrawProfileCocos2D::preDraw();

    live2DModel->update() ;
    live2DModel->draw() ;

    live2d::DrawProfileCocos2D::postDraw() ;

    kmGLPopMatrix();
}

SampleLive2DSprite* SampleLive2DSprite::createDrawNode()
{
    SampleLive2DSprite *ret = new SampleLive2DSprite();
    if (ret && ret->init())
    {
        ret->autorelease();
        return ret;
    }
    else
    {
        CC_SAFE_DELETE(ret);
        return nullptr;
    }
}

実行結果

これで簡単にモーション再生できました!
001.gif

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away