Zero, prepare knowledge

Today we will analyze the process of loading a Live2D model, so the focus of this article is on the Live2D format and the API usage of the SDK. There is not much else to explain, but the basic knowledge of cmake, C++ and JNI. If you search for this article in the source code, you may be disappointed.

The last article introduced the Java layer implementation of Live2D and the official Android Demo, portal:

[Android] fishing plan: to App also add a Live2D | 7 clock

1. File structure of Live2D

(This document only provides the contents of the sample model in the Demo. It cannot be used as reference documentation.)

This time we use the model of Haru. Although the Mark used in the last article is simple, its appearance is a little poor. Who doesn’t like beautiful girls?

. ├ ─ ─ Haru. 2048 │ ├ ─ ─ texture_00. PNG │ └ ─ ─ texture_01. PNG ├ ─ ─ Haru. Moc3 ├ ─ ─ Haru. Model3. Json ├ ─ ─ Haru. Pose3. Json ├ ─ ─ Haru. Userdata3. Json ├ ─ ─ expressions │ ├ ─ ─ F01. Exp3. Json │ ├ ─ ─ F02. Exp3. Json │ ├ ─ ─ F03. Exp3. Json │ ├ ─ ─ F04. Exp3. Json │ ├ ─ ─ F05. Exp3. Json │ ├ ─ ─ F06. Exp3. Json │ ├ ─ ─ F07. Exp3. Json │ └ ─ ─ F08. Exp3. Json └ ─ ─ motions ├ ─ ─ haru_g_idle. Motion3. Json ├── Haru_g_m03.motion3.json ├─ Haru_g_M03.motion3.json ├─ Haru_g_M03.motion3.json ├─ Json ├── Haru_g_m07.motion3.json ├─ Haru_g_m07.motion3.json ├── Haru_g_m08.motion3.json ├── Json ├── Haru_g_m10.motion3.json ├─ Haru_g_m10.motion3.json ├─ Haru_g_m12.motion3.json ├─ Json ├── Haru_g_m13.motion3.json ├─ Haru_g_m15.motion3.json ├── Haru_g_m16.motion3.json ├── Json ├── Haru_g_m20.motion3.json ├─ Haru_g_m18.motion3.json ├─ Haru_g_m20.motion3.json ├─ Json ├── Haru_g_m24.motion3.json ├─ Haru_g_m23.motion3.json ├─ Haru_g_m24.motion3.json ├─ Haru_g_m25. Motion3. Json └ ─ ─ haru_g_m26. Motion3. JsonCopy the code

Looks like a lot, can be sorted into seven parts.

  • Haru.2048| texture (map) resource folder
  • Haru.moc3| model file
  • Haru.model3.json| global configuration model
  • Haru.pose3.json| configuration model posture
  • Haru.userdata3.json| user data configuration
  • expressions| folder emotional expression
  • motionsAction | folder

(There are a lot of “3s” because the version number of Live2D is 3)

Loading the model (Cubism SDK API)

Model loading begins with the constructor of LAppLive2DManager, a lazy-loaded singleton that holds and manages the life cycle of a Live2D model and handles interactions between the model and the user. The Live2D model is encapsulated in the LAppModel object and initialized via SetupModel.

The starting file of the model load is fixed, which is the global configuration file of the model (xxx.model3.json), and this is exactly what the code does:

/ / ModelDir [] に keep し た デ ィ レ ク ト リ name か ら / / model3. Json の パ ス を decided す る. / / デ ィ レ ク ト リ name と model3. Json の former を consistent さ せ て お く こ と. STD: : string model = ModelDir[index]; std::string modelPath = ResourcesPath + model + "/"; std::string modelJsonName = ModelDir[index]; modelJsonName += ".model3.json"; ReleaseAllModel(); _models.PushBack(new LAppModel()); _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());Copy the code

The global configuration file is read and converted into a CubismModelSettingJson object, the order of which is determined by CubismModelSettingJson. The process of loading the model calls Java code to load assets files. We can add log here to see the specific reading order.

After reading the model from the file into memory, there is a CubismUserModel. The model data is converted into images to draw on the screen. The next step is to initialize the CubismRenderer according to the CubismUserModel.

void CubismUserModel::CreateRenderer()
{
    if (_renderer)
    {
        DeleteRenderer();
    }
    _renderer = Rendering::CubismRenderer::Create();
    _renderer->Initialize(_model);
}
Copy the code

Texture file is the last one to be read. After the CubismRenderer is initialized, the texture is read. After the PNG file is read, a series of OpenGL functions are called to create the texture object. Finally, the model and texture are bound:

GetRenderer<Rendering::CubismRenderer_OpenGLES2>()->BindTexture(modelTextureNumber, glTextueNumber);
Copy the code

After the above process, when nativeOnDrawFrame trigger calls CubismRenderer: : DrawModel can update the drawing on the screen content.


Accidentally made another day of Live2D, tomorrow fang Zhou fan works are quite a lot, but why no one to do Crosi.

The Japanese I learned last year and the JNI+OpenCV experience I was assigned to work with finally paid off, and I didn’t expect to be able to figure out the entire Demo workflow by looking through the source code of the Cubism SDK Demo in my time. I have to say, it never pays to learn more.