GameObject finder/picker method in gdx-runtime module
Closed this issue · 4 comments
Is your feature request related to a problem? Please describe.
I think a game object finder/picker method by screen x and y coordinates in the gdx-runtime module would be useful.
Describe the solution you'd like
A GameObject findBy(int screenX, int screenY)
method in SceneGraph
class.
Additional context
The editor uses a finder method in GameObjectPicker
class but it uses opengl hack what is not really recommended ( http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-an-opengl-hack/ ).
An other way that use libgdx's Intersector.intersectRayTriangle(...)
method to check for every model's meshes.
(Examples: libgdx/libgdx#1256 , https://stackoverflow.com/questions/56837626/libgdx-intersect-ray-with-mesh-from-modelinstance ). But I think it is cause huge CPU usage if there are lot of game objects on the map.
A possible solution:
private GameObject getObject(final int screenX, final int screenY) {
final Vector3 position = new Vector3();
Ray ray = scene.cam.getPickRay(screenX, screenY);
GameObject selectedGO = null;
float distance = -1;
for (int i = 0; i < scene.sceneGraph.getRoot().getChildren().size; ++i) {
final GameObject gameObject = scene.sceneGraph.getRoot().getChildren().get(i);
final ModelComponent modelComponent = (ModelComponent) gameObject.findComponentByType(Component.Type.MODEL);
if (modelComponent != null) {
gameObject.getPosition(position);
position.add(modelComponent.getCenter());
if (!ModelUtils.isVisible(scene.cam, modelComponent.getModelInstance(), modelComponent.getCenter(), modelComponent.getDimensions())) {
continue;
}
final float len = ray.direction.dot(position.x - ray.origin.x, position.y - ray.origin.y, position.z - ray.origin.z);
if (len < 0f) {
continue;
}
float dist2 = position.dst2(ray.origin.x + ray.direction.x * len, ray.origin.y + ray.direction.y * len, ray.origin.z + ray.direction.z * len);
if (distance >= 0f && dist2 > distance) {
continue;
}
if (Intersector.intersectRayBoundsFast(ray, position, modelComponent.getDimensions())) {
selectedGO = gameObject;
distance = dist2;
}
}
}
return selectedGO;
}
This uses the model component's dimension to detect model game object.
@JamesTKhan Is this accurate enough?
This is not intended to replace the Editor picking right? Just a new method to add to the runtime for raypicking GameObjects in runtime applications?
This is not intended to replace the Editor picking right? Just a new method to add to the runtime for raypicking GameObjects in runtime applications?
Yes, just a new method in runtime. Maybe we could put this method into runtime and if someone needs a more accurate method then she/he can use bullet or ode4j for picking, like in your video.
I was thinking about this issue and I will close it. If anyone need a picker method can use bullet or ode4j like in previous comment.