이제 상자의 스케일을 조정하고, 몸의 각 파트를 계층적으로 나누어 사람을 그려주었다. 하위 단계의 값들은 상위 단계의 값을 계승하며, 각 파트는 부모의 상대 좌표를 기반으로 계산된다. 이렇게 계층 구조로 설정된 방식은 게임 엔진의 트리 구조와 비슷하게 동작한다.
Human 초기화
먼저 사람의 각 신체 부위를 초기화하는 작업부터 시작했다. 몸통을 중심으로 머리, 팔, 다리 등 모든 부위를 트리 구조로 정리해주었다. 각 파트는 위치(translate
), 회전(rotate
), 크기(scale
), 색상(color
) 정보를 가지며, 이 값들은 계층적으로 상위 값을 계승한다.
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, 0.3f), sglm::vec3(1.0f, 0.0f, 0.0f)};
// body 자식
m_head = {sglm::vec3(0.0f, 0.75f, 0.0f), sglm::vec3(0.0f, 0.0f, 0.0f), sglm::vec3(0.5f, 0.5f, 1.0f), 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(0.3f, 0.7f, 1.0f), 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(0.3f, 0.7f, 1.0f), 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.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.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(0.45f, 0.75f, 1.0f), 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(0.45f, 0.75f, 1.0f), 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.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.767f, 0.634f, 0.591f)};
// 노드 트리 구조 설정
Node head = {&m_head, {}};
Node leftLowerArm = {&m_leftLowerArm, {}};
Node rightLowerArm = {&m_rightLowerArm, {}};
Node leftLowerLeg = {&m_leftLowerLeg, {}};
Node rightLowerLeg = {&m_rightLowerLeg, {}};
Node leftUpperArm = {&m_leftUpperArm, {leftLowerArm}};
Node rightUpperArm = {&m_rightUpperArm, {rightLowerArm}};
Node leftUpperLeg = {&m_leftUpperLeg, {leftLowerLeg}};
Node rightUpperLeg = {&m_rightUpperLeg, {rightLowerLeg}};
// body를 루트로 하는 트리 구조 완성
m_root = {&m_body, {head, leftUpperArm, rightUpperArm, leftUpperLeg, rightUpperLeg}};
}
이 초기화 과정에서는 신체 각 부위를 정의하고, 계층적인 트리 구조로 설정해주었다. 몸통을 루트 노드로 설정하고, 그 아래에 머리, 팔, 다리 등을 연결했다. 이제 이 구조를 기반으로 각 부위를 쉽게 제어할 수 있게 되었다.
Human 그리기
Draw
함수에서는 트리 구조로 설정된 사람의 각 부위를 계층적으로 그려준다. 이때 DrawNode
함수는 부모의 변환 값을 자식에게 전달하면서 재귀적으로 그리기 작업을 수행한다.
void Human::Draw(const Mesh* mesh, const Program* program, const Transform& transform) const {
DrawNode(m_root, mesh, program, transform);
}
void Human::DrawNode(const Node& node, const Mesh* mesh, const Program* program, const Transform& transform) const {
sglm::mat4 translateModel = sglm::mat4(1.0f);
sglm::mat4 rotateModel = sglm::mat4(1.0f);
sglm::mat4 scaleModel = sglm::mat4(1.0f);
translateModel = sglm::translate(translateModel, node.part->translate);
translateModel = transform.translateModel * translateModel;
rotateModel = sglm::rotate(rotateModel, 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));
rotateModel = transform.rotateModel * rotateModel;
scaleModel = sglm::scale(scaleModel, node.part->scale);
scaleModel = transform.scaleModel * scaleModel;
sglm::mat4 newTransform = transform.projection * transform.view * translateModel * rotateModel * scaleModel;
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);
Transform childTransform = {transform.projection, transform.view, translateModel, rotateModel,
scaleModel};
for (const auto& child : node.children) {
DrawNode(child, mesh, program, childTransform);
}
}
이 함수는 각 신체 부위에 대해 translate
, rotate
, scale
을 적용한 후, 트랜스폼 행렬을 통해 그려준다. 자식 노드로 내려갈 때마다 부모의 트랜스폼 값을 이어받아 그리기 때문에, 계층적으로 정확한 위치에 각 부위가 그려진다.
이렇게 해서 사람의 신체를 계층적으로 설정하고 그리는 작업을 완료했다. 초기화와 그리기 함수가 갖춰졌으니, 이후에는 이 구조를 활용해 다양한 움직임과 애니메이션을 추가할 것이다.
'Computer Graphics > HumanGL' 카테고리의 다른 글
HumanGL - 5. transform 행렬 계산식 변경 (0) | 2024.10.18 |
---|---|
HumanGL - 4. 문제 발견 (0) | 2024.10.17 |
HumanGL - 2. Scale 적용 해보기 (1) | 2024.10.17 |
HumanGL - 1. 초기 설정, 상자 띄우기 (1) | 2024.10.17 |
HumanGL - 0. 과제 해석 (0) | 2024.10.16 |