HowTo/Build a cab interior
Jamesmoody (Talk | contribs) |
m (→A basic config file) |
||
Line 38: | Line 38: | ||
} | } | ||
− | Note: There are also other base tags that should be added that are common to all asset types - e.g. the download station will require a valid thumbnails container before the asset can be uploaded. See the documentation for [[ | + | Note: There are also other base tags that should be added that are common to all asset types - e.g. the download station will require a valid thumbnails container before the asset can be uploaded. See the documentation for [[KIND TrainzBaseSpec]] for details of tags which apply to all trainz assets. Depending on which Trainz version you have and which trainz-build number you have specified, some of these may be required - content manager will tell you what is required, listing missing tags as errors. |
==camera positions== | ==camera positions== | ||
Line 59: | Line 59: | ||
You may wish to return to this and tweak the values later once all the controls are in place - but it's handy to have a good starting position for the camera while testing. | You may wish to return to this and tweak the values later once all the controls are in place - but it's handy to have a good starting position for the camera while testing. | ||
− | |||
=Cab controls= | =Cab controls= |
Revision as of 16:19, 25 June 2011
Trainz uses an interior object to represent a locomotive cab, or view from another vehicle, e.g. a passenger coach, brake van or caboose. Interiors can also be attached to some non-train assets. For this howto, I am going to assume that we are creating a traincar interior, and focus primarily on a cab interior for a diesel or electric locomotive.
Contents |
Basic structure
The basic structure of a cab is quite similar to a number of different assets. You will have a main mesh with a number of attached sub-meshes, which are arranged using a mesh-table.
The main cab mesh typically consists of the interior walls, roof and floor of the cab, the control desk or stand, all furniture or other static objects visible inside the cab, and also all parts of the locomotive exterior that are visible from inside the cab - e.g. the top of any projecting nose below the cab windows. Remember to consider the sightlines out of rear windows too for visible bodywork panels - the user can move around the cab and rotate the camera to any angle. Users are not restricted to looking forward out of the front windows only.
Artwork considerations
There are some differences in style between the construction of an interior object and a typical trainz object.
Except in very specific circumstances, there will not be more than one interior object in existence at any time, and that interior is always viewed from very close range - the user is inside it. Because of this, interiors are typically modelled with a high polygon count and with high resolution textures, to give an impressive visual feel. LOD is not used, as the user never gets far enough away from the interior for LOD techniques to have worthwhile benefit.
Trainz lights interior objects differently to map objects like buildings and other scenery - the main illumination is ambient, not directional. (A steam loco does have a directional light coming from the firebox, but a diesel or electric cab typically has no directional light inside, and relies entirely on ambient illumination).
With ambient illumination, effects such as normal and specular mapping do not have much (if any) effect. Because of this, more effort needs to be put into the diffuse texture for a cab interior than would normally be applied to Trainz objects. Drawing or baking shadows and other effects into the diffuse textures is required to produce a nice looking cab interior.
A basic config file
The minimal required config for an interior to show in-game is:
kind interior kuid <kuid2:YOUR:KUID:HERE> trainz-build 2.9 username "Your interior name here" category-class ZI mesh-table { default { mesh "your_interior_mesh_name.im" auto-create 1 } }
Note: There are also other base tags that should be added that are common to all asset types - e.g. the download station will require a valid thumbnails container before the asset can be uploaded. See the documentation for KIND TrainzBaseSpec for details of tags which apply to all trainz assets. Depending on which Trainz version you have and which trainz-build number you have specified, some of these may be required - content manager will tell you what is required, listing missing tags as errors.
camera positions
If we load a cab up with that config file, we will note that the view is not particularly appealing. Chances are we're right down near the floor. To fix this, we need to define some default positions for camera views. This is done with the cameralist container and the cameradefault tag. Add the following to your config.txt file:
cameralist { camera0 0,0,2,0,0 }
cameradefault 0
The cameralist container can contain any number of cameras, but they must be numbered sequentially and start at zero.
The five numbers are the X, Y and Z coordinates of the camera in metres relative to the 0,0,0 point of the interior mesh, and the Yaw and Pitch in radians. Luckily you don't have to work these values out from scratch - add the line "-freeintcam" to your trainzoptions.txt file, and you can move the camera about in the cab with the mouse and keyboard, and the precise position will be displayed in the bottom right corner.
When you have found a position you like, write the numbers down. When you've got a good selection of positions recorded, add them to the cameralist container.
You may wish to return to this and tweak the values later once all the controls are in place - but it's handy to have a good starting position for the camera while testing.
Cab controls
A locomotive cab interior needs working cab controls. What fun would sitting in the drivers seat be without being able to pull on the levers, change the switches, and watch the gauges and dials move?
The moving part of each lever, switch, gauge or dial is created as a separate mesh, which is then attached to the cab with an attachment point. (The static part, e.g. guide rails for levers, should be part of the cab mesh itself).
Lever
The lever is the basic input device in a cab. It is based on rotational movement, and any object that requires rotational movement (e.g. a wheel or ring) can be implemented as a lever.
If you actually want linear movement, you can still use a lever - just move the attachment point a long way away - e.g. 10 or 20 metres away from the control. The resulting small arc will not be noticable over the length of movement. As an example, sliding windows in Trainz cabs have been implemented as levers "attached" something like 10 or 20 metres out to the side of the vehicle for a long time. (The exception to this is a horn pull rope - trainz provides a control specifically for this purpose).
You will need to create the lever in your modelling program aligned correctly - the rotation needs to be around the Z axis, and main part of the object will point along the Y axis.
When adding the attachment point to the main mesh, align it so the Z axis is the axis of rotation. It is common to point the Y axis at the default position - e.g. levers in the 'off' or 'neutral' position, and needles pointing to zero. This is not strictly required, as the range of movement can be adjusted at both ends, but it provides a handy reference when creating the config file.
It is worth noting that you can reuse a mesh for multiple attachments. This is particularly useful for switches, as identical appearance switches are often used repeatedly in a cab for different purposes.
Throttle Lever
A good example of a standard lever in use is a locomotive throttle control. A typical US diesel throttle has 9 notched positions (from 0 to 8 inclusive).
As noted above, the lever is created in the modelling package so it points along the Y axis and the axis of rotation is along the Z axis. The attachment point is added to the cab interior mesh at the correct position, and rotated so the Z axis is aligned with the axis of rotation, and the Y axis points to the default position.
Now we need to add an entry to the config file to add our throttle lever.
Into the mesh table, add an entry like this:
throttle_lever { kind "lever" mesh "throttle_lever.im" att "a.throttle_lever" limits 0,8 angles 0,1.57 notches 0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1 notchheight 1,2,2,2,2,2,2,2,1 radius 0.35 auto-create 1 att-parent "default" }
... remember to set your attachment point and mesh name correctly.
The 'angles' line defines how far the control rotates. It is in radians - there are 2 x Pi (6.28) radians in a complete circle. My default of 1.57 will give you about 90 degrees of rotation, in the positive direction. Adjust this number to get the control to rotate the correct amount. You should be able to work out the number you need in your modelling program by using the rotate tool on the attachment point, and recording the amount of rotation required to move to the intended maximum location. It should not require significant trial and error.
The 'radius' line defines the position of the notch position overlay and the text label. It is in metres. If the overlay is too close in, increase this number. If it is too far out, decrease it.
If the lever is the wrong way round (notch 8 is at the wrong end), swap the numbers in the 'angles' tag over, so the higher one is first.
If the lever moves the wrong way when you drag it with the mouse (i.e. it goes left in response to a right drag), add the line:
mousespeed -1
This will invert the mouse movement.
The fact we called this lever "throttle_lever" means it will be used to control the throttle by the default cab script.
So what happens if we wanted a different number of notches? Below is an example of a throttle which has 22 notches. The second value in the 'limits' tag has been edited to return up to notch 22, and more entries have been added to the 'notches' and 'notchheight' tags:
throttle_lever { kind "lever" mesh "throttle_lever.im" att "a.throttle_lever" limits 0,22 angles 0,0.94 notches 0,0.045,0.091,0.136,0.182,0.227,0.273,0.318,0.364,0.409,0.455,0.5,0.545,0.591,0.636,0.682,0.727,0.773,0.818,0.864,0.909,0.955,1 notchheight 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 radius 0.35 auto-create 1 att-parent "default" }
Reverser Lever
The reverser lever is created in a similar manner to throttle lever. The mesh table entry for this will look like:
reverser_lever { kind "lever" mesh "reverser_lever.im" att "a.reverser_lever" limits 0,2 angles -0.79,0.79 notches 0,0.5,1 notchheight 1,1,1 radius 0.25 auto-create 1 att-parent "default" }
In this case, because the 'angles' entry has a range both positive and negative, the lever can move in both directions relative to the attachment point. The game will set the default position to neutral (1), so if you've lined up your attachment point at one end, don't worry - you can use angles which range from zero if you need to.
Train Air Brake Lever
There are two types of train air brake lever. A given locomotive only has one type - the brakes are either require manual lapping or are self-lapping. Use the appropriate name and configuration for the loco you are modelling.
Manual Lapped Brakes
The manual train brake lever has five positions numbered from zero to four, each one representing a different function. Those functions are Release, Lap, Application, Emergency and Handle Off respectively.
A lever for a manual lap train air brake is defined as follows:
trainbrakelap_lever { kind "lever" mesh "train_brake_lap_lever.im" att "a.train_brake_lap_lever" limits 0,4 angles 0,0.94 notches 0,0.25,0.5,0.75,1 notchheight 1,1,1,1,1 radius 0.25 att-parent "default" auto-create 1 }
In this case, the attachment for the lever has been created in the 'release' position. If it had been created in the 'handle off' position, the angle tag would have been more like:
angles -0.94,0
Self Lapping Brakes
A self lapping trainbrake lever has a number of primary notches similar to the manual lap train brake lever. However, instead of a 'lap' and 'apply' position, it has a grade of application between the 'initial' and 'full application' positions. An example of a self-lapping brake handle is this one:
trainbrake_lever { kind "lever" mesh "train_brake_lever.im" att "a.train_brake_lever" limits 0,4 angles 0,0.94 notches 0,0.25,0.27,0.29,0.31,0.33,0.35,0.37,0.39,0.41,0.43,0.45,0.47,0.49,0.5,0.75,1 notchheight 1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1 radius 0.25 att-parent "default" auto-create 1 }
In this case, there are 14 possible levels of brake application - initial at 0.25, 12 intermediate levels, and full application at 0.5. There is no restriction on the number of intermediate levels - if you are modelling a prototype brake handle with a specific number, you may create precisely that number of notches and arrange them between 0.25 and 0.5 as required.
Combined throttle brake lever
There is also another control option - a combined throttle brake lever. This type of control is often found on multiple unit trains. This control is split into two halves. The first half of the movement is an inverted throttle - i.e. max power at zero, no power at 0.5. The second half is an auto lapped train brake application, with 0.5 as release, and 1.0 as emergency. An example of how to configure a combined throttle and brake lever is below:
throttle_brake_lever { kind "lever" mesh "throttle_brake_handle.im" auto-create 1 att "a.throttle_brake_handle" limits 0,16 angles 0.94,-0.94 notches 0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.8125,0.75,0.875,0.9375,1 notchheight 1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1 att-parent "default" radius 0.12 invert 1 }
Unfortunately, trains that use this type of control generally use blended and/or EP brakes, and this control uses the standard Trainz air brake, which operates in a distinctly different manner, and as a result, can feel very wrong for this control type. (See the section on scripting controls for how a better combined brake and throttle lever may be implemented).
Pull lever
This is a sprung lever. You pull on this lever to activate it, and when you let it go, it returns to the original position. This kind of action is commonly associated with a locomotive horn, and this is what I am using as an example:
horn { kind "pulllever" mesh "horn.im" att "a.horn" auto-create 1 angles 0,-0.55 limits 0,1 mousespeed -1 radius -0.02 notches 0,1 notchheight 0,0 }
Switch
A switch is a lever that does not require the user to 'drag' it with the mouse - it operates on a click only. This is used for smaller controls that are 'on' or 'off', and do not have intermediate positions. Parameters are much like they are for a 'lever', only a switch should only have two notches - on and off.
Unfortunately, some things you'd normally associate with being a 'switch' (e.g. the headlight switch control) require mulitple positions, and will need to remain as a 'lever' in order to allow the player to set the correct position for the control.
An example of a switch would be:
switch1 { kind "switch" mesh "switch.im" att "a.switch1" limits 0,1 angles 1.4,0 notches 0,1 notchheight 0,0 mousespeed -1 }
As 'switch' was introduced in TS2009 SP2, interiors that use kind 'switch' controls should be marked trainz-build 3.1 or later in the config.txt.
Pull rope
This is a linear pull rope control. Unlike the rotating controls discussed previously, this control type moves the mesh linearly along the Z axis of the attachment. It behaves as you would expect from a suspended rope - click and drag to pull, let go to release. It will spring back to it's initial position in the same manner as kind 'pulllever'.
horn { kind "pullrope" mesh "horn_rope.im" att "a.horn" limits 0,1 angles 0.1,0 notches 0,1 notchheight 0,0 mousespeed -1 }
needle
A needle is the standard Trainz output device. Like the lever, it is based on rotational movement, and any gauge, dial, or other output device based on rotational movement can be implemented. Any static part of the gauge should be modelled as part of the cab, and only the moving part as part of the needle. Like the lever, the rotation will be around the Z axis of the needle, and it is common practice to point the point of the needle along the Y axis. Cabs often have a number of similar gauges, and re-using the same needle repeatedly in each gauge is a lot easier if this setup is done consistently.
As an example of a needle, here is a basic speedometer:
speedo_needle { kind "needle" auto-create 1 mesh "speedo_needle.im" att "a.speedo_needle" limits 0,67.056 angles 0,4.712
}
The default cab script knows to move the "speedo_needle" object as the train speed changes, so simply by naming this control "speedo_needle", it has become a speedometer.
For a speedo, the 'limits' values will be the minimum and maximum reportable speed in m/s.
Creating other rotational gauges is similar - refer to the mesh-table (interior version) documentation to see all the different values that Trainz can show by default.
light
Another common type of control is a light. This is created simply as a textured plane, which is either hidden or shown to represent light off or light on. It is attached as any other standard mesh attachment would be - there is no rotation to worry about here.
wheelslip_light { kind "light" mesh "wheelslip_light.im" att "a.wheelslip_light" }
This light will be used to show wheelslip in a default cab.
digital-dial
Some locomotives use a digital readout for speed or pressure display information.
Trainz has two control kinds to support digital displays - one for speed units, and one for pressure.
These have some font specific options.
"font" defines the typeface. For a list of valid typefaces, see the mesh-table (interior version) documentation. Generally this follows closely with a number of default windows font names.
"fontsize" defines the size of the font. The default value for this is 0.02, and this is a pretty respectable size display.
"fontcolor" defines the RGB color of the text. Each value is a floating point number between 0.0 and 1.0.
digital-dial-spd
For a speedometer (or any other gauge that shows units in speed, e.g. a speed limit display), use kind 'digital-dial-spd'.
An example speedometer using this kind would be declared as:
speedo_needle2 { kind "digital-dial-spd" att "a.digispeedo" font "arial" fontsize 0.01 fontcolor 1.0,1.0,1.0 auto-create 1 }
digital-dial-prs
For a display using pressure units, use digital-dial-prs. This is a digital brake pipe pressure gauge:
bptrainbrakepipe_needle2 { kind "digital-dial-prs" att "a.trainpipe_pressure" font "arial" fontsize 0.01 fontcolor 0.0,1.0,0.0 auto-create 1 }
-~= To Be Continued... =~-