1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍 3장 – 입력과 상호작용 4장 – 기하학적 객체와 변환 10장 모델링 1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍 3장 – 입력과 상호작용 4장 – 기하학적 객체와 변환 5장 – 관측 6장 – 음영 7장 – 구현 8장 – 이산적 기법들 기하학적 객체의 렌더링 외에 프레임 버퍼에 대한 작업을 이해 텍스처 매핑 등의 매핑 방법을 이해 합성방법의 이해
10장 모델링 학습목표 계층적 모델 Tree와 DAG 모델 특정 모델에 독립적인 일반적인 트리모델 구조를 구축 관절모델 로봇 Tree와 DAG 모델 특정 모델에 독립적인 일반적인 트리모델 구조를 구축 장면 그래프의 소개
모델에서 객체의 출현은 사례(인스턴스)이다 인스턴스 변환 프로토타입 객체(심볼)에서 시작 모델에서 객체의 출현은 사례(인스턴스)이다 크기변환, 회전, 이동 되어야함 인스턴스 변환을 정의
사례화(instancing)
심볼-인스턴스 테이블 각 심볼에 번호를 할당하고 인스턴스 변환을 위한 매개변수를 저장함으로써 모델을 저장
심볼-인스턴스 테이블은 모델의 부분들 사이의 관계를 보여주지 않는다 자동차의 모델을 생각해보자 자동차 모델에서의 관계들 심볼-인스턴스 테이블은 모델의 부분들 사이의 관계를 보여주지 않는다 자동차의 모델을 생각해보자 차체 + 4 개의 동일한 바퀴들 두 개의 심볼들 전진속도는 바퀴의 회전속도에 의해서 결정된다
함수호출을 통한 구조 관계를 잘 보여주지 못한다 그래프를 이용해서 문제를 살펴봄 car() { float s; // 속도 float d[3]; // 방향 . // 속도와 방향을 결정한다 draw_right_front_wheel(s,d); draw_left_front_wheel(s,d); draw_right_rear_wheel(s,d); draw_left_rear_wheel(s,d); draw_chassis(); } 관계를 잘 보여주지 못한다 그래프를 이용해서 문제를 살펴봄
자동차의 트리 모델
모든 바퀴들이 같다는 사실을 이용하면 방향성 비순환그래프 (directed acyclic graph) 를 얻는다 DAG 모델 모든 바퀴들이 같다는 사실을 이용하면 방향성 비순환그래프 (directed acyclic graph) 를 얻는다 트리를 다루는 것과 크게 다르지 않음
노드와 에지에 어떤 정보를 넣을 것인지를 결정해야 한다 트리를 이용한 모델링 노드와 에지에 어떤 정보를 넣을 것인지를 결정해야 한다 노드 그릴 내용 자식 노드에 대한 포인터 에지 변환행렬에 대한 증분적 변화정보를 가질 수 있다(노드에 저장될 수도 있다)
로봇 팔 자기 자신의 좌표계 에서의 부품들 로봇 팔
관절모델 로봇 팔은 관절모델의 예이다 부품들이 관절에서 연결된다 모델의 상태를 모든 관절각으로 표현할 수 있다
로봇 팔에서의 관계들 베이스는 독립적으로 회전 아래 팔이 베이스에 연결됨 위 팔이 아래 팔에 연결됨 하나의 각이 위치를 결정 그것의 위치는 베이스의 회전에 의존적 베이스에 상대적으로 이동해야 하고 연결관절을 중심으로 회전 위 팔이 아래 팔에 연결됨 그것의 위치는 베이스와 아래 팔에 의존적 아래 팔에 상대적으로 이동해야 하고 아래 팔에 연결된 관절을 중심으로 회전
요구되는 행렬들 베이스의 회전: Rb 베이스에 상대적으로 아래 팔을 이동: Tlu 아래 팔을 관절을 중심으로 회전: Rlu M = Rb 를 베이스에 적용 베이스에 상대적으로 아래 팔을 이동: Tlu 아래 팔을 관절을 중심으로 회전: Rlu M = Rb Tlu Rlu을 아래 팔에 적용 아래 팔에 상대적으로 위 팔을 이동 : Tuu 위 팔을 관절을 중심으로 회전 : Ruu M = Rb Tlu Rlu Tuu Ruu 을 위 팔에 적용
로봇을 위한 OpenGL 코드 display() { glRotate(theta, 0.0, 1.0, 0.0); base(); glTranslatef(0.0, h1, 0.0); glRotate(phi, 0.0, 0.0, 1.0); lower_arm(); glTranslatef(0.0, h2, 0.0); glRotate(psi, 0.0, 0.0, 1.0); upper_arm(); }
앞의 코드를 보면, 모델의 부분들 사이의 관계를 보이고 있다 로봇의 트리 모델 앞의 코드를 보면, 모델의 부분들 사이의 관계를 보이고 있다 관계를 바꾸지 않고 부분들의 “모양”을 쉽게 바꿀 수 있다 트리 모델의 간단한 예
가능한 노드 구조 부분을 그리는 코드 또는 그리기 함수로의 포인터 자식 노드로의 포인터의 연결 리스트 노드를 부모와 관련 짓는 행렬
사람 모양
quadric(ellipsoid나 cylinder)을 사용하여 간단히 구현할 수 있다 모델의 구축 quadric(ellipsoid나 cylinder)을 사용하여 간단히 구현할 수 있다 다음 함수들을 이용해서 부분들에 접근할 수 있다 torso() left_upper_arm() 행렬들은 노드의 위치를 그 부모에 상대적으로 기술한다 Mlla 는 왼쪽 아래 팔의 위치를 왼쪽 위 팔에 상대적으로 기술한다
행렬이 표시된 트리
이 사람 모형의 위치는 11개의 관절각 (머리를 위한 2개와 다른 부분들을 위한 각 하나)으로 결정된다 디스플레이와 순회 이 사람 모형의 위치는 11개의 관절각 (머리를 위한 2개와 다른 부분들을 위한 각 하나)으로 결정된다 트리의 디스플레이를 위해서 그래프 순회가 필요하다 각 노드를 한 번 방문 위치와 방향을 위한 올바른 변환행렬을 적용, 그 노드에 관련된 부분을 기술하는 디스플레이 함수가 디스플레이
변환 행렬들 10 개의 관련된 행렬들 M 은 루트 노드인 토르소를 통해서 전체 모형의 위치와 방향을 정한다 Mh 토르소에 상대적으로 머리의 위치를 정한다 Mlua, Mrua, Mlul, Mrul 토르소에 상대적으로 팔과 다리의 위치를 정한다 Mlla, Mrla, Mlll, Mrll 해당 상지에 상대적으로 하지의 위치를 정한다
스택 기반 순회 모델-관측 행렬을 M 으로 설정하고 토르소를 그린다 모델-관측 행렬을 MMh 으로 설정하고 머리를 그린다 왼쪽 위 팔을 위해서 MMlua 이 필요하다… MMlua 을 처음부터 다시 만들거나 역행렬을 구하지 않고, 트리를 순회하며 행렬 스택을 이용해서 M 과 다른 행렬을 저장한다
순회 코드 figure() { glPushMatrix(); // 현재 모델관측행렬 저장 torso(); glTranslate3f(…); glRotate3f(…); // 머리를 그리기 위해서 모델관측행렬 변경 head(); glPopMatrix(); // 원래 모델관측행렬 복구 glPushMatrix(); // 모델관측행렬 다시 저장 glTranslate3f(…); // 왼쪽 윗 팔을 위해서 glRotate3f(…); // 모델관측행렬 변경 left_upper_arm(); glTranslate3f(…); // 왼쪽 아래 팔을 위해서 left_lower_arm(); glPopMatrix(); // 원래 모델관측행렬을 다시 복구하고 glPushMatrix(); // 저장 // 나머지 코드
앞의 코드는 특정 트리와 특정 순회전략을 기술하고 있다 분석 앞의 코드는 특정 트리와 특정 순회전략을 기술하고 있다 보다 일반적인 접근방법을 개발할 수는 없는가? 예제 코드는 컬러의 변경 등 상태 변경을 포함하지 않고 있다 코드의 후반부에 영향을 주는 예기치 않은 상태 변화로부터 보호하기 위해서 glPushAttrib와 glPopAttrib를 사용할 수 있다
트리를 표현하는 자료구조와 트리를 순회하는 알고리즘이 필요 일반적 트리 자료구조 트리를 표현하는 자료구조와 트리를 순회하는 알고리즘이 필요 left-child right-sibling 구조의 사용 연결 리스트 사용 자료구조 내의 각 노드는 두 개의 포인터이다 왼쪽: 자식 노드 오른쪽: 형제 노드들의 연결 리스트
Left-Child Right-Sibling 트리
트리 노드 구조 각 노드에 다음 것들을 저장 Sibling에 대한 포인터 Child에 대한 포인터 노드가 표현하는 객체를 그리는 함수에 대한 포인터 현재 모델-관측 행렬의 오른쪽에 곱할 동차좌표 행렬 부모로부터 해당 노드로 가는 변경을 표현 OpenGL 에서 이 행렬은 열(column) 순으로 저장된 1D 배열이다
트리 노드의 C언어 정의 typedef struct treenode { Glfloat m[16]; void (*f)(); struct treenode *sibling; struct treenode *child; } treenode;
토르소 노드의 정의 treenode torso_node, head_node, lua_node, … ; /* 행렬을 구성하기 위해서 OpenGL 함수를 사용 */ glLoadIdentity(); glRotatef(theta[0], 0.0, 1.0, 0.0); /* 모델-관측 행렬을 m으로 이동 */ glGetFloatv(GL_MODELVIEW_MATRIX, torso_node.m) torso_node.f = torso; /* torso()는 토르소를 그림 */ Torso_node.sibling = NULL; Torso_node.child = &head_node;
모형의 위치는 theta[11]에 저장된 11 개의 관절각이다 유의사항 모형의 위치는 theta[11]에 저장된 11 개의 관절각이다 관절각들을 변경하고 다시 그림으로써 애니메이션 glRotate 와 glTranslate를 사용해서 요구되는 행렬을 구성 소프트웨어보다 효율적 모델-관측 행렬에 행렬이 형성되므로, 먼저 원래의 모델-관측 행렬을 행렬 스택에 푸시하기 원할 수 있다
전위 순회 void traverse(treenode *root) { if(root == NULL) return; glPushMatrix(); glMultMatrix(root->m); root->f(); if(root->child != NULL) traverse(root->child); glPopMatrix(); if(root->sibling != NULL) traverse(root->sibling); }
모델-관측 행렬에 노드 행렬을 곱하기 전에 모델-관측 행렬을 저장해 두어야 한다 유의사항 모델-관측 행렬에 노드 행렬을 곱하기 전에 모델-관측 행렬을 저장해 두어야 한다 갱신된 행렬은 노드의 자식들에게 적용되지만 자기 자신의 행렬을 가진 형제들에게는 적용되지 않는다 순회 프로그램은 임의의 left-child right-sibling 트리에 적용된다 특정 트리는 개별 노드의 정의에 인코드 된다 함수들 내에서 상태 변화가 가능하므로 순회의 순서가 중요하다
노드와 순회의 정의는 이전과 같지만 실행 중에 노드들을 추가 제거할 수 있다 동적 트리 포인터를 사용하면, 동적 구조가 될 수 있다 typedef treenode *tree_ptr; tree_ptr torso_ptr; torso_ptr = malloc(sizeof(treenode)); 노드와 순회의 정의는 이전과 같지만 실행 중에 노드들을 추가 제거할 수 있다
장면의 모든 요소(카메라, 광원, 재질, 기하)를 C++ 객체로 표현할 수 있다면, 그것들을 트리로 보여줄 수 있을 것이다 장면 기술 앞의 인물모형의 예에서 다음을 보게 된다 모델을 트리나 그와 등가적인 코드로 기술할 수 있었다 디스플레이를 위해서 일반적 순회를 작성할 수 있었다 장면의 모든 요소(카메라, 광원, 재질, 기하)를 C++ 객체로 표현할 수 있다면, 그것들을 트리로 보여줄 수 있을 것이다 이 트리를 순회함으로써 렌더링한다
장면 그래프
전위 순회 glPushAttrib glPushMatrix glColor glTranslate glRotate Object1 glPopMatrix glPopAttrib …
Separator 노드 상태 변화를 차단하기 위해 필요 인물모델에서처럼 OpenGL Push/Pop과 등가적 일반적인 순회 알고리즘을 작성할 수 있다 순회의 순서가 중요 separator 를 사용하지 않으면, 상태변화가 계속 전파될 수 있다
Inventor와Java3D 는 장면 그래프 API 를 제공 장면 그래프는 파일(텍스트 또는 이진)에 의해서도 기술될 수 있다 구현에 독립적으로 장면을 이식하는 방식 장면 그래프 API 들에 의해서 지원됨 그러나, 지원되는 기본요소들이 그래픽스 시스템들 간에 일치되어야 함 따라서 대부분의 장면 그래프 API들은 OpenGL 이나 DirectX (for PCs)의 상위에 구축된다
World Wide Web에서 사용될 수 있는 장면 그래프를 원함 VRML World Wide Web에서 사용될 수 있는 장면 그래프를 원함 분산 데이터 베이스를 지원하기 위해서 다른 사이트로의 링크가 필요 Virtual Reality Markup Language Inventor 데이터베이스에 기반함 OpenGL로 구현