PDA

View Full Version : Help with GLM based mouse picking



paul_g_griffiths
01-30-2017, 04:57 PM
I'm using the following code to try to do mouse picking with GLM but it's only picking one object on the screen and that even isn't correct.
Any ideas?


glm::f32 tmin = 1000.0f;
for (int i = 0; i < frame.objects.size(); i++)
{
VObject *object = frame.objects[i];

glm::mat4 model = object->model;
model *= object->scale;

glm::mat4 mpvInverse = glm::inverse(model * projection * this->camera->GetViewMatrix());

glm::vec4 origin = mpvInverse * glm::vec4(
(x - glm::f32(screenWidth / 2.0f)) / glm::f32(screenWidth / 2.0f), (glm::f32(screenHeight / 2.0f) - y) / glm::f32(screenHeight / 2.0f), -1.0f, 1.0f);
glm::vec4 dir = mpvInverse * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f);
glm::vec3 O = glm::vec3(origin.x, origin.y, origin.z);
glm::vec3 D = glm::normalize(glm::vec3(dir.x, dir.y, dir.z));


for (int j = 0; j<object->numVertices; j += 3)
{

glm::vec3 K = glm::vec3(object->vertices[j]);

glm::vec3 L = glm::vec3(object->vertices[j + 1]);

glm::vec3 M = glm::vec3(object->vertices[j + 2]);
// Compute vectors E, F, and G
glm::vec3 E = K - M;
glm::vec3 F = L - M;
glm::vec3 G = O - M;
// Compute the vector containing t and the coordinates k and l
glm::vec3 tkl = 1.0f / glm::dot(glm::cross(D, F), E) *
glm::vec3(glm::dot(glm::cross(G, E), F),
glm::dot(glm::cross(D, F), G),
glm::dot(glm::cross(G, E), D));
// Check if t and the intersection point (k, l) are acceptable
if (tkl.x < tmin && tkl.y > 0.0f && tkl.z > 0.0f && (tkl.y + tkl.z) < 1.0f)
{
tmin = tkl.x;
}
}


}
if (tmin < 1000.f)
{
MessageBox(NULL, "hit", "", 0);
return;
}

john_connor
01-31-2017, 02:53 AM
another way to do picking is to render each item in the scene with a unique identifier (int) into a texture
when finished with rendering, you can read a certain part of the texture and re-interpret the identifiers

http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/
http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-an-opengl-hack/

if you use MRT (multi-render-target) framebuffer, you can do it without an extra render pass
using a 32 bit integer texture as a color attachment makes it easy to re-interpret the identifiers

https://sites.google.com/site/john87connor/framebuffer/tutorial-10-1-4-multiple-rendertargets-mrt

example (Renderer_OpenGL.cpp):
https://sites.google.com/site/john87connor/advanced-opengl-tutorials/tutorial-04-object-selection


looping over each vertex in a model isnt a good idea, sometimes models have 100k+ vertices / faces

Silence
01-31-2017, 05:43 AM
I'm using the following code to try to do mouse picking with GLM but it's only picking one object on the screen and that even isn't correct.
Any ideas?

Do you expect it to be able to pick several objects ?

This (http://antongerdelan.net/opengl/raycasting.html) can be useful to you.

What john_connor gave can be better than your code, since it does not need to project/unproject and do ray/triangle intersection on all the polygons of all the objects involved in your scene. Even if this involves read/write to a framebuffer. However, if you need some mathematical information about your picking, then don't go to this.