Grid floor and walls UNSOLVED! PLEASE HELP

Hey guys!



I’m trying to make a floor and walls, textured with a grid, and whereif I click a square from the grid, a cube, with sides in the same size as the square from the grid. But, I don’t know a jME3 function to build this! I tryed several methods but all of them doesn’t work! So, I ask you now: Is it possible to do?



Thanks in advance, borba.

Is the grid size of the texture always the same and known?

Thanks for your reply, durandal!



That’s the problem, I don’t know the size.

I found a class named Grid, and i’m using it. Is there a way to apply it in a box? Like, a texture and detect which square did the user clicked!



Thanks in advance, borba.

[java]

com.jme3.texture.Texture2D text = new Texture2D(image);

text.setWrap(com.jme3.texture.Texture2D.WrapMode.Repeat);

[/java]

You can get the click coordinate (searc on the forum) on the wall or floor and then map that back to the texture it has and find out which square on the grid you clicked. It will take some math though.

Then create a box that side and glue it on the square.



If you really don’t know the grid size and all you have is the texture then I think you’ll need to analyse that.

I’m thinking on use jme3 Grid class. Is that possible in this case?

I’m not sure i understand what you are trying to do.

here is what i got :

You want a wall and floor that are basically grids. if a cell of the grids is clicked, you want to create a cube with the dimensions of the cell, that would emerge from the cell.



If i’m correct, yes you could use the Grid class. but the grid geometry is a subdivided plane so if you need thick walls, it won’t do the trick.

Durandal’s approach is what i would do to compute the coordinates of cell that has been clicked.

Thanks for your reply, nehon.



I searched on the forum but I only found how to get click coorddinates on a terrain page, is there a way to do it in Box object?



Thanks in advance, borba.

alternative approach - Create a wall of Boxes. Then click a box and have it move forward out of the wall. Presto.

You should check the documentation Documentation/JMonkeyEngine3 in the menu above.

And precisely this doc https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:beginner:hello_picking

Hey guys! I tried to do my own, but it really sucks, it jsut create strange boxes (and not size 1x1x1), I don’t if the problem is in my block class or in the main code!



Block class:



[java]public class Block extends Node {



private Box blockBox;

private Geometry block;

private PhysicsNode blockNode;

private String blname;

private Vector3f pos;

private Vector3f size;



private Material mat;



public Block(String blname, Vector3f pos, Vector3f size)

{

this.blname = blname;

this.size = size;

this.pos = pos;

blockBox = new Box(pos, size);

blockBox.scaleTextureCoordinates(new Vector2f(10f, 10f));



block = new Geometry(blname, blockBox);



blockNode = new PhysicsNode(block, new BoxCollisionShape(size), 0);

blockNode.setLocalTranslation(pos);

this.attachChild(blockNode);

}



public Node getBlockNode()

{

return blockNode;

}



public void setBlockMaterial(Material mat)

{

this.mat = mat;

this.setMaterial(mat);

}



@Override

public String getName()

{

return blname;

}

}[/java]



Mouse picking code:



[java]private ActionListener actionListener = new ActionListener() {

@Override

public void onAction(String name, boolean keyPressed, float tpf) {

if (name.equals(“Create”) && !keyPressed) {

CollisionResults results = new CollisionResults();

Ray ray = new Ray(cam.getLocation(), cam.getDirection());

rootNode.collideWith(ray, results);



CollisionResult closest = results.getClosestCollision();

if(closest != null) {

int c_contact_x = (int) closest.getContactPoint().x;

int c_contact_y = (int) closest.getContactPoint().y;

int c_contact_z = (int) closest.getContactPoint().z;

String block_name = "Block " + blockid;

Block b = new Block(block_name,

new Vector3f(c_contact_x, c_contact_y , c_contact_z),

new Vector3f(1f, 1f, 1f));

b.setBlockMaterial(mat_grid);

System.out.println("Criar bloco de nome " + block_name +

" x = " + c_contact_x +

" y = " + c_contact_y +

" z = " + c_contact_z);

rootNode.attachChild(b);

bulletAppState.getPhysicsSpace().add(b.getBlockNode());

blockid++

}

}

}

};[/java]

Ei borba, vc eh o único brasileiro que eu encontrei aqui no jmonkey ;), ou vc eh português?

@OFFTOPIC: Sim, eu sou brasileiro.



@TOPIC: Can someone see a problem on my code?

Hey guys! Sorry for double-post.



I’m trying to solve this problem but it’s just creating strange boxes! Not in the right pos neither in the right size! I’ve debugged my block class and it seems do be ok, but I think the problem is in here:



[java]private ActionListener actionListener = new ActionListener() {

@Override

public void onAction(String name, boolean keyPressed, float tpf) {

if (name.equals(“Create”) && !keyPressed) {

CollisionResults results = new CollisionResults();

Ray ray = new Ray(cam.getLocation(), cam.getDirection());

rootNode.collideWith(ray, results);



CollisionResult closest = results.getClosestCollision();

if(closest != null) {

int c_contact_x = (int) closest.getContactPoint().x;

int c_contact_z = (int) closest.getContactPoint().z;

String block_name = "Block " + blockid;

Block b = new Block(block_name,

new Vector3f(c_contact_x, -0.03f, c_contact_z),

new Vector3f(1f, 1f, 1f),

new Vector2f(1, 1));

b.setBlockMaterial(mat_grid);

blockid++;

rootNode.attachChild(b);

bulletAppState.getPhysicsSpace().add(b.getBlockPhysicsNode());

}

}

}

};[/java]



if someone wanna take a look at my block class:



[java]public class Block extends Node {



private Box blockBox;

private Geometry block;

private PhysicsNode blockNode;



private String blname;

private Vector3f blpos;

private Vector3f blsize;

private Vector2f text_scale;



public Block(String blname, Vector3f blpos, Vector3f blsize, Vector2f text_scale)

{

this.blname = blname;

this.blpos = blpos;

this.blsize = blsize;

this.text_scale = text_scale;

this.setLocalTranslation(blpos);

System.out.println("Node pos = " + blpos);

blockBox = new Box(blpos, blsize);

System.out.println("Creating a box in " + blpos + " with " + blsize);

blockBox.scaleTextureCoordinates(text_scale);

System.out.println("Texture Scale: " + text_scale);



block = new Geometry(blname, blockBox);

System.out.println("New Geometry with name: " + blname + " using " + blockBox.toString());



blockNode = new PhysicsNode(block, new BoxCollisionShape(blsize), 0);

System.out.println(“New physics node, usiong geometry:” + block.toString());

blockNode.setLocalTranslation(blpos);

this.attachChild(blockNode);

}



public Node getBlockPhysicsNode()

{

return blockNode;

}



public void setBlockMaterial(Material mat)

{

this.setMaterial(mat);

}



@Override

public String getName()

{

return blname;

}



public String getInfo()

{

String info;

info = "(POS: " + blpos + ") n(SIZE: " + blsize + “)”;

return info;

}

}

}[/java]



Thanks in advance, and sorry for double-post, borba.

I thought you were trying to get the square being clicked? If you use this code:



[java]CollisionResults results = new CollisionResults();

Ray ray = new Ray(cam.getLocation(), cam.getDirection());

rootNode.collideWith(ray, results);[/java]



You’re going to get whatever is in the very center of the screen. You need this:



[java]rootNode.updateGeometricState();

Vector3f origin = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.0f);

Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.3f);

direction.subtractLocal(origin).normalizeLocal();

Ray ray = new Ray(origin, direction);[/java]



if you’ve disabled the flyCam and you want whatever’s under the mouse cursor when it’s clicked.

Also, I think you’re using the Box constructor incorrectly. Look at the Javadoc for Box. You’re passing it two Vector3f, assuming that the first is the position and the second is the size, but that’s not the case. Box with two Vector3f passed in is defined as follows:


public Box(Vector3f min,
Vector3f max)

Constructor instantiates a new Box object.
The minimum and maximum point are provided, these two points define the shape and size of the box but not it’s orientation or position. You should use the #setLocalTranslation() and #setLocalRotation() methods to define those properties.

Hey!



Block class was messed up, so I re-writed all the code in a single class. But I think the problem is the round method I’m using, some squares are placed correctly but others stay a little bit strange (the full class):



[java]public class AppState extends SimpleApplication {



private BulletAppState bulletAppState;



///-- Scene

Node scene;

Material mat_grid;



///-- Crosshair

Picture crosshair;



public static void main(String[] args) {

AppState thelab = new AppState();

thelab.start();

}



public void simpleInitApp() {

scene = new Node(“Scene”);



loadContent();

setupWorld();

setupKeys();

setupGUI();

}



public void loadContent()

{

mat_grid = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);

Texture floortexture = assetManager.loadTexture(“Textures/Floor/grid.png”);

floortexture.setWrap(WrapMode.Repeat);

mat_grid.setTexture(“m_ColorMap”, floortexture);

}



public void setupWorld()

{

///-- Setup Physics Space

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);



flyCam.setMoveSpeed(100f);



///-- Objects

scene.attachChild(makeFloor());

rootNode.attachChild(scene);



///-- Simple Light

PointLight light = new PointLight();

light.setPosition(new Vector3f(0, 10, 0));

light.setColor(ColorRGBA.White);

rootNode.addLight(light);

}



public void setupKeys()

{

inputManager.addMapping(“Create”, new MouseButtonTrigger(0));

inputManager.addListener(actionListener, “Create”);

}



private ActionListener actionListener = new ActionListener() {

@Override

public void onAction(String name, boolean keyPressed, float tpf) {

if (name.equals(“Create”) && !keyPressed) {

CollisionResults results = new CollisionResults();

Ray ray = new Ray(cam.getLocation(), cam.getDirection());

scene.collideWith(ray, results);



if (results.size() > 0) {

CollisionResult closest = results.getClosestCollision();

scene.attachChild(makeBlock(“Block”,

round(closest.getContactPoint().x),

1,

round(closest.getContactPoint().z)));

rootNode.attachChild(scene);

}

}

}

};



public void setupGUI()

{

///-- Clear all children to start display the gui.

guiNode.detachAllChildren();



///-- Crosshair

crosshair = new Picture(“Crosshair”);

crosshair.scale(20);

crosshair.setImage(assetManager, “Interface/crosshair.png”, true);

crosshair.setPosition(settings.getWidth() / 2 - 10, settings.getHeight() / 2 - 10);

guiNode.attachChild(crosshair);

}



@Override

public void simpleUpdate(float tpf) {



}



///-- Make Floor

protected Geometry makeFloor() {

Box box = new Box(new Vector3f(0f, -.1f, 0f), 10, .1f, 10);

box.scaleTextureCoordinates(new Vector2f(10f, 10f));

Geometry floor = new Geometry(“Floor”, box);

floor.setMaterial(mat_grid);

return floor;

}



///-- Make Block

protected Geometry makeBlock(String name, float x, float y, float z) {

Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);

box.scaleTextureCoordinates(new Vector2f(1f, 1f));

Geometry block = new Geometry(name, box);

block.setMaterial(mat_grid);

return block;

}



///-- Round

protected int round(float num)

{

BigDecimal big = new BigDecimal(num);

int result;



big.setScale(1, BigDecimal.ROUND_UP);

result = big.intValue();



System.out.println(result);

return result;

}

}[/java]



Picture:

Why is your round method so complicated? Just use



java;[/java]



That’s the ceiling function, it rounds your number up to the next whole integer. It returns a float, but just cast it to an int and you’ll have your original number rounded up.



–EDIT–

fixed the example, was supposed to be casting to an int, not a float.

Hello!



If I’m reading this right…



You want the blocks to be unit cubes right? (1x1x1)? If so, the blocks you’re making are actually 2x2x2. When you create a box with the constructor you’re using (and the other constructors I believe too), the Vector3f() is the center of the box you’re making, and the x,y,z components afterwards are the extents from the center, not the overall length of the sides. So new Box(new Vector3f(x, y, z), 1, 1, 1); is actually creating a box at the supplied vector with extents 1,1,1 which is a 2x2x2 cube.



This might explain why your round method doesn’t always work as it’s rounding to the nearest int?



Again, if I’m reading this right. You’re close though, I’ll tell you that.



Another thing, have you tried the Wireframe material? I’m thinking it’s not exactly what you want here, but I just wanted to make sure you were aware of it. The sample code below will construct a wireframe material. It would only help you if you wanted to see the entire wireframe, and in your case you’d need to make the floor a more dense mesh to get the grid effect.



[java]

Material wireMat = new Material(assetManager, “Common/MatDefs/Misc/WireColor.j3md”);

wireMat.setColor(“m_Color”, ColorRGBA.Green);

[/java]



~FlaH

1 Like

Thank you for your reply, theflah.



I understood what you said. The new code :



[java]protected Geometry makeFloor() {

Box box = new Box(new Vector3f(0f, -.1f, 0f), 10, .1f, 10);

box.scaleTextureCoordinates(new Vector2f(20f, 20f));

Geometry floor = new Geometry(“Floor”, box);

floor.setMaterial(mat_grid);

return floor;

}



///-- Make Block

protected Geometry makeBlock(String name, float x, float y, float z) {

Box box = new Box(new Vector3f(x, y, z), 0.5f, 0.5f, 0.5f);

box.scaleTextureCoordinates(new Vector2f(1f, 1f));

Geometry block = new Geometry(name, box);

block.setMaterial(mat_grid);

return block;

}[/java]





But the boxes still in the wrong place, just like the picture.