btVector3 getRayTo(int x, int y)의 함수를 분석하겠다. 이것은 사용자의 클릭을 통해 Object picking을 구현하기 위해서 이다.
btVector3 getRayTo(int x, int y) { CommonRenderInterface* renderer = m_guiHelper->getRenderInterface(); if (!renderer) { btAssert(0); return btVector3(0, 0, 0); } float top = 1.f; float bottom = -1.f; float nearPlane = 1.f; float tanFov = (top - bottom) * 0.5f / nearPlane; float fov = btScalar(2.0) * btAtan(tanFov); // 구하기 Vertical Field of View // float fov = camera.Zoom 그냥 이렇게 해도된다. // 즉 perspective에 보내는 Vertical Field of View값을 말한다. btVector3 camPos, camTarget; renderer->getActiveCamera()->getCameraPosition(camPos); renderer->getActiveCamera()->getCameraTargetPosition(camTarget); // Camaera Pos에서 ray를 날림 btVector3 rayFrom = camPos; // Ray Forward는 카메라가 바라보는 방향으로 던지기 위해서 함. btVector3 rayForward = (camTarget - camPos); rayForward.normalize(); float farPlane = 10000.f; rayForward *= farPlane; // farplane을 10000으로 설정하여 멀리 날림 btVector3 rightOffset; btVector3 cameraUp = btVector3(0, 0, 0); // World-Up 방향을 받음 cameraUp[m_guiHelper->getAppInterface()->getUpAxis()] = 1; btVector3 vertical = cameraUp; // 이것을 위로가는 방향으로 설정해놓고 btVector3 hor; hor = rayForward.cross(vertical); // rayForward를 기준으로 기저를 다시 구함. hor.safeNormalize(); // hor을 통해 local x축 구하고, vertical = hor.cross(rayForward); // 다시 local y축 다시 구하기 vertical.safeNormalize(); // safeNormalize는 cross값이 epsilon보다 작으면 x축 가리키는 것을 반환함. // 그리고 이를 통해 far plane의 width와 height를 구하려함. float tanfov = tanf(0.5f * fov); hor *= 2.f * farPlane * tanfov; // 여기다가 screen ratio곱하면 far plane width됌 vertical *= 2.f * farPlane * tanfov; // vertical은 far plane height 길이 구해짐 btScalar aspect; float width = float(renderer->getScreenWidth()); float height = float(renderer->getScreenHeight()); aspect = width / height; hor *= aspect; // far plane width 완성 btVector3 rayToCenter = rayFrom + rayForward; // 1. camera에서 farPlane의 중앙으로 보냄 btVector3 dHor = hor * 1.f / width; btVector3 dVert = vertical * 1.f / height; // 2. farPlane 중앙에서 윈도우 창은 왼쪽 상단에서부터 좌표가 시작하여 // 오른쪽으로 x값 증가, 아래쪽으로 y값 증가임. // hor은 far plane의 x축, 그러니까 오른쪽 가는 방향 길이를 가지고 있고 (far plane width) // verticla은 far plane의 y축, 그러니까 위로 가는 방향 길이를 가지고 있음 (far plane height) // 그래서 rayTo은 far plane의 왼쪽 상단을 가리키게 됌. btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; // 위에서 dHor = hor * 1.f / width 했는데 // width는 near plane의 길이임. // 클릭은 near plane에서 이루어지므로, 그 near plane의 길이만큼 scale한 거임 // dVert도 마찬가지임 // 그래서 far plane의 어디지점에 향하는지 가리키기 위해 // rayTo에 더해지는 것을 자세히 보면 // rayTo += (x / width) * dHor임. // 그말은 dHor이 1.f / width가 없다하면, far plane의 오른쪽 방향으로 가는 길이인데 // near plane에서 얼마만큼 가서 찍었냐는 거임 // 그래서 아래의 식을 통해 far plane의 x축 어디에 있는지 알 수 있고 // dVert는 위를 향하고 있고, 윈도우 좌표계는 아래를 향하고 있기 때문에 -를 통해 해결함. rayTo += btScalar(x) * dHor; rayTo -= btScalar(y) * dVert; return rayTo; }
힘든 길로 가시는 군요. 동병상련(?)을 느낍니다. 화이팅~!^^
답글삭제댓글을 이제 봤네요. 응원 감사합니다~
삭제블로그랑 깃헙을 둘러보게 됐는데.. 제 미래의 목표이신 분이네요!
오픈소스 게임엔진 릴리즈 하셨는데 종종 참고하겠습니다!