Skip to content

Commit

Permalink
Initial Commit of ZR code
Browse files Browse the repository at this point in the history
=========================
  • Loading branch information
djw-zr committed Feb 4, 2021
1 parent 97a2c32 commit e30cb3a
Show file tree
Hide file tree
Showing 52 changed files with 19,956 additions and 51 deletions.
53 changes: 2 additions & 51 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,52 +1,3 @@
# Prerequisites
*.d
.gitignore
zr

# Object files
*.o
*.ko
*.obj
*.elf

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
65 changes: 65 additions & 0 deletions Documents/README.COMPILE
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
README.COMPILE
==============

Required Software
=================

The program has been developed using the OpenSUSE 15.1 version of linux. As far as I know, no specialist packages are required so the compiers and libraries should be also available for the standard linux distributions such as Debian, Ubuntu and Fedora.

Compilation and linking of the program is carried out by the makefile. This requires installation of the programs:
make :: Gnu make program of equivalent
gcc :: GNU C compiler

In addition the program needs the following libraries
glibc :: This is a group standard C libraries including libm (-lm on the compile line).
libz :: Library implementing the deflate compression algorithm (-lz).
libX11 :: Core X11 library (-lX11)
libXext :: X11 extension library (-lXext)
libXmu :: X11 extensions (-lXmu)
libGL :: OpenGL library (-lGL)
libGLU :: Extensions for GLU (-lGLU)
libglut :: GLUT library (-lglut)
The libraries glibc and X11, Xext and Xmu should be installed by default. The others may need to be installed using a package manager. Unfortunately the name of the package can change from one system to another so you may need to obtain expert help.

Often the library exists in directory '/usr/lib64' with a name such as "libXmu.so.6". However the program linker will be looking for "libXmu.so" so if the latter does not exist it will fail. The solution is to change directories to '/usr/lib' and use the superuser command to create the link:
sudo ln -s libXmu.so.6 libXmu.so

To compile the program, the header (*.h) files for these libraries will also be needed. These are usually held in packages with similar names but with the addition of '-devel' Thus in OpenSUSE 15.1 the GLU and glut packages are:
libGLU1 :: Installs the GLU library files
glu-devel :: Installs the header files
libglut3 :: Installs the glut library files
freeglut-devel :: Installs the header files
zlib-devel :: Header file for the deflate compression algorithm.

Compiling
=========

To compile open a console window, and use the 'cd' command to change to the ZR directory. Then type
make
This prints the compiler command. Compilation should then proceed and end after only a few seconds without any error messages. The resulting program file is file 'zr' in the same directory.

Starting the program
====================

The program needs a file "$HOME/.zrails/config" which contains information on 'ORroutedir' the route to use and 'ORdir', the directory containing both the 'Routes' directory containing different routes and the 'Global', 'Sound' and 'Trains' directories. The 'Trains' directory contains specifications of the engines and wagons being used.

If the file does not exist when the program is first run, it is created with the
lines starting:
MSTSdir =
ORdir =
ORroutedir =
left otherwise blank. The lines need to be completed. At present 'MSTSdir' is not used but it is there to allow the standard MSTS routes to be added later. In my test system:
MSTSdir =
ORdir = / ... /Open_Rails_Train_Simulator/
ORroutedir = / ... /Open_Rails_Train_Simulator/Routes/au_great_zig_zag/

The program can now been run from the ZR directory:
./zr -help :: Request help.
./zr :: Check loading of data files.
./zr -p :: Load data files and run.






33 changes: 33 additions & 0 deletions Documents/README.KUJU_BINARY_FILES
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
README.KUJU_BINARY_FILES
========================

These start with the normal MSTS compressed header. This 16 characters starting "SIMISA@F", followed by a four byte binary integer giving the size of the uncompressed file, followed by "@@@@".

When handling files in a command shell this can be stripped off with the linux tail command.
>tail -c +17 file_with_header > file_without_header

The next 2 bytes are "0x78 0x9c" indicating that it is a zlib compressed stream. This can by uncompressed with my program zpipe.
>./zpipe -d < file_without_header > uncompressed_file

The uncompressed file then starts with the 16 characters of the MSTS sub-header. The exception are the ace files (*.ace) which contain textures. These do not contain the MSTS sub-header. See README.ACEFILE for details.

Openrails file SBR.cs indicates that 'world' files, with 'w' in sub-header [5] position, use an 300 offset in the table of tokens. This means that when reading world files 300 has to be added to the tokens when looking up the meaning in the 'enum' table. This implies that the original MSTS program uses a different set of enums for world files and other files.

OpenRails handling of binary files
==================================

Reading the header section and setting up the offset is carried out by 'SBR Open' in file SBR.cs. This then starts a new Binary File reader with the file pointer, filename and offset as parameters.

The binary file reader asumes that
fb is positioned just after the SIMISA@F header
filename is provided for error reporting purposes

The binary file is split into blocks. Each block starts with a tokenID, whose value corresponds to one of the TokenID enums. The comment says that for some file types, the token value is offset by the value given - but only refers to the world files although the 'some' implies there might be others.

Note: In C# the enum structure stores both the enum and the associated string, so it is easy to convert between the two. In my c code, enum.h contains the same information.

The comment also states that "Every block must be closed with either Skip() or VerifyEndOfBlock()". This is true for both unicode and binary files so it is possible that some of the subroutines are to promote symmetry between the two sets of routines. In fact it looks as if a switch is set so that the subroutines reading the file do not care whether it is a binary or unicode file - read_int returning the correct value whatever scheme is chosen.

This means that the "name ( data ... )" structure is reproduced in binary - the brackets being skipped and the position of the final bracket being assumed when the end of block has been reached, all the expected data has been read or no more tokens are found at the same level. As the data is ordered in a hierarchical structure, it is usually possible to determine whether the next token is another token 'at the same level within the brackets' or a token 'at the previous or higher level'.

The end of block is reached when PeekChar() in C# returns a -1. The C# routine Skip(), calls Peek() until and of block is found. However the call VerifyEndOfBlock appears to close the file whatever is found there.
22 changes: 22 additions & 0 deletions Documents/README.MAKEFILE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
README.MAKEFILE
===============

The makefile has a slightly unusual structure but this has been chosen:

1. To work with the multi-level source directory structure
used by openrail.
2. To use only a single level of makefile
3. To remove the requirement for dependency files
4. Because at present, compilation of the whole program is fast

The main program 'zr.c' in the top level directory is the only C file in the makefile line calling the C compiler. 'zr.c' then loads all the include files (*.h) and other C files (*.c) through include statements.

New include (*.h) files should be placed under directory 'include' and their names should be added to the beginning of the file 'include/zr.h'.

New C (*.c) files should be added to one of the directories under 'src'. Then statements to include the new files should be added at the end of zr.c.

If more sub-directories are added under the 'include' or 'src' directories, these should be added to the INC_DIR or SRC_DIR lines in the makefile.

As the program grows and compilation times increase, there may come a time for a more traditional makefile in which each C file is compiled separately.

The makefile works correctly with the gmake (GNU) version of make.
64 changes: 64 additions & 0 deletions Documents/README.QUATERNIONS
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
README.QUATERNIONS
==================

OR and Rotations

The OR files can either use 3x3 rotation matrices or quaternions to represent the rotation of objects. According to wikipedia (https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) quaternions have the advantage of being more compact and more numerically stable than rotation matrices.

They are defined by four numbers. If these are A, B, C and D, the quaternion is A + Bi + Cj + Dk, where i, j and k are the unit vectors along the X, Y and Z axes. A, a scalar, is the cosine of half the angle of rotation about the axis defined by Bi + Cj + Dk.

Given a unit quaternion (bb+cc+dd = 1??), the corresponding rotation matrix is (possibly):
aa+bb-cc-dd 2bc-2ad 2bd+2ac 0
2bc+2ad aa-bb+cc-dd 2cd-2ab 0
2bd-2ac 2cd-2ab aa-bb-cc+dd 0
0 0 0 1

For use with OpenGL, ZR converts the queternion into a unit vector and the angle of rotation.

glRotate Definition
===================
void glRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )

angle Specifies the angle of rotation, in degrees.
x, y, z Specify the x, y, and z coordinates of a vector, respectively.

glRotate produces a rotation of angle degrees around the vector (x,y,z). The current matrix (see glMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix, as if glMultMatrix were called with the following matrix as its argument:
x2(1−c)+c xy(1−c)−zs xz(1−c)+ys 0
yx(1−c)+zs y2(1−c)+c yz(1−c)−xs 0
xz(1−c)−ys yz(1−c)+xs z2(1−c)+c 0
0 0 0 1
Where c=cos(angle), s=sin(angle), and ||(x,y,z)||=1 (if not, the GL will normalize this vector).

If the matrix mode is either GL_MODELVIEW or GL_PROJECTION, all objects drawn after glRotate is called are rotated. Use glPushMatrix and glPopMatrix to save and restore the unrotated coordinate system.

This rotation follows the right-hand rule, so if the vector (x,y,z) points toward the user, the rotation will be counterclockwise.

GL_INVALID_OPERATION is generated if glRotate is executed between the execution of glBegin and the corresponding execution of glEnd. This is true for any matrix operation. However glRotate can be used in display lists.

OpenGl 4x4 matrix
=================

OpenGl transformation matrices are stored in a non-standard order. A vector v1 (x1,y1,z1,1.0) is transformed to v2 with the operation:

x2 / m0 m4 m8 m12 \ x1
y2 = | m1 m5 m9 m13 | * y1
z2 | m2 m6 m10 m14 | z1
w2 \ m3 m7 m11 m15/ w1

Usually w1 and w2 both equal 1

If the current matrix is C and the coordinates to be transformed are v = v0 v1 v2 v3, then the current transformation is C × v , or

c0 c4 c8 c12 v0
c1 c5 c9 c13 × v1
c2 c6 c10 c14 v2
c3 c7 c11 c15 v3

Calling glMultMatrix with an argument of m = m0 m1 ... m15 replaces the current transformation with C × M × v , or

c0 c4 c8 c12 m0 m4 m8 m12 v0
c1 c5 c9 c13 × m1 m5 m9 m13 × v1
c2 c6 c10 c14 m2 m6 m10 m14 v2
c3 c7 c11 c15 m3 m7 m11 m15 v3

81 changes: 81 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Program ZR
==========

Introduction
============

Program ZR is intended initially to be a GNU version of OpenRails, the open source program based on MSTS (MicroSoft Train Simulator), using Mesa/OpenGL and X11 for the 3D graphics and GLUT for the window and user interfaces. It is written in C, but as OpenGL is also available on other systems, such as Windows and OS 11, there is no reason why it should not be converted.

The basic design principal is the engineers' KISS (Keep It Simple Stupid). GNU does not support C#, so as ZR is a bit-shoving program we are limited to C or C++. ZR started as a C++ project but I was concerned about speed (not helped by some comments in Stroustrup's book) and I was not convinced that the extensions (overtyping etc) were optimal (or needed) for a relatively small project like OpenRails. So I chose C.

I have thought about the name and after some thought junked either GLOR or GOR (Gnu-Linux OpenRails or the Great Ocean Railroad), for ZR (Zero Rails). Zero is the typographical sibling of 'O' and it means that any special names can start with the shorter 'zr' or 'zr_' without possibly confusion with dictionary words.

Be warned that in its present state, nothing moves. Many OpenRails files, including MTST style compressed and binary files can be read, and the landscape and the fixed shapes (stations, tracks, buildings, rail crossings, signals, etc.) displayed. There are also compiler options which separately display wagons/engines, shapes and textures. However the remaining OpenRails code, which includes all the dynamics, still has to be converted.

Version Status
===============

The program has been developed using the "Great Zig Zag Railway" route available from:
https://www.zigzag.coalstonewcastle.com.au/
With this route the program successfully displays the route, topography and fixed structures but with some exceptions. The exceptions are:
No textures are applied to the topography.
Forests are not displayed.
Water is not displayed.

Display rates can be low - but will depend on the graphics card being used. At present the code does not store vertex arrays on the graphics card, so this is an obvious next step. It also tends to plot everything nearby - even if it is not in the viewport.

At this stage of development, the code is also likely to contain further bugs and hit problems with common mis-spellings of MSTS tokens - which MSTS and OpenRails either ignore or allow for. For this reason it is suggested that users first test the code using the zig-zag route, before trying the it out on other routes

Compilation
===========

The program is designed to be compiled and run from a linux bash shell. It uses a GNU style makefile to compile the program and the shell command "./zr -p" to run the program.

More details are given in file "Documents/README.COMPILE". This also contains information on generating the config file which contains information on the location on the route directory and the other directories needed by the program.

Running the program
===================

You can move around the 3D scene using the arrow keys. If the -Dkb_dev option is used in the makefile, the arrow keys will move the viewpoint forwards, backwards and sideways at the same level. The keys page-up and page down will move up and down. The normal steps are 32 m, increased to 1024m if the 'Shift' key is depressed and reduced to 1 m if 'Alt' is depressed. The arrow keys with 'Ctrl' depressed turn the direction of view to the left, right, up or down in steps of 1 degree. If both 'Ctrl' and 'Shift' are pressed the step is 30 degrees.

Without the -Dkb_dev option, the behaviour is nearer the standard MSTS behaviour, the arrow keys moving forward and backward but not necessarily at the same level. In this case the default steps are 1 m (10 m with Shift) and 0.1 degree.

These values are defined by the variables del_d and del_a in file keyboard.c.

As with the MSTS keyboard, 'Shift-Z' gives an estimate of frames per second. The value displayed is an cumulative average over the previous 5 seconds - so it takes 5 seconds to stabalise.

Other Options
=============

Main compiler options in makefile:

#CFLAGS += -Dsketch_tracks_and_roads
This option plots the path of railway tracks and road at an additional elevation of 1 meter above the actual path. This option also provides data on the model index of each section of track.

#CFLAGS += -Dgrid_lines
The generates a rectangular grid, with a spacing of 2048 m, which spans the model region and shows the boundaries of model tiles. Not all tiles are used, but those that are in use have associated files specifying the topography and the fixed structures within the tile.

#CFLAGS += -Dfull_topog
Because of the time taken to display the contents of each tile, MTST, OpenRails and ZR usually only display the 9 tiles immediately surrounding the viewpoint - the 9 tiles changing as the viewpoint moves from one tile to the next. If the comment sign '#' is removed and the program is recompiled, this option displays the full topography.

CFLAGS += -Dkb_dev
Discussed above.

There are three additional compiler options. These can be triggered, one at a time, by removing the '#' comment tag at the beginning of one of the lines in the makefile and recompiling the program:
#CFLAGS += -D_Display_Shapes # For fixed structures
#CFLAGS += -D_Display_Wagons # Engines and trucks
#CFLAGS += -D_Display_Textures # Textures
These options display the 3D figures and 2D textures on a regular grid. The names of the 3D figures are also displayed.

Contributing
============

Obviously a lot more work is needed - and at the moment I'm running out of steam. Most of the software needed to read and decode the MSTS format ascii and binary, compressed and uncompressed files is provided.

I admit that the organisation of the code is poor, it needs improvements, it is also not easy to read (also true of OpenRails) and my OpenGL knowledge is still limited to version 2.1. However despite all of that, I hope that there is enough here to attract other people to develop the project.

Of course if you just want to take a copy and do your own thing - that's fine. However if you are interested in collaborating, it would be a good idea to first have a look at the OpenRails code and then let me know of which aspects of the model you would like to develop.

Three simpler things that currently need development are water, forests and adding texture to topography. After that it should be primarily about the user interface and dynamics.

djw - February 2021
22 changes: 22 additions & 0 deletions include/display_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* =============================================================================
* 45678901234567890123456789012345678901234567890123456789012345678901234567890
*
* File: display_info.h
*
* This file is part of ZR. Released under licence GPL-3.0-or-later.
* You should have received a copy of the GNU General Public License
* along with ZR. If not, see <https://www.gnu.org/licenses/>.
*
* Include file containing the structures used by ZR to store the data
* included in each world file.
*
* =============================================================================
*/

int display_info = 0 ; // When set display extra information on world
// and track items.
GLfloat display_info_radius = 100.0 ;
GLfloat display_info_height = 4.0 ;


Loading

0 comments on commit e30cb3a

Please sign in to comment.