Besiege

Besiege

Not enough ratings
Solving dissymmetry and related instabilities caused by floating point imprecisions
By Narzu
This guide is addressing dissymmetry and related instabilities in besiege and solves them by editing.bsg files using regular expressions in notepad++. If you already wonder why symetrical things actually don't behave like you think they should, or why rotating things brings annoying oscillations you should continue to read!
   
Award
Favorite
Favorited
Unfavorite
Dissymmetry & related instabilities : where do they come from ?
That is a good question, I couldn't answer accurately but here is a start : it can come either from the game engine and how it calculates things, or from the data of your machines and how it is stored in the files.

We will only talk about the data because It's easier than looking into the game engine : the data is in the .bsg files located in you besiege/savedmachines directory!

If you open those files with a text editor (eg: notepad++) you can find the data of the machine, including the data of all the blocks you've placed, their positions, their rotations, their size, their attributes, everything is organized in XML format.



If you look closer you will see something weird : some numbers are not rounded anymore. Like a 0.5 displayed in the game could actually be a 0.4999982 in the real data. Some people say that it comes from floating point imprecisions, I don't know much about it so I won't explain that but here are few things I observed about those imprecisions :
  • They tend to appear when you load or save a machine (if you load a perfectly cleaned file and save it instantly, imprecisions would have already appeared. Since even perfectly cleaned files are not 100% behaving like symmetrical / stable I guess imprecisions appear while the file is loaded
  • They also tend to appear when you change something on a block, if you move it, rotate it or change any attribute, the xml tag will be full rewriten and imprecisions will appear.

Personally I believe that it might also has to do with the fact that imprecisions are part of the reality and that nothing it perfectly symmetrical or stable in reality, meaning either Devs decided to make them intentionally happen in the game engine, or they just discovered it and thought "okay fine, that's even closer from reality". I would have done the same.

But we'll probably never know that for sure.
Imprecisions : how to spot them ?
So now that you know about imprecisions, what does they look like ? here is a bunch of example :
  • 0.4999981
  • -1.000003
  • 0.4499993
  • 2.842171E-14
  • 0.3484899

It's easy to target weird numbers and know what they should be when you're doing simple design. If you make complex design it's more complicated but here some tracks :
  • If you use sliders you will generate weird numbers that are complex to analyse and correct (I would recommend to never use sliders)
  • if you input directly from the keyboard, you can only use 2 figures after the dot of a decimal number (meaning, if you want to use exact numbers, everything after the 2 figures that are after the dot could be considered as imprecision)
  • Only 7 significant figures are stored in a number
  • When an number with exponent appears, it means that the original number is actually so small that you can consider it was 0 (0.01 is the smallest you are supposed to use if you do not use sliders and does not make a number with exponent appear)
  • Complex to analyse imprecisions mostly doesn't have a lot of occurrences, if so, it might be a special number intentionally generated (rotations for example, see below).



I didn't talk about those quaternions : this is the way besiege store data about rotations. The numbers generated are complex to analyse because they are not intuitively translatable into angles. For exemple if you rotate something by 90° it will generate the value 0.7071068, when you use specific rotations amounts, you will get numbers like this one and it's not easy sometime to know if it's normal or imprecision.

You can't decide neither to round those rotation numbers because the 4 values of a quaternion are strongly related to each other, meaning if you are not sure of what you are doing, any operation on the number will probably change the angle in the game.

0.7071068 is a well know number and will appear very often in your .bsg files. since 7 significant number is a lot, you can presume that it's nearly impossible that an imprecision from another number turn it into 0.7071068 so you can consider that everything that is around are imprecisions about this specific number.

So you will want to change 0.7071069, 0.7071071, or 0.7071058 to 0.7071068 because you are 99,99% sure about what is the imprecision and what is the original number.
RegEx : How to efficiently correct the imprecisions
You could just look at you numbers and correct one by one if you have only few blocks but this will quickly get boring. So you will start using a replacement functionality. But still, a lot of imprecisions are different but have the same pattern. What you truly need is to replace patterns, and the only way to do that (in my mind) is to use regular expressions, and you have at the bottom of the 'find' window in notepad++, just tick the radio button and you are set.

For example if you search: (["|>]-?[0-9]*[.][0-9]{2})([0-9]+)(["|<])

It means: I want all the pieces of text that begin with " or >, followed by a - or not, then by as much as figures you want, then by a dot,then by 2 figures, then by at least one but as many figures you want, and finally by " or <

What is interesting here is that it will return you all the number that have more than 2 figures after the dot : meaning ALL the POTENTIAL imprecisions. I said potentiel because this will also bring number that are not necessarily imprecisions.

If you don't know about RegEx you can learn it on wikipedia or any website about RegEx (there are a lot) and practice on a RegEx test site (where you can type text & expression to see how it works)


Replacement functionality : with RegEx you can make groups using parenthesis. This allow you to then re-use the data in the replacement field using $1 to input the data in the 1st group for example. This is very powerful.

Few RegEx that I use all the time, and their replacements, you can fine tune them depending on what you get in your file:



To search and anayse for potential imprecisions :
RegEx: (["|>]-?[0-9]*[.][0-9]{2})([0-9]+)(["|<])

To get all the numbers that have 2 figures after the dot and followed by some zeros and then by other numbers (but should only keeps 2 figures after the dot). Make a quick analyse at what you get in case it gather few bizarre rotation numbers that might not be imprecisions. Start with 3 zeros in between and then you can broader the search with fewer zeros, you should get more imprecisions but also more rotation numbers that are not imprecisions, so it's better to do it step by step an analyse :
RegEx: (["|>]-?[0-9]+[.][0-9]{2})(000[0-9]*)(["|<]) Replacement: $1$3
RegEx: (["|>]-?[0-9]+[.][0-9]{2})(00[0-9]*)(["|<]) Replacement: $1$3
RegEx: (["|>]-?[0-9]+[.][0-9]{2})(0[0-9]*)(["|<]) Replacement: $1$3

To get rid of all the numbers with exponents and replace them with 0 :
RegEx: (["|>])(-?[0-9]+[.][0-9]+E-[0-9]+)(["|<]) Replacement: $1(0)$3

To get rid of all the imprecisions around 0.7071068 which is a frequent rotation number that appear when you have 90° angles :
RegEx: ("-?0.70710)([0-9][0-9]?)(["|<]) Replacement: $1(68)$3

To search for the numbers that have 2 figures finishing by 9 after the dot (they have negative imprecision by contrast with numbers followed by zeros, the correction is different).
RegEx: (["|>]-?[0-9]+[.])([0-8]9)([0-9]+)(["|<])

To get rid of the imprecisions found with the last RegEx, for each different figure before the 9 there is a different replacement, just correct those you have spotted :
RegEx: (["|>]-?[0-9]+[.])(09)([0-9]+)(["|<]) Replacement: $1(10)$4
RegEx: (["|>]-?[0-9]+[.])(19)([0-9]+)(["|<]) Replacement: $1(20)$4
RegEx: (["|>]-?[0-9]+[.])(29)([0-9]+)(["|<]) Replacement: $1(30)$4
RegEx: (["|>]-?[0-9]+[.])(39)([0-9]+)(["|<]) Replacement: $1(40)$4
RegEx: (["|>]-?[0-9]+[.])(49)([0-9]+)(["|<]) Replacement: $1(50)$4
RegEx: (["|>]-?[0-9]+[.])(59)([0-9]+)(["|<]) Replacement: $1(60)$4
RegEx: (["|>]-?[0-9]+[.])(69)([0-9]+)(["|<]) Replacement: $1(70)$4
RegEx: (["|>]-?[0-9]+[.])(79)([0-9]+)(["|<]) Replacement: $1(80)$4
RegEx: (["|>]-?[0-9]+[.])(89)([0-9]+)(["|<]) Replacement: $1(90)$4

Same thing but for the numbers where the 2 figures after the dot are 99 (the correction is also different so they have to be taken care separately).
RegEx: (["|>]-?[0-9]*)([0-8][.]99)([0-9]+)(["|<])

To get rid of the imprecisions found with the last RegEx, for each different figure before the dot there is a different replacement, just correct those you have spotted :
RegEx: (["|>]-?[0-9]*)(0[.]99)([0-9]+)(["|<]) Replacement: $1(1.00)$4
RegEx: (["|>]-?[0-9]*)(1[.]99)([0-9]+)(["|<]) Replacement: $1(2.00)$4
RegEx: (["|>]-?[0-9]*)(2[.]99)([0-9]+)(["|<]) Replacement: $1(3.00)$4
RegEx: (["|>]-?[0-9]*)(3[.]99)([0-9]+)(["|<]) Replacement: $1(4.00)$4
RegEx: (["|>]-?[0-9]*)(4[.]99)([0-9]+)(["|<]) Replacement: $1(5.00)$4
RegEx: (["|>]-?[0-9]*)(5[.]99)([0-9]+)(["|<]) Replacement: $1(6.00)$4
RegEx: (["|>]-?[0-9]*)(6[.]99)([0-9]+)(["|<]) Replacement: $1(7.00)$4
RegEx: (["|>]-?[0-9]*)(7[.]99)([0-9]+)(["|<]) Replacement: $1(8.00)$4
RegEx: (["|>]-?[0-9]*)(8[.]99)([0-9]+)(["|<]) Replacement: $1(9.00)$4

Now I wish you good luck because this is not an easy guide and this is quite technical, but if you get used to RegEx you will then be able to make your own queries. English is not my mother tongue so I hope this is not too bad written and that it will help you to achieve better stability on your machines.

Also leave a comment if you have ideas to improve the guide (better RegEx, script to automatize the thing), anything I didn't thought about.. thank you.
13 Comments
beep 11 Jul @ 1:55am 
@Yamato
The machine file format has changed over the years, it probably edits something incorrectly and causes the file to fail to load.
Yamato 1 Mar, 2024 @ 12:39am 
I know its an old guide, but when I tried copy pasting all the regex and replacements then load my edited machine in besiege, I end up with just the source cube (as if my entire machine has been deleted). What did I do wrong?
Narzu  [author] 16 Sep, 2018 @ 11:05am 
Hello guys, thanks! Yes I had a lot of fun doing it, and happy to see that it helps!
The funny story is I actually got the idea from stuff I used to automate at work, when I was already working with regEx replacements on large xml files.
Grey Wolf Jack 9 Aug, 2018 @ 3:46am 
Although fascinating, you just removed the challenge! (For me)

But I'm sure you had loads of fun figuring this out and you've helped lots of people. Good job! Very well done.
Small Giant 8 Aug, 2018 @ 10:45pm 
this just proves besiege is way to woke for me
V 16 Jan, 2018 @ 10:34am 
My eyes just fell out!
JCUDOS 17 Mar, 2017 @ 5:53am 
Finally a solution to THE most annoying thing in Besiege (at least to me). I'll have to get a good night of sleep before reading it though. Anyway, thank you!
Narzu  [author] 23 Sep, 2016 @ 6:58am 
Haha, I know that's a very bizarre title
Bongin' 22 Sep, 2016 @ 2:51pm 
lol
Confession of Lazarus ムカデ 19 Sep, 2016 @ 9:01pm 
never thought i would see a steam guide named something as amazing as "Solving dissymmetry and related instabilities caused by floating point imprecisions"