-
Notifications
You must be signed in to change notification settings - Fork 43
以更细粒度控制 Live2D 模型(编写中)
live2d.v3.Model 将 live2d.v3.LAppModel 的诸多方法拆分为多个子方法,并提供了更多功能。
示例代码:main_pygame_fine_grained.py
创建 Model 实例前应当先初始化 live2d。
from live2d.v3 import init, Model
init()model = Model()
model.LoadModelJson("path/to/model3.json")LoadModelJson 首先会根据 model3.json 读取其中引用的表情 exp3.json,姿势 pose3.json,动画 motion3.json,以及模型网格数据 moc3。
model3.json 中所有文件路径均以相对路径给出,当前目录为 model3.json 文件所在目录。
调用 LoadModelJson 后,可以调用以下函数获取模型的基本信息:
def GetParameterIds(self) -> list[str]: ...
def GetParameterValue(self, index: int) -> float: ...
def GetParameterMaximumValue(self, index: int) -> float: ...
def GetParameterMinimumValue(self, index: int) -> float: ...
def GetParameterDefaultValue(self, index: int) -> float: ...
def GetMvp(self) -> list[float]: ...
def GetMotions(self) -> dict[str, list[dict[str, str]]]: ...
def GetPartIds(self) -> list[str]: ...
def GetDrawableIds(self) -> list[str]: ...
def GetExpressions(self) -> list[str, str]: ...
def GetCanvasSize(self) -> tuple[float, float]: ...
def GetCanvasSizePixel(self) -> tuple[float, float]: ...
def GetPixelsPerUnit(self) -> float: ...在 LoadModelJson 后,绘制模型需要为模型创建内部 Renderer:Model.CreateRenderer(maskBufferCount=2)。
-
CreateRenderer必须在 OpenGL 上下启用后调用 -
Draw必须在CreateRenderer后调用
makeContextCurrent() # 创建 OpenGL 上下文
model.CreateRenderer(2)
...
# 渲染循环
while running:
live2d.clearBuffer()
model.Draw()
...Model.SetExpression(expId: str):覆盖所有通过Add添加的表情
Model.SetRandomExpression() -> str:同上
Model.AddExpression(expId: str):叠加表情,戴帽子、星星眼、手势 这类不冲突的表情可以同时设置;有些表情会冲突(比如金瞳和赤瞳),只能显示其中一个表情
Model.RemoveExpression(expId: str) :清除通过Add添加的表情
Model.ResetExpressions():清除所有表情
Model.ResetExpression(): 清除通过Set设置的表情,此时如果 Add 激活的表情没有被 Remove,那么这些表情会重新显示
内部原理:
Model.SetExpression(expId: str):使用单独的 ExpressionManager 更新表情
Model.AddExpression(expId: str)、Model.RemoveExpression(expId: str) :通过 Map<ExpId, ExpressionManager> expMgrs 管理,每个表情对应一个单独的 expMgr,AddExpression 时开启对应的 ExpressionManager。
UpdateExpression 逻辑:
if (_expressionManager->IsFinished())
{
for (auto &pair : _expManagers)
{
pair.second->UpdateMotion(_model, deltaSecs);
}
}
else
{
_expressionManager->UpdateMotion(_model, deltaSecs);
}