Computer Graphics/HumanGL

HumanGL - 5. transform 행렬 계산식 변경

surkim 2024. 10. 18. 14:20

전에 발견한 문제를 해결하기 위해 transform 행렬 계산식을 수정했다. 이전 방식에서는 스케일이 translate에 영향을 주어 직관적이지 않았고, 이를 독립적으로 계산하려 했던 것이 문제의 원인이었다.

문제 원인 분석

기존에는 transform 계산식을 다음과 같이 적용했다:

transform = projection * view * model
model = translate * rotate * scale

그런데 상속을 받을 때, 스케일을 translate과 독립적으로 적용하려다 보니 다음과 같은 방식으로 계산했다:

model = 부모 translate * 자식 translate * 부모 rotate * 자식 rotate * 부모 scale * 자식 scale

이 방식으로는 부모와 자식의 좌표계가 서로 독립적으로 되어 회전, 스케일 계승이 정확하게 이루어지지 않았다.

해결 방법

문제를 해결하기 위해 계산식을 다음과 같이 변경했다:

model = 부모 translate * rotate * scale * 자식 translate * rotate * scale * size

그리고 스케일 값을 처음에는 1로 설정한 뒤, 각 파트에 적용할 size 요소를 Part 구조체에 추가하여 따로 관리했다. 이렇게 하면 스케일은 부모와 자식의 계승을 따르고, size는 각 파트에 독립적으로 적용할 수 있게 된다.

코드 변경 내용

Part 구조체 수정

struct Part {
    sglm::vec3 translate;
    sglm::vec3 rotate;
    sglm::vec3 scale;
    sglm::vec3 size;
    sglm::vec3 color;
};

DrawNode 함수 수정

void Human::DrawNode(const Node& node, const Mesh* mesh, const Program* program, const sglm::mat4& transform) const {
    sglm::mat4 translateModel = sglm::translate(sglm::mat4(1.0f), node.part->translate);
    sglm::mat4 rotateModel = sglm::rotate(sglm::mat4(1.0f), sglm::radians(node.part->rotate.x), sglm::vec3(1.0f, 0.0f, 0.0f));
    rotateModel = sglm::rotate(rotateModel, sglm::radians(node.part->rotate.y), sglm::vec3(0.0f, 1.0f, 0.0f));
    rotateModel = sglm::rotate(rotateModel, sglm::radians(node.part->rotate.z), sglm::vec3(0.0f, 0.0f, 1.0f));
    sglm::mat4 scaleModel = sglm::scale(sglm::mat4(1.0f), node.part->scale);
    sglm::mat4 sizeModel = sglm::scale(sglm::mat4(1.0f), node.part->size);

    sglm::mat4 childTransform = transform * translateModel * rotateModel * scaleModel;
    sglm::mat4 newTransform = childTransform * sizeModel;

    program->Use();
    program->SetUniform("objectColor", sglm::vec4(node.part->color.x, node.part->color.y, node.part->color.z, 1.0f));
    program->SetUniform("transform", newTransform);
    mesh->Draw(program);

    for (const auto& child : node.children) {
        DrawNode(child, mesh, program, childTransform);
    }
}

Init 함수 수정

모든 신체 파트의 초기화에 size를 추가하여 각 파트마다 크기를 따로 지정할 수 있게 했다.

void Human::Init() {
    m_body = {sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(1.0f, 1.0f, 0.3f), sglm::vec3(1.0f, 0.0f, 0.0f)};

    m_head = {sglm::vec3(0.0f, 0.75f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.5f, 0.5f, 0.3f), sglm::vec3(0.767f, 0.634f, 0.591f)};
    m_leftUpperArm = {sglm::vec3(-0.65f, 0.15f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.3f, 0.7f, 0.3f), sglm::vec3(1.0f, 0.0f, 0.0f)};
    m_rightUpperArm = {sglm::vec3(0.65f, 0.15f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.3f, 0.7f, 0.3f), sglm::vec3(1.0f, 0.0f, 0.0f)};

    m_leftLowerArm = {sglm::vec3(0.0f, -0.7f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.3f, 0.7f, 0.3f), sglm::vec3(0.767f, 0.634f, 0.591f)};
    m_rightLowerArm = {sglm::vec3(0.0f, -0.7f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.3f, 0.7f, 0.3f), sglm::vec3(0.767f, 0.634f, 0.591f)};

    m_leftUpperLeg = {sglm::vec3(-0.25f, -0.875f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.45f, 0.75f, 0.3f), sglm::vec3(0.0f, 0.0f, 1.0f)};
    m_rightUpperLeg = {sglm::vec3(0.25f, -0.875f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.45f, 0.75f, 0.3f), sglm::vec3(0.0f, 0.0f, 1.0f)};

    m_leftLowerLeg = {sglm::vec3(0.0f, -0.75f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.45f, 0.75f, 0.3f), sglm::vec3(0.767f, 0.634f, 0.591f)};
    m_rightLowerLeg = {sglm::vec3(0.0f, -0.75f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(1.0f, 1.0f, 1.0f), sglm::vec3(0.45f, 0.75f, 0.3f), sglm::vec3(0.767f, 0.634f, 0

 

 

0
렌더링마다 scale, rotate 를 변경해주었다.

'Computer Graphics > HumanGL' 카테고리의 다른 글

HumanGL - 7. ImGui 추가  (0) 2024.10.23
HumanGL - 6. Animation 적용  (0) 2024.10.23
HumanGL - 4. 문제 발견  (0) 2024.10.17
HumanGL - 3. 사람 그리기  (0) 2024.10.17
HumanGL - 2. Scale 적용 해보기  (1) 2024.10.17