OpenGL

OpenGL: Selection and Picking

FunnyPR 2014. 5. 5. 18:51

■ OpenGL: Selecting Object


사용자와 상호작용, 즉 인터랙티브한 효과가 필요함

  - Selecting and Picking of Objects


OpenGL 의 강력한 기능 중 하나가 선택한 객체의 정보를 얻어 사용자에게 제공하고 그에 따른 반응을 할 수 있는 점


1. Selection(선택)

선택모드: 하나의 랜더링 모드, 프레임 버퍼에 픽셀이 복사되지 않음

 - 기본 모델이 관측 공간내에 그려지며, 선택 버퍼 내에 히트 수가 만들어짐(정수 값을 가짐)


선택버퍼

 - 물체나 모델 또는 그룹 구별하기 위해 선택버퍼를 설정해야 함

 - 선택버퍼 설정 이후 해석하여 어떤 물체가 관층 공간 내에 있는지 검사 하면 됨

 - 부호 없는 정수의 배열로, 각 히트 레코드는 적어도 네 개의 요소 자리를 차지 함

 - 렌더링 과정에서 발생하는 히트 수를 기록하는데 사용됨



기본 모델의 이름

 - 장면 내 모든 객체들의 이름을 짓는 것도 가능하지만 비효율적임

 - 가장 많이 사용하는 방법은 그룹 식별(이름 목록)

 - 이름 목록은 네임 스택에 저장됨 

     - 네임 스택 초기화 -> 이름 입력

 - 선택과정에서 히트(hit)가 발생하면 현재 네임 스택에 있는 모든 이름들이 선택 버퍼 끝에 추가됨


step 1: 구분할 그룹 이름과 정수 정의 

step 2: 네임 스택 초기화 

step 3: 모델의 이름을 정하고 드로잉 


객체를 선택하기 위해서는 랜더링 모드 변경을 해줘야 한다. 

glRenderMode(GL_SELECTION); //선택모드로 변경

glRenderMode(GL_RENDER);//다시 드로잉 모드로 변경 


선택버퍼 


2. Picking 

- 선택버퍼에서 어떤 물체가 클릭되었는지 확인

void gluPickMatrix(

GLdouble   x, //Specify the center of a picking region in window coordinates.

GLdouble   y,

GLdouble   delX, //Specify the width and height, respectively, of the picking region in window coordinates.

GLdouble   delY,

GLint *   viewport //Specifies the current viewport 

);

x, y 는 현재 사용자가 클릭한 공간이 되고, delX와 delY는 사용자가 클릭한 point에서 picking region이 된다. 그리고 viewport는 현재 화면 뷰포트의 포인터 변수가 된다. 여기서 사용되는 뷰 포트 정보를 가져 오기 위해 다음 함수를 사용한다.

The glGetIntegerv function returns the value or values of a selected parameter.

void WINAPI glGetIntegerv(

  GLenum pname,//The parameter value to be returned. The following symbolic constants are accepted.

  GLboolean *params//Returns the value or values of the specified parameter.

);

pname에 정해진 심볼을 사용한다. 이 심볼 중 GL_VIEWPORT를 사용할 경우 다음과 같다. 

The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height. See glViewport.

4개의 파라미터를 반환: x, y, width, height 

즉 glGetIntegerv(GL_VIEWPORT, viewport)를 하게 되면 현재 뷰포트의 x, y, width, height 값을 viewport 변수에 리턴하게 된다. 


http://msdn.microsoft.com/en-us/library/windows/desktop/ee872027(v=vs.85).aspx


즉 어떠한 객체를 picking하기 위해서는 먼저 뷰포트에 대한 정보를 가져오고 그 뷰포트 정보 중 선택된 좌료 값에 매칭되는 객체가 있는지 확인하는 과정을 가진다. 


gluPickMatrix 함수를 사용하는 방법은 다음과 같다.

step 1: 현재 투영 행렬 상태 저장

step 2: glLoadIdentity 호출(단위 크기의 관측 공간 생성) - 변환된 회전이나 좌표의 행렬을 처음 상태로 돌려줌

step 3: gluPickMatrix 를 통해 관측 공간을 적절한 위치로 옴김

step 4: 원래 장면의 투영 방법을 적용 

- 정확한 매핑이 안이루어 질 수 있다. 



3. 정리 (객체를 선택하기 위한 단계)

step 1: 선택버퍼 선언

step 2: glSelectBuffer()함수로 선택 버퍼 할당

step 3: 현재 viewport 값 가져오기

step 4: 투영 모드 전환 및 배열 저장

step 5: 랜더링 모드 GL_SELECT 로 변환

step 6: 행렬 초기화 및 현재 마우스 클릭된 좌표의 객체 정보를 가져옴

step 7: 관점 설정 및 투영 시작

step 8: 다시 드로잉

step 9: 랜더링 모드 GL_RENDER 로 다시 돌아가면서 선택된 객체 index 값 받음

step 10: 투영 행렬 재저장

step 11: 정상 랜더링을 위한 모델 뷰로 돌아감


step 9에서 쓰이는 함수 

glRenderMode(GL_RENDER)에서 어떻게 선택된 객체의 index 값을 받는가?

The call to glRenderMode(GL_RENDER) exits selection mode and returns the number of hit records stored in the selection buffer. 

return: 

GL_SELECT: The number of hit records transferred to the select buffer.


흠 그렇군 책에는 자세히 안써져 있다. 




흣 작업 완료


ref

[1] Richard S. Wright. Jr. - Benjamin Lipchak 외 저(최연호 역), "OpenGL SuperBible", 정보문학사, pp. 651-680, 2005.