ChaseCamera and Billboards

Hello!



How can I use a ChaseCamera together with Billboards?

If I create a BillboardControl and the attach a Geometry to it.

Evertime I move my mouse the Billboard moves with the camera?

Probably the Billboard is facing the Screen but it should’nt move with the camera.



Have anyone an idea?



Thanks!





regards



-René

1 Like

You can align the billboard.



[java]

[…]

BillboardControl bc = new BillboardControl();

bc.setAlignment(BillboardControl.Alignment.Camera);

geometry.addControl(bc);

[…]

[/java]



You have 4 types of alignments.



Camera

Screen

AxialY

AxialZ

Hello!



I’ve selected first Camera-Alignment and then Screen-Alignment, but everytime

the Geometry moves with the rotation of the camera.



If I use the flycam everything works properly.







regards



-René

Could you provide a test case?

Here is it…


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.input.ChaseCamera;
import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.control.BillboardControl;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Line;
import com.jme3.scene.shape.Sphere;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import com.jme3.texture.Texture;

public class TestCase extends SimpleApplication {

Node helperNode;
static Node geometryNode,lightNode,sceneNode, translationNode,rotationNode,scaleNode;
private static JFrame window;
private PointLight pl;
private float zPos;
private float angle;
Geometry lightMdl;
int gizmo;
ChaseCamera chaseCam;

@Override
public void simpleUpdate(float tpf)
{
angle += tpf;
angle %= FastMath.TWO_PI;

pl.setPosition(new Vector3f(FastMath.cos(angle) * 5f, 0.5f, FastMath.sin(angle) * 2f));
lightMdl.setLocalTranslation(pl.getPosition());
}

@Override
public void simpleInitApp() {
System.out.println("App");
// activate windowed input behaviour
flyCam.setDragToRotate(true);
flyCam.setMoveSpeed(6.0f);
flyCam.setEnabled(false);

// display a cube
Box boxshape1 = new Box(new Vector3f(0f,0f,10f), 1f,1f,1f);
Geometry cube = new Geometry("My Textured Box", boxshape1);
//cube.setLocalTranslation(.5f, .5f, .01f);
Material mat_stl = new Material(assetManager, "Common/MatDefs/Misc/SimpleTextured.j3md");
Texture tex_ml = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
mat_stl.setTexture("m_ColorMap", tex_ml);
cube.setMaterial(mat_stl);

sceneNode = new Node ("sceneNode");
geometryNode = new Node ("geometryNode");
lightNode = new Node ("lightNode");

sceneNode.attachChild(geometryNode);
sceneNode.attachChild(lightNode);
rootNode.attachChild(sceneNode);

helperNode = new Node("helperNode");
//helperNode.attachChild(makeFloor());
helperNode.attachChild(createGrid());
rootNode.attachChild(helperNode);


Node bb = new Node ("billboards");
BillboardControl bbCtrl = new BillboardControl();
bbCtrl.setAlignment(BillboardControl.Alignment.Screen);
bb.addControl(new BillboardControl());
bb.attachChild(cube);
geometryNode.attachChild(bb);

// mock for the point light
lightMdl = new Geometry("Light", new Sphere(10, 10, 0.1f));
Material mat3 = assetManager.loadMaterial("Common/Materials/RedColor.j3m");
mat3.getAdditionalRenderState().setDepthTest(false);

lightMdl.setMaterial(mat3);
lightMdl.getMesh().setStatic();

lightNode.attachChild(lightMdl);

zPos = -10f;

DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
lightMdl.addLight(dl);

// set one point light
pl = new PointLight();
pl.setColor(ColorRGBA.White);
pl.setRadius(4f);
rootNode.addLight(pl);

pl.setPosition(new Vector3f(0f, 0f, zPos));

// Create the default camera
// in this case a chase camera
chaseCam = new ChaseCamera(cam, lightMdl, inputManager);
// Set the maximum vertical rotation angle to 60°
chaseCam.setMaxVerticalRotation((float) ((Math.PI)/3));

}

public Node createGrid()
{
Node gridNode = new Node("gridNode");

// Grid
for (int x = -30; x <= 30; x=x+1) {
Line l = new Line(new Vector3f((float) x, 0f, -30f), new Vector3f((float) x, 0f, 30f));
Geometry gridLine = new Geometry("line", l);
Material matGridLineX = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
matGridLineX.setColor("m_Color", ColorRGBA.DarkGray);
gridLine.setMaterial(matGridLineX);
gridLine.setModelBound(new BoundingBox());
gridLine.updateModelBound();
gridNode.attachChild(gridLine);
}

for (int z = -30; z <= 30; z=z+1) {
Line l = new Line(new Vector3f(-30f, 0f, (float) z), new Vector3f(30f, 0f, (float) z));
Geometry gridLine = new Geometry("line", l);
Material matGridLineX = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
matGridLineX.setColor("m_Color", ColorRGBA.DarkGray);
gridLine.setMaterial(matGridLineX);
gridLine.setModelBound(new BoundingBox());
gridLine.updateModelBound();
gridNode.attachChild(gridLine);
}

// red Axis
Line xAchse = new Line (new Vector3f(-30f, 0f, 0f), new Vector3f(30f, 0f, 0f));
Geometry gridLineX = new Geometry("xAchse", xAchse);
Material matXAchse = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
matXAchse.setColor("m_Color", ColorRGBA.Red);
gridLineX.setMaterial(matXAchse);
gridLineX.setModelBound(new BoundingBox());
gridLineX.updateModelBound();
gridNode.attachChild(gridLineX);

// blue Axis
final Line zAchse = new Line (new Vector3f(0f, 0f, -30f), new Vector3f(0f, 0f, 30f));
Geometry gridLineZ = new Geometry("zAchse", zAchse);
Material matZAchse = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
matZAchse.setColor("m_Color", ColorRGBA.Blue);
gridLineZ.setMaterial(matZAchse);
gridNode.attachChild(gridLineZ);


return gridNode;
}

public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
AppSettings settings = new AppSettings(true);
System.out.println("Main");
settings.setWidth(640);
settings.setHeight(480);
// create new canvas application
SwingCanvasTest canvasApplication = new SwingCanvasTest();
canvasApplication.setSettings(settings);
canvasApplication.createCanvas(); // create canvas!
final JmeCanvasContext ctx = (JmeCanvasContext) canvasApplication.getContext();

ctx.setSystemListener(canvasApplication);
Dimension dim = new Dimension(640, 480);
ctx.getCanvas().setPreferredSize(dim);

// Create Swing window
window = new JFrame("Swing Application");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Fill Swing window with canvas and swing components
JPanel panel = new JPanel(new BorderLayout());

panel.add(ctx.getCanvas(), BorderLayout.CENTER);
JPanel optionPanel = new JPanel(new GridLayout(2,1));
optionPanel.setMinimumSize(new Dimension(30, 30));
optionPanel.setPreferredSize(new Dimension(200, 10));
panel.setMinimumSize(new Dimension(100, 50));
JSplitPane split = new JSplitPane();
split.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
split.setLeftComponent(optionPanel);
split.setRightComponent(panel);


window.add(split, BorderLayout.CENTER);
window.pack();
window.setSize(1024, 768);

// Display Swing window including JME canvas!
window.setVisible(true);
canvasApplication.startCanvas();
}
});

}
}

What’s the SwingCanvasTest?

Got it to start. What is it you’re expecting to see? The cube to follow the sphere I guess?

Not sure if that’s what you want, but you attached the billboard to the node. If you want the cube to be following the camera, you have to attache the control to the cube.



Like this instead:

[java]

Node bb = new Node(“billboards”);

BillboardControl bbCtrl = new BillboardControl();

bbCtrl.setAlignment(BillboardControl.Alignment.Screen);

cube.addControl(bbCtrl);

bb.attachChild(cube);

geometryNode.attachChild(bb);

[/java]

Hello!



I tried both ways.

What I’m expecting is that the cube stays in the exact same position 0, 0, 10 and when the camera is orbiting around.

One face should be aligned to the camera.



That’s an billboard or I understand something wrong? Have you tried to orbit with the camera.

What does the cube stays it in the exact same position?





regards



-René

Ok then. Test this instead.



From you last post this should work as you want. The cube is on 0, 0, 10 and “rotates” to show only 1 face to the camera and do not move around.



You had several problems. The billboard wasn’t attached to the cube (THIS is the object you want to face the camera). Then the billboard was on the wrong alignment mode, it has to be facing the camera. And finally, you have to tell the node where it should be located.



Hopefully that’s what you want.



[java]

Node bb = new Node(“billboards”);

BillboardControl bbCtrl = new BillboardControl();

bbCtrl.setAlignment(BillboardControl.Alignment.Camera);

cube.addControl(bbCtrl);

bb.attachChild(cube);

geometryNode.attachChild(bb);

geometryNode.setLocalTranslation(0,0,10f);

[/java]

Hello!



I’m such an idiot. I must place the “billboard”, better say the Geometry with the BillboardControl inside a Node and then transform this node.

A typical case of not seeing the wood for the trees.

Thanks!





regards



-René

Don’t worry, we all make that kind of mistakes. I’ve posted some things here I wish I could delete. :wink: