모델 정보(Native)

업데이트: 2019/11/07

모델 정보 편집에 대하여

모델 정보는 기본적으로 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 인스턴스로부터 파라미터의 조작이나 draw를 위한 정보 취득 등을 실시합니다.

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는 모델의 텍스쳐 정보를 그래픽 API에 의존하지 않기 위해 CubismRenderer 클래스의 파생 클래스를 사용합니다.
모델과 관련된 그래픽 관련 정보는 모두 CubismRenderer 클래스의 파생 클래스에서 관리합니다.
CubismRenderer 클래스에서 그래픽 API에 대한 파생 클래스를 생성하고,
CubismRenderer::Initialize 함수로 CubismModel 인스턴스를 등록하면 CubismRenderer 인스턴스와 CubismModel 인스턴스가 연결됩니다.

// C++
Rendering::CubismRenderer* renderer = Rendering::CubismRenderer::Create();

renderer->Initialize(model);

텍스쳐 연결

Framework에서 모델이 가지는 텍스쳐는 CubismRenderer 클래스의 파생 클래스가 관리합니다.
그러나 그 기능은 그래픽 API에 대한 의존을 피하기 위해 CubismRenderer 클래스에 그 메소드의 등록은 되어 있지 않습니다.
대상으로 하는 그래픽스 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 인스턴스에 대한 파라미터 조작을 아트메쉬의 정점에 반영하기 위해 CubismModel::Update 함수를 실행합니다.

// 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을 파기해야 합니다.
이 순서를 지키기 위해, CubismModel의 파기는 CubismMoc::DeleteModel로 삭제합니다.
이 함수를 경유하지 않을 경우 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; 
}
이 기사가 도움이 되었나요?
아니요
이 기사에 관한 의견 및 요청사항을 보내 주시기 바랍니다.