LibGDX 3Dで衝突イベントを発生させるにはどうすればよいですか?


9

以下のコードには、やりたいことの例を示しています。カメラを持っているのですが、ボックスにぶつかったときにカメラの動きを止めたいのですが、どうすればよいですか?

public class Main extends ApplicationAdapter {

    private final ModelBuilder builder = new ModelBuilder();
    private final Environment environment = new Environment();
    private ModelBatch modelBatch;
    private PerspectiveCamera camera;
    private Model model;
    private ArrayList<ModelInstance> instance = new ArrayList<ModelInstance>();
    private FirstPersonCameraController controller;
    private BoundingBox[] boxBounds = new BoundingBox[1000];
    private BoundingBox cameraBox = new BoundingBox();
    private Vector3 cameraSpeed = new Vector3();
    private Vector3 oldCameraPos = new Vector3();
    private Vector3 newCameraPos = new Vector3();

    @Override

    public void create() {
        modelBatch = new ModelBatch();


        //build the camera
        camera = new PerspectiveCamera(67, graphics.getWidth(), graphics.getHeight());
        camera.position.set(0f, 10f, 0f);
        camera.lookAt(0, 10, 0);
        camera.near = 1f;
        camera.far = 1000f;
        camera.update();

        //build all the boxes
        for (int i = 0; i < 1000; i++) {
            model = builder.createBox(
                    (float) Math.random() * 50,
                    (float) Math.random() * 50,
                    (float) Math.random() * 50,

                    new Material(ColorAttribute.createDiffuse(

                            (float) random(),
                            (float) random(),
                            (float) random(), 1)
                    ), Position | Normal);

            instance.add(new ModelInstance(model));
            instance.get(i).transform.setToTranslation(
                    (float) random() * 1000 - 500,
                    (float) random() * 1000,
                    (float) random() * 1000 - 500);

            boxBounds[i] = new BoundingBox();
            boxBounds[i] = model.calculateBoundingBox(boxBounds[i]);
        }

        //build the ground
        model = builder.createBox(700f, 1f, 700f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Position | Normal);
        ModelInstance ground = new ModelInstance(model);
        instance.add(ground);

        //build the center
        model = builder.createBox(5f, 5f, 5f, new Material(ColorAttribute.createDiffuse(Color.RED)), Position | Normal);
        ModelInstance center = new ModelInstance(model);
        instance.add(center);


        //code the lights here
        DirectionalLight light = new DirectionalLight().set(255, 255, 255,
                (float) random(),
                (float) random(),
                (float) random());

        //set up the enviroment
        environment.set(new ColorAttribute(AmbientLight, 255f, 255f, 255f, 1f));
        environment.add(light);

        //set up the camera controller
        controller = new FirstPersonCameraController(camera);
        controller.setDegreesPerPixel(0.25f);
        controller.setVelocity(20);
        input.setInputProcessor(controller);
    }

    @Override
    public void render() {
        //set up OpenGL
        gl.glViewport(0, 0, graphics.getWidth(), graphics.getHeight());
        gl.glEnable(GL_BLEND);
        gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        gl.glClearColor(0, 0, 0, 0);

        //render the modelInstances
        modelBatch.begin(camera);
        modelBatch.render(instance, environment);
        modelBatch.end();
        controller.update();

        if (input.isKeyPressed(Input.Keys.R)) {
            camera.lookAt(0, 0, 0);
        }

        cameraSpeed = newCameraPos.sub(oldCameraPos);

        cameraBox = new BoundingBox(new Vector3(camera.position.x,
                camera.position.y,
                camera.position.z),

                new Vector3(camera.position.x + 10,
                        camera.position.y + 10,
                        camera.position.z + 10));

        for (int i = 0; i < 1000; i++) {
            if (cameraBox.contains(boxBounds[i])) {
                camera.position.x = camera.position.x - cameraSpeed.x;
                camera.position.y = camera.position.y - cameraSpeed.y;
                camera.position.z = camera.position.z - cameraSpeed.z;
            }
        }

        System.out.println(cameraSpeed.x + " " + cameraSpeed.y + " " + cameraSpeed.z);
    }

    @Override
    public void dispose() {
        modelBatch.dispose();
        model.dispose();
    }
}

結果:

結果


あなたは彼がボックス上にあるかどうかを検出できます(彼のyが<box.y && y> box.y + box.heightで、必要に応じてxとzについて同じことを行っている場合は、彼のYを速度で上に変更します)
アーティクル

回答:


1

私が書いた物理エンジンは3つのステップで動作します

各フレーム:

  1. すべての物理オブジェクトが独自の速度ベクトルを計算します
  2. 物理エンジンはオブジェクトをループし、以下に基づいて新しい位置を更新します

    位置+ =速度* deltaTime;

  3. 物理エンジンはすべての衝突を解決します

まず、FirstPersonCameraControllerにカメラの位置を設定させるのではなく、FirstPersonCameraControllerに位置ではなくカメラの速度を制御させ、物理エンジンにカメラの位置を更新させることで、カメラを物理オブジェクトにすることをお勧めします。

物理エンジンの作成は恐ろしいように聞こえるかもしれませんが、実際には、シーン内のすべてのオブジェクトを移動して、ソリッドオブジェクトが重複しないようにする方法にすぎません。

最後に、あなたのニーズに応じて、衝突を解決するために私が使用した2つのアプローチがあります。

  1. 基本的なオーバーラップ

物理エンジンがすべてのオブジェクトを移動した後。次に、オブジェクトをループして、重複しているオブジェクトを確認します。いずれかが重なっている場合、それらは衝突しています。この衝突をどのように解決するかを決定する必要がありますが、通常これは、オブジェクトが重ならないようになるまで、一方または両方のオブジェクトを後方に移動することを意味します。

このアプローチの最大の欠点は、紙の問題による弾丸です。カメラが1フレームでキューブ全体を通過するのに十分な速さで移動している場合、衝突をチェックするときに、2つのオブジェクトが衝突したことを登録しません。これを克服する方法は、オブジェクトが恐ろしく速くならないことを確認したり、タイムステップ修正したりすることです

  1. スイープ衝突検出

私はこの方法でさまざまな成功を収めてきました。基本的には、移動フェーズと衝突検出フェーズを組み合わせて、2つのオブジェクトの速度ベクトルが与えられた場合、それらがまったく衝突する場合は何時に衝突するかを判断できるという考え方です。これを達成する方法について深く掘り下げることは、このすでに長い応答の範囲外ですが、ここに良い記事があります

この方法は紙の問題を通じて弾丸を解決しますが、理解/実装が難しく、計算コストも高くなります。

衝突検出のためにインターネットを検索することによってあなたに利益をもたらすかもしれないもっと多くの方法がそこにあるかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.