I want to set up the ray casting. I saw some topics about it (e. g this) and “Click on 3D object” manual, but I don’t understand yet why my code doesn’t work. Can someone help me please?
Note: Ground.bam is created with gltf2bam.
#include <iostream>
#include <pandaFramework.h>
#include <pandaSystem.h>
#include <asyncTask.h>
#include <collisionHandlerQueue.h>
#include <collisionRay.h>
#include <CollisionBox.h>
#include <mouseWatcher.h>
PT(MouseWatcher) mouseWatcher;
WindowFramework* window;
PT(CollisionRay) pickerRay;
PT(CollisionNode) pickerNode;
NodePath pickerNP;
CollisionTraverser myTraverser = CollisionTraverser("ctraverser");
PT(CollisionHandlerQueue) myHandler;
void func(const Event* event, void* data) {
// This gives up the screen coordinates of the mouse.
MouseData mpos = window->get_graphics_window()->get_pointer(0);
std::cout << window->get_graphics_window()->get_pointer(0).get_x() << window->get_graphics_window()->get_pointer(0).get_y() << "\n";
// This makes the ray's origin the camera and makes the ray point
// to the screen coordinates of the mouse.
pickerRay->set_from_lens(window->get_camera(0), mpos.get_x(), mpos.get_y());
myTraverser.traverse(window->get_render());
for (int i = 0; i < myHandler->get_num_entries(); ++i) {
CollisionEntry* entry = myHandler->get_entry(i);
std::cout << *entry << "\n";
}
if (myHandler->get_num_entries() == 0) {
std::cout << "No collisions :(\n";
}
}
int main(int argc, char* argv[]) {
PandaFramework framework;
if (argc > 0) {
framework.open_framework(argc, argv);
}
else {
framework.open_framework();
}
framework.set_window_title("Raycast");
window = framework.open_window();
window->enable_keyboard();
//Setup the camera
NodePath camera = window->get_camera_group();
camera.set_pos(20 * sin(0), -20.0 * cos(0), 3);
camera.set_hpr(0, 0, 0);
//Setup mouse and collisions
mouseWatcher = new MouseWatcher("Watcher");
pickerNode = new CollisionNode("mouseRay");
pickerNP = camera.attach_new_node(pickerNode);
pickerNode->set_from_collide_mask(GeomNode::get_default_collide_mask());
pickerRay = new CollisionRay();
pickerNode->add_solid(pickerRay);
myHandler = new CollisionHandlerQueue();
myTraverser.add_collider(pickerNP, myHandler);
myTraverser.show_collisions(window->get_render());
//Loading models
NodePath ground = window->load_model(window->get_render(), "models/Ground.bam"); ground.set_scale(16, 10, 1); ground.set_pos(0, 5, 0);
ground.set_tag("RayCastEnabled", "1");
/*PT(CollisionNode) grcn = new CollisionNode("grcnode");
for (int i = 0; i < ground.get_num_nodes(); i++) {
if (ground.get_node(i)->is_geom_node()) {
grcn->set_into_collide_mask(static_cast<GeomNode*>(ground.get_node(i))->get_into_collide_mask());
}
}
ground.attach_new_node(grcn);*/
//Event handler
//framework.define_key("mouse1", "event", &func, nullptr);
framework.get_event_handler().add_hook("mouse1", &func, nullptr);
framework.main_loop();
framework.close_framework();
return (0);
}
A quick note: be aware that, as I understand it, colliding with normal, visible geometry may be slower than with dedicated collision geometry (even if that geometry is generated from the same base mesh).
Of course, if you’re not hitting a performance issue, then well and good!
This is more a caveat to have in mind should you hit performance issues later.
This warning comes from a misinterpretation of the visible geometry. The whole point is that the geometry for the collision needs to be modeled separately from the geometry for rendering. Accordingly, it should be simplified as much as possible to calculate the collision.
I do not know where this term came from in the Panda3D game engine, but it is very wrong. Because the geometry for the collision is also modeled in a 3d editor, and there is no other way.
I seem to think that I’ve seen drwr or some other such dev comment to that effect.
And indeed, looking around, I found this post:
Note that drwr there indicates that visible geometry is less efficient for collision than even collision geometry of the exact same shape. And further that collision geometry is optimised for the purpose.
I’d guess that Panda has a different internal structure for collision geometry than for visible geometry, allowing faster traversals.
[edit]
Here’s an even clearer post:
In particular, note this line:
Although it is true that simpler geometry is faster still, collision geometry would be about 100 times faster even if you exactly duplicated your visible geometry 1:1 in the scene graph.