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 ?
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).
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.
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.
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…
And didn’t really find it . 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).
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().
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.