9
\$\begingroup\$

In the code below I've put an example of something I want to do. I have the camera and I want it to stop moving whenever it hits one of the boxes, how do I do this?

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();
    }
}

Result:

The result

\$\endgroup\$
1
  • \$\begingroup\$ You can detect if he is on a box (If his y is < box.y && y >box.y+box.height and do around same for x and z if you want, Then change his Y up by his velocity) \$\endgroup\$
    – Artsicle
    Commented Jan 14, 2017 at 11:19

1 Answer 1

1
\$\begingroup\$

The physics engines that I have written work in three steps

Each frame:

  1. All physics objects calculate their own velocity vector
  2. The physics engine loops through the objects and updates their new positions based on

    position += velocity * deltaTime;

  3. The physics engine resolves all collisions

First, I suggest that instead of letting your FirstPersonCameraController set the position of the camera, make the camera a physics object by having the FirstPersonCameraController control the camera's velocity, not position, and then letting the physics engine update the Camera's position.

Writing a physics engine may sounds scary, but it is really just a method which moves all the objects in a scene and then makes sure that solid objects aren't overlapping.

Lastly, depending on your needs, there are two approaches that I have used for resolving the collisions.

  1. Basic Overlapping

After your physics engine has moved every object. Then loop through the objects to see which are overlapping. If any are overlapping then they have collided. You have to decide how this collision will be resolved, but usually this means that you move one or both objects backward until they are no longer overlapping.

The biggest drawback to this approach is called the bullet through paper problem. If your camera is moving fast enough that it goes through an entire cube in one frame, then when you check for collisions, you won't register that the two objects collided. There are ways to overcome this such as making sure that no object goes horribly fast and fixing your timestep

  1. Swept collision detection

I have had varied success with this method. Basically the idea is that you can combine the movement and collision detection phase to determine that given two objects' velocity vectors, what time will they collide if they will collide at all. Going into depth on how to accomplish this is out of scope for this already long response, but here's a good article

This method solves the bullet through a paper problem, but it is harder to understand/implement as well as more computationally expensive.

There may be more methods out there which may benefit you by searching the internet for collision detection.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .