Problem positioning a CollisionRay

So, I’m trying to create a collision Ray for selecting 3d objects in my world by following the manual and other posts on this forum, and I’m running into a peculiar problem.

I’ve created my collision ray, and attached it to my camera, and set it to show the ray and collisions. Then I call the “set_from_lens” on the collision ray when I click my mouse… however, I cannot see the ray anywhere. Checking the CollisionRay’s direction and origin, it seems they are being set to values that make no sense to me.

I know the Ray is being created, because I can retrieve it’s origin and direction, though the values seem wrong to me. Also, I randomly tried attaching the ray to one of the other nodes in my scene, and manually set it’s origin to my camera’s location, and the direction to a fixed point. I can see the ray just fine then, and it follows my other node around.

Also, as a side note, my collision traversal seems to be working fine.

What I’m guessing is wrong with my code is that I’m retrieving the wrong node when I’m looking for my camera and attaching the Ray to it… so I’ll post here what I’m using for each of those:

Here’s my camera:

Camera *camera = DCAST(Camera, window->get_camera_group().node()->get_child(0));

Here’s how I set up my Collision Ray:

pickerRay = new CollisionRay();
pickerNode = new CollisionNode("mouseRay");	
pickerNode->add_solid(pickerRay);
pickerNode->set_from_collide_mask(GeomNode::get_default_collide_mask());
pickerNP = window->get_camera_group()->attach_new_node(pickerNode);
pickerNP.show();
mouseTrav.add_collider(pickerNP, mouseHandler);

Here’s how I call set_from_lens:

pickerRay->set_from_lens(camera, window->get_graphics_window()->get_pointer(0).get_x(), window->get_graphics_window()->get_pointer(0).get_y()); 

And for a little data, here’s a readout of the origin and direction of my collision ray after clicking my mouse near the center of my screen.

CollisionRay:

origin
x: 190.78
y: 1
z: 101.821

direction
x: 1.90519e+007
y: 99863.4
z: 1.01682e+007

Meanwhile, window->get_camera_group().get_pos() gives:
x: -0.9
y: -50
z: 4.5

Any help on this is greatly appreciated, and just let me know if I’m not providing enough information.

Thanks!

set_from_lens() expects a value of x, y in the range -1 … 1, whereas MouseData::get_x(), get_y() return values in the range 0 … window size, so that’s where you’re going wrong.

Instead of get_pointer()->get_x(), use something like this:

PT(MouseWatcherNode) mwatcher = DCAST(MouseWatcherNode, window->get_mouse().node());
if (mwatcher->has_mouse()) {
  pickerRay->set_from_lens(camera, mwatcher->get_mouse_x(), mwatcher->get_mouse_y());
}

Note that the values of your ray will be in the coordinate space of the camera node, so they will be based on an eyepoint of (0, 0, 0), and looking down the y axis, regardless of the position and rotation of the camera (they inherit the camera’s position and rotation by virtue of being parented to the camera in the scene graph).

Also note that a CollisionNode is hidden by default, so you won’t see it unless you call show(). And when it is correctly created and positioned, your CollisionRay will be exactly aligned with your camera’s viewing direction, so the camera will be looking at the infinitely thin ray from directly behind, and won’t see it even if it is not hidden.

David

Ah I see! Thanks so much for the info…

I’ve switched over to attempting to use the mousewatcher, but it seems I’m having an issue with it now. I’ve noticed a few posts regarding this problem on the forum, but haven’t seen a solution for C++ as of yet.

My MouseWatcher never seems to “have the mouse” when checking with has_mouse(), nor does it ever return a value other than 0 for get_mouse_X() or y.

Here’s my set up:

PT(MouseWatcher) myMouseWatcher;

...

framework.open_framework(argc, argv);
framework.set_window_title("My Panda3D Window");
window = framework.open_window();
camera = DCAST(Camera, window->get_camera_group().node()->get_child(0));
window->enable_keyboard(); // Enable keyboard detection
window->setup_trackball(); // Enable default camera movement    

myMouseWatcher = DCAST(MouseWatcher, window->get_mouse().node());

Perhaps I’m missing a crucial step that I haven’t gleaned from the C++ manual / reference?

I’ve tried setting the window properties first:

WindowProperties props = window->get_graphics_window()->get_properties();
props.set_cursor_hidden (false);
props.set_mouse_mode (WindowProperties::M_absolute);	
window->get_graphics_window()->request_properties (props);

And I’ve tried adding a region to the MouseWatcher like this (though this causes a crash):

myMouseWatcher->add_region(new MouseWatcherRegion("test", 
		window->get_display_region_2d()->get_left(),
		window->get_display_region_2d()->get_right(),
		window->get_display_region_2d()->get_bottom(),
		window->get_display_region_2d()->get_top()
		));

Once again, any help is appreciated :slight_smile:

has_mouse() is supposed to be true when the window has the focus and the mouse pointer is over the window. Of course, it will never be true while you’re stepping through with the debugger. Is that not working?

David

That’s correct – the MouseWatcher does not appear to be working as intended (if I’m not missing any steps in its setup of course).

To clarify what I’m doing – I’m not running my program through the VS debugger, I’m printing out values to the console window when I click my mouse button somewhere within my Panda3D window.

Right now, I’m actually using a work around by using the first method I’d attempted to find the mouse coordinates, and converting them manually to a value between -1 and 1, and things appear to be working correctly. I can select 3d objects, and the collisions look to always be on target with where I clicked.

However, I would certainly like to get my MouseWatcher functioning correctly… so yes, any idea as to what I missed?

The manual and reference don’t seem to indicate any more steps necessary to set it up… and looking into the .cxx file, I see that just calling “get_mouse” on the window should set up a new MouseWatcher node if one doesn’t exist… So I’m confused as to why it wouldn’t be working.

Indeed, it is true–the only other setup is that the MouseWatcher has to be parented in the datagraph beneath the MouseAndKeyboard node, and the data task has to be running properly–but all of this should be handled by the PandaFramework setup code.

When I try inserting that code in pview.cxx, it does appear to work. Maybe you could try that too, as a sanity check?

David

Good thought there – I gave that a try, but I’m still getting 0s from the MouseWatcher node.

I set the mousewatcher up in pview.cxx similarly to how I had it in my code… I declared a global variable:

PT(MouseWatcher) myMouseWatcher;

I set the mousewatcher right here (though I’d also tried setting it right after the check if the window opened was null with the same results):

window->enable_keyboard();
window->setup_trackball();
myMouseWatcher = DCAST(MouseWatcher, window->get_mouse().node());	

I set up my mouse click event:

framework.define_key("mouse1", "mouse1", event_mouse1, NULL);

And that event is simply:

void 
event_mouse1(const Event *, void *) {
	std::cout << "has_mouse: " << myMouseWatcher->has_mouse() << " x: " << myMouseWatcher->get_mouse_x() << " y: " << myMouseWatcher->get_mouse_y() << std::endl;	
}

And all I get is:

has_mouse: 0 x: 0 y: 0

when I click around in the window

Hmm, something is certainly not right here. What platform are you building on; is this Windows? Are you sure the project settings are correct? Which version of Panda are you using? Is it the standard download available here, or did you build your own version of Panda? If it is the standard download, did you (a) set your project to Release mode, and (b) remove NDEBUG from the project settings?

Try printing your MouseWatcher’s type to prove that you’ve got the right object:

cerr << myMouseWatcher->get_type() << "\n";

And also, for good measure:

cerr << *myMouseWatcher << "\n";

David

Ah hah! You got it!

The issue was that I hadn’t removed NDEBUG from the settings. For anyone using Visual Studio 2008, that’s under: Project -> Properties -> Configuration Properties -> C/C++ -> Preprocessor

By the way, I’m using the 1.7.0 SDK, downloaded from the site, and I’m on Windows Vista 64bit.

After I removed NDEBUG, the MouseWatcher started functioning perfectly. I imagine finding this now will save me more headaches that would have happened down the road as well.

Thanks so much for all the help.