How can I find out what side of a Box I have clicked?

Hello,

I am trying to learn JME3 and need some help to progress.

I want to build a simple Minecraft Clone, I have everything working alright except the placing of the Blocks. I need to add the Cube depending on what the player Clicks. If he clicks the top, the new cube should go on the top etc.
I just can not figure out how to do this. I tried some trigonometrics with the cube translation and the camera but only got half working results. It’s okay but it often places blocks inside of each other.
Is there maybe some functionallity in JME I am not using?
The Block is a Geometry with a RigidBodyControl if this helps.

This is the code I already have. Maybe someone sees my mistake. The placeBlock() is called on a mousclick

public void placeBlock(Camera camera, int idx) {
Ray ray = new Ray(camera.getLocation(), camera.getDirection());
CollisionResults results = new CollisionResults();
blocks.collideWith(ray, results);

    if (results.size() > 0) {
        CollisionResult closest = results.getClosestCollision();
        Vector3f hitPoint = closest.getContactPoint();

        Vector3f relativePosition = calculateRelativeBlockPosition(hitPoint, camera);

        placeBlockAtPosition(relativePosition, idx);
    }
}

private Vector3f calculateRelativeBlockPosition(Vector3f hitPoint, Camera camera) {
    Vector3f cameraDirection = camera.getDirection();

    Vector3f cameraPosition = camera.getLocation();
    cameraPosition.setY(cameraPosition.getY());

    Vector3f hitToCamera = hitPoint.subtract(cameraPosition);

    cameraDirection.normalizeLocal();

    float distance = hitToCamera.dot(cameraDirection);

    Vector3f relativeBlockPosition = cameraPosition.add(cameraDirection.mult(distance));

    int gridSize = 2;
    float x = Math.round(relativeBlockPosition.x / gridSize) * gridSize;
    float y = Math.round(relativeBlockPosition.y / gridSize) * gridSize;
    float z = Math.round(relativeBlockPosition.z / gridSize) * gridSize;

    return new Vector3f(x, y, z);
}

private void placeBlockAtPosition(Vector3f position, int idx) {
    Block block = new Block(position, idx, assetManager);
    blocks.attachChild(block.getGeometry());
    physics.getPhysicsSpace().add(block.getBlock_phy());
    rootNode.attachChild(blocks);
}

You can use the collision normal to calculate that the relative position. Something like:

CollisionResult closest = results.getClosestCollision();
Vector3f normal = closest.getContactNormal();
Vector3f relativePosition = normal.mult(blockSize);

Edit: this will only work on cubes, so if you plan to add other shapes, you will have to try something else.

4 Likes

For future wanderes:
I was able to fix this with codex idea of normal vectors. This works for me without any problems.

private Vector3f calculateRelativeBlockPosition(Vector3f hitPoint, Vector3f hitNormal, Camera camera) {
Vector3f cameraDirection = camera.getDirection();
Vector3f cameraPosition = camera.getLocation();

    Vector3f hitToCamera = hitPoint.subtract(cameraPosition);
    cameraDirection.normalizeLocal();
    float distance = hitToCamera.dot(cameraDirection);
    Vector3f relativeBlockPosition = cameraPosition.add(cameraDirection.mult(distance));

    int gridSize = 2;
    float x = Math.round(relativeBlockPosition.x / gridSize) * gridSize;
    float y = Math.round(relativeBlockPosition.y / gridSize) * gridSize;
    float z = Math.round(relativeBlockPosition.z / gridSize) * gridSize;

    if (hitNormal.x < 0) {
        x -= gridSize;
    }
    if (hitNormal.y < 0) {
        y -= gridSize;
    }
    if (hitNormal.z < 0) {
        z -= gridSize;
    }

    Vector3f adjustedPosition = new Vector3f(x, y, z);//.add(hitNormal.mult(gridSize));

    return adjustedPosition;
}
2 Likes

Note: it’s counter-intuitive but block worlds are not made of blocks… they are made of batches of visible faces (quads).

If you are making your world out of actual cubes then you won’t be able to have a world bigger than 16x16 or so.

Also note: some people decide to make a block world because they think it’s the simplest game… in fact it is one of the HARDEST types of games to make. Nearly everything is custom. You have to deal with manually creating meshes almost immediately, etc… Way easier to make a level in a 3D modeling tool and slap some prebuilt assets into it than to make a block world game from scratch.

Also also note: if you really really want to pursue this then there are existing libraries that can get you part of the way there and/or have source code to look at.

3 Likes

Oh but I am already done. I just wanted to copy the first version of minecraft. Its not going to be a big game, I just wanted to work with JME a bit more. The stuff JME provided was enough for me. But yeah, from the performance alone I figuered this is not scalable the way I did it, thanks for confirming and giving me ideas!

2 Likes