Issue
도형을 마우스로 클릭하고 어떤 도형을 클릭했는지 값을 알아오고 싶었다. 스크린에 물체를 그릴 때 Projection 모드에서 glOrtho로 물체의 투영 영역을 지정하게되면 피킹값을 잘 받아오지 못했다.
Solution
마우스로 클릭한 영역을 얻기위한 GL_SELECT 모드에서 물체가 그려지는 투영값을 동일하게 설정해서 물체를 그리게 된다. 이때 GL_SELECT 모드를 위한 투영값 설정과 그림을 그릴 때 적용하는 투영값 설정이 이중으로 적용된 것이 문제였다. 그래서 Picking을 확인할 때는 그림을 그릴때 투영값을 설정하지 못하도록 했다.
void MyView::drawModel(){ //물체를 그리는 함수
if(!pickMode){ //pick할 때는 적용하면 안된다.(pick자체에서 적용되므로)
/*pick하지 않을 때 그려지는 투영값 설정*/
glMatrixMode(GL_PROJECTION); //모든 물체를 다시 그려주기위해
glOrtho(-100, 100, -100, 100, 0.1, 100); //보여줄 영역 지정 (비율 조정)
}
glPushName(1000000);
glPushMatrix();
glTranslatef(10,20,0);
glutSolidSphere(100, 10, 10);
glPopMatrix();
glPopName();
}
void MyView::CheckPickPoint(int x, int y) { //마우스 클릭 좌표 (마우스클릭할때 호출되도록한 함수)
GLuint selectBuf[BUFSIZ]; //물체의 이름이 저장되는 변수
GLint hits; //마우스클릭시 선택된 물체가 몇개나 되는지
GLint viewport[4]; //pick됐는지 확인할 영역지정
//viewport[0] = x좌표 [1] = y좌표 [2] 영역의 너비값 [3] 영역의 높이값
glSelectBuffer(BUFSIZ, selectBuf); //피킹 버퍼의 크기와 버퍼로 사용될 메모리 영역을 잡아주는것
glMatrixMode(GL_PROJECTION); //모든 물체를 다시 그려주기위해
glPushMatrix(); //PROJECTION Mode의 이전 행렬값을 저장해 놓는 코드
glRenderMode(GL_SELECT); //렌더링할때 Render mode를 Selection Buffer에 렌더링 하도록 지정하는것
glInitNames(); //Name Stack을 초기화하는 코드 (물체의 이름을 저장할 공간 초기화)
glLoadIdentity(); //PROJECTION Mode를 초기화(단위행렬) 시켜주는 코드이다.
CRect window;
GetClientRect(&window); //클라이언트 영역의 좌측상단 꼭지점 좌표와 우측하단 꼭지점 좌표가 RECT구조체에 저장
/*클릭했는지 확인할 영역 지정*/
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = window.width(); //스크린 영역 전부를 확인
viewport[3] = window.Height();
gluPickMatrix(x, window.Height() - y, 2, 2, viewport);
/*
void gluPickMatrix( GLdouble x, GLdouble y, GLdouble width, GLdouble height, GLint viewport[4])
Selection을 위한 Picking 행렬을 생성해 주는 코드
첫번째 인자 : 마우스로 클릭한 곳의 x좌표
두번째 인자 : 마우스로 클릭한 곳의 y좌표
세번째, 네번째 인자 : 마우스로 클릭했을시에 주변으로 얼마만큼의 위치에 있는 물체까지도 선택
되도록 하는 여유분 값 값을 5로주면 (x,y)위치로부터 1~5픽셀에 위치한 물체도
선택된 것으로 간주
다섯번째 인자 : Pick을 확인할 영역 viewport
*/
glOrtho(-100, 100, -100, 100, 0.1, 100); //보여줄 영역 지정
//원래 그림을 그리는 투영값이랑 똑같이 설정해줘야한다.
glMatrixMode(GL_MODELVIEW); //물체를 그리기 위해 Model View모드로 전환
glLoadIdentity(); //Model View를 단위벡터로 초기화
PickMode = true;
drawModel(); //함수 호출해서 한번 더 Selection Buffer에 그려준다
PickMode = false;
hits = glRenderMode(GL_RENDER); //이제 물체를 Render Buffer에 그려라 몇개의 물체가 선택되었는지를 반환해줌
processHits(hits, selectBuf, dispaly_number);
if(hits > 0)
print("%d", selectBuf[4]); //클릭 된 번호 확인 (1000000 이 pick된 걸 확인할 수 있을 것이다.)
glMatrixMode(GL_PROJECTION);
glPopMatrix(); //PROJECTION Mode를 다시 원상태로 복귀
glMatrixMode(GL_MODELVIEW); //다시 Model View모드로 전환
}
'◼️OpenGL' 카테고리의 다른 글
[OpenGL] 모델의 특정축을 고정하여 회전 (0) | 2023.09.12 |
---|---|
[OpenGL] 투명 도형 그리기 (0) | 2023.09.11 |
[OpenGL] 종횡비 조절 및 물체 형태가 변하지 않게 평행이동 (0) | 2023.09.04 |
MFC 마우스 이동으로 OpenGL 화면 회전 값 받기 (1) | 2023.05.19 |
OpenGL x, y, z축 회전 후 좌표값 구하기 (0) | 2023.05.19 |