OpenGL 3d picking 과정에서 질문 드립니다.

조회수 1022회

동영상 링크

3d 피킹을 구현하고 있습니다. 현재 피킹이 되는 구조는 먼저 수학 개념상의 평면(Plane)을 점 0,0,0을 지나고 법선벡터가 앞(forward)방향을 바라보도록 만들었습니다.

planes = new Plane(vec3(0, 0, -1), Vector3d(0.f, 0.f, 0.f));

그리고 매프레임마다 카메라가 바라보는 방향에서 윈도우좌표계상의 마우스 위치를 월드 좌표계로 변환한 Ray를 반환합니다.

Ray는 direction과 origin 두개의 vec3를 갖는 구조체입니다. 이 Ray와 평면과의 교차점을 Raycast()를 통해 알아내어 true일때 해당 point를 얻어 동영상에서 보이는 모델(model)을 위치시키고 있습니다.

// ray casting
if (Input::GetMouseButtonHeld(MOUSE_LEFT)) {
// 마우스 위치를 월드좌표계의 ray로 반환
 Ray ray = camera->ScreenPointToRay(Input::GetMousePosition()); 
 float enter = 0.f;

 if (planes->Raycast(ray, &enter)) { // 평면과 Ray가 교차할떄 true 반환과 enter에 distance 넣어줌
  vec3 hitPoint = ray.GetPoint(enter); 
  model->SetPosition(hitPoint); // 모델 위치 이동
 }
}
// position을 ray로 변환
Ray Camera::ScreenPointToRay(const vec3& position) {
 Ray ray;
 ray.mOrigin = ScreenToWorldPoint(vec3(position.x, position.y, 0.f)); // 위치
 ray.mDirection = ScreenToWorldPoint(vec3(position.x, position.y, 1.f)); // 방향
 ray.mDirection = (ray.mDirection - ray.mOrigin).Normalize(); // 두개의 차를 normalize
 return ray;
}
// 화면좌표계에서 월드좌표계로 변환
vec3 Camera::ScreenToWorldPoint(const vec3& position) {
      // 프로젝션 행렬의 역행렬과 view to world 행렬(inverse of world to view matrix)을 곱함
      Matrix4x4 invProjectionView = Matrix4x4::Inverse(GetProjectionMatrix()) * GetCameraToWorldMatrix();
      // viewport[0] = 0, viewport[1] = 0, viewport[2] = 800(w), viewport[3] = 600(h) 
      int viewport[4];
      glGetIntegerv(GL_VIEWPORT, viewport); 
      vec3 screenCoords(position.x - viewport[0], viewport[3] - position.y - (1 - viewport[1]), position.z);
      screenCoords.x = (2 * screenCoords.x) / viewport[2] - 1.f;
      screenCoords.y = (2 * screenCoords.y) / viewport[3] - 1.f;
      screenCoords.z = 2 * screenCoords.z - 1;

      return invProjectionView * screenCoords;
}

제대로 동작하는것 같은데 projection matrix가 perspective일때는 잘 안되는것 같습니다. 동영상을 보시면 처음부분이 그것인데, 마우스의 방향에 따라 움직이긴 하는데 위치가 되게 작습니다. 실제로 반환되는 hitPoint 를 콘솔에 찍어보았는데요, 동영상에서도 잠깐 나왔지만 xyz전부 1 미만의 값이 찍힙니다.

하지만 orthographic view일때는(동영상에서 잘 동작하는 예) 정상적으로 잘 동작합니다. hitPoint 또한 실제의 큰 값(1이상)이 찍힙니다.

3d picking 결과로 나온 좌표가

  1. projection matrix가 perspective일때 너무 작은 값이 나옴
  2. orthographic view일때 실제 월드 좌표로 잘됨

무엇을 고쳐야 해야할지 조언 부탁드립니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)