This is an entry point for new RoR developers - it describes how RoR currently works, why it sucks and what I'd like to do about it. The reason to write it down right here right now is this excellent contribution from a new developer
** split to multiple posts because of character limit **
Document status:
Early draft, just notes from the top of my head. I'll edit this to add more later. Hopefully I'll compose something meaningful to put to our Doxygen docs.
Design :
RoR history (why is it such a mess?)
** split to multiple posts because of character limit **
Document status:
Early draft, just notes from the top of my head. I'll edit this to add more later. Hopefully I'll compose something meaningful to put to our Doxygen docs.
Design :
- RoR isn't OOP, it's structured and just makes use of objects. I think OOP has 'one O too many'. However, some previous authors seem to have loved OOP while disregarding common sense.
- We embrace global variables via 'GVar' mechanism inspired by Quake's cvars - see file 'Application.h' and older 'GlobalEnvironment.h'
- Our entry point is straightforward 'main()' function - it performs inits and then enters game state loop governed by GVar 'app_state'
- We use OGRE 3D for rendering - we init engine at startup and shut down on exit. We use it's built-in windowing.
- Our main simulation loop lives in `RoRFrameListener::EnterSimulationLoop()` and calls OGRE's 'renderOneFrame()' which invokes `frameStarted()` callback (same thread).
- When loading an actor [aka vehicle/truck/load, see below] ( Truck file format) we load+parse the file first into `RigDef::File` object, then spawn from it. But for historical reasons, the parsed object is not reused.
- Our physics use Euler integration and run on 2khz frequency. We accumulate time spent rendering and then advance physics. But for historical reasons, some physics calculations run on variable timestep (time since last frame).
- We employ a threadpool but make limited use of it. Our design is singlethreaded: {1. update sim 2. render 3. repeat}. As part of the 'update sim' phase, we parallelize some tasks but immediately wait for them to complete. Our fancy 'threadpool' is a contribution from mikadou . GitHub
- We have 2 ways of attaching meshes (3d models) to our actors: 'props' (just positioning) and 'flexbodies' (positioning+deformation, see Truck file format -). Flexbodies work entirely on CPU. On spawn, for each vertex, 3 nodes are selected to form reference space. On runtime, the vertex is positoned relatively to this space and the updated mesh is then uploaded to graphics card.
- Proper Overview
RoR history (why is it such a mess?)
- Until v0.4.5, RoR had no main menu and no unloading mechanisms. Usage was: {use RoRConfig to edit RoR.cfg -> start RoR -> choose map -> play (load and "unload" vehicles) -> exit RoR}. Thus none of the subsystems could un-initialize itself, all unloading logic was added later.
- Until v0.4.5, OGRE's rendering loop (which updates whole game via 'frameStarted()' callback) was started as soon as the game started, and game state detection was done at last minute, so there were "is this initialized yet? (check pointer)" checks everywhere - some are still lying around.
- Until v0.4.5, loading vehicles was done on the fly while truckfile was being read line by line. This caused heavy dependence on order of definitions, much of it undocumented. Also there was tight coupling with simulation data structures.
- Same thing with terrains. This is still mostly true.
- Until v0.4.6 the physics timestep was not constant 0.0005 (2khz) but it slightly varied thanks to nonsense computation logic. Fixed by Ulteq.
- Until v0.4 RoR was singlethreaded. Ulteq (ulteq . GitHub) added multithreading sometime around Version 0.4.0.7 - but it was just limited.
- Also see 'development timeline by Aivar' in our archived forum
Last edited: