Irrlicht provides a simple interface for performing a lot of standard tasks like adding models to a scene, animating them, creating a camera etc. However in order to perform more customized tasks you need a way to tap into the render loop. Traditionally in a single threaded 3D application the various independent elements update themselves once per frame, which is once for every pass through the render loop.
To demonstrate how this is done we will create two new classes: BaseObject and CirclingLight.
BaseObject.java Source Code
The BaseObject class contains a function, enterFrame, which will be called one per frame by the EngineManager. It registers itself with the EngineManager with the startupBaseObject function, and deregisters itself with the shutdown function. The property inUse, accessed through the getInUse function, identifies the object as being active in the application or not.
CirclingLight.java Source Code
The CirclingLight class extends BaseObject to create an object that updates itself during the render loop. CirclingLight creates a light and a billboard (a 2D graphic that always faces the camera) which rotate around a central point. You will notice that it is during the enterFrame function that the rotation of the light is updated, and it is done so according to how much time has passed during the last frame in order to produce movement that is not dependant on a fixed frame rate.
As before the ApplicationManager class is used to manage the logic of the application, which in this case involves creating 3 CirclingLights and a model in the centre of them all to receive the light.
ApplicationManager.java Source Code
The EngineManager class gains quite a few new functions in order to manage the collection of BaseObjects. The enterFrame function has been created to sync up any new or removed GameObjects (with insertNewBaseObjects and removeDeletedBaseObjects), and then to call enterFrame on all the current GameObjects. It is called once per frame from the main loop inside the enterGameLoop function. The addBaseObject and removeBaseObject functions place GameObjects in holding collections, which are used by the insertNewBaseObjects and removeDeletedBaseObjects functions to keep the main baseObjects collection in sync without baseObjects being modified while it is being looped over.
EngineManager.java Source Code
With these changes to the EngineManager class, and the addition of the BaseObject class, it is easy to create objects that have the ability to update themselves between frames. Check out the online demo here, browse the source code here, and download the source code in a TAR file here.