Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: Space station atmosphere simulator  (Read 13024 times)

moneyl

  • Bay Watcher
    • View Profile
Space station atmosphere simulator
« on: June 29, 2018, 11:35:51 pm »

Hey everyone, here to show you a project I've been working on. It's an atmosphere / gas flow simulator like what can be found in SS13. Currently it simulates the flow of gases on a grid. It supports custom gas types and mixtures through json definition files. It also simulates heat flow through gases and solids. Note: As of version 0.02 pressure flow is partially broken as a result of adding gas mixtures. The pressure flow had a direction bias in the first version but now in version 0.02 its more unstable. I aim to fix this and the direction bias of gas flow in the next version. Eventually I'd like to make this into a game, though I want to make a decent simulation first. I'm thinking some sort of space mining game or exploration game set in space.

The simulation is written in C++, using OpenGL for graphics, and Dear ImGui for the gui.


Above, a tile based view of a testing map. The more red overlay the greater the pressure.


In the above picture the red tiles have the highest pressures. This view is used as a tool to better see pressure differences.

Some additional pictures are in my Imgur Album.

0.02 Download (Windows 64bit)

If you'd like to see this on other systems let me know. Linux 64/32 bit and Windows 32bit should be doable. Mac is questionable as I don't own one.
Spoiler: How to use (click to show/hide)

Please let me know your thoughts. Any ideas, feedback, bug reports, etc, are appreciated.

Spoiler: Original Post (click to show/hide)
« Last Edit: November 16, 2018, 01:16:34 am by moneyl »
Logged

RadtheCad

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #1 on: September 19, 2018, 01:36:31 pm »

Cool project.  How are you going to implement the player character movement?  Free, float-based?  Or tied to the grid, like in SS13?

I could imagine a lot a cool stuff being done in a system like this, say particles being moved based on the air flow, for example.  You could even implement air-physics based puzzles, if you wanted.

Funnily enough, iterating on a tile array is probably already pretty efficient due to cache hits.  Well done/curse you for your premature optimisation!
Logged
You have to kill your son or nuke the commonwealth.

Caz

  • Bay Watcher
  • [PREFSTRING:comforting whirs]
    • View Profile
Re: Space station atmosphere simulator
« Reply #2 on: September 28, 2018, 06:39:12 pm »

Neeeeat. Make sure to implement "you mined into a high-pressure pocket and were immediately spaghettified"

 PTW
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #3 on: October 25, 2018, 09:55:07 pm »

Thanks for the interest! I was going to wait until I had more to show before replying, but I was taking too long. I spent the summer working on a different project and then this fall moved back into this one.

What I've been doing:
- Added heat flow to the simulation. It works fairly well, though I'm still trying to tweak it and figure out how true to real life it is. It's a game so I know it doesn't need to be perfect, but I'd still like to find a nice balance. Likely a few oddities I haven't noticed yet.
- Added mixtures and gas types. Still a few things to fix with this. For example: gas flow doesn't transfer individual gases and so no mixing occurs, just didn't get to that yet. Spent most of the time with this fixing the heat simulation as I broke it in the process.
- The point of mixtures are so that the player could have tanks of air or other gas mixtures that may be useful or common.
- Moved tile, gas, and mixture (ex: air) definitions into json files so people can edit their values.

Cool project.  How are you going to implement the player character movement?  Free, float-based?  Or tied to the grid, like in SS13?

I could imagine a lot a cool stuff being done in a system like this, say particles being moved based on the air flow, for example.  You could even implement air-physics based puzzles, if you wanted.

Funnily enough, iterating on a tile array is probably already pretty efficient due to cache hits.  Well done/curse you for your premature optimisation!

Currently I'm thinking it'll be free movement. I agree that it'd allow many more interesting things to happen. I think it'd be fun to see the everything blowing out into space or around a room in the case of a breach or an explosion. I luckily have some experience optimizing a similar system from a previous project when I made a procedural world generator. The tile code in this is just a modified version of what I had in that. I found that much of the optimization consisted of caching a value that would be used often, usually with minimal memory cost. I gotta figure a maximum map size though, currently testing on a 100x100 map and I manage to get 60-ish fps without issue. I also need to spend some time optimizing my graphics code. Still learning opengl.

Neeeeat. Make sure to implement "you mined into a high-pressure pocket and were immediately spaghettified"

 PTW

I'll be sure to. I think part of my reason for wanting these systems is because of unexpected things which could happen if the player isn't careful. Hopefully it'll cause some emergent behavior in the game once the sim has enough layers. I gotta stop screwing with the simulation at some point and actually make a game... I figure I'll clean up and tweak what I have now and then start with basic player movement and interaction. Before I move on to player movement I'll upload a newer version.

Here's an image of the heat overlay, doesn't really look very different from the pressure overlay due to coloring being the same. I just super-heated some tiles and let the sim run for a few minutes:
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #4 on: October 25, 2018, 10:05:07 pm »

Another version of the temperature overlay, gives an idea of the room geometry. In this image I heated up the walls in the bottom center and the heat flowed into the surrounding air. I heated the walls to ~25000K for dramatic effect. You can also see the air mix info on the mouse tooltip. Another thing to note, I set the walls initial temperature to 203K and the airs initial temp to 273K, so you can see a bit of a color change at the boundaries of walls and floor representing the temperature difference.


Fun bug I fixed that apparently is back in action. Went to add some nitrous oxide to the air and the pressure and temperatures jumped to ridiculous values and exploded across the map. Btw, should I stick my images into spoilers to save on data for people with slow connections? That'll stop them from loading until they click the spoilers, right?:
« Last Edit: October 25, 2018, 10:20:32 pm by moneyl »
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #5 on: October 29, 2018, 04:36:47 pm »

Small update. I'm currently starting work on porting this over to unity. Assuming I can squeeze enough performance out of it this will give me a lot of benefits in the long run by not taking weeks or months to learn how to add a new graphics effect or feature. The OpenGL portion of this alone took me several months as I learned it. While I learned a lot I think this will be much more productive in the long run. I'll start off by making a basic build only using C# and see what kind of performance I can get. If I want more I'll end up writing the intensive parts in c++ and connect it to unity as a native plugin. I'm also playing around with procedural maps, though they'll be basic as hell to begin with. Here's an example, just generated a heightmap with perlin noise and assigned different tiles to different elevation ranges:


It'll look much better, and be larger once I put some work into it.
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #6 on: October 30, 2018, 06:38:22 am »

Played around with the noise used in map generation this morning. I used LibNoise (C# port) to generate my heightmap below as it gives many options for noise generation. I used billow noise with turbulence applied and averaged it with ridged multifractal noise. Here's the result on a 1000x1000 map, much better than the perlin noise:


Here's what the heightmap looks like for this type of noise. Not the same seed as I forgot to take a picture of the heightmap for that one:


Average of billow and ridged noise. This time there's no turbulence on the billow noise:


A few more images in my imgur album for this: https://imgur.com/a/2W9xF0A
« Last Edit: October 30, 2018, 07:00:02 am by moneyl »
Logged

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: Space station atmosphere simulator
« Reply #7 on: October 31, 2018, 09:28:34 am »

This is pretty cool.  Out of curiosity, did you solve your issues with the gas flows being weird (in particular, with them being biased in the direction of the loop over the tiles)?  I ask because I tried to write a meteorological simulator once for a fantasy world using some similar ideas, and I ran into so many problems I eventually just stopped trying.  I was trying to generate weather patterns based on land masses and incident sunlight, but my attempts to connect temperature, pressure and so on either led to unstable simulations that exploded as pressure flowed wildly back and forth between cells or other issues like the pressure flowing in one direction more strongly than it should have.

A two step process like you mentioned might have helped, but I never tried it for performance reasons.  I think what I was trying to do was probably infeasible.
Logged
Through pain, I find wisdom.

Starver

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #8 on: October 31, 2018, 10:24:46 am »

(...)the pressure flowing in one direction more strongly than it should have.

A two step process like you mentioned might have helped, but I never tried it for performance reasons.  I think what I was trying to do was probably infeasible.
If I read you right, you did a 1-step iteration over the 'grid' (or however you organised nodes/quanta). That would have been your problem.

A line of pressures (1,10,1), for example using sample numbers, might be expected to settle out as (4,4,4). But if you do it in a single pass you may go towards (5,6,1) on assessing the left two then (5,4,3) on assessing the right two, assuming here that you go as far as possible towards equalising without over-equalising in that step*.

You really need a two-or-more step process, calculating instantaneous differentials in one step (1(<9)10(9>)1) then apportioning the excesses according to 'flow share'.

At its simplest. Because you might also take into account the derivative of the prior movement (the air in the central cell already has monentum towards the left, so' sloshes' more that way this turn, or doesn't if the left-cell has is actually the wavefront of the vanguard spill that came from the right and has already encountered our simulated 3-cell container's left wall and is itself bouncing back) but that's getting into the kind of fluid-dynamics that moneyl is doubtless working with at the moment, and I couldn't right now tell you how much complexity is needed in that or a more open meteorological simulator like your own. You could added coriolis effects, Hadley cells, etc, which would have generated stramgely paradoxical (yet realistic) prevailing wind systems, but I'm not sure you did do, or needed to for what you needed.

Or I'm telling you something you already know, and I'm misunderstanding the emergent behaviours you accepted and didn't accept from your evolving cellular system. But maybe it's not total codswallop, at least to some reader, so I'm saying it anyway. ;)


* - Doing it in increments, over several unit steps, (1,10,1) becomes (2,8,2) becomes (3,6,3) becomes (4,4,4), nicely, with those numbers, but falls down with less nice numbers. While an alternate methods that uses the more obvious method of proportionate flow go even further off-kilter before settling, in this small closed system. But in a larger array with more dimensions to it, it could easily generate artefact flows that defy visual explanation as neighbouring cells exacerbate the anomolies chaotically.
Logged

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: Space station atmosphere simulator
« Reply #9 on: October 31, 2018, 10:51:40 am »

Yeah, you're very likely right.  I don't want to derail this thread talking about my own project, but I was trying to do way too much I think.  It was initially a set of 2D grids, each with about 550K cells representing a 64x64km square of the planet's surface.  There were grids that stored surface temperature, air temperature, air pressure, humidity and wind velocity if I recall right.

On each update step, I did a lot of very likely erroneous calculations that tried to determine how much energy was added to the air and ground in a tile based on inbound solar radiation balanced with outbound blackbody radiation.  I'd do some calculations to conduct heat to or from the air and ground, then try to determine if the air pressure changed based on the temperature change.  Based on air pressure change, I'd calculate changes to wind velocity.  Then after that, I tried to move air between air cells.  Mixed into that mess somewhere was attempts to create cloud systems by evaporating water over the ocean and increasing air humidity, then moving that humidity along with the winds and raining it out over land as the air became super saturated.

Or, that was the plan anyway.  I quickly realized that I needed to model the atmosphere in 3 dimensions to get air flows and humidity -> cloud formation models accurate, and it was just computationally infeasible.  Not to mention the simulation instabilities I mentioned, which now that I think about it were probably also fed by a circular dependency between pressure and temperature.

Something much more abstract would have probably worked better and still given believable results.

But, in any case, if moneyl wants to describe how the air flows and temperature conduction is performed here, that would be interesting to read and could be helpful to others.
Logged
Through pain, I find wisdom.

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #10 on: November 02, 2018, 11:38:16 pm »

This is pretty cool.  Out of curiosity, did you solve your issues with the gas flows being weird (in particular, with them being biased in the direction of the loop over the tiles)?  I ask because I tried to write a meteorological simulator once for a fantasy world using some similar ideas, and I ran into so many problems I eventually just stopped trying.  I was trying to generate weather patterns based on land masses and incident sunlight, but my attempts to connect temperature, pressure and so on either led to unstable simulations that exploded as pressure flowed wildly back and forth between cells or other issues like the pressure flowing in one direction more strongly than it should have.

A two step process like you mentioned might have helped, but I never tried it for performance reasons.  I think what I was trying to do was probably infeasible.

No I haven't managed to solve that yet. Though, if your pressure flow is unstable it may be due to very small pressure differences between tiles. I set a minimum pressure difference between tiles for flow to occur, so that the sim isn't infinitely pushing tiny amounts of gas. Before I added mixtures in I attempted to move over to a two step process. The result was amusing, it looked very similar to a wave diffraction simulation for whatever reason. I failed to recreate the effect now to get a gif of it sadly. Anyways, I couldn't get it to behave correctly, so I tabled it for later as I wanted to move onto adding mixtures and heat flow to the sim. If the way I was doing the two step method worked it shouldn't have been any more performance intensive than before, though perhaps it wasn't a valid method.

It turns out that when I added mixtures I broke everything horribly. I didn't realize how much until I tested it out more. The pressure simulation still had a direction bias and was less stable, and heat flow had halted completely. Before I decided to move over to Unity(still debating the switch) I had the heat sim partially working again, and I was still fixing the pressure flow. I think that part of the reason I've been having so many issues with bugs is just bad code. For my tile and gas mix classes I had most of the member variables as public, and was accessing them directly. While I was cleaning up code I made many of the members private and made functions to access them, that way there is only one point of failure instead of me forgetting to set a variable or two on occasion. Below, I'll do my best to explain how my pressure and heat flow worked before adding mixtures, as it will be simpler to describe and everything was functioning at that point. These systems are still prototypes so any input is welcome. I'm no expert in this by any means.

I set up a tick system to allow the simulation speed to be changed on the fly. At each frame the delta time would be pushed to the atmos code, and if enough time had passed for a tick (I used 10ms as my default) then the pressure for the whole map would be updated. Keep in mind that the heat flow sim had this as well and I just locked it to the same rate as the pressure sim. The thought behind this was that the update rate could be lowered for slower computers if necessary.

The pressure simulation is really basic. It doesn't keep track of the momentum or velocity of the gas in each tile. The important values tracked for each tile are pressure, temperature, amount of gas (in moles), whether the tile is solid, and whether or not it's a "space" tile. Each update cycle the function UpdateAtmosphere() is called. It loops through the entire map and checks if each tile should flow gas to its surrounding tiles. If the tile is solid for example it won't flow, as it has no pressure. The effect of a tile being space is configurable depending on performance needs. I currently simulate space tiles, but it could ignore them if more speed was needed. If the tile is determined suitable for pressure flow then Flow(int Tile1, int Tile2) is called for the tile and all of it's surrounding tiles. With Tile1 being the index of the tile in question and Tile2 being the index of the tile which gas is being moved to. This is called once for each adjacent tile.

Here's the code for Flow(), simplified with the assumption that space tiles are being simulated:
Spoiler (click to show/hide)
Things worth noting are that flow does not occur if Tile2 is a solid, and the amount of flow to Tile2 is dependent on the amount of adjacent flowable tiles. A flowable tile is simply defined as a non solid tile. It also considers map borders, so a tile on the border of the map can only have 5 adjacent flowable tiles maximum. One issue I see now is that if there is only one adjacent flowable tile, then the entirety of the gas on Tile1 will be moved to Tile2. I should probably set up a minimum flow ratio variable to avoid this. A benefit of checking the number of adjacent flowable tiles is that a small hallways or gap should have a higher flowrate than a larger one. Another thing to note is that I made the minimum pressure zero throughout my code as it is absolute pressure not relative. I started with this manner for pressure flow as I couldn't find any equations to define the movement rates of gases in this scenario during the first pass of my research. Any suggestions on that are welcome.

The heat flow simulation worked in a similar manner. Each tick the sim would loop through every tile, and flow heat from it to all adjacent tiles. Below I'll derive the equation I use to calculate temperature change for each tile, from what I can tell it's fairly accurate, though some assumptions are made for the sake of performance / simplicity.

Our first equation, from the 1st law of thermodynamics, assuming the work done by the system is zero:
ΔQ = mcΔT = mc(T2 - T1)  [1] (c is the specific heat of the object (J / kg * K), m is the mass in kg, T is the temperature in kelvin)

Next, with T1,a and T1,b being the initial temperatures of tile a and tile b (1 and 2) respectively:
ΔQ = Δt * (T1,a - T1,b) / Rtotal  [2] (Δt is the change in time is seconds, T1,a and T1,b are the initial temperatures of tiles a and b respectively)

With Rtotal is the total thermal resistance of the system, in this case I'm assuming a system with conductive and convective resistance acting in series. Parallel might be a better way to do this but I made the assumption of series for now to keep it simple. If you'd like some more info on thermal resistance this guide is pretty good: https://neutrium.net/heat_transfer/thermal-resistance/ Note:

Rconduction = L / kA  [3] (L = conduction length (m), k = thermal conductivity (W / m * K), A = conduction area (m^2))
Rconvection = 1 / hA  [4] (h = heat transfer coefficient (W / m^2 * K), A = convection area (m^2))

Rtotal = Rconduction + Rconvection  [5] (Assuming series thermal resistance. Rconvection is zero if neither tile has gas present)

Note that I am assuming a constant value for heat transfer coefficient for each gas. IIRC heat transfer coefficient is highly variable dependent on the gas type, pressure, and temperature. So this is a bad way to do it. I will have to look back as my thermodynamics class notes and read up a bit on approximating the value. If worst comes to worst I could toss one of the charts into excel and try to form an equation for the value with regression, then just have the json files for each gas take a regular expression for the heat transfer coefficient value. We'll see though, a constant value could work well enough for our purposes. Anyways, the final equation is formed by setting (1) equal to (2) and solving for T2,a, like so:

ΔQ = maca(T2,a - T1,a) = t * (T1,a - T1,b) / Rtotal

By solving for T2,a you get our final equation:

T2,a = [t * (T1,a - T1,b) / (macaRtotal)] + T1,a  [6]

From here you can easily calculate the change in energy of the system and the final temperature of tile b using equation 1. That's quite the info dump and there are likely a few errors I missed. I wrote it in two sessions so there might be conflicting info between the pressure and heat portions of the post. An update on the project. I've been working with Unity more, playing around with character movement and map gen, and getting a handle on the system. Honestly still debating the switch as there are merits to sticking with c++. I'll make a final decision at some point. Let me know what you think or if you have more questions / see some mistakes.

Edit: I ignored radiative resistance and heat transfer for now for performance reasons. I might add it later for certain situations, such as if you wanted to cool your gases by sticking a radiator out into space filled with them or perhaps having heat radiate from hot objects in space in certain instances. Perhaps could result in a dumped nuclear core being dangerous at range even in vacuum or other fun ideas.
« Last Edit: November 04, 2018, 01:02:48 pm by moneyl »
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #11 on: November 04, 2018, 09:12:08 pm »

Small update, I implemented a basic version of the pressure sim in unity which is near equivalent code-wise to an old copy of the c++ version. I took the average of the time spent in the atmos loop over 5000 samples. Here are the results:

C#/Unity version avg atmos loop time: 1.005 ms
C++ version avg atmos loop time: 0.399 ms

Of course this may not be the best comparison, however, it also isn't very surprising. After using unity for a while and along with other considerations I've decided to stick with c++. Partly being that I enjoy using c++ more, even with possible bugs. I also like the theoretical better performance and the fine control. Next I'll be working on fixing bugs and cleaning up my code a bit.
Logged

Starver

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #12 on: November 04, 2018, 09:57:42 pm »

Being basically a wrapping framework, I suppose Unity could have had some clever in-built mechanisms optimise the rawer code but what you found doesn't surprise me. It has other strengths, I think, but I don't know if they're as useful to you as they could be if you already have a way of handling your other needs.
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #13 on: November 05, 2018, 12:21:41 am »

I think there some things that Unity would be useful for, like the editor, and continued updates. It should also be easier to port to other platforms on unity. If I wanted to get performance closer to c++ I could make a c++ plugin and write most of my performance intensive code with that. From what I can tell, the game Oxygen Not Included does that. People have also mentioned using "unsafe" C# code, which I think refers to code which bypasses memory safety for speed increases. I played around with plugins a bit by making a function that just calls random() from a c++ plugin. For the benchmark I should've made a plugin for the atmos and tilemap code and tested the performance on that too, just didn't think to do so. I just don't want to sink all my time into getting good performance with C# and working around unity's weaknesses and then still find it lacking. Both sides have trade-offs, though sticking with c++ is more useful for me currently.
Logged

moneyl

  • Bay Watcher
    • View Profile
Re: Space station atmosphere simulator
« Reply #14 on: November 10, 2018, 04:02:40 am »

I tracked down a few more sources of bugs and tried getting the "two step" system for pressure flow to work. Again, with the idea behind that system being that it would remove the direction bias on gas flow that currently exists in the sim. It does remove the direction bias (though not in the gifs below, different math), but results in very chaotic changes in pressure each tick. I can play with the math a bit and get it to be stable, but then the gas hardly moves, and breaches have next to no effect. I tried changing some of the math on how much gas should be transferred between tiles each tick, and got the bizarre results below.



This next one is the same thing, just with gas flow restricted to cardinal directions as I wanted to see what effect that would have.


I'm going to do more research into fluid flow simulation and try out a few other ideas I have. I don't mind the simulation being inaccurate in some ways since it's for a game, but the problem of gas flow being biased to certain directions is something I won't accept. Luckily there a quite a few resources online about fluid simulation, so I'll have some reading to do.
Logged
Pages: [1] 2