New block placement not working

I’m trying to make a block building enigne, but I have stumbled on a problem. My block placement algorithm is not working :frowning:
So without any further delay, here’s the code:

CollisionResults results = new CollisionResults();
// 2. Aim the ray from cam loc to cam direction.
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in results list.
placeAbles.collideWith(ray, results);
            
if (results.size() == 0) return;
//Get all coordinates
Vector3f boomLocation = results.getCollision(1).getContactPoint();
Spatial blockHit = (Spatial) results.getClosestCollision().getGeometry();
Vector3f blockLocation = blockHit.getLocalTranslation();
float xBoom = boomLocation.x, yBoom = boomLocation.y, zBoom = boomLocation.z;
float xBlock = blockLocation.x, yBlock = blockLocation.y, zBlock = blockLocation.z;
            
//Figure out where to put a new block
Vector3f newBlockLocation = new Vector3f();
if (xBoom < xBlock){
    newBlockLocation.x = blockLocation.x - 0.1f;
}else {
    newBlockLocation.x = blockLocation.x + 0.1f;
}
if (yBoom < yBlock){
    newBlockLocation.y = blockLocation.y - 0.1f;
}else {
    newBlockLocation.y = blockLocation.y + 0.1f;
}
if (zBoom < zBlock){
    newBlockLocation.z = blockLocation.z - 0.1f;
}else {
    newBlockLocation.z = blockLocation.z + 0.1f;
}
//Create a block and place it
Block newBlock = new Block(GUIBlocks[GUIBlocksIndex].getBlockType(), assetManager);
newBlock.getBlockRender().setLocalTranslation(newBlockLocation);
blocks.attachChild(newBlock.getBlockRender());

So I want the new block to appear on the clicked surface of the block, but this is what I get:

The block should be on this side of the construction block, but is instead placed in the middle of construction block.

Help anyone? :confused:

If you use the jme Box shape. the localTranslation is the center of the block. so you should add block.with/2 to x,y,z to your local translation.

something like

newBlockLocation.addLocal(0.05f,0.05f,0.05f)
newBlock.getBlockRender().setLocalTranslation(newBlockLocation);

Now this is what I get:

Changing it to 0.2f would do the job, but the block would be placed diagonally and that’s not what I want…

EDIT: Also I am using default JME3 Boxes

Sorry, I read to quickly. The issue is in your logic, you should find wich face of the cube is hit, then increase only x xor y xor z, not two or three of the coordinnate, only one.

EDIT: If you world is a grid, you can take the hit point move back half step (size of the box/cell) and div by size of the cell, round the value and you have the center of the cell.

In my game I did something along the lines of this.

// Grab the location of the block you are currently pointing at
final Vector3f locationOfBlockWeAreLookingAt = collisionResult.getGeometry().getLocalTranslation();

// Set the new block location to the location of the block we are pointing at plus the normal of the triangle where the ray collided.
final Vector3f newBlockLocation = locationOfBlockWeAreLookingAt.add(blockResults.getClosestCollision().getTriangle(null).getNormal());

Bare in mind here that the normal is most likely 1 in the direction we want the new block so you might need to modify that to fit with your sized blocks.

In my game I also had blocks which where not always cubes but could be slopes or pyramids and I basically had my own implementation of Collidable on the blocks so they created an invisible cube which the ray could hit.

With this code this is the result:

We are getting closer to the solution, but the problem is that I don’t know how to modify the Normal to 0.2f…

Ok, after some tinkering this is a working result:

       //Figure out where to put a new block
        Vector3f newBlockLocation = new Vector3f(blockLocation);
        Vector3f direction = results.getClosestCollision().getTriangle(null).getNormal();
        
        if (direction.x != 0){
            if (direction.x < 0){
                newBlockLocation.x = blockLocation.x - 0.2f;
            }else {
                newBlockLocation.x = blockLocation.x + 0.2f;
            }
        }else if (direction.y != 0){
            if (direction.y < 0){
                newBlockLocation.y = blockLocation.y - 0.2f;
            }else {
                newBlockLocation.y = blockLocation.y + 0.2f;
            }
        }else if (direction.z != 0){
            if (direction.z < 0){
                newBlockLocation.z = blockLocation.z - 0.2f;
            }else {
                newBlockLocation.z = blockLocation.z + 0.2f;
            }
        }

Thanks for all help :wink:

Great to see you got it working, like I said you basically just needed to scale down that normal to the size of your own bocks which you seem to have managed.

You could pretty much have just multiplied the normal by 0.2 I suppose in this case.

Vector3f direction = results.getClosestCollision().getTriangle(null).getNormal();
newBlockLocation.addLocal(direction.multLocal(0.2f));