RayCasting in Libgdx 3d

前端 未结 2 1139
北荒
北荒 2020-12-21 00:58

Alright so I\'ve been trying for quite some time too Raycast in libgdx for 3d collision detection based on where im looking.. But I\'ve drawn a blank and doesn\'t seem to be

相关标签:
2条回答
  • 2020-12-21 01:09

    It is actually really easy with libgdx to achieve what you are trying to do. The following is what I'm using to do a ray test and find the closest collision object that my ray would hit. Let's assume it is located in a class called BulletUtil.

    private static final Vector3 rayFrom = new Vector3();
    private static final Vector3 rayTo = new Vector3();
    private static final ClosestRayResultCallback callback = new ClosestRayResultCallback(rayFrom, rayTo);
    
    public static btCollisionObject rayTest(btCollisionWorld collisionWorld, Ray ray) {
        rayFrom.set(ray.origin);
        // 50 meters max from the origin
        rayTo.set(ray.direction).scl(50f).add(rayFrom);
    
        // we reuse the ClosestRayResultCallback, thus we need to reset its
        // values
        callback.setCollisionObject(null);
        callback.setClosestHitFraction(1f);
        callback.getRayFromWorld().setValue(rayFrom.x, rayFrom.y, rayFrom.z);
        callback.getRayToWorld().setValue(rayTo.x, rayTo.y, rayTo.z);
    
        collisionWorld.rayTest(rayFrom, rayTo, callback);
    
        if (callback.hasHit()) {
            return callback.getCollisionObject();
        }
    
        return null;
    }
    

    Now what else you need is an InputProcessor that reacts on the click events.

    public class BulletInputProcessor extends InputAdapter {
    
        private Viewport pickingViewport;
        private btCollisionWorld collisionWorld;
    
        // a constructor which takes a Viewport and the collision world and stores them
        public BulletInputProcessor(...) { ... }
    
        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            if (button == Input.Buttons.LEFT) {
                Ray pickRay = pickingViewport.getPickRay(screenX, screenY);
    
                btCollisionObject body = BulletUtil.rayTest(collisionWorld, pickRay);
                if (body != null) {
                    // do whatever you want with this body now
                    return true;
                }
            }
    
            return false;
        }
    }
    

    The Viewport is responsible to create the picking Ray. You should use the viewport here which manages the PerspectiveCamera that you use to render the world. Don't forget to register the input processor via Gdx.input.setInputProcessor(new BulletInputProcessor(collisionWorld, viewport)).

    0 讨论(0)
  • 2020-12-21 01:24

    @noone In your code, there are two lines which didn't work our for me. May be deprecated?

    callback.getRayFromWorld().setValue(rayFrom.x, rayFrom.y, rayFrom.z);
    callback.getRayToWorld().setValue(rayTo.x, rayTo.y, rayTo.z);
    

    I have changed them to

      Vector3 rayFromWorld = new Vector3();
      rayFromWorld.set(rayFrom.x, rayFrom.y, rayFrom.z);
      Vector3 rayToWorld   = new Vector3();
      rayToWorld.set(rayTo.x, rayTo.y, rayTo.z);
    

    which made the whole function work like a charm.

    Another thing I found out was, that you have to activate the body (which is returned by this function) in order to apply forces on it. Mostly rigid bodys are set to sleep after a certain interval of time and a ClosestRayResultCallback does not wake them up.

    btCollisionObject target = CollisionUtils.rayTest(dynamicsWorld, ray);
    //test for collisionflags and stuff here
    //and if your target is instance of btRigidBody
    btRigidBody body = (btRigidBody)target;
    body.activate();
    body.applyCentralForce(ray.direction.scl(50000));
    
    0 讨论(0)
提交回复
热议问题