Collision ray using mouse

Hi everyone,

First, thanks for this excellent library. It’s really a pleasure to work with.

I try to use mouse collision ray for detecting when the user passes the mouse over (all) other objects. My code is inspired from the tutorial.

I first declare “global stuff”:

WindowFramework* window;
NodePath camera;

PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr();

PT(MouseWatcher) mouseWatcher;
PT(CollisionRay) pickerRay;
PT(CollisionHandlerQueue) myHandler;
PT(CollisionNode) pickerNode;

Then, in main function, I draw some triangles, and move the camera:

PandaFramework framework;
framework.open_framework(argc, argv);

window = framework.open_window();
window->set_background_type(WindowFramework::BT_gray);

// Draw triangles ...

camera = window->get_camera_group();

camera.set_hpr(0, 90, 90);
camera.set_pos(0, 0, -20);

NodePath mouseNode = window->get_mouse();
mouseWatcher = DCAST(MouseWatcher, mouseNode.node());

pickerNode = new CollisionNode("mouseRay");
pickerNode->set_from_collide_mask(GeomNode::get_default_collide_mask());
pickerRay = new CollisionRay();
pickerNode->add_solid(pickerRay);
NodePath pickerNP = camera.attach_new_node(pickerNode);

myHandler = new CollisionHandlerQueue();
CollisionTraverser myTraverser = CollisionTraverser("ctraverser");
myTraverser.add_collider(pickerNP, myHandler);

taskMgr->add(new GenericAsyncTask("souris", &survolSouris, nullptr));
taskMgr->add(new GenericAsyncTask("sourisC", &collisionSouris, nullptr));

framework.main_loop();
framework.close_framework();

The two asynchronous tasks above:


AsyncTask::DoneStatus collisionSouris(GenericAsyncTask* task, void* data)
{
    if (myHandler->get_num_entries() > 0)
    {
        myHandler->sort_entries();
        CollisionEntry* entry = myHandler->get_entry(0);
        cout << entry << endl;
        myHandler->clear_entries();
    }

    return AsyncTask::DS_cont;
}

AsyncTask::DoneStatus survolSouris(GenericAsyncTask* task, void* data)
{
    if (!mouseWatcher->has_mouse()) {
        // The mouse is probably outside the screen.
        return AsyncTask::DS_cont;
    }

    LPoint2 mpos = mouseWatcher->get_mouse();

    pickerRay->set_from_lens(window->get_camera(0), mpos.get_x(), mpos.get_y());

    return AsyncTask::DS_cont;
}

I know that it’s better to do it with events, I just wanted to test with this method. My will is simple: when the mouse is inside the screen, pickerRay is set with set_from_lens, and theorically, myHandler must contain the collisions, collisions that are thus handled (and showed) by collisionSouris.

  1. I showed pickerRay's direction and origin, and whether I move or rotate the camera or not, it’s the same value, it only depends on mouse position on screen.
  2. myHandler->get_num_entries() is always equal to zero. None collision is detected.

Also, I already read all the messages of this forum about this (kind of) question(s), but can’t find any solution at all.

What am I doing wrong, here?

Thanks a lot,

ChoCChoK.

Hi, welcome to the community!

You need to call traverse(render) on your CollisionTraverser every frame for collision detection to occur. I don’t see this in your code.

Thanks a lot! It’s working, now… I’m sorry, I don’t know why this line disappeared lol (at first, it was here…).

ChoCChoK.