leezer3 / OpenBVE

OpenBVE- A free train simulator
http://www.openbve-project.net
272 stars 52 forks source link

[Suggestion] Cycle option for rail types #81

Closed marcriera closed 8 years ago

marcriera commented 8 years ago

After using BVE and OpenBVE for a long time and developing routes, I have always wondered why the .Cycle option is limited to .Ground objects. It is a good option to avoid repeating the same grass texture each block, but extending it to .Rail objects would basically add the possibility of ignoring the legacy block sytem while retaining compatibility with existing addons. Let me explain the concept.

The legacy BVE block system limits the placement of track-dependant objects to positions that must be a multiple of 25. OpenBVE took a major step forward by allowing the user to choose a custom block length; short blocks can be used to achieve accurate track geometry in a similar way to what BVE5 does. However, a smaller repeating distance means that rails and track-dependant objects (walls, dikes, etc.) must be shorter, so long and realistic textures are impossible. Also, if the user wants to place an object every 20 metres with a block length of 5 metres, for example, the only solution is to type hundreds of lines of .FreeObj commands or to use the .Pole command (which has its own limitations).

Enabling the option to cycle through rail objects not only would make development easier and faster, but better results could be achieved. For example, let's say an addon developer wants to repeat a long track ballast texture every 25 metres while using 5-metre blocks. With a .Cycle option, the developer could split a 25-metre rail object into five 5-metre objects, each with one part of the texture, and make OpenBVE cycle through them to get the same result. Needless to say, it would be extremely simple to create a curve with these textures without the need to create a specific curved object.

However, the possibilities could expand even more if we defined the length and the span of the cycle. This would produce interesting results in curved tracks. 'Length' refers to the actual object length, and 'span' to the repetition distance. If a cycle had a 'span' of 100, each new object would be placed 100 metres after the previous one (think of the current .Pole command). 'Length' would be used to apply rotation to the object so that its end is correctly centered on the track position where the next object of the cycle is placed (the same rotation already used to connect blocks in curves but expanded beyond the current block length). This new option would be on par with the .Repeater command used in BVE5. Of course, we all know 'rails' in BVE are used for more things than just tracks (overhead wires, trees, etc).

The current CSV route format has a specific namespace for .Cycle structures that already handles ground cycles, but it is only used for Cycle.Ground. 'Cycle.Rail' could be easily defined without breaking compatibility with existing addons. A simple cycle option without 'length' or 'span' would be pretty much straightforward, but the two additional option would not be too difficult to add either (it is just some additional calculations). A rail cycle definition could look like this:

Cycle.Rail(0;length;span) 0;1;2,

Sorry if the explanation is a bit confusing, the concept is a bit complicated without real examples. Maybe some pictures could make it clearer? I will keep digging in the code to see how far can be OpenBVE pushed to its 'block' limits.

Regards,

leezer3 commented 8 years ago

Interesting thoughts.

A basic kludge along these lines wouldn't be too difficult to build, but the current block structure as relative to Rail0 would probably limit the potential applications considerably.

How the parser works:

  1. The routefile is read line by line.
  2. If a line starts with a track position, this is validated, and converted into a block number. (If using 'standard 25m blocks, this is just divided by 25 and cast to an integer)
  3. Our object is then placed within the block, and has various fields, including the track position (double)

We should therefore just be able to simply clone this object into new blocks, adjusting the track position as appropriate.

What you've got to remember is that all track related fields have known values within a block, so the sim engine can always adjust the position accordingly. Introducing variable length blocks is another whole kettle of fish.

(It's a little more complex than this, and the whole function in question is completely oversize and in need of re-writing, but that's the basic idea)

The length parameter might be a little more problematical; I'd have to have a proper dig into where the relative points used for rotation are generated.

leezer3 commented 8 years ago

A further thought- I think one of the essential missing pieces in order to make this work, is the ability to add a Z-parameter to an object placed at a specified track position within a block:

offset

It also needs us to decouple the concept of a curve from that of Rail0 , as otherwise our repeated objects may end up with some very funky positioning.

I think that the ability to add a custom curve to secondary rails is essentially achievable, but it'll need careful thought, as doing this will cause issues with object creation and disposal within the renderer if these aren't taken account of.

marcriera commented 8 years ago

All these 'problems' made me think of an alternative implementation of this, directly related to a future route format.

First of all, I have modified the route parser in both OpenBVE and RouteViewer to support rail cycles. They are defined exactly the same as Cycle.Ground (but Cycle.Rail instead). If the Railtype structure index of a rail matches that of a defined cycle, the cycle will be used. If it is not, a normal rail object will be loaded as usual. No fancy 'length' or 'span' options (will explain why later), just basic yet useful functionality. #82

Secondly, while adding this new option I have learnt a lot about how OpenBVE processes route data. As far as I know, if someone wanted to, it should be possible to write a parser for a route format without blocks. The program creates a world around a vector (track 0) that goes straight or curves, but is continuous. Because BVE was based on 25m blocks, the route parser is based on blocks too (which are placed on this vector), but the core program has no idea about blocks. Think of it as placing a FreeObj; it will be part of a block, yes, but you are placing it directly on the vector, on a desired track position.

A proper 'Repeater' command (which essentially was the goal of Cycle.Rail) should behave as a FreeObj (or more like an array of FreeObj), in the meaning that we should have the ability to place it directly without blocks. Of course, a customisable repeater command with 'length' and 'span' options would make the traditional 'Dike', 'Wall' or 'Form' commands (just to name some) unnecessary, and this would definitely make the new route format block-free. The user would be developing a route by editing this vector directly, and a 'block' would only refer to the actual 3D objects that repeat over and over by this 'Repeater'.

So this is why I think repeated objects with 'length' and 'span' are very difficult to add to the legacy CSV/RW formats, and why we should probably forget about them until we begin developing a new route format (potentially block-free). This way we would be able to add very interesting features to OpenBVE while keeping compatibility with legacy content.

leezer3 commented 8 years ago

The relationship to blocks is rather complex, but I think essentially, you're right.

As I understand it, the track's path is generated, and then the world position of each object is generated, and placed by the renderer as necessary. I can't think of a way off the top of my head to generate a world in a linear fashion without using blocks in some fashion, so I don't know that it's so much a BVE thing, as the fact that the world was originally designed to be linear, rather than completely 3D. The block concept is also used in simpler by the main engine for object disposal (Try creating a route with extreme curves and setting a ~100m viewing distance), so I suspect that without some major work in the renderer it'll be difficult to drop entirely.

I'm sure I've noted this before, but I'm very reluctant to make major backwards incompatible changes to the current file formats. They were never designed to do much of what Michelle started, and adding even more complexity isn't necessarily a good idea. The BVE5 file formats have some advantages in regards to allowing repeaters etc. , but they've still got a lot of problems IMHO. Supporting them would give us a few more options.

Note: I've made a decent start on a BVE5 format parser. bve5

Nowhere near complete at the minute, but simple BVE2/4 routes which have been run through Mackoy's convertor generally load and look OK-ish....

With all of that in mind, What we really need is a way to place objects in terms of world co-ordinates, rather than vector co-ordinates in any new format. Having said that, the linear format is really good for ease of coding, so if we were to drop it, I suspect that you'd probably require a GUI editor?

marcriera commented 8 years ago

I agree that such a change must take place with a new route format, not by making backwards-incompatible changes to current formats. One of the advantages of OpenBVE (and in fact its original purpose) is that it provides compatibility with legacy content from BVE2/4. That is why small tweaks to the existing formats are always welcome, but major changes such as my intended repeater option have a better place in a new format. Of course, OpenBVE allows multiple parsers for different types of files, so we can make it compatible with both legacy and new formats.

As you say, the linear format is indeed very good when it comes to manual coding (and it makes sense in a railway context, as you are driving a vehicle on a fixed path), but an open-world format would give users more flexibility. I like the linear format too much, but I would immediately switch to an open-world format if a powerful GUI editor was available. Yes, text coding an open-world format would be possible, but for most users it would mean trouble (and potentially choosing not to develop for OpenBVE).

When I imagine a GUI editor for OpenBVE, I always think of the old RouteBuilder for BVE. Yes, it was a program with a lot of bugs that made development even more difficult, but it is the type of program I would be using for an open-world format. There is no need to build a new program in full 3D (as most commercial software do); a top-view grid would be easier to use (it would look as if you were building a model railroad). Then, if it was linked in some way to RouteViewer and ObjectViewer, the user would see how everything being built would look in-game. It also sounds like the kind of program that could be easily built with Mono (so that it is multiplatform).

Having said all this, I know it is a bit off-topic, but I will be happy to help you with the BVE5 parser (which I suppose is not just a proof of concept). I have not used BVE5 as much as OpenBVE, but I can understand Japanese to a certain extent and it could be useful for the part of the documentation that has not been translated to English.

leezer3 commented 8 years ago

A 3D grid would be essentially what I'd be thinking of too. Doesn't actually need much, and I suspect a lot of the work is actually already done for us (The route preview function can be used to create a 2D map at any size we choose, and positions on this can relatively easily be converted into world co-ordinates)

If we're thinking along the lines of changing world formats, a top-down editor is probably actually a lot easier. Most of RouteBuilder's problems stemmed from the fact that it had to generate the linear file format from a 3D world base, and it really wasn't happy doing so when things such as really complex pointwork were involved. (It's exactly the same problem as building by hand- A point is never going to be exactly a block in length for both splines)

Whilst I know this is wandering even further O/T, my instinct for a 3D world editor would actually be procedurally generated track. This solves practically all the block length problems, although it doesn't really handle 'odd' types of track, and pointwork could potentially be a problem....

BVE5- What I've got at the minute is very much based upon Michelle's original parser, just adapted to the BVE5 syntax, although I'm also using it as a testbed for the cleanup I'm intending to do in the original parser.

The current list of what's working reasonably well:

Partially working:

Not implemented, planned:

In essence, most stuff converted from legacy files will work OK at the end of this. Secondary tracks haven't been implemented at the minute, so repeaters and structures attached to them don't really work.

leezer3 commented 8 years ago

Tracking issue opened for the BVE5 parser here & the current code branch uploaded: https://github.com/leezer3/OpenBVE/issues/83