PROGRAMMING COMMENTS

PROGRAMS

ORTS has three executable programs:


Users launch ORTS with ORTS.exe - all it does is verify dependancies are installed.  This program
appears in Visual Studio as Launcher.   Once dependancies are checked, ORTS.EXE executes MENU.EXE.

MENU.EXE presents a menu for selection of the mini-route, route, and activity.  It also meant in
the future to provide settings for details levels, performance etc.   Once a route is selected
it executes RUN.EXE

RUN.EXE is the program that runs an activity.
It consists of a railroad Simulator module with one or more Viewers attached.   

The simulator engine contains all the elements for an operational route including representation
of signal conditions, switch track alignment, rolling stock location and movement, track paths, 
AI logic, physics calculations, essentially everything except the 3d representation of the objects.  
It is intended that the simulator engine could run in separate thread, or even on a separate computer.

There can be multiple viewers looking at the simulator - ie straight down activity editor type views,
or full 3D viewers, or perhaps in the future Tower operator's panels etc.   The 3D viewer is 
responsible for loading and rendering all the shape files in the 
scene.  It also handles movement of wheels and other animations embedded in the shape files. 
        
The source code consists of the following sub folders:

	Main - contains the openning dialog boxes to select a route and launch the sim
	Simulator - contains the simulation processes, including physics, ai etc
	3DViewer - contains the code for rendering the Simulator data in 3D on a users computer
	MSTS - contains code for reading and processing MSTS files
	Physics - contains rolling stock classes - these files contain only simulation behaviour - no rendering classes are included
	Common - classes common to the others


THREADING - the program is designed to make maximum use of multiprocessing.   There are at least three
threads planned:
- the main thread runs the 3d viewer
- a second thread handles background loading and unloading assets into the viewer - this is complete now
- the simulator engine engine will run in a third thread ( not done yet )
- the sound engine operates in a fourth thread.

Notes:  Use care to ensure drawablecomponent objects are fully initialized before adding them to the viewer.components list.


TIMING - as the simulator engine runs in a separate thread, and possibly on a separate computer, it
does not run necessarily in sync - TODO how will we handle this


ERROR HANDLING STRATEGY
- ORTS will always attempt to complete the load even in the presence of errored or missing files
	- when it encounters a recoverable error, it will list them in a ORTS Warnings file on your desktop
	- in order to continue, ORS may omit objects, use defaults etc
- if it can't continue, it will report the situation in a message box, and in the ORTS Warnings file and exit.

SCALAR UNITS
- meters are assumed for coordinates
- other scalers must have units appended, ie MpS, N, KG, MpS2 etc to avoid mistakes
- R = radians 
See also the info in Coordinates.cs on the coordinate spaces used in ORTS


TODO - use this comment to flag incomplete parts of your code.


COMMENTING STYLE

I place a lot of value on having a paragraph or two at the top of each file explaining what it contains, 
how the classes are used, and a few details about the internals.  I find this more useful than embedded
comments in the code so if you have to take shortcuts in commenting, try to at least provide the file header
comment block.


ERROR HANDLING

General practice on errors is to report and continue. 
- Console.Error.WriteLine( errormessage )
- then make adjustments, ie defaults etc to continue
If you can't continue, throw an exception
- and attempt to handle it further up


ROLES  PROPOSED
1 - engineer - in future, number cycles through engineers on train
	- arrows move - right - headout, left - head in
	- home end, page down, page up - must be stopped while on the ground
2,3,4 - railfans
6 - brakeman1
7 - brakeman2
	ctrl left right, moves from car to car
	pgdn, on the ground
	pgup, on the train , nearest car
	home, front of train
	end, back of train
5 - passenger
	up down, home, end - move along train
 - railfan
	- pgup - home, end, up, down
	- pgdn - on the ground
	
9 - fireman -  in future, number cycles through fireman on train
	- arrows move - right - headout, left - head in
	- home end, page down, page up



public Viewer3D(Simulator simulator)

public void UserSetup()

public void Configure(RenderProcess renderProcess)

public void Initialize(RenderProcess renderProcess)

public void LoadPrep()

public void Load( RenderProcess renderProcess )

public void HandleUserInput()

public void Update( GameTime gameTime )

public void PrepareFrame(RenderFrame frame, GameTime gameTime)

void Render(GraphicsDevice graphicsDevice, Material previousMaterial, RenderPrimitive renderPrimitive,
                            ref Matrix XNAWorldMatrix, ref Matrix XNAViewMatrix, ref Matrix XNAProjectionMatrix);

void Draw(GraphicsDevice graphicsDevice);

void ResetState(GraphicsDevice graphicsDevice, Material nextMaterial);

public void Unload(RenderProcess renderProcess)


SIMULATOR

public TrainCar(WAGFile wagFile)

public virtual TrainCarViewer GetViewer(Viewer3D viewer)

public virtual void Update(GameTime gameTime)

VIEWER

public virtual void HandleUserInput()

public virtual Update(GameTime gameTime)



// Processes
/// 
/// Open Rails can use multiple processors.  In a multiprocessor environment, 
/// we set up the following threads:
///     - the RenderProcess thread 
///             - is actually the XNA game engine thread 
///             - handling initializing and drawing to the graphics card
///     - a LoaderProcess thread runs in the background 
///             - 10 times per second 
///             - to give the 3D viewer an opportunity to load content as the player moves
///     - an UpdaterProcess thread runs in the background
///             - updating the simulator state
///             - and preparing content for the next rendered frame to be drawn
///     - in additon, IrrKlang, can be configured to run in its own separate thread
///     
/// Thread Safety:
/// 
/// Thread safety is maintained more by data partitioning rather than through the use
/// of semaphores or locks (which can slow down the program).  UpdaterProcess, has 
/// exclusive access to all input devices, all simulator state data and local matrices for 
/// 3D components.   Information exchange with the main render process is through the 
/// RenderFrame class.  UpdaterThread prepares a RenderFrame ( list of primitives and 
/// their position matrices ) and hands it off to the RenderProcess for drawing.  While 
/// RenderProcess does the drawing, UpdaterProcess is preparing the next frame.
/// RenderProcess is assured that the RenderFrame contents won't change after it begins
/// drawing.
/// 
/// LoaderProcess needs access to volatile data in the simulator and viewer classes such
/// as train location and camera location.   To make this thread safe, RenderProcess calls
/// LoaderProcess.Update as soon as UpdaterProcess has finished with the simulator and
/// viewer classes.   UpdaterProcess will be blocked while LoaderProcess copies any needed
/// volatile data.  When LoaderProcess.Update returns, the UpdaterProcess continues on with 
/// updating train location and camera locations for the next frame.  Meanwhile LoaderProcess
/// analyzes the data it copied and continues with loading/unloading graphics content as
/// needed.
/// 
/// Process Synchronization:
/// 
/// These processes don't free-wheel.   In order to prevent jitter and memory contention
/// they operate synchronously to the frame rate.   Each frame triggers UpdaterProcess 
/// to update the Simulator state, and to build a RenderFrame.   While thats being done,
/// RenderProcess draws the previous RenderFrame.   LoaderProcess is launched by 
/// UpdaterProcess immediately after the UpdaterProcess has finished.  
/// Note that when the program is minimized no frame draw calls are made.  During this
/// time, RenderProcess continues to update the LoaderProcess and the Simulator state
/// at a fixed 10 times per second rate.
/// 
/// And on machines with only one processor, we eliminate UpdaterProcess to reduce the
/// overhead of frame swapping etc.

public virtual void PrepareFrame(RenderFrame frame, GameTime gameTime)

public virtual void Unload()

TIME
----

The following time variables are used:

double Program.RealTime 
- global static variable representing number of seconds the program has been running

double Simulator.ClockTime 
- class variable representing the number of seconds since 00:00:00 on the day of the activity, this 
clock stops when the game is paused, and runs fast when the game is sped up.

When various objects are updated, they are passed an elapsed time consisting of one of the following:

struct ElapsedTime
float RealSeconds;
float ClockSeconds;

This represents the elapsed time since that function was last called in both real time and clock time 
units. Functions interacting with the player generally want to use real time, ie camera motion doesn't 
stop when the game is stopped. Functions related to animating game elements, ie wheels turning, use 
clock time.

At a certain point it doesn't make sense to propagate both types of time. For example, the simulator 
classes ( ai, signals etc ) have no concept of real time and work only in clock time. To avoid errors, 
they recieve a float elapsedClockSeconds parameter to eliminate any possibility of error.

Also there are other classes that receive only a float elapsedRealSeconds parameter.

Most floating point variables in Open Rails are stored as float's including elapsed time. But notice 
that to avoid accumulated errors, ClockTime and RealTime are doubles. Keep that in mind if you have 
to create variables that store one of these values. 

The times always represent the target time of the frame currently being prepared and rendered.

All timekeeping is handled in the UpdaterProcess ( see the Architecture Diagram ) for thread safety 
reasons. If any other process is examining time variables, there is probably something wrong and 
warning bells should go off. 


TRAINCARS
---------

Custom parsers.
Don't even need a parser.

