关于模型(Native)
最終更新: 2019年11月7日
关于编辑模型信息
模型信息基本上由Modeler创建。
.moc3文件中记录了相对于参数的顶点等动作。
附加到其他物理模拟、图形网格的用户数据等作为单独的文件输出,
.model3.json文件记录模型相关的所有文件参考。
从Modeler输出.moc3文件时,可以同时输出。“输出嵌入数据”
您还可以使用Cubism Viewer(for OW)追加动态、表情文件和姿势文件的内置设置。
使用Framework从.model3.json文件导入
使用Framework导入时,从.model3.json文件中提取模型所需的信息,
然后考虑将维护和使用继承CubismUserModel类的副本。
// C++ const csmChar* dir = "example/"; const csmChar* fileName = "example.model3.json"; const csmString jsonpath = csmString(dir) + fileName; csmSizeInt size; csmByte* buffer = CreateBuffer(jsonpath.GetRawString(), &size); ICubismModelSetting* setting = new CubismModelSettingJson(buffer, size); DeleteBuffer(buffer, jsonpath.GetRawString());
ICubismModelSetting类中提取的各元素都可以通过CubismUserModel::Load~~系函数导入。
// C++ csmSizeInt size; //Cubism Model if (strcmp(setting->GetModelFileName(), "") != 0) { csmString path = setting->GetModelFileName(); path = dir + path; if (_debugMode)LAppPal::PrintLog("[APP]create model: %s", setting->GetModelFileName()); csmByte* buffer = CreateBuffer(path.GetRawString(), &size); LoadModel(buffer, size); DeleteBuffer(buffer, path.GetRawString()); }
.model3.json文件开始的全体读取流程按照范例中的LAppModel::LoadAssets函数
到LAppModel::SetupModel函数、CubismUserModel::CreateRenderer函数、LAppModel::SetupTextures函数的流程将会容易理解。
创建副本(导入.moc3文件)
首先,将.moc3文件导入到内存记忆中。
将导入缓冲区和大小传递给CubismMoc::Create函数,首先创建一个CubismMoc副本。
然后调用CubismMoc::CreateModel函数来创建一个CubismModel副本。
从这个CubismModel副本中,您可以操作参数并获取绘图信息等。
CubismMoc::CreateModel函数计算CubismMoc内部函数生成的Model数量,
放弃CubismMoc时,您需要放弃从CubismMoc生成的所有CubismModel。
// C++ csmString path = "example.moc3"; path = dir + path; csmSizeInt size; csmByte* buffer = CreateBuffer(path.GetRawString(), &size); CubismMoc* moc = CubismMoc::Create(buffer, size); CubismModel* model = _moc->CreateModel();
图形环境关联
Framework使用从CubismRenderer类派生的类,以便模型的纹理信息不依赖于图形API。
所有与模型相关的图形相关信息都由CubismRenderer类的派生类管理。
从CubismRenderer类中生成图形API的派生类,
并通过使用CubismRenderer::Initialize函数注册CubismModel副本,关联CubismRenderer副本和CubismModel副本。
// C++ Rendering::CubismRenderer* renderer = Rendering::CubismRenderer::Create(); renderer->Initialize(model);
纹理关联
Framework中模型的纹理由CubismRenderer类的派生类管理。
但是,该方法没有在CubismRenderer类中注册,因为该功能避免了对图形API的依赖。
请注意,方法规格会根据对象图形API的不同而有所不同。
在OpenGL处理中,使用CubismRenderer类的派生CubismRenderer_OpenGLES2类中的CubismRenderer_OpenGLES2::BindTexture函数进行注册。
第一个参数可以通过模型纹理编号和Editor上的纹理集编号来确认。
第二个参数是纹理在OpenGL中的管理编号。
下面的例子是在Cocos2d-x中导入纹理。
// C++ // 将纹理读取到OpenGL纹理单元中 csmInt32 modelTextureNumber = 0; csmString texturePath = "example.2048/texture_00.png"; texturePath = dir + texturePath; //cocos2d Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(std::string(texturePath.GetRawString())); const csmInt32 glTextureNumber = texture->getName(); const Texture2D::TexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; texture->setTexParameters(texParams); texture->generateMipmap(); //OpenGL GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->BindTexture(modelTextureNumber, glTextureNumber);
不使用Cocos2d-x管理Texture,且单独使用OpenGL的情况下,通过应用程序端的管理进行注册。
// C++ // 将纹理读取到OpenGL纹理单元中 csmString texturePath = _modelSetting->GetTextureFileName(modelTextureNumber); texturePath = _modelHomeDir + texturePath; LAppTextureManager::TextureInfo* texture = LAppDelegate::GetInstance()->GetTextureManager()->CreateTextureFromPngFile(texturePath.GetRawString()); const csmInt32 glTextureNumber = texture->id; //OpenGL GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->BindTexture(modelTextureNumber, glTextureNumber);
指定显示位置和大小
您可以通过到目前为止的设置绘制模型,
但在很多情况下,显示位置和比例尺相差太大,无法在画面上显示。
有关csmGetDrawableVertexPositions函数返回的顶点范围,请参考“DrawableVertexPositions范围”。
使用CubismModelMatrix类、CubismModel::GetCanvasWidth函数和CubismModel::GetCanvasHeight函数来调整大小。
// C++ CubismModelMatrix* modelMatrix = CSM_NEW CubismModelMatrix(_model->GetCanvasWidth(), _model->GetCanvasHeight());
这个矩阵在绘制前乘以Projection矩阵,作为MVP矩阵传递给渲染器。
// C++ CubismMatrix44 projectionMatrix; projectionMatrix.Scale(1, window.width / window.height); projectionMatrix.MultiplyByMatrix(modelMatrix); GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->SetMvpMatrix(&projectionMatrix); GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->DrawModel();
顶点更新
执行CubismModel::Update函数,将CubismModel副本相对的参数操作应用在图形网格的顶点上。
// C++ model->Update();
绘制
绘制不是从CubismModel副本执行的,而是被指示给关联的渲染器。
// C++ CubismMatrix44 projectionMatrix; projectionMatrix.Scale(1, window.width / window.height); projectionMatrix.MultiplyByMatrix(modelMatrix); GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->SetMvpMatrix(&projectionMatrix); GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->DrawModel();
放弃
放弃副本需要在放弃所有CubismlModel后,放弃CubismMoc。
要保持此顺序,请使用CubismMoc::DeleteModel删除来放弃CubismModel。
如果您不经由该函数,由于CubismMoc内部确认的模型数量不匹配,您将收到警告。
// C++ CubismUserModel::~CubismUserModel() { CSM_DELETE(_motionManager); CSM_DELETE(_expressionManager); _moc->DeleteModel(_model); // <<< CubismMoc::Delete(_moc); // <<< CSM_DELETE(_modelMatrix); CubismPose::Delete(_pose); CubismEyeBlink::Delete(_eyeBlink); CubismBreath::Delete(_breath); CSM_DELETE(_dragManager); CubismPhysics::Delete(_physics); CubismModelUserData::Delete(_modelUserData); DeleteRenderer(); }
// C++ CubismMoc::~CubismMoc() { CSM_ASSERT(_modelCount == 0); CSM_FREE_ALLIGNED(_moc); } void CubismMoc::DeleteModel(CubismModel* model) { CSM_DELETE_SELF(CubismModel, model); --_modelCount; }
在CubismModel类中使用模型中不存在的参数ID
在CubismModel类的参数和部件不透明度的操作中,可以处理.moc3文件中不存在ID的功能。
该功能被CubismMotion类、CubismPose类等使用,
使用它创建新结构时,请注意您使用的ID,避免与现有功能冲突。
另外,请注意使用解读Framework时也会创建的参数与其他功能联动的可能性。
* 访问不存在的最大值、最小值和初始值时会出现错误。
// C++ csmInt32 CubismModel::GetParameterIndex(CubismIdHandle parameterId) { csmInt32 parameterIndex; const csmChar** idArray = Core::csmGetParameterIds(_model); csmInt32 idCount = Core::csmGetParameterCount(_model); for (parameterIndex = 0; parameterIndex < idCount; ++parameterIndex) { if (parameterId != _parameterIds[parameterIndex]) { continue; } return parameterIndex; } // 如果模型中不存在,则搜索不存在的参数ID列表并返回其索引 if (_notExistParameterId.IsExist(parameterId)) { return _notExistParameterId[parameterId]; } // 如果不存在的参数ID列表中没有,则追加一个新元素 parameterIndex = Core::csmGetParameterCount(_model) + _notExistParameterId.GetSize(); _notExistParameterId[parameterId] = parameterIndex; _notExistParameterValues.AppendKey(parameterIndex); return parameterIndex; }