Draw 2D text in 3D world

Hi,



I have looked on the web of ways to write 2D text over 3D shapes, for example player names. The only example I found was this:





import com.jme3.app.SimpleApplication;

import com.jme3.font.BitmapText;

import com.jme3.material.Material;

import com.jme3.math.*;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;





public class DrawText extends SimpleApplication {



public static void main(String[] args) {

DrawText app = new DrawText();

app.start();

}



Geometry geom;

BitmapText ch;



@Override

public void simpleInitApp() {



Box a = new Box(Vector3f.ZERO, 1, 1, 1);

geom = new Geometry(“Box”, a);



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

mat.setColor(“Color”, ColorRGBA.Blue);

geom.setMaterial(mat);



rootNode.attachChild(geom);





// guiNode.detachAllChildren();

guiFont = assetManager.loadFont(“Interface/Fonts/Default.fnt”);

ch = new BitmapText(guiFont, false);

ch.setSize(guiFont.getCharSet().getRenderedSize());

ch.setText(geom.getName()); // crosshairs

ch.setColor(new ColorRGBA(1f,0.8f,0.3f,0.8f));





guiNode.attachChild(ch);











viewPort.setBackgroundColor(ColorRGBA.Gray);

flyCam.setMoveSpeed(10);

}







@Override

public void simpleUpdate(float tpf)

{



guiNode.getChild(0).setLocalTranslation(cam.getScreenCoordinates(geom.getLocalTranslation().add(0, 0, 0)));





}



}





The bug is that if I look right away from the cube, I will also see the text. Is there an easier way if I have a lot of 3D objects and want to attach names to them?

Don’t attach the text on the gui node, set it to the location of the object you want to attach it to and attach it to the root node, or just attach it to your cube.

Take a look at BillboardControl as well to have it always face the screen.

Thanks,



I cant attach it to my cube, geom.attachChild(ch); doesn’t work. Is there a guide somewhere or a small example which show how to use BillboardControl?

TestBillboard.java

Attach your geom to a node, and attach the text to that node. Move and rotate that parent node and have it represent your character.

Create a node, attach both the cube and the label into it.



There is a weakness to that approach though which is that the text will change size as you approach/move away.



If you don’t want that then you are back to using the GUI node. There is a simple test you can do with dot products to see if the object is behind the screen or not although I can’t remember the details off hand.

just test if its in the frustrum, this is probably done anyway once a rendering, maybee it is storing taht even somewhere where you can just get it (not sure about that)

Anyone can give me code for a small example? It is too hard for me to look in the API Documentation. I know how to add text to a node, but it becomes 3D. I want the text always to be the same size and directed towards the user. Just like player names in BF3, WOW, ect…

@hakdnljsa6473 said:
I want the text always to be the same size and directed towards the user. Just like player names in BF3, WOW, etc...


Then you'll have to implement a scaling function.

I haven't played WoW in quite some times, but I do think the name tag do scale up/down depending on the distance. There might be a threshold where it starts though.

No, I want the name tag to be the same size regardless of distance. But yes, a threshold where it starts would be great.

The way I do that is actually by having them as panels on an absolutely laid out nifty layer.



Each frame I get the center of the spatial, get the screen co-ordinates of that and then adjust the position of the nifty panel accordingly. If the object is too close to the edge of the screen I hide the nifty panel.



In my case labelled objects never go behind the camera so I don’t need to worry about that.

…or just use BitmapText in the guiNode and similarly set the position every frame.