전에 발견한 문제를 해결하기 위해 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
'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 |