CubismWebFrameworkを直接利用する方法

最終更新: 2020年1月30日

Cubism SDK for Webに同梱されているサンプルプロジェクトは、SDKパッケージの 「/Framework」 ディレクトリ以下の処理を用いてCubismモデルを扱っています。
Cubismモデルを扱うプロジェクトを作成する場合はサンプルプロジェクトを基礎にご利用できますが、既存のアプリケーションやユーザ独自のエンジンなどに実装するときはCubismWebFrameworkのAPIを直接扱いたい場合がございます。
しかし、同梱されているサンプルプロジェクトは高機能なため、そちらを参考にするだけでは構造の理解と切り分けが難しくなっております。

以下では、上記のようなユーザを対象として、CubismFrameworkを直接呼び出してモデルを扱う最小のスニペットを紹介します。

CubismFrameworkのサイクル

CubismFrameworkを扱うための手順は以下のとおりです。

  1. CubismFrameworkの初期化
  2. モデルファイルのパスを取得
  3. モデルの読み込み
  4. アップデート処理
  5. モデルの破棄
  6. CubismFrameworkの終了処理

CubismFrameworkの初期化

CubismFrameworkの初期化処理は以下のとおりです。

CubismFrameworkは、CubismFramework.startUp()を使用して初期化をおこないます。
Cubism SDK for Nativeでは第一引数にアロケータ(ICubismAllocator)をとっていましたが、Cubism SDK for Webでは使用しません。

    // ログ等のオプション設定。
    _cubismOption: Csm_Option;

    // メッセージ出力関数。
    public static printMessage(message: string): void

printMessage() の内容は サンプル中の同名関数を参考に実装してください。

import {Live2DCubismFramework as live2dcubismframework, Option as Csm_Option, LogLevel} from "../../../../Framework/live2dcubismframework";
import Csm_CubismFramework = live2dcubismframework.CubismFramework;    
・
・
・
    // ログ出力のレベルを設定。LogLevel_Verboseの場合は詳細ログを出力させる。
    this._cubismOption.logFunction = printMessage;
    this._cubismOption.loggingLevel = LogLevel.LogLevel_Verbose;
    
    // CubismNativeFrameworkの初期化に必要なパラメータを設定する。
    Csm_CubismFramework.startUp(this._cubismOption);
    
    // CubismFrameworkを初期化する。
    Csm_CubismFramework.initialize();
Tips

CubismFramework.initialize() を呼び出すのは初期化時に一度のみとなり、その後はCubismFramework.dispose() によってCubismFrameworkインスタンスが破棄されない限り、連続で呼び出してもスキップします。
ただし、一度CubismFrameworkインスタンスを破棄した後であれば、再度初期化を行う場合にはCubismFramework.initialize() を呼び出します。

モデルファイルの取得

Cubismの組み込み用データ一式は、.model3.jsonにそれぞれの相対パスが記述されており、これを参照してバイトデータを読み込みます。
.model3.jsonをパースしてモデルファイル等のパスを取得して読み込むことを推奨します。

.model3.jsonのパースは、CubismFrameworkのCubismModelSettingJsonクラスを使用します。

.moc3ファイルやテクスチャなどを直接指定して読み込ませることも可能です。
直接指定して読み込ませる場合、コード改修が必要となります。

サンプルでは、LAppModel.loadAssets() にて fetch() を使用しリソースパスからファイルを取得してバイトデータを読み込んでJsonの内容を取得します。

fetch(path).then(
    (response) =>
    {
        return response.arrayBuffer();
    }
).then(
    (arrayBuffer) =>
    {
        let buffer: ArrayBuffer = arrayBuffer;
        let size = buffer.byteLength;
        // Jsonに記載されているモデルデータのパスなどを取得する
        let setting: ICubismModelSetting = new CubismModelSettingJson(buffer, size);

        // 結果を保存
        this.setupModel(setting);
    }
);

モデルの読み込み

モデルの読み込みには、CubismModel のインターフェースによっておこないます。

CubismModel のインスタンスは、CubismNativeFramework では CubismUserModel._model が保持しており、CubismUserModel.loadModel() を使ってモデルデータを取得・保存します。

CubismModelを利用する場合、CubismUserModel を継承したクラスから扱うことを推奨しています。
サンプルでは、LAppModel クラスが CubismUserModel を継承して取り扱っています。

また、テクスチャやモーション、表情モーション等のリソース管理は外部で行うことも可能です。

サンプルでは、LAppModel.setupModel() 内で fetch() を使用して ICubismModelSetting に保存されたファイルパスからモデルデータを読み込む処理をおこなっています。

// ICubismModelSetting に保存されているモデルファイルパスを取得する
let path: string = this._modelSetting.getModelFileName();
path = this._modelHomeDir + path;

fetch(path).then(
    (response) =>
    {
        return response.arrayBuffer();
    }
).then(
    (arrayBuffer) =>
    {
        buffer = arrayBuffer;
        // モデルデータを読み込む
        this.loadModel(buffer);
        deleteBuffer(buffer, path);
    }
);
this._state = LoadStep.WaitLoadModel;

読み込む.moc3ファイルのパスは上記の通り.model3.jsonで取得できますが、同様に.model3.jsonから表情、物理演算、ポーズ、まばたき、リップシンク、ユーザデータ、モーションのパスも取得できます。
SDKのサンプルではモデルの読み込みと同時にこれらの読み込みも行っております。
それぞれの読み込み方法につきましては以下を参考にしてください。

Tips

上記のスニペットは、画面にモデルを1体表示することを前提としたものです。
画面上に同時に複数体のモデルを表示する場合、表示するモデルと同数のCubismUserModelの派生クラスのインスタンスを生成してください。

アップデート処理

Cubismモデルのアップデート処理は、対象のモデルにCubismModel のインターフェースである CubismModel.setParameterValueById() などで更新するパラメータと値を渡して設定し、
CubismModel.update() を呼び出して更新します。
CubismModel.update() を呼び出すとCubism Coreで更新処理が行われ、それまでに設定されたパラメータやパーツの値から頂点情報などを更新します。

この更新後の頂点情報などをレンダラに渡すことで、Cubismモデルを画面に描画することができます。

以下コードでは、_model(CubismModel) を持つクラス内でモデルのパラメータ操作を直接おこない、Cubism Coreの更新処理を呼び出して操作を適用しています。

public update(): void
{
    // パラメータ操作。
    // ParamAngleX を value へ動かす
    this._model.setParameterValueById(CubismFramework.getIdManager().getId("ParamAngleX"), value);

    // パーツ不透明度操作。
    // PartArmL の不透明度を opacity にする
    this._model.setPartOpacityById(CubismFramework.getIdManager().getId("PartArmL"), opacity);

    // モデルを更新
    this._model.update();
}

アップデート処理では必ずCubismModel.update()以前に、視線追従や物理演算、モーション再生などを行います。

CubismModel.update()よりも後にパラメータの値を操作しても反映されません。
その後に再度CubismModel.update()を呼べば反映されますが、この処理は負荷が高いため一つにまとめることを推奨します。

    // 頂点に反映される
    _model.setParameterValue(CubismFramework.getIdManager().getId("ParamAngleX"), value1);
    
    // モデルの頂点情報を更新
    _model.update();
    
    // 頂点に反映されない
    _model.setParameterValue(CubismFramework.getIdManager().getId("ParamAngleX"), value);

モーションを再生するCubismMotionManager.updateMotion()は、再生するモーションに使用されているIDのパラメータの値をすべて上書きします。
そのため、この処理以前にパラメータの値を操作してもすべてCubismMotionManager.updateMotion()によって上書きされてしまいます。
視線追従などの値操作や物理演算などは、先にモーションの再生処理を行い、その後に行うことを推奨します。

    // 再生中のモーションをモデルに反映
    _motionManager.updateMotion(_model, deltaTimeSeconds);
    
    // 視線追従などの値操作や物理演算処理
    
    // モデルの頂点情報を更新
    _model.update();

また、再生するモーションにすべてのパラメータが使用されていない場合や、モーションの再生が停止しているなどの理由からパラメータの値を操作しない場合、前のフレームで行った値操作の結果が残ったままになります。
そのため、その後に行う相対的なパラメータの値操作の結果が意図しないものになる可能性があります。
これは、モーションをモデルに反映させる処理の前後にCubismModel.loadParameter()、CubismModel.saveParameter()を呼び出すことで、その後に行う相対的な値操作をリセットすることが可能です。

    // すべてのパラメータの値を保存時の状態に復元
    _modelloadParameters();
    
    // 再生中のモーションをモデルに反映
    _motionManager.updateMotion(_model, deltaTimeSeconds);
    
    // すべてのパラメータの値を保存
    _model.saveParameters();
    
    
    // 相対的な値操作処理
    
    
    // モデルの頂点情報を更新
    _model.update();

視線追従や物理演算、モーションの再生などの処理自体についてはそれぞれのドキュメントを参照してください。

この更新後の頂点情報などをレンダラに渡すことで、Cubismモデルを画面に描画することができます。

モデルの破棄

モデルを破棄するには、生成したCubismUserModelの派生クラスのインスタンスを破棄します。
これにより、このモデルが保持しているモーションや表情、物理演算などの情報がCubismUserModelのデストラクタから破棄されます。

    // モデルデータの破棄
    this._model.release();
    this._model = null;

Cubism Frameworkの終了処理

CubismFrameworkが確保した共通部分のリソースを解放するには、CubismFramework.dispose() を呼び出します。
CubismFramework.dispose() は、 CubismFramework.initialize() を呼ぶ前には呼び出さないでください。

    // CubismFrameworkの破棄
    CubismFramework.dispose();
Tips

CubismFrameworkで初期化したデータはstaticな領域に配置されており、モデルデータには依存していません。
そのため複数のモデル間で使い回すことができ、モデルの切り替えだけであればCubismFramework.dispose()を呼び出す必要はありません。

この記事はお役に立ちましたか?
はいいいえ
この記事に関するご意見・
ご要望をお聞かせください。