[SOLVED] - Get Picking Point with CollisionRay Issue

Hello everyone,
Im trying to get mouse-click point on my terrain.
I loaded terrain as plane-mesh.egg and set from a heightmap with a shader;
But I’m getting incorrect coordinates depending on the camera angle.
Here code;

void PickMouseCol(const Event* pTheEvent, void* pData) {
	if (!mouseWatcher->has_mouse()) { return; }
	LPoint2 mpos = mouseWatcher->get_mouse();
	pickerRay->set_from_lens(window->get_camera(0), mpos.get_x(), mpos.get_y());

	myTraverser.traverse(render);
	if (myHandler->get_num_entries() < 0) { return; }
	myHandler->sort_entries();
	NodePath pickedObj = myHandler->get_entry(0)->get_into_node_path();
	pickedObj = pickedObj.find_net_tag("obj_terrain");
	if (!pickedObj.is_empty()) {
		std::cout << "Hit!" << std::endl;
		LPoint3 hit_pos = myHandler->get_entry(0)->get_surface_point(render);
		//hit_pos.add_z(25);
		playerNP.set_pos(hit_pos);
		return;
	}
	std::cout << "NO Hit!" << std::endl;
}

MouseManager::MouseManager() {
	mouseWatcher = (MouseWatcher*)window->get_mouse().node();
	pickerNode = new CollisionNode("mouseRay");
	pickerNP = camera.attach_new_node(pickerNode);

	pickerRay = new CollisionRay();
	pickerNode->add_solid(pickerRay);
	pickerNode->set_from_collide_mask(GeomNode::get_default_collide_mask());

	myHandler = new CollisionHandlerQueue();
	myTraverser.add_collider(pickerNP, myHandler);
	framework.define_key("mouse1", "Get Terrain Click", PickMouseCol, nullptr);
}

And issue;

Wait, are you saying that you’re using a shader to deform a flat mesh via a height-map?

Because if so, the collision-system won’t I daresay have access to the deformed state of the mesh–only the original, un-deformed state.

As a result, the issue may be that the ray is detecting positions on the underlying flat mesh, which naturally doesn’t match the height-mapped visuals.

Yes i did like you said. Before i tried ShaderTerrainMesh but i couldn’t use collision with it. Then i decide to do this.
Another option is using GeoMipTerrain, do you know is that have collisions? Or maybe i can use another plane to get collision without rendering?

Thanks for the answer btw…

GeoMipTerrain… may allow this sort of visible-geometry collision? I’m not sure, to be honest.

I would like to give a note of warning that colliding with visible geometry as you currently are may become a performance issue as your scenes become more complex.

Returning to the main topic, let me say: it’s probably not impossible to get a collision-point with your shader-based terrain–but it’s not something that I’ve looked at much myself, I fear, so I don’t know what method to recommend.

(Off the top of my head, one idea is that you might be able to access the depth-buffer, then use that with the mouse-position to determine the point in 3D space that is being indicated.

But I stand to be corrected by others if there are better approaches!)

I did same test without deforming plane with heightmap but still getting wrong result :stuck_out_tongue:

Hmm… Very odd!

What happens if you make your ray visible? (By calling “show” on “pickerNP”, if the API is the same between Python and C++.)

I would expect a line touching the point at which you clicked…

I already did that by calling pickerNP.show(); but nothing happend. There is no any visible thing
same as the video :slight_smile:

Hmm… This is perhaps a long shot, but in your flattened version, your shader doesn’t still have some sort of vertical offset, does it…?

Because in that version it really does look like the picker is simply off in the vertical–note that it seems to be accurate when looking directly downwards…

its something like this but still dont know why :slight_smile:
issue_dem

If it were like that, I’d expect the point to still be offset when looking directly down–but it actually seems pretty accurate in that case…

In case you missed it in typing your post, let me quote my question asked just before that post:

Hmm… Ok i’ll test it without shaders on flat-plane again. Thank you…

1 Like

Nope, same even without any shaders :slight_smile:
Im gonna try GeoMipTerrain but im not sure how to detect click-point with CollisionRay…

1 Like

Good luck!

I’m really not sure of what’s going wrong in your code, at least without examining more of it.

Pretty much the same way, I daresay!

What you’re doing is pretty much correct I believe (save for the whole “colliding with visible geometry” thing, arguably)–which is why it’s so odd to me that it’s not working!

On another note, by the way, something that I noticed in your code:

This should, I believe, never be true: the list should never have fewer than zero items in it.

1 Like

There is a new experimental CollisionHeightfield solid in the master branch of Panda3D, if you are comfortable building from source and/or using a development build.

1 Like

Omg same with GeoMipTerrain too :scream:
I tried;
-LoadModel(plane.egg) with vertex/frag shaders - same
-LoadModel(plane.egg) withot any shader - same
-ShaderTerrainMesh - i think the best option i ever tried for a terrain but CollisionRays did not detect this idk why?
-GeoMipTerrain - same

i cant even doing this basic things for the game :frowning:

There is a new experimental CollisionHeightfield solid in the master branch of Panda3D, if you are comfortable building from source and/or using a development build.

Hmm… I’ll check that thanks…

ShaderTerrainMesh is deformed on the GPU, so it doesn’t have a CPU-based mesh that you can meaningfully test against collisions with.

Is this a coordinate space issue? Does your player have a parent that has a position relative to render?

ShaderTerrainMesh is deformed on the GPU, so it doesn’t have a CPU-based mesh that you can meaningfully test against collisions with.

So, if we use ShaderTerrainMesh, we cant use any collision events? (like getting mouse click pos)
Is there no way for this?

Is this a coordinate space issue? Does your player have a parent that has a position relative to render?

Yes, I think there is something wrong with camera or ray vector im not sure . Or like you said im not sure again. Its getting wrong coordinates depends camera angle;

Plain.egg test with shaders (using heightmap in vertex shader);
https://streamable.com/fe2y8m

Plaing.egg test without using heightmap;
https://streamable.com/h3o6rp

Also i tried wiıthout any shader and other terrain options.
Here my actor codes;

playerNP = window->load_model(window->get_render(), "bin/neuera/characters/models/orc.bam");
playerNP.set_scale(LVecBase3(5, 5, 5));
window->load_model(playerNP, "bin/neuera/characters/anims/orc-idle.bam");
window->loop_animations(0);

As I said, I daresay that it can be done–such as via accessing the depth-buffer–but it’s not as simple as colliding with visible geometry.

I think that rdb is suggesting that the problem might be to do with the setup of your character, not of the ray.

All right, let me ask this: if you use the out-of-the-box “smiley” model, or even “Ralph”, does that affect the results that you’re seeing at all? (When using an untransformed, flat landscape, of course.)

Oh ok you are right i never test it with default models. I’ll try that. Thank you…

1 Like

your shader doesn’t still have some sort of vertical offset, does it…?

@Thaumaturge thank you! Like you said it was about vertex shader! I couldn’t see at first :stuck_out_tongue:

I used GeoMipTerrain and removed any deformation in shaders. Problem solved :slight_smile:

https://streamable.com/3tsqb9

1 Like