Hello, I was hoping someone here could help me identify the issue with my 3D mouse picking mechanic. I have a basic scene and I am trying to pick a mesh (a triangle in my case) and move it around with my mouse. So far I have been able to implement that correctly but I can't seem to be able to pick the object from far away. I'd have to move the camera closer to the triangle bounded by a sphere in order for it to intersect with my ray. What I am trying to do is simply make it so that you can pick the object up and move it around even from far away. I will include code that is relevant to the mechanic below: Get the ray direction
// Function that takes mouse position on screen and return ray in world coords
glm::vec3 PhysicsEngine::GetRayFromMouse()
{
glm::vec2 ray_nds = glm::vec2(mouseX, mouseY);
glm::vec4 ray_clip = glm::vec4(ray_nds.x, ray_nds.y, -1.0f, 1.0f);
glm::mat4 invProjMat = glm::inverse(m_Camera.GetProjectionMatrix());
glm::vec4 eyeCoords = invProjMat * ray_clip;
eyeCoords = glm::vec4(eyeCoords.x, eyeCoords.y, -1.0f, 0.0f);
glm::mat4 invViewMat = glm::inverse(m_Camera.ViewMatrix());
glm::vec4 rayWorld = invViewMat * eyeCoords;
glm::vec3 rayDirection = glm::normalize(glm::vec3(rayWorld));
return rayDirection;
}
Check for ray-sphere collision
Here is where I believe I am having the problem. After debugging the code, I noticed that it does pick up an intersection between ray and the sphere even from far away because b^2 - 4ac is greater than 0. However, the real solutions (normally when b^2 - 4ac is > 0 this means we have 2 real solutions) are not returning true for some reason. To be more clear, I have commented the parts where I believe the problem is occurring.
// Function that checks for ray-sphere intersection and returns true or false
bool PhysicsEngine::ray_sphere(vec3 ray_origin_wor, vec3 ray_direction_wor, float sphere_radius)
{
// work out components of quadratic
vec3 v = glm::vec3(m_Transformation.GetPos().x, m_Transformation.GetPos().y, m_Transformation.GetPos().z) - m_Camera.GetCameraPosition();
double a = glm::dot(ray_direction_wor, ray_direction_wor);
double b = 2.0 * glm::dot(v, ray_direction_wor);
double c = glm::dot(v, v) - sphere_radius * sphere_radius;
double b_squared_minus_4ac = b * b + (-4.0) * a * c;
// b^2-4ac is greater than 0 even from far away
if (b_squared_minus_4ac > 0)
{
// Potential calculation error here
double x1 = (-b - sqrt(b_squared_minus_4ac)) / (2.0 * a);
double x2 = (-b + sqrt(b_squared_minus_4ac)) / (2.0 * a);
// None of these cases test true from far away
if (x1 >= 0.0 && x2 >= 0.0)
return true;
if (x1 < 0.0 && x2 >= 0.0)
return true;
}
return false;
}
I am thankful for any guidance you can give me.
↧