如何直接使用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接口导入模型。

在CubismNativeFramework中,CubismUserModel._model持有CubismModel的副本,使用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.dispose()释放CubismFramework保存的通用资源。
在调用CubismFramework.initialize()之前,请不要调用CubismFramework.dispose()。

    // 放弃CubismFramework
    CubismFramework.dispose();
Tips

通过CubismFramework原始化的数据置入static区域,不依赖于模型数据。
因此,它可以在多个模型之间复用,如果只是想切换模型,则无需调用CubismFramework.dispose()。

关于本报道,敬请提出您的意见及要求。