如何直接使用CubismNativeFramework
最終更新: 2020年1月30日
Cubism SDK for Native中包含的范例项目使用CubismNativeFramework(SDK包/Framework/以下)来处理Cubism模型。
在创建处理Cubism模型的项目时,基于范例项目使用为宜,但在现有应用程序或用户自己的引擎等中实装时,有些情况需要直接处理CubismNativeFramework的API。
但是,由于包中包含的范例项目功能强大,因此仅参考它并不容易理解和区分结构。
下面,我们将介绍以上述用户为对象,直接调用CubismFramework处理模型的最小片段。
CubismFramework周期
使用CubismFramework的步骤如下:
CubismFramework的原始化
CubismFramework的原始化处理如下所示。
CubismFramework通过使用传递给CubismFramework::StartUp()第一参数的分配器来确保内存记忆。
Cubism SDK for Native在CubismNativeSamples中有分配器范例。
CubismFramework中使用的分配器也需要实装来指定和确保对齐。
因此,基本上,因为可以快速嵌入,为此可以使用范例,但如果您想自定义内存记忆的分配,您可以将其替换为用户端实装的那一个,并修改范例并将其嵌入。
有关分配器的具体实装,请参考 此处 ,有关创建自定义内存记忆分配器的注意事项,请参考 此处 。
// 记录等选项设置。 CubismFramework::Option _cubismOption; // 分配器。 LAppAllocator _cubismAllocator; // 信息输出函数。 static void PrintMessage(const Csm::csmChar* message);
// 设置记录输出级别。在LogLevel_Verbose的情况下,输出详细记录。 _cubismOption.LoggingLevel = CubismFramework::Option::LogLevel_Verbose; _cubismOption.LogFunction = PrintMessage; // 设置CubismNativeFramework原始化所需的参数。 CubismFramework::StartUp(&_cubismAllocator, &_cubismOption); // 原始化CubismFramework。 CubismFramework::Initialize();
Tips
原始化时只调用一次CubismFramework::Initialize(),然后跳过连续调用,除非CubismFramework被放弃。 但是,一旦CubismFramework被放弃,再次对其进行原始化时将调用CubismFramework::Initialize()。
获取模型文件路径
对于Cubism的嵌入数据集,各相对路径都在model3.json中描述。
可以直接指定一个.moc3文件或者纹理进行导入,但基本上推荐从model3.json获取路径并导入。
要解析model3.json,请使用CubismFramework的CubismModelSettingJson类。
csmByte* CreateBuffer(const csmChar* path, csmSizeInt* size) { if (DebugLogEnable) { LAppPal::PrintLog("[APP]create buffer: %s ", path); } return LAppPal::LoadFileAsBytes(path, size); } void DeleteBuffer(csmByte* buffer, const csmChar* path = "") { if (DebugLogEnable) { LAppPal::PrintLog("[APP]delete buffer: %s", path); } LAppPal::ReleaseBytes(buffer); }
// 导入model3.json。 csmSizeInt size; const csmString modelSettingJsonPath = _modelHomeDir + modelSettingJsonName; csmByte* buffer = CreateBuffer(modelSettingJsonPath, &size); ICubismModelSetting* setting = new CubismModelSettingJson(buffer, size); DeleteBuffer(buffer, modelSettingJsonPath.GetRawString()); // 获取model3.json中描述的模型路径。 csmString moc3Path = _modelSetting->GetModelFileName(); moc3Path = _modelHomeDir + moc3Path;
导入模型
模型通过CubismModel接口进行导入。
CubismModel的副本由CubismNativeFramework中的CubismUserModel::_mode持有。
使用时,建议从继承CubismUserModel的类中处理。
还可以在外部管理诸如纹理、动态和表情动态等资源。
作为一个例子,这里我们将说明使用继承CubismUserModel的CubismUserModelExtend。
// 创建模型的副本。 CubismUserModelExtend* userModel = new CubismUserModelExtend(); // 导入moc3文件。 buffer = CreateBuffer(moc3Path.GetRawString(), &size); userModel->LoadModel(mocBuffer, mocSize); DeleteBuffer(buffer, moc3Path.GetRawString());
要导入的moc3文件的路径可以通过上面介绍的model3.json获取,表情、物理模拟、姿势、眨眼、口形同步、用户数据和动态路径也可以从model3.json获取。
在SDK范例中,这些是在导入模型的同时导入的。
各导入方法请参考以下内容。
Tips
上面的代码片段基于在画面上显示1个模型的假设。 如果要同时在画面上显示多个模型,请创建与要显示的模型一样多的CubismUserModel派生类的副本。
更新处理
Cubism模型的更新处理是通过调用CubismModel的接口CubismModel::Update()来完成的,方法和模型原始化一样。
当CubismModel::Update()被调用时,将进行Cubism Core更新处理,从目前为止设置的参数和部件的值更新顶点信息。
void CubismUserModelExtend::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::SaveParameter(),可以重置之后执行的相对值操作。
// 将所有参数的值恢复到保存时的状态 _model->LoadParameters(); // 将正在播放的动态应用到模型中 _motionManager->UpdateMotion(_model, deltaTimeSeconds); // 保存所有参数的值 _model->SaveParameters(); // 相对值操作处理 // 更新模型顶点信息 _model->Update();
视线追踪、物理模拟、动态播放等处理本身请参考各文档。
通过将更新后的顶点信息等传递给渲染器,可以在画面上绘制Cubism模型。
放弃模型
要放弃模型,请放弃生成的CubismUserModel派生类的副本。
通过该操作,将从CubismUserModel析构函数中放弃该模型保存的动态、表情、物理模拟等信息。
// 放弃模型数据 delete userModel;
Cubism Framework退出处理
调用CubismFramework::Dispose()释放CubismFramework保存的通用资源。
在调用CubismFramework::Initialize()之前,不要调用CubismFramework::Dispose()。
另外,在调用CubismFramework::Dispose()之前,必须放弃所有模型。
这是因为放弃模型的处理使用了分配器的Deallocate()。
// 放弃CubismFramework CubismFramework::Dispose();
Tips
通过CubismFramework原始化的数据置入static区域,不依赖于模型数据。 因此,它可以在多个模型之间复用,如果只是想切换模型,则无需调用CubismFramework::Dispose()。