Guide to Performance-Friendly Vehicle Construction

From OMSIWiki

This article is originally written by Marcel Kuhnt. So I refers to him.

As the name suggests, this guide is to provide opportunities and food for thought to make OMSI-vehicles as performance-friendly as possible.

A OMSI vehicle consists of 3D-models, textures, sounds and scripts - and in all four areas you should pay attention more or less intense on an optimization in terms of performance!

But one thing always applies: Even if you no longer have to be stingy as in the past: You should waste by no means! So for each part that you model, for each sound and for each texture you should have in mind what is both useful and necessary, or what may be more than you need. That this is a matter of taste, of course, goes without saying.

3D-Models

Theory

First we must define the term 'drawcall':

While the bus is drawn (as everything else) of single triangles, the triangles are combined to meshes with the same material properties, textures, and so on. Such a combined drawing process is called 'drawcall'. Internally, this is first prepared by OMSI, then all the parameters are passed to the graphics card and finally the graphics card processes "independently" the drawcall with all its triangles.

This connection also explains why one drawcall with 100,000 vertices is processed considerably faster than 1000 Drawcalls with each 100 vertices.

Not too many o3d-files and not too many individual textures

Each o3d-file causes at least one drawcall per texture that uses the o3d-file. Each o3d file causes at least one Drawcall per texture that uses the o3d-file. In certain cases - and in particular at x-files - it may even be multiple drawcalls per texture and o3d file.

This results in the following rules:

Use a minimal number of o3d-files per bus.

Inevitable is a separation for animations and often for transparent things where the rendering order is set on the separation. There is no way out of that.

However, it is easily possible to put the vehicle together out of very few non-animated o3d files, e.g. (order = rendering order):

  1. Interior mesh including driver's workplace without indicator lights, switches, etc.
  2. Transparencies in the interior
  3. Exterior mesh
  4. window panes from the inside
  5. window panes from the outside

Within an o3d-file as little different textures as possible.

With the explanation above probably easy to understand: If my entire exterior mesh has only one texture, then it is only one drawcall. This is better than my exterior mesh using two textures, so that it must be rendered in two drawcalls. If a component is always getting animated anyway (typical example: wheels), then it is less tragic if the texture is separate. However, the LODs should also be considered: Since our cars do not have animated wheels at a greater distance, we have integrated their texture into the main texture, too.

Use of reduced display for distance and AI vehicles

By using LODs, a vehicle can be drawn simpler at greater distance. It should also be simplified when not in use by the user.

Every vehicle should have at least two LOD-levels, so it is simplified a lot below about 10% of the screen size.

The very simple LOD mesh of the SD77 for greater distance. Although rather simple, it is sufficient for greater distance and fairly economical. Only downside: Because of the repaint-possibilities the big 1024-texture for the exterior mesh must be loaded all the same, but apart from the reflexion texture that is all!

In this scale one can already do without the interior, the exterior should only be a very simple mesh anymore (20-50 vertecies). We also renounced on night textures and light effects in this distance entirely. One must only see that "there is a bus driving".

All vehicles should be greatly simplified for AI. (The same applies to "abandoned" user vehicles. All flags, such as the following, which relate to this nomenclature, classify abandoned user vehicles as AI vehicles.)

This purpose serves the viewpoint command. The number underneath can take following values:

  • 0 = always visible
  • 1 = only visible from outside on the current user vehicle
  • 2 = only visible from inside on the current user vehicle
  • 3 = 1 + 2, visible from inside and outside on the current user vehicle
  • 4 = only visible on AI vehicles
  • 5 = 4 + 1, visible on AI vehicles or only from outside on the current user vehicle
  • 6 = 2 + 4, visible on AI vehicles or only from inside on the current user vehicle
  • 7 = 1 + 2 + 4, always visible (same as 0)

Note: You only look at an AI vehicle from outside and usually not so accurately. However it can be close by and you often look into it from behind (at traffic lights or at a bus stop).

  • AI vehicles should therefore have the complete and detailed exterior mesh and rough things of the interior mesh like panelling, seats etc. Those things that you see from behind are particularly important.
  • AI vehicles do not need an animated cockpit (animated seat, steering wheel) and handrails can be greatly simplified. Theoretically this also goes for your own bus from outside but you do not need to be so saving here because your own bus is visible only once - AI vehicles on the other hand often in large numbers.
  • Drawcalls provide a high potential again: Typically with all optimization there will be more than one textur for the interior but only one for the exterior mesh. So it makes sense to save as many textures of the interior as possible. The static dashboard, the steering wheel, the remaining handrails etc. often use seperate textures and should be mapped on a small area of a still necessary texture in the AI-mesh, e.g. a simple dark-grey, slightly "roughened" surface. But be careful: This is only useful if one or more complete textures can be saved.

The AI model of the SD77 as an example

The AI interior mesh of the SD77 only needs the textures SD77_02.bmp, _03.bmp and _04.bmp. The textures of the driver seat, panel, thermometer and cashdesk are saved compared with the user interior:

Picture

Differences between AI and user mesh of the SD77. In the view from behind those slight differences can be spotted, which especially mesh simplifications with larger poly-reduction potential have: handrails, stop-request buttons, handles on the seats. Important details like seats, stringers or lamps must remain:

Picture

Do not use too many vertecies - textures can provide reasonable assistance

Once upon a time™, when we began to build models for Flight Simulator, we had to draw the mesh by hand on graph paper and measure out and convert the coordinates ourselves. Then we sat down in front of the punch-card punching machine and we had better not make a mistake... okay, enough of those antiquated tales of former times™! :-D (Although the beginning is correct, the design programs for Flight Simulator only really got going with the versions 2000/2002 with FSDS and Gmax...)

What you can learn from this story: Simply out of selfishness one was frugal with polys and vertices. You keep this attitude - while today we look at the freeware-NL202 and admire the 3D-lion and the 3D-letters - and are just as amazed that OMSI tolerates this...

Of course, the NL202 is a successful and naturally very popular OMSI addon. Nevertheless, I am being cheeky and put it next to our NG272 (WIP at that time):

Picture

What do you notice? The NL202 has much more polygons than the NG272. Of course, certain things can only be represented with appropriately detailed modelling, e.g. the oblique position of the air vents or the profile of the rubber bars of the windows. But when building a vehicle one must constantly wonder: Do I really need that? Is the effort and the higher polygon count worth it? Certainly it looks very nice but how often are you back at the engine compartment?

If you look at it from far away, a photo real texture is generally sufficient. Of course, in return our air vents do not shine so prettily in the sun! :)

Only put verticies in places where they make sense

Another example on vertex saving:

Picture

Of course, the pipe in the middle is the nicest! :) But it also has most polygons. Now, the question is - how exactly do you save polygons and how much optical loss does it take?

In this case, polys can either be saved longitudinally or circumferentially. What is better? If you would like to maintain about the same numbers of vertecies and faces, then the pipes look as shown. The left pipe is no longer broken in longitudinal direction, but the scope still has 32 ​​edges. The right pipe on the other hand has only 8 edges, but all seven breaks (also corresponds to 32 corners along the full circle!) could be maintained which is obviously the better solution since you only notice the cross-section where the profile ends (e.g. exhaust) or where it encounters a different-coloured surface respectively takes on a different coulour itself while you often look directly at the longitudinal direction, as you do in this example.

Handrails, which are often lively designed in today's buses, typically resemble this: There the swing should also be sufficiently round - in return the profile can be a bit edgier (octagon or even hexagon).

So in order to get back to the beginning: In 1995 the FlightShop-Jumbo for Flight Simulator 95 had an octagonal (!!!) fuselage profile! You schoul always consider this when constructing a handrail profile with 32 edges! :D

Textures

An important aspect has already been mentioned:

Few big textures are generally better than many small ones

... especially when they are applied together on one o3d file. Obviously there are limits: On one hand textures become a bit unhandy at a certain resolution. That is why we usually only go up to 1024x1024, although this limit is certainly not quite up to date.

Use regular resolutions!

Once every object builder for Flight Simulator knew what is no more common knowledge today: Textures should have pixel dimensions that follow the power-of-two row:

1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, (2048, 4096, ...)

The values ​​in parentheses are beyond what we usually use and frankly I do not know what restrictions there may be even today. But up to 1024 is no problem.

Rectangles are also ok, as long as the series above is maintained. Earlier in Flight Simulator, 256x256 was the ultimate standard for all textures, thus "old stagers" often use this measure today still. But 1024x128 is also ok, as is 512x512 or 4x128. You should only avoid crooked measures (200x300 or 256x77) because the processing tends to get worse. To what extent this is still the case on current graphics cards, I do not know - but in order to achieve compatibility to older graphics cards it cannot hurt to stick to the rule.

Such "crooked" cases are rounded to the next "allowed" measure, anyway. So you can round up by yourself right away and use the remaining areas sensible instead of letting them expire.

File formats

DirectX loads quite a lot formats. The traditional format is bitmap (*.bmp). Since this format is not compressed, some are inclined to use JPG.

Wether the loading time gets faster or slower, I cannot say and that certainly also depends on the look of the texture and a variety of other factors. But it should be clear to you that (as far as I know) it does not help to save graphics memory because JPEG-formats cannot be applied in the graphics memory.

So if you want to save graphics memory, you should rather take the DDS-format which offers a compression that - if I am correctly informed - also carries over to the graphics memory.

Sound

When it comes to sound you cannot do much wrong, actually. Basically OMSI is quite frugal there and designed so that vehicles can have maaaany sounds in order to make a whole lot of fun and normally slightly longer samples of 48kHz should be no issue.

However OMSI has for reasons of performance a sound counter and a sorting function which ensure that a certain maximum number of sounds is not exceeded. This affects not only currently audible sounds but also "theoretically audible" sounds, which must be constantly checked whether they need to be heard soon. So that no free "sound spaces" are unnecessarily wasted, there is the possibility that AI-vehicles (and abandoned user-vehicles) are equipped with a simpler sound set.

This is quite simple to realize:

1. First you create the normal sound.cfg as usual and finish it completely.

2. Now you copy and rename it, e.g. to sound_AI.cfg.

3. Now you delete all sound entries in this file that are unnecessary for vehicles which are not controlled by the user - these are:

  • starter and switch off sound
  • sound effects that are primarily audible from within, e.g. the air compressor or the rattling in stand in the SD
  • cockpit or similar system sounds like switches, warnings, IBIS, rollsigns, wipers, etc. pp.
  • But we have kept the sounds of engine and gearbox, which are audible from outside, and of retarder, doors, auxiliary heating and brake squeal as well.

4. Last but not least you have to add the following entry to the *.bus/*.ovh-file: [sound_ai] | sound\sound_AI.cfg, so that OMSI knows that there is an AI-soundset.

You will quickly find out how much you can save here and how many more vehicles will then still "sound" nearby as opposed to previously.

Script

Generally

Similar to the sound, it is possible to run a simplified script. How this is done is described in the article Scripting System.

However, in order to be able to take over a vehicle at all times, all normal variables are always keep ready. But this is usually not a major problem.

Apart from that OMSI is also frugal in terms of the script respectively there is no big optimization potential. In general one can give script developers this to take along: as little as possible as much as is necessary. You need not be stingy and you should not waste. When you can decide between two variants, you should try to take the one with better performance.

Incidentally, if repeatedly used script sequences are outsourced in a shared macro, you save loading time and memory. Probably only microscopically little, but all the same! ;-)

Special performance problems

However, what you should be aware of, are possible bottlenecks. The script itself is relatively uncritical. But system macros need occasionally some processing by OMSI, e.g. when some .hof-file is searched. So it makes sense to be sparing with system macros.

In addition, the variable Refresh Strings allows a specific updating of OMSI-fonts on the vehicle (or sceneryobject): This should only happen when something actually changed. On your own vehicle this is not so critical but AI-vehicles should only refresh their strings when something actually changes - e.g. the matrix display.