该问题的一个常见解决方案是使用光线投射,其中测试一条假想线是否与虚拟形象(跑步对象)下方的对象(地面、道路)相交。
这是一个使用 jMonkeyEngine 3 提供的机制的示例:
public boolean isOnRoad(Vector3f avatarPosition, Geometry road) {
// Pointing downwards (assuming that the Y-axis is facing upwards in your game)
Vector3f direction = new Vector3f(0, -1, 0);
// Create a line that starts at 'avatarPosition' and has a direction
Ray ray = new Ray(avatarPosition, direction);
// Results of the collision test are written into this object
CollisionResults results = new CollisionResults();
// Test for collisions between the road and the ray
road.collideWith(ray, results);
// If there is a collision, avatarPosition is above the road
return results.size() != 0;
}
你需要将头像的位置传递给函数。
avatarPosition = avatar.getLocalTranslation();
如果您的道路由打包到一个节点中的多个几何体组成,您也可以将节点而不是单个几何体传递给函数。在节点上调用collideWith() 将测试其所有子节点。
如果节点还包含场景的其他部分,上述功能可能无法正常工作。
road.collideWith(ray, results) 的调用将在第一次使用时为 road-Mesh 隐式构建一个 BIH-Tree (Bounding Interval Hierarchy Tree)。这将加快碰撞测试,因为它不必针对道路的每个三角形检查光线。在每个更新周期中都足够快。
此外,您可以使用碰撞测试的结果。
这将返回最接近起点的交点的确切点:
Vector3f p = results.getClosestCollision().getContactPoint();
使用迭代器,您可以分别处理所有碰撞,从最近到最远的碰撞排序:
Iterator<CollisionResult> it = results.iterator();
while(it.hasNext())
{
CollisionResult collisionResult = it.next();
Vector3f p = collisionResult.getContactPoint();
Geometry geom = collisionResult.getGeometry();
// Do something with contact point and geometry
}
更多关于碰撞的信息:
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:collision_and_intersection
射线投射还用于使用十字准线或鼠标在 3D 场景中选择对象。
这叫做拣货:
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_picking