Proper use of lookAt or billboard effect?


What could be the best way to handle this scenario:

I have a sphere with text pads on its surface. The aim is that whenever a moving observer (a secondary camera) is looking at the sphere, the text zones must be properly oriented towards the observer, even when the sphere is rotating ie its hpr are changed.

I have something set with textNP.LookAt(observer), the issue is that this only works ok as long as the sphere is rotating on H.

I’ve seen somewhere in the doc that billboard effect can be used in such a case, I’m afraid I didn’t find out how!

Thanks for your hints.

BillboardEffect basically does an implicit lookAt every frame, so if you can’t solve your problem with lookAt, you can’t solve it with a billboard either.

But I don’t understand why you can’t solve it with a lookAt. You have text that is written on a rotating sphere, and you want the text to rotate independently of the sphere. Doesn’t that mean your text isn’t actually parented to the sphere, but instead both are parented to the same common node for their position? That way the sphere can rotate whichever way it likes, and the text will rotate whichever way it likes.


It could well be that I’ve misunderstood or misused LookAt from the very beginning…

What I actually have is a sphere to which are attached sort of small biz cards. (they’re parented to the sphere’s centre)
The intent is to have the bizcards move with the sphere (ie follow any hpr rotation) but then to have their text in horizontal positionning and pointing towards a moving observer.

For sure I’m missing something (maybe obvious) here.

If I understand correctly, than a setup like this should work:

render -> sphere -> dummy -> text cards.

You add one additional node between each text card and the sphere center. You place a dummy where the text should be relative to the sphere, and attach your text cards (with billboard effect) to the dummies.

This way the dummy should act like a ball joint attached to a specific point on the sphere, following that point, but allowing the text to rotate on its own around that point on the sphere, and thus face the observer.

If that’s not what you’re trying to do, then maybe you could try drawing what the result should look like?

Thanks Coppertop,

I’ll try your suggestion. The paradigm of the intermediate ball joint is correct.

However I still don’t see if keeping them horizontal while facing the observer is possible.

I think it should, but if it doesn’t, you can always manually do lookAt every frame with a specified up vector. Obviously, that would probably be less efficient.


Actually, I just checked that it’s possible to set the upVector by hand for the billboard effect as well, so it shouldn’t be a problem to keep them horizontal.

Thanks so much, but I’m afraid to say that I still don’t get it properly.

(1) when setting a billboard effect: to what axis does the up vector refer to (ie global or local wrt to the parent node?)
(2) would you be using set_billboard_point_eye(node) or do_billboard_point_eye(node)? (in c++)

If I may, would you be kind enough to drop a few (sketched) line of pseudo code that shows the trick.


You probably want set_billboard_point_eye().

The three kinds of billboard rotations are:

axis, which rotates about the up-axis (usually Z, but can be specified)

point-world, which rotates freely, and keeps the top of the object oriented towards the world’s up axis (usually Z, but can be specified)

point-eye, which rotates freely and keeps the top of the object oriented towards the camera’s up axis.

point-world and point-eye are identical as long as the camera’s up axis is aligned with the world’s up axis (i.e. the camera has no roll).

There are also additional, more obscure, options, which can be controlled via the underlying BillboardEffect. If you want to specify the particular up axis, or any of these more obscure options, you must use a BillboardEffect directly instead of using the high-level NodePath interface.

Edit: do_billboard_point_eye() is intended for one-time computation of the billboard motion. For a persistent billboard effect, you want set_billboard_point_eye(), which adds a BillboardEffect, or simply do set_effect() with the specific BillboardEffect you construct.


Just made it with a proper use of look_at and no intermediate ball joints nodes


have a fixed point (ie fixed reference axes) at the center of the sphere
have a rotor colocated at the center of the sphere, attached to it and to which all the cards on the sphere are attached

Then any time the ‘rotor’ changes hpr

LVector3f direction_up =marker.get_pos(rotor);

for (int tag=0; tag<nb_tags; tag++) {
    texttag[tag].look_at(camera_node, LPoint3f(0,0,0), direction_up);	 

The key point was to keep track of the local vector direction_up.

I must say that in this case the use of billboard effect was sort of confusing.