How can I have something follow the flyCam of a SimpleApplication?

I wanted to have a PointLight attached to the camera and move with it.
I found this that could be useful to achieve that. But I can’t find a way to get a “Spatial” from the flyCam.
What I’m doing currently is adjust position in the update loop:

  private val lantern = new PointLight
  override def simpleUpdate(tpf: Float) = {
    lantern.setPosition(cam.getLocation)
  }

But this seems a bit “brute force” to me. Is there a more elegant way ? Or is LightControl doing the same (kind of) thing anyway ?

http://javadoc.jmonkeyengine.org/com/jme3/scene/LightNode.html
http://javadoc.jmonkeyengine.org/com/jme3/scene/CameraNode.html
…or…
http://javadoc.jmonkeyengine.org/com/jme3/scene/control/CameraControl.html

I’m sorry, even with that I don’t find how to access a Node (or Spatial) related to the camera, from cam nor flyCam (attributes of SimpleApplication). I’m not sure how they are implemented, but could they be not part of the scenegraph ?

CameraControl seems to be for the inverse use case: attaching a camera to something (vs attaching something to a camera).

Well, you might actually have to look at them.

FlyCam has a camera. It has nothing to do with nodes. A camera is not a node. A camera is a camera.

However, with CameraNode or CameraControl you can LINK a camera to a node or a node to a camera.

I finally got something to work:

lanternNode = new LightNode("light", lantern)
cc = new CameraControl(cam, ControlDirection.CameraToSpatial)
lanternNode.addControl(cc)
rootNode.attachChild(lanternNode)
rootNode.addLight(lantern)

What I find strange is that I have to “add” the light twice. Why does the LightNode need to be attached into the graph ? Is this a way to have all controls automatically processed (“for each node in the graph, process its controls”). If I don’t call attachChild, the light will still be effective, but won’t move.

No… you only added the light once. rootNode.addLight(lantern)

Lights are not nodes. Nodes are not lights.

As to why you have to attach nodes to things, maybe this is helpful:
http://wiki.jmonkeyengine.org/doku.php/jme3:scenegraph_for_dummies

Put another way…

This is exactly what happens already.

Because it wouldn’t be in the graph if you didn’t attach it.

I didn’t ask “is there a way” but “is this a way”.

That’s my point: I don’t really need it in the graph, I just need the controllers to operate their sync actions. When I used setPosition(), it worked perfectly without being in the graph.

Nodes need to be in the graph or they aren’t part of the graph. Only things that are part of the graph are updated.

Lights are not nodes… which is why you had to wrap it in a node to get it to move with the graph.

I’m not sure why this is hard.

Its probably easier to just do light.setPosition(cam.getPosition())
With the controls it will first need to change the node position from the camera, then the next control will need to set the light position from the node - seems too complicated for me…

Yeah, that’s the way I’d do it to… as part of an app state even. He was looking for ‘elegance’. :slight_smile:

And didn’t really find it :smile:. More seriously, this give me insights on how the engine works. Like:

which of course is obvious, phrased like that. But “controllers” synchronizing things could have been implemented as listeners instead of requiring manual registration so that they are looped over. (I’m not saying it should have been so. This is probably not efficient).

Sure… you would still had to have added them somewhere… but then that’s what the scene graph is for.

With a listener system, you don’t need to register things in a global list to have changes propagated.

The scene graph stores “Spatials” which are objects having a transform. You have to put yourself into a new user’s shoes and realize it is not obvious at all, seeing that, that its role is to schedule updates (some objects you might want to schedule for updating might even not have spatial localization at all).

Of course you need to register objects somewhere if they’re supposed to be called. You can’t just make an object and leave it there and expect code to know about it and call it. There isn’t a single java library that I know that would work that way.

Hello Update Loop pretty much explains how the update of the scenegraph works, so yes, it should be obvious that the scenegraph is updated this way.

It’s called “binding”.
Once you have a “control” to which you passed an object in parameter, and then you registered that control into a second object (addControl), a binding could be achieved without the need for additional manual registrations.

If you want Java, you can look at examples on (starting from ex#3):
http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm
No one is calling update() or registering objects into an external list. Yet setSomething() automagically has visible effects on another object’s getSomethingElse().

Again, not saying it should be this way in JME …

Yeah, you addControl() to the spatial which in turn you add to the scenegraph, thats exactly whats happening in jME. Or you add an AppState to the StateManager…

Those binding systems are nice, but I think they would add too much overhead. In a GUI system like JavaFX you only have a few controls here and there. In a game engine you might have to track thousands of objects… the direct approach often works best.

The binding is surprisingly low cost in javafx,

however it would reduce the power the developer has, wich is not a good idea since this is the one feature where JME easily beats all AAA engines.