Noob lookat problem


I have problem with my rotations. I have node called wordsCloud which has bitmapText’s added to random local translations. wordsCloud is in rootnode. In simpleUpdate I have this:


if (rotateCloud)

wordsCloud.rotate(0, tpf, 0);


Vector3f tolookat = cam.getLocation().clone();

for (int i = 0; i < bitmaps.length; i++) {

bitmaps.lookAt(tolookat, Vector3f.UNIT_Y);



What I want is that all those bitmaps looks at my camera position all the time, but it seems that bitmaps don’t know that their parent has rotated. If I move camera it updates bitmaps rotations as they wouldn’t have rotated around their axel at all. If I comment out that wordsCloud.rotate() it seems to be working all right.

I’ve been reading similiar lookat problems from these forums for while now and I still don’t get it.



There is a class called BillboardNode for exactly that purpose.

I’m using Platfrom Alpha-3 and I think its not implemented in it?

I found BillboardControl which I added to my bitmaptext’s. Effect was same as it was in my code posted there. If I don’t rotate the wordsCloud then everything works, but if I rotate it then it doesn’t work.

Yeah, I meant BillboardControl. Why do you rotate it yourself still? The BillboardControl is supposed to take care of that.

I’m rotating parent Node (wordCloud) of nodes that are supposed to face camera. Child nodes are in random positions around the parent Node. Idea is to create effect where words would fly around in 3D space by rotating parent and words would face the camera all the time after rotating the parent.


hehe, I had fun making this one. I don’t know if this is what you’re attempting to do, but it sure sounds like it…

Center Node ->(1…*) Children → Billboard

I’m not smart enough to know exactly why the billboard node doesn’t work directly on the children, so I added a controller to counter the rotation of the children (Just went in and did it in update instead, but either way works). I forget why this is so… Going to look into it now, but here’s what I wrote:


package com.flah.playground;



import com.jme3.export.JmeExporter;

import com.jme3.export.JmeImporter;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.control.AbstractControl;

import com.jme3.scene.control.BillboardControl;

import com.jme3.scene.control.Control;

import com.jme3.scene.shape.Quad;

import com.jme3.scene.shape.Sphere;

public class WordCloud extends SimpleApplication {

private Node center;

public static void main(String[] args) {

WordCloud app = new WordCloud();




public void simpleInitApp() {


// Center Node

center = new Node(“Center Node”);


// Sphere for the Center (visual)

Sphere centerSphere = new Sphere(32, 32, 1.25f);

Geometry centerGeom = new Geometry(“Center Geom”, centerSphere);

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

centerMat.setColor(“m_Color”, ColorRGBA.Red);



// Plop a few nodes around the center

for (int i = 0; i < 25; i++) {





public void simpleUpdate(float tpf) {


center.rotate(0, tpf, 0);

for (int i = 0; i < center.getChildren().size(); i++) {

center.getChild(i).rotate(0, -tpf, 0);



private void createNode() {

Node orbit = new Node(“Orbit Node”);

// Sphere for node location (visual)

Sphere orbitSphere = new Sphere(32, 32, 0.5f);

Geometry orbitGeom = new Geometry(“Orbit Geom”, orbitSphere);

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

orbitMat.setColor(“m_Color”, ColorRGBA.randomColor());


// Quad for Billboard (visual)

Quad quad = new Quad(3, 3);

Geometry billboardGeom = new Geometry(“Billboard Geom”, quad);

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

billboardMat.setTexture(“m_ColorMap”, assetManager.loadTexture(“Interface/Logo/Monkey.jpg”));





// Attach a Billboard Control to the quad

billboardGeom.addControl(new BillboardControl());

// orbit.addControl(new AbstractControl() {

// @Override

// public Control cloneForSpatial(Spatial spatial) {

// return null;

// }


// @Override

// protected void controlUpdate(float tpf) {

// spatial.rotate(0, -tpf, 0);

// }


// @Override

// protected void controlRender(RenderManager rm, ViewPort vp) {

// }

// });

// Setup the orbit position

orbit.setLocalTranslation(getMeAFloat(20f), getMeAFloat(20f), getMeAFloat(20f));


private static float getMeAFloat(float max) {

if(FastMath.rand.nextBoolean()) {

return FastMath.rand.nextFloat() * max;


else {

return FastMath.rand.nextFloat() * -max;





1 Like

Thats exactly what I’m trying to do!

Hmm. I kind of tried that solution also, but I think I was thinking too hard when I was taking quaternion from Center node and applying negative of it to the children. :smiley:

Well. Thanks for the solution tehflah!