鼠标点击选取物体错误的问题

问题

在3D场景中,通过鼠标点击选取物体,有时会出现明明点选了上层物体,程序却反馈点选了下层物体。

原因和解决办法

鼠标点击选取要先启用Camera的对象拾取(physics_object_picking)功能,从视口相机向屏幕位置投射一条射线,如果这条射线命中了某个对象,就会调用对象的 CollisionObject._input_event() 函数。所以这个问题和碰撞功能相关。
如果两个碰撞盒(CollisionShape)非常接近,可能会出现投射光线的错误穿透,触发了下层碰撞盒(却没有触发上层碰撞盒)。
碰撞盒的Margin值最小只能设置到0.001(1毫米)。
经测试,对于厚度2毫米(Extents.y=0.001)的碰撞盒,如果两个碰撞盒中心距离小于0.008,都可能会出现错误。
BoxShape.Margin=0.001
具体原因要调查引擎的源代码实现。
找到godot\modules\bullet\godot_ray_world_algorithm.cpp:

// Epsilon to account for floating point inaccuracies
#define RAY_PENETRATION_DEPTH_EPSILON 0.01
...
void GodotRayWorldAlgorithm::processCollision(...
...
	const btRayShape *ray_shape;
	btTransform ray_transform;
...
	btTransform to(ray_transform * ray_shape->getSupportPoint());
	btCollisionWorld::ClosestRayResultCallback btResult(ray_transform.getOrigin(), to.getOrigin());
	m_world->rayTestSingleInternal(ray_transform, to, other_co_wrapper, btResult);
	if (btResult.hasHit()) {
		btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1));
		if (depth > -RAY_PENETRATION_DEPTH_EPSILON) {
			depth = 0.0;
		}

depth是两个数的乘积,当(depth > -0.01)就清零。
设置里0.001的细腻那都是骗人的,0.01的粗糙才是真实。

如果使用到屏幕光线投射功能,对于小物件的最小长度和物体间隔要以厘米级来设计。

参考

Godot: 来自屏幕的 3D 光线投射
Godot: 使用InputEvent

猜你喜欢

转载自blog.csdn.net/feiyunw/article/details/127130445