CubismJavaFrameworkを直接利用する方法
最終更新: 2022年12月8日
Cubism SDK for Javaに同梱されているサンプルプロジェクトは、CubismJavaFramework (SDKパッケージの /Framework/ 以下)を用いてCubismモデルを扱っています。
Cubismモデルを扱うプロジェクトを作成する場合はサンプルプロジェクトを基礎にご利用いただくのがよいかと思いますが、既存のアプリケーションやユーザー独自のエンジンなどに実装するときはCubismJavaFrameworkのAPIを直接扱いたい場合があるかと思います。
しかし、同梱されているサンプルプロジェクトは高機能なため、そちらを参考にするだけでは構造の理解と切り分けが容易ではありません。
以下では、上記のようなユーザーを対象として、CubismFrameworkを直接呼び出してモデルを扱う最小のスニペットを紹介します。
CubismFrameworkのサイクル
CubismFrameworkを扱うための手順は以下のとおりです。
- CubismFrameworkの初期化
- モデルファイルのパスを取得
- モデルの読み込み
- アップデート処理
- モデルの破棄
- CubismFrameworkの終了処理
1.CubismFrameworkの初期化
CubismFrameworkの初期化処理は以下の通りです。
CubismFrameworkは、CubismFramework.startUp() を使用して初期化を行います。
Cubism SDK for Native では第一引数にアロケータ(ICubismAllocator)をとっていましたが、Cubism SDK for Java では使用しません。
public class LAppDelegate{ public void onSurfaceCreated() { ... // Initialize Cubism SDK framework CubismFramework.initialize(); // シェーダーの初期化 _view.initializeShader(); } private LAppDelegate() { ... // ログ出力のレベルを設定。LogLevel.VERBOSEの場合は詳細ログを出力させる。 _cubismOption = new CubismFramework.Option(); _cubismOption.logFunction = new LAppPal.PrintLogFunction(); _cubismOption.loggingLevel = LAppDefine.cubismLoggingLevel; CubismFramework.cleanUp(); // CubismJavaFrameworkの初期化に必要なパラメーターを設定する。 CubismFramework.startUp(_cubismOption); } private CubismFramework.Option _cubismOption; }
Tips
CubismFramework.initialize() を呼び出すのは初期化時に一度のみで、その後はCubismFrameworkが破棄されない限り、連続で呼び出してもスキップします。
ただし、一度CubismFrameworkを破棄した後であれば、再度初期化を行う場合にはCubismFramework.initialize() を呼び出します。
2.モデルファイルのパスを取得
Cubismの組み込み用データ一式は、.model3.jsonにそれぞれの相対パスが記述されています。
MOC3ファイルやテクスチャなどを直接指定して読み込ませても構いませんが、基本的には.model3.jsonからパスを取得して読み込むことを推奨します。
.model3.jsonのパースは、CubismFrameworkのCubismModelSettingJsonクラスを使用します。
public class LAppModel{ ... private static byte[] createBuffer(final String path) { if (LAppDefine.DEBUG_LOG_ENABLE) { LAppPal.printLog("create buffer: " + path); } return LAppPal.loadFileAsBytes(path); } }
// model3.jsonの読み込み final String modelSettingJsonPath = _modelHomeDir + modelSettingJsonName; byte[] buffer = createBuffer(modelSettingJsonPath); ICubismModelSetting setting = new CubismModelSettingJson(buffer); // model3.jsonに記述されたモデルのパスを取得 String moc3Path = _modelSetting.getModelFileName(); moc3Path = _modelHomeDir + moc3Path;
3.モデルの読み込み
モデルの読み込みには、CubismModelのインターフェースによって行います。
CubismModelのインスタンスは、CubismJavaFrameworkではCubismUserModel._modelが保持しています。
こちらを利用する場合、CubismUserModelを継承したクラスから扱うことを推奨しています。
また、テクスチャやモーション、表情モーション等のリソース管理は外部で行うことも可能です。
ここでは、例としてCubismUserModelを継承したCubismUserModelExtendを用いて説明します。
// モデルのインスタンスを作成 CubismUserModelExtend userModel = new CubismUserModelExtend(); // moc3ファイル読み込み buffer = CreateBuffer(moc3Path); userModel.loadModel(mocBuffer);
読み込むMOC3ファイルのパスは上記の通り.model3.jsonで取得できますが、同様に.model3.jsonから表情、物理演算、ポーズ、まばたき、リップシンク、ユーザデータ、モーションのパスも取得できます。
SDKのサンプルではモデルの読み込みと同時にこれらの読み込みも行っております。
それぞれの読み込み方法につきましては以下を参考にしてください。
Tips
上記のスニペットは、画面にモデルを1体表示することを前提としたものです。
画面上に同時に複数体のモデルを表示する場合、表示するモデルと同数のCubismUserModelの派生クラスのインスタンスを生成します。
4.アップデート処理
Cubismモデルのアップデート処理は、モデルの初期化と同様にCubismModelのインターフェースであるCubismModel.update() を呼び出すことで行います。
CubismModel.update() を呼び出すとCubism Core の更新処理が行われ、それまでに設定されたパラメータやパーツの値から頂点情報を更新します。
public class CubismUserModelExtend{ public void update() { // パラメーター操作 _model.setParameterValue(CubismFramework.getIdManager().getId("ParamAngleX"), value); // パーツ不透明度操作 _model.setPartOpacity(CubismFramework.getIdManager().getId("PartArmL"), opacity); // モデルの頂点情報を更新 _model.update(); } }
アップデート処理では必ずupdate() 以前に、視線追従や物理演算、モーション再生などを行います。
CubismModel.update() よりも後にパラメータの値を操作しても反映されません。
その後に再度CubismModel.update() を呼べば反映されますが、この処理は負荷が高いため一つにまとめることを推奨します。
// 頂点に反映される _model.setParameterValue(CubismFramework.getIdManager().getId("ParamAngleX"), value); // モデルの頂点情報を更新 _model.update(); // 頂点に反映されない _model.setParameterValue(CubismFramework.getIdManager().getId("ParamAngleX"), value);
モーションを再生するCubismMotionManager.updateMotion() は、再生するモーションに使用されているIDのパラメータの値をすべて上書きします。
そのため、この処理以前にパラメータの値を操作してもすべてCubismMotionManager.updateMotion() によって上書きされてしまいます。
視線追従などの値操作や物理演算などは、先にモーションの再生処理を行い、その後に行うことを推奨します。
// 再生中のモーションをモデルに反映 _motionManager.updateMotion(_model, deltaTimeSeconds); // 視線追従などの値操作や物理演算処理 // モデルの頂点情報を更新 _model.update();
また、再生するモーションにすべてのパラメータが使用されていない場合や、モーションの再生が停止しているなどの理由からパラメータの値を操作しない場合、前のフレームで行った値操作の結果が残ったままになります。
そのため、その後に行う相対的なパラメータの値操作の結果が意図しないものになる可能性があります。
これは、モーションをモデルに反映させる処理の前後にCubismModel.loadParameter() 、CubismModel.saveParameters() を呼び出すことで、その後に行う相対的な値操作をリセットすることが可能です。
// すべてのパラメータの値を保存時の状態に復元 _model.loadParameters(); // 再生中のモーションをモデルに反映 _motionManager.updateMotion(_model, deltaTimeSeconds); // すべてのパラメータの値を保存 _model.saveParameters(); // 相対的な値操作処理 // モデルの頂点情報を更新 _model.update();
視線追従や物理演算、モーションの再生などの処理自体についてはそれぞれのドキュメントを参照してください。
物理演算や_model.update関数で更新された頂点情報などをレンダラーに渡すことで、Cubismモデルを画面に描画することができます。
5.モデルの破棄
Cubism SDK for Javaでは基本的にはリソースの解放をガベージコレクションに任せていますが、モデルの生成においてはJava Native Interface(JNI)を使用してNativeの関数にアクセスすることで実現しています。
従って、この箇所に関してはdelete処理を実行する必要があります。
// モデルデータの破棄 userModel.delete();
6.Cubism Frameworkの終了処理
CubismFrameworkが確保した共通部分のリソースを解放するには、CubismFramework.dispose() を呼び出します。
CubismFramework.dispose() は、CubismFramework.initialize() を呼ぶ前には呼び出さないでください。
// CubismFrameworkの破棄 CubismFramework.dispose();
Tips
CubismFrameworkで初期化したデータはモデルデータには依存していないため、複数のモデル間で使いまわすことができます。
そのため、モデルの切り替えだけであればCubismFramework.dispose() を呼び出す必要はありません。