| 6 | #include "Physics.h" |
| 7 | |
| 8 | void ScreenPosToWorldRay( |
| 9 | int mouseX, int mouseY, // Mouse position, in pixels, from bottom-left corner of the window |
| 10 | int screenWidth, int screenHeight, // Window size, in pixels |
| 11 | glm::mat4 ViewMatrix, // Camera position and orientation |
| 12 | glm::mat4 ProjectionMatrix, // Camera parameters (ratio, field of view, near and far planes) |
| 13 | glm::vec3 &out_origin, // Ouput : Origin of the ray. /!\ Starts at the near plane, so if you want the ray to start at the camera's position instead, ignore this.Reall |
| 14 | glm::vec3 &out_direction // Ouput : Direction, in world space, of the ray that goes "through" the mouse. |
| 15 | ) { |
| 16 | |
| 17 | // The ray Start and End positions, in Normalized Device Coordinates (Have you read Tutorial 4 ?) |
| 18 | glm::vec4 lRayStart_NDC( |
| 19 | ((float) mouseX / (float) screenWidth - 0.5f) * 2.0f, |
| 20 | ((float) mouseY / (float) screenHeight - 0.5f) * 2.0f, |
| 21 | -1.0, // The near plane maps to Z=-1 in Normalized Device Coordinates |
| 22 | 1.0f |
| 23 | ); |
| 24 | glm::vec4 lRayEnd_NDC( |
| 25 | ((float) mouseX / (float) screenWidth - 0.5f) * 2.0f, |
| 26 | ((float) mouseY / (float) screenHeight - 0.5f) * 2.0f, |
| 27 | 0.0, |
| 28 | 1.0f |
| 29 | ); |
| 30 | |
| 31 | |
| 32 | // The Projection matrix goes from Camera Space to NDC. |
| 33 | // So inverse(ProjectionMatrix) goes from NDC to Camera Space. |
| 34 | glm::mat4 InverseProjectionMatrix = glm::inverse(ProjectionMatrix); |
| 35 | |
| 36 | // The View Matrix goes from World Space to Camera Space. |
| 37 | // So inverse(ViewMatrix) goes from Camera Space to World Space. |
| 38 | glm::mat4 InverseViewMatrix = glm::inverse(ViewMatrix); |
| 39 | |
| 40 | glm::vec4 lRayStart_camera = InverseProjectionMatrix * lRayStart_NDC; |
| 41 | lRayStart_camera /= lRayStart_camera.w; |
| 42 | glm::vec4 lRayStart_world = InverseViewMatrix * lRayStart_camera; |
| 43 | lRayStart_world /= lRayStart_world.w; |
| 44 | glm::vec4 lRayEnd_camera = InverseProjectionMatrix * lRayEnd_NDC; |
| 45 | lRayEnd_camera /= lRayEnd_camera.w; |
| 46 | glm::vec4 lRayEnd_world = InverseViewMatrix * lRayEnd_camera; |
| 47 | lRayEnd_world /= lRayEnd_world.w; |
| 48 | |
| 49 | |
| 50 | // Faster way (just one inverse) |
| 51 | //glm::mat4 M = glm::inverse(ProjectionMatrix * ViewMatrix); |
| 52 | //glm::vec4 lRayStart_world = M * lRayStart_NDC; lRayStart_world/=lRayStart_world.w; |
| 53 | //glm::vec4 lRayEnd_world = M * lRayEnd_NDC ; lRayEnd_world /=lRayEnd_world.w; |
| 54 | |
| 55 | glm::vec3 lRayDir_world(lRayEnd_world - lRayStart_world); |
| 56 | lRayDir_world = glm::normalize(lRayDir_world); |
| 57 | |
| 58 | |
| 59 | out_origin = glm::vec3(lRayStart_world); |
| 60 | out_direction = glm::normalize(lRayDir_world); |
| 61 | } |
| 62 | |
| 63 | btCollisionShape *Physics::buildFrustumShape() { |
| 64 | float m_ScreenHeight = 768; |