Friday, September 30, 2016

Airship art

I was perusing DeviantArt and came across some interesting airship art.  One artist in particular, The-Necromancer, has an entire gallery (7 pages worth) of airship art.  Some I like, some I don't.  Some are realistic, some artsy, and some I do not like.  Despite the Communist iconography of the artist's avatar and a few of his other galleries, I found some of the airship art quite compelling.  Its worth taking a look if you're into airships.

Another artist, JanBoruta, has a Steampunk gallery with number of pencil sketches of airships, aircraft, steam-powered armored vehicles, etc.

A third, donaguirre, has a number of fascinating airship drawings, but they're not particularly organized. There's just a ten page unorganized gallery of all of his art.  My favorite may will be his movie poster for the classic movie version of Lazarus Long's Airship Troopers, staring Roald Regan.  :)

The Dawn Patrol

This Saturday and Sunday, October 1-2, 2016, there is going to be a World War I event at the National Museum of the US Air Force in Dayton, Ohio.  Since the Ruritania story I'm working on takes place in the aftermath of (an alternate) World War I, this has me very excited, and I'm hoping to make it up there one of those days.

From the museum's website "The World War I Dawn Patrol Rendezvous features vintage original and reproduction WWI aircraft, radio-controlled models, era automobiles, period re-enactors, educational activities and a collector's show. This flying event is offered by the museum and the Great War Aeroplanes Association. FREE admission and parking."  They're also going to have food trucks!

Thursday, September 29, 2016

Some interesting series of blog posts on procedural content

I've mentioned some other procedural content blogs and web sites in previous posts, but I realized last night that I never mentioned the wonderful works of Shamus Young.  He has at least five series of blog posts that cover various procedural content projects.  There's source code available (C++ / OpenGL) for at least some of them, but the blog posts are more about process, technique, algorithms, and experiment results than about the code itself.

Maybe once I've gotten the world building tools a bit more refined I might try one of his approaches and try to visualize a world closer up than the previous planetary examples I've posted.  In any event, below are links to the first blog post in each of the five series I wished to draw attention to.

Terrain Engine


Procedural City


Frontier Rebooted

Shapely land masses

The initial continent shape shown in yesterday's post was simply a circle.  This evening I enhanced code to generate a very irregular polygons that make a decent stand-in for an island or continent.  The irregularity is formed by creating a basic polygon, then applying several iterations of two-dimensional midpoint displacement to the line segments.  The two shapes in the images below started as four-sided convex polygons.

An island or continent.

Another island or continent

The code for the midpoint displacement is fairly simple, and is shown below.  The images were originally generated at a resolution of 1024 x 512.  Six iterations of midpoint displacement were applied, with an initial maxDisplacement value of 70; by the sixth iteration this would have been reduced to a maxDisplacement of only 2 pixels.

/// <summary>
/// Performs midpoint displacement upon each line segment that
/// makes up the polyon.  When multiple iterations are requested,
/// maxDisplacement is halved at each iteration.
/// </summary>
/// <param name="iterations">number of iterations of midpoint displacement to apply</param>
/// <param name="maxDisplacement">number of pixels a midpoint may be displaced by</param>
/// <param name="rand">optional pseudo-random number generator (PRNG) instance to use;
/// supplying an instance of a PRNG can be used as part of a strategy to
/// allow deterministic results based upon the seed used</param>

public void MidpointDisplace(int iterations,
    int maxDisplacement = 10, Random rand = null)
    if (rand == null) rand = new Random();
    for (int i = 0; i < iterations; i++)
        int numPoints = Vertices.Count;
        int k = numPoints - 1;
        int j = 0;
        while (j < Vertices.Count)
            Point p1 = Vertices[j];
            Point p2 = Vertices[k];
            int mx = (p1.X + p2.X) / 2;
            int my = (p1.Y + p2.Y) / 2;
            mx += rand.Next(0, 2 * maxDisplacement) - maxDisplacement;
            my += rand.Next(0, 2 * maxDisplacement) - maxDisplacement;
            Vertices.Insert(j, new Point { X = mx, Y = my });
            k = j + 1;                  
            j += 2;
        maxDisplacement /= 2;
        if (maxDisplacement < 1) break;

I still have more work to do to implement the "step 3" from yesterday's post.  As it is, the easternmost and westernmost continents are shifted, but any others are left where they are.  They should also move, either colliding with the other plates or moving into clear space.  That should then be sufficient to use as input for an Experilous-style planet generator to generate a more desirable set of initial land masses.

The red continent reminds me of the southern portion of South America.

Colorful continents

I took a break from finishing the Planets program up to play a bit with a terrestrial land mass generation approach very loosely inspired by plate tectonics.  There are more complicated, simulation-driven approaches that more accurately simulate this type of of thing, but they can take minutes to hours to run.  There's a faster approach that works quickly enough, but has what seems to me less believable continent shapes, and another slow one that often ends up with even poorer results.

Here's the approach I'm going to try.  I only got through step 3 today.

  1. Generate an initial land mass.  In the example photo below, the initial land mass was simply a circle.  More interesting results could be obtained using something like the polygon map generator I've mentioned before, and I'll probably go there in the future.
  2. Assign land to plates via a probablistic growth algorithm, but just covering the land mass, not the wider world.  All these plates will be considered continental, not oceanic, plates.
  3. Shift the eastmost and westmost plates to east and west.
  4. Shift the remaining plates either to random unoccupied parts of the map, or collide them with the already-shifted plates. (Yes, so far this is rather more like the original continental drift theory than plate tectonics.)
  5. Break the unoccupied space on the map (i.e. the oceans) into plates, which will be considered oceanic.
  6. Generate a list of all plates vs. all other plates, with an additional floating point number in the range -1..1 being probablistically generated for each combination.  This represents the force of collision or spreading between the two plates.
  7. In the vicinity of plate borders, use the number from above to determine if we're creating a rift or mountains, and the degree of depth or height involved.
  8. The results from 7 could then be used to directly generate a basic elevation map, possible with some fractal component added in for additional noise.  Alternately, the height/depth values of each cell and the adjacent cells could be used to control a mixture of noise from different distributions of noise. So if it hills in half the adjacent cells and mountains in this cell and mountains in the other half of the adjacent cells, we'd consider it 2/3 mountains and 1/3 hills, and mix noise from hill distribution and a mountain distribution.  Which sounds very confusing, so I will consider a fuller explanation if I wander down that path later.

A round central land mass was split into three "continents" of which two were shifted.  This is the result of steps 1-3.

I can skip steps 3-4 to generate a supercontinent like Pangea.  I can use fractals if I simply want a whole bunch of small islands, or if I want mostly land with small bodies of water interspersed, like that world from Star Wars 7. Alternately, I could use the results up through step 4 as the input for that fast planet generation approach mentioned earlier.  We'll see when I get a chance to experiment some more.

Wednesday, September 28, 2016

Book Review: Forcing The Spring

I recently purchased and read Forcing The Spring by Alma T. C. Boykin.  It is book 9 in her Colplatschki Chronicles series (although book 8 has not yet been released).  Colplatschki, the titular world of the series, had been colonized by humans, abandoned by the colonial sponsors, and then struck by a series of Carrington Events that crippled the technology base.  Society, technology, and politics are very roughly equivalent to our early modern period here on Earth.  While this is book 9 in the series, the book does stand alone quite well, and no knowledge of the previous novels is required, though I'll recommend them as well; the first of the series is Elizabeth of Starland.

Forcing The Spring starts with a teenager named Pjotr, who is the Tsar of NovRodi.  As the story opens, Pjotr is not yet old enough to rule, NovRodi is under the regency of his half-sister, whom he loathes and fears.  This is not strictly a personal fear, but a fear for the fate of his nation and its people, who live with a foreign threat his half-sister and here lover are doing little to address. The novel chronicles his trials and tribulations as he grows to become a young adult and deal with both his troublesome half-sister and a deadly foreign menace.

I won't say more about the plot for fear of spoiling it.  It was a fun read, and an easy one. Typographical issues were few and far between, and the prose presents no distractions.  I enjoyed it thoroughly and recommend it.  Even if you're not generally a fan of science fiction, fantasy, or the like, I recommend Forcing The Spring  as a darn good adventure story, and something of a coming of age tale, as well.

One additional comment:  Mark Twain was reputed to have said "History doesn’t repeat itself but it often rhymes."  On Colplatschki, historical rhyming may well be the planetary sport.

Monday, September 26, 2016

Some Interesting Websites

I've been doing a bit of research for the Ruritania story, and stumbled across a few interesting web sites over the past few days.

1. The US Navy's Office of Naval Intelligence (ONI) compiled a series of recognition handbooks depicting ships, submarines, and aircraft from WWI and WWII.  A number are available online from the Historic National Ships Association.

2. In Britain, the Airship Heritage Trust is a group promoting education and preservation regarding airships.  I came across their website years ago, but revisited it just recently. They've got some neat pictures and plans of a lot of different airships from several nations.

3. The web site is devoted to, as the title on their page says, "The Graf Zeppelin, Hindenburg, U.S. Navy Airships, and other Dirigibles."  More neat stuff.

4. I also encountered a blog post at the Dieselpunks website about the British R100, complete with a few photos, one of which was new to me.

Sunday, September 25, 2016

Why does Ruritania exist?

In the strictest sense, the realm of reality, of course Ruritania does not exist.  It is fictional country invented by Anthony Hope, which he wrote of in a three novel series, the most renowned of which was "The Prisoner of Zenda".  But for the sake of argument, assume that it really did exist in Central or Eastern Europe.  Assume further that the other microstates mentioned in Hope's "The Heart of Princess Osra", such as the Grand Duchy of Mittenheim and the Kingdom of Glottenberg, are also real.  How do they exist?

"The Heart of Princess Osra" is definitively set around 1734, per the first sentence of chapter two.  The other two novels, "Prisoner of Zenda" and "Rupert of Hentzau", could be set anytime from about the time Zenda was (1894) to a decade or two earlier.  In 1734, it would perhaps be plausible for all three microstates to exist.  Italy and Germany were both collections of states at the time, and the Holy Roman Empire was still a going concern comprising portions of both, as well as what would later become the Austro-Hungarian Empire.  So two extra kingdoms and an extra grand duchy in 1734 fit easily into the realm of possibility, geographically.

Over the next century and half, however, most of those smaller states disappeared as sovereign entities, subsumed by  larger nations.  The unified Kindom of Italy and the German Empire replaced, respectively, the previous collections of small Italian and German states, in 1861 and 1871.  As my previous Ruritania post mentioned, the location of Ruritania lies within a day's train ride of Dresden; Wikipedia suggests between Saxony and Bohemia.  I suggested an area just slightly further east, in a small part of southern Silesia (now part of Poland) and small parts of what is now the Czech Republic (once the Duchy, later the Kingdom, of Bohemia).

Ruritania circa 1648, from a public domain map

Control of Silesia was contested, by arms, lawyers, and diplomats, for several hundred years.  Initially it was part of Poland as the Duchy of Sileia, and disintegrated into the Duchies of Silesia, which via various inheritance and treaty agreements ended up under the control of the Kingdom of Bohemia. Bohemia in turn fell under control of the Habsburg crown.  In the middle of the eighteenth century most of Silesia was acquired by Prussia in a series of wars against Habsburg-ruled Austria.  The Sudetes mountains largely formed the border between Silesia and Bohemia, though it moved at at times - sometimes by war, sometimes not.

A bit of change to the fabric of history could alter these facts a little, but Ruritania is more-or-less set in the real world, so the fabric shouldn't be disturbed more than necessary.  How do we get Ruritania in Silesia?  Intermarriage between the House of Elphberg, the Ruritanian dynasty, and the Piast dynasty, founders of the Duchy of Silesia and subsequent rulers of the various Duchies of Silesia, can help with the land coming under Elphberg control.  Perhaps the Battle of Legnica, which took place against the Mongols in Silesia in 1241, played a part - battles are nice at messing with normal plans for inheritance and succession.  So maybe an Elphberg succeeds to rule one of the duchies, or part thereof.  That's the land portion dealt with.

But how can Ruritania become an independent kingdom no later than 1734?  That'll require something after Ruritania exists, but well before 1734, that either prompts the Holy Roman Emperor to raise Ruritania to the status of kingdom, or allows the Elphberg dynasty of Ruritania to assert there status as a kingdom and make it stick - probably by force of arms.  The latter seems more improbable than the former.  So likely the Elphbergs and/or Ruritania did something that the Holy Roman Emperor heartily approved of.  Maybe something during the Thirty Years War, or help to Austria in repelling an Ottoman onslaught, or something else in support of Austria or Bohemia in some conflict against Poland or a German state. Or something.

Ruritania also to survive quite a few years as a territory encapsulated inside the Habsburg lands.  Then it has to withstand the Silesian Wars between Prussian and Austrian, without being conquered by either.  Then in the nineteenth century it has to survive Prussian-led attempts at consolidation of northern German states into the German Empire.  On that last point, a few points may help Ruritania.  It is a largely-Catholic state, and it appears to have a Slavic population, based upon some of the names.  Certain Prussian elements preferred to avoid adding more non-Protestants and non-Germans to their empire.  It is also a smaller state, approximately twice the area of Luxembourg, and hence not a major threat.  Does it suffer unwarranted German occupation during the Great War?

More thought is required, but at least I've now done enough reading and thinking to know more.  I know the questions and the framework in which they'll need to be answered.  Answering them will help fill in the backstory for story I plan to tell.

Saturday, September 24, 2016

Outlook cloudy... and bumpy!

As mentioned in the last post, among other things, I needed to add clouds and the POV-Ray export. The initial POV-Ray export lacked bump mapping, so was flat looking.  It also needed to be flipped horizontally and vertically.  I think the handedness of the coordinate systems was different.
POV-Ray rendering of initial POV export from the Planets program.  Note that it is rather flat looking.
So I added the export of the bump map information, and added a scaling statement to the POV export such that the image map was applied in the necessary flipped manner.  It didn't look nearly so flat.

POV-Ray rendering of POV export, this time with bump mapping applied.

I also added the first cut of the cloud feature.  Below is a screenshot as seen in Planets and as rendered in POV-Ray, though from different angles.

Planets showing the initial version of clouds applied.

POV-Ray rendering of Planets export, with bump map and clouds.

I'm not entirely happy with clouds at this point, and think I need to invest more time still.  Also, the Map doesn't currently show the clouds.  I may enhance the map view so it does.

At this point, aside from completing the clouds, the "dimple" at the center of craters is probably the last major visual component that I need to complete before making an initial release.  There's other things that need to be done - code cleanup, UI for entering parameters to control planet formation, possible performance improvements for noise generation - but with crater and clouds working properly it will be more-or-less feature complete.  By next weekend I hope to be at that stage and have this up on GitHub.  We'll see what the coming week actually holds.

Friday, September 23, 2016

Export fixed, bump maps working

When last I wrote, I mentioned the image exports were being offset, the texture in the OBJ export looked wrong when viewed in Blender, and that bump maps were incomplete.  You can see how wrong it looked in the screenshot below.

Bad uv coordinates and lack of normals make for a poor model of a planet.

The problem with the texture in the OBJ export turned out to be horribly incorrect u components in the uv mapping (texture coordinates).

Normalizing (converting to 0..1 range) the longitude in radians should simply be a matter of dividing by two pi, like so
     u = lon / twoPI
and not the utterly wrong
    u = (twoPI - (lon / twoPI)) / twoPI
that I was using.  Somehow the latter had worked inside the Microsoft WPF 3D library, perhaps due to some automatic normalization code in that library.  Anyhow, with that corrected, the texture on the OBJ export looked better inside Blender.  

But it still looked faceted, rather than smooth.  Why?  Because there was no normal data!  3D models emulate curved surfaces by providing vertex normals.  This may sound crazy since a normal is by definition tangent to a surface, not a point.  What 3D programs do without normal data when rendering each pixel of a face (i.e. triangle) is use the normal of the face for its calculations.  If normal data is present, then the rendering algorithm at each pixel of the face uses the normals at each vertex to produce an interpolated normal at that point.  This emulates a rounded surface.  Calculating the vertex normals for a sphere is easy.  At each vertex, the center point of the sphere is subtracted from the vertex, resulting in a vector difference.  This vector is then normalized.  Et voila, we have the vertex normal.  And suddenly, in Blender, it now looks like so.

Exported OBJ model as seen in Blender, with vertex normals helping to simulate a smooth ly-curved surface

The bump maps for terrestrial worlds were also completed.  When exported to OBJ and imported into Blender, a rendering of the bump map shows how bumpy the effect can be.  I might need to do some tweaking.

Blender rendering of a planet, with bump mapping applied.

A couple of hints for anybody using Blender who has even less experience than I do.  After importing a model, the texture will not initially show.  You have to click Alt+Z to turn on the texture.  The other hint is that bum maps aren't applied in the usual editor mode or the OpenGL render, but only the render done by clicking the Camera button in the properties/toolbox.

The regular 2D image export also works properly now.  You can see a terrestrial world in globe mode.  For the map view, I changed the export code to simply export the entire image more directly, regardless of window size, aspect ratio.
Globe image exported from the Planets generator.  Note the alpha/transparency.
Next up is probably the POV-Ray export, which some brief research suggests will be very similar to the OBJ export if I export the geometry as mesh2 objects.  It may even be a copy/paste of the OBJ writer class code with minor modifications for the language/format differences.  Then the UI for entering planet parameters. Clouds probably come after that, and finishing up the craters. It probably wouldn't hurt for me to run a few tests of the export for the other planet types, as well.

Thursday, September 22, 2016

Ice caps and exports

I made a little bit of progress today.  There are now ice caps!

Map with ice caps

There are also specular maps such that water and ice appear relatively shiny in 3D mode, and in exports that support specular maps.  A little more work is required but I should be able to generate bump maps in the near future as well.

Globe with specular map applied - note the shiny spot toward upper center,
just below the ice, where the sun is glinting off it.

The general code reorganization is complete.  Each planet type is created by its own class that inherits from PlanetCreator.  The abstract method CreateMaps accepts a PlanetParaneters object with all the necessary parameters.  It returns an object containing texture, elevation, bump map, and specular map.

It looks like Blender is wrapping a quarter or half the texture around the entire circumference.  I need to learn why.

I also managed have some basic export functionality working.  The save of the map or globe images to file works - except it is shifted down 25 pixels, with the bottom 25 pixels being cut off, because of some WPF implementation details.  This problem should be correctable by simply placing the Viewport3D and Image elements inside new Border elements.  The initial 3D export to OBJ format is also almost working, but when I import and view the model in Blender the mapping of the texture appears wrong.  I need to investigate further.

That leaves three things in progress: bump maps, fixing the exports, and figuring out why the texture is mapped wrong when imported into Blender.  I've also got to start on clouds, the UI for entering parameters for more control over planet creation, the crater dimples, and a proper DNoise implementation.

Wednesday, September 21, 2016

Colorful planets

I accomplished only a little of what I set out to do today, but I think it was fairly effective.  Terrestrial worlds now have a nice color scheme applied, based upon latitude and elevation.  A fractally-perturbed latitude value and the elevation value are used to calculate an index into a one-dimensional color map that ranges from a desert-like tan at the equator through several shades of green to a gray and white for the tallest mountains and the desolate polar regions.  You can see the resulting texture being applied to both a 3D globe and as a flat map.

A terrestrial world, in globe view

There's a flaw in the color map I used (based upon the one from Ken Musgrave's dissertation) which is that the desert-like tan colors are along the equatorial belt.  On Earth, the equatorial region is largely a lush region of vegetation, with drier regions to north and south before wetter regions are again encountered a bit further from the equator.  Musgrave mentions this in his dissertation, and I wondered why he didn't use a more Earth-like color map, but I realized as I was implementing that it would make the latitudinal and elevation contributions to the position on the color map harder to calculate.

Terrestrial world, in map view
What's left, then?  Well, a lot, actually, but most are fairly simple.  Clouds and ice caps, for example. The dimples for the craters on the rocky worlds are still missing, and should be added.  A toolbar in the GUI might be nice.  A form allowing the user control of some parameters would be nice.

In the example from his dissertation, Musgrave implemented a steeper "bump" in the color map for higher elevations. I haven't done that, but think I probably should.  Mountains in regions closer to the equator than the poles currently end up with dark green mountains; some are high enough they should really be gray or even white if tall enough.

A second terrestrial world, in globe view

A proper implementation of the DNoise algorithm, to improve the Venus-style clouded worlds, would also be nice - but that's a bit more complex.  Another idea is to add a feature for export to OBJ format to allow importing into 3D programs like Blender, POV-Ray output is another possibility.

Another somewhat-involved improvement would be to parallelize the fractal noise generation, possibly even offloading it from CPU to GPU using OpenCL. Generating fractal noise is only part of this program where the performance is poor - it can take several minutes to generate the noise for a terrestrial world at a resolution of 4096 x 2048, while turning that noise into a texture with pretty colors takes a few seconds (or less).  I want the ability to go to higher resolutions than that, so performance really needs to be improved. Generating the fractional Brownian motion (fBm) noise with Perlin noise as its basis function is definitely possible using the GPU; I experimented with it sometime in the last year or so in a stand-alone application.

That second terrestrial world again, in map view

I'm also not sure about the color scheme I'm applying to the ocean based upon depth.  I'm going to look at some more photos of Earth from space.  While the seas are somewhat lighter in shallow waters, I don't think the deepest of the deeps become noticeable darker, like in my images.

On the code structure aspect of this, I'm planning to split the planet texture generation into separate classes, with a common base class containing many of the common functions (noise generation, color mapping, etc.) and a virtual method GenerateTexture, which shall accept as arguments the width and height (in pixels), and sea level, cloud cover, and ice cover as percentages.  Crater activity may also be an argument.

Star systems, and planets, and fun, oh my!

I made much progress this evening.  For the star system generator, I completed the export to CSV feature and the initial work on giving the gas giants their fair share of moons.  As you can see in the screenshot below, that can be a lot of moons!  As a result, there's now a View menu with an option to display the moons or not.

The Habitable column and calculations for it were also added.  This makes it easy to see if a world is human habitable rather than checking gravity, pressure, and temperature values and trying to remember what levels are acceptable or not.  Since I've added that, I've run many iterations and have ended up with some interesting worlds.  There've been a few marginally-habitable ice worlds, and a couple water worlds that would be fine for humans - if there was any land!

Alternate console and web front ends also seem like they'd be easy to add once the last of the code (finish the moon stuff, and atmospheric calculations) is complete and cleaned up.  A console version could easily be made to work with .NET Core, and hence should be able to run on Linux and Mac OS/X.


For the planet generator program, I did a bit of refactoring which leaves the code a bit cleaner.  It still needs a bit of work, but I should be able to split off the planet texture generation into code that can be used by non-WPF applications, like the web.  Also, the code for terrestrial planet generation has reached a state where it generates something worth showing.

At the moment, everything at or below sea level is a single shade of blue, and gray scale elevation-based shading has been applied to the land masses.  As I continue, I aim to apply fractal-perturbed latitude-based coloring like Musgrave demonstrated in his dissertation.  The two images demonstrating the current state are the 3D and flat map views of the same world.

Additional development should include clouds, and ice.  The star system generator can generate hydrosphere, cloud, and ice percentages that could be used as inputs for the planet generator.

I'm not sure about the cross-platform potential on this one.  The 3D graphics would have to be almost completely redone for OpenGL if I were to retain 3D capability, but 2D mode would definitely be possible via web and as binary output from a console application.  I don't know if I'll go there or not, I'm just musing aloud.

Tuesday, September 20, 2016

Ice Giants

My original plans for finishing up the star system generator were rudely interrupted by finally finding favorable weather for lawn mowing, and by my favorite Philly steak place, Penn Station East Coast Subs (which despite the name is based out of Cincinnati).  Alas, while the Philly steak sandwich was most excellent, I don't like cheese on mine.  After what seemed like a long delay, I asked what was taking so long.  They were making me a new sandwich because the put cheese on it.  Okay, that's fine, but then they confused my order with another person's with a similar named, and when he came in to pick up his order, they gave him my sandwich.  Nearly 3/4 of an hour elapsed before I was finally able to chow down on my dinner.  They tossed in fries for free to make up for the delay, which was nice, I suppose, except I was trying to avoid the added calories.  With them sitting there, beckoning to me, I did devour them in the end.

Anyhow, no more progress on the star system generator this evening.  However, I did spend a few minutes on the planets program again.  I did some refresher reading in an astronomy text and online and discovered Neptune and Uranus are now considered "ice giants" rather than "gas giants." Visually, they're a bit different in appearance from Jupiter and Saturn, as well, with less chromatic variation in the photos I've seen, and being generally blue and green.  Therefore, I've adjusted the code to use a more restricted set of colors that are much closer, and I think that works better.

That's it for tonight.  Hopefully I'll get the chance tomorrow to complete what I had planned to do tonight.  On the code cleanup front, I've decided to put the code into an AwesomeWorlds namespace going forwards.  Implementing that will be part of my final code cleanup process for the programs, before I upload them to GitHub.

Monday, September 19, 2016

Gas Woes

I am writing this as I eat lunch at work.

Before work this morning, I took another look at the star system generator and found out where the negative masses were coming from.  Smaller, lighter planets that are nonetheless heavy enough to attract hydrogen and helium tend to lose those gases over time.  To allow for this, there was a calculation of mass lost due to gas loss over the life of the planet.  Alas, this loss was being calculated without respect to the fact that there was only a finite amount of gas to lose.  As a result, mass of gas loss was being calculated as exceeding the total mass of the gas present.  Oops.  There were no more negative mass planets after that.

Also, I added the feature for generating a star system with a habitable planet.  No changes were made to the simulation core, but instead when this feature is used the GUI code just keeps generating systems until one with a habitable planet is found.  This sometimes means it takes up to fifteen seconds to generate an acceptable star system, but it beats repeatedly hitting the New menu item tens of times until a suitable system emerges.

Some interesting systems do get generated.  While most habitable worlds belong to type F and G stars, one will sometimes appear for other types of stars, or as a moon of a gas giant or other type of planet.  I've had multiple habitable worlds appear very rarely, and once there was a habitable world whose moon was marginally habitable, as well.

So what will I work on this evening?  Probably the moons, calculation of atmospheric compositions, and the export feature.  If I'm feeling very ambitious, I may start code cleanup.  This thing is looking closer to completion.  It should generate all the data I should need as inputs to a planet generator.

For now, I should get back to finishing my lunch.

Sunday, September 18, 2016

Sunday night stuff

Much of the work outstanding work on the star system generator that I discussed in yesterday's post is now finished.  Some data is simply not generated for gas worlds - you'll see NaN (not a number) showing up in those cases.

The moon count is still low for the gas giants, but that's because the method in the simulation by which planetesimal's become moons makes it unlikely for large numbers to accrue around any planet.  I may need to add some code to specifically generate additional moons for the larger gas worlds.  A few bits and pieces remain to be taken care of - there's a bug that can result in negative mass(!?) for small planets around very massive stars.

There's more work to be done. The orbital data for the moons is incorrect/incomplete. The GUI and the simulation core need to be separated out into an application and a library, as I have every intention of reusing the simulation core with the planet program in the future, and with other things.  The GUI needs an export capability.  It also needs an option to restrict the star selection to a smaller selection of spectral types; currently it will randomly select from any main sequence type.  Another option should be to keep creating star systems until one is found with a habitable world - that'll make it easier for authors, game masters, game designers, etc. who might try to use this to generate a star system with a habitable world for a story or game.

Code cleanup will probably require a couple days - the original examples I ported from and/or used as a template were in multiple computer languages with different naming conventions, indent styles, bracketing styles, comment styles, etc.  Where I copy-and-pasted I need to go back and achieve consistency.

On other matters, I ran across an interesting agent-based language evolution simulator. Its implemented in JavaScript and runs in the browser, so just visit the link if you want to take it for a spin. I've included a screenshot below.  At first glance, it appears to add words from language A to language B when individuals from A and B interact, with possible mutations.  In and of itself, merely interesting, but when combined with some other techniques it could be useful.  I'll have to take a more in-depth look again when I jump back to language synthesis at some point.  On a  related note, I should probably finish cleanup of my C# port of LangGen and put that up on GitHub sometime soon.

Last night I found out that a new novel in Alma T. C. Boykin's Colplatschki Chronicles series had been released.  I purchased Forcing the Spring from Amazon and read it on my aging Nook.  I quite enjoyed it, and will likely write up a review at some point in the near future.  I eagerly await the next book in the series.

Currently I am reading Paul Lendvai's The Hungarians: A Thousand Years of Victory in Defeat.  I ran across this book in downtown Cincinnati late Friday afternoon, when I stopped in at the main branch of the Public Library of Cincinnati and Hamilton County.  Alas, I had arrived via streetcar, and had to cart the book and two others I checked out through much of downtown Cincinnati, including a stop at crowded Findlay Market, before I could finally drop them at my vehicle.

There was a bizarre bit of convergence after I left the library and hopped the streetcar.  I was reading the book on the streetcar, and from early on Lendvai makes mention of German settlements within Hungary.  I look up from my reading at one of the stops, and there are people in old-timey German attire boarding.  I was puzzled for a few seconds, and then remembered - Oktoberfest!  Cincinnati's Oktoberfest, the largest in America, was starting in an hour or so, and people were boarding the streetcar to reach it.

Between the weather on Friday and Saturday, the crowds, not being a big beer drinker, and the fact that most food booths were from area restaurants I can get the same food from anytime, I wasn't really inspired to go to Oktoberfest.  It was still rather neat seeing so many people getting into it and dressing up for event.

And that's it for this Sunday.  I'll probably have more to write about come tomorrow.

More planetary data

I've continued to play with the star system generation code during my spare time today.  I fixed the problems that were plaguing me yesterday and have more of the planetary data being generated, although you'll actually see fewer columns in the screenshot, as I hid many of them.  I need to finish up porting the rest of the planetary data calculations from C to C# - there's probably a couple dozen more useful attributes, particularly relating to atmosphere, temperatures, and hydrology, which all play a part in determining visual appearance (when I get to that stage).

I've also implemented the moon code, but the numbers of moons being generated seem awfully low. I shall have to check for bugs.  If there are none to be found, I may need to do some tweaking of the constants that control whether planets with overlapping/intersecting orbits coalesce or if one becomes a moon of the other.

Saturday, September 17, 2016

More star system fun

In my last post, I mentioned how I had created a C# version of the venerable Accrete star system simulation program, using Ian Burdell's Java applet variant as a template.  The StarGen variant has more planetary details, like orbital period (year), planetary radius, axial tilt, etc., plus moons.  Alas, when I began coding calculations for these details myself, I didn't make it past coding up four of the calculations before I discovered the main algorithms needed to be enhanced to track gas and dust masses separately in order to provide the necessary data for a few of the subsequent calculations... whose results are required as inputs for most of the remaining calculations.  [sigh]

That's not complete yet, so there's nothing new to show at this point.  This is taking longer than it would otherwise because I'm also doing some code cleanup.  When I wrote my initial code based upon the C and Java code by others, I used the basic data structures they'd used, including old-school singly-linked lists.  I've been replacing all such data structures with C# generic collections, particularly List.  With those changes in place, many routines were shortened, some by as much as 60%, since a number of code loops were replaced by LINQ queries.  Of course, under the hood the LINQ queries will be turned into similar looping code, but it is much easier to read when reviewing the source code.

Hopefully I'll have time to finish up the changes for tracking gas and dust masses separately.  With those in place, the rest of the calculations can be performed, and I should be able to have more detailed temperatures, radius, day length, planet type, etc.  For now, I'm going to do a bit of reading, then get some sleep.  Good night, world.

Friday, September 16, 2016

Star system generation

I took a break from working on the planets program to look at star system generation.  There's a set of programs that have been floating around the net for decades that do that, based upon a pair of astronomy articles from the 1970's.  As I understand it, the accretion model used is known to be wrong (or at least incomplete) based upon some of the exoplanet data that has been collected over the past twenty years.  Unfortunately, everything I can find about simulations of newer models suggests that they're computationally expensive, requiring much code to be written and much time to execute each time.  I was considering going that route anyhow, when a saying I'd heard in the past came to mind:  "All models are wrong.  Some models are useful."  In this case, the accretion model is useful for quickly generating fictional star systems that aren't entirely arbitrary.

I created a quick and dirty C# star system generator based upon one of the simpler variants I found on the net, a Java applet called Accrete that was written by Ian Burrell in 1997.  Based upon a class of star (e.g. spectral type K1) it generates planets with some minimal data: orbit, mass, and whether it is a gas giant.  There's a rather more complex variant called StarGen which looks to deal with planetary details in greater depth, like atmosphere, more planet types, etc.  I'll be taking a look at that at some point.  A program like this could be useful for feeding details into the planets program I've been tinkering with, about which there are other posts here.

In its own right, StarGen is worth taking a look if you want a star system and aren't picky about the visual details (it has a fixed image for each planet type).  If you're an author, or designing a game of some sort, or a role-playing game campaign, you might find it useful.  It won't generate new pretty images of planets or maps for terrestrial worlds, but it will generate a nice batch of somewhat useful information about the planets in the star systems it generates.

Thursday, September 15, 2016

No post right now

No post right now, I'm too tired.  Day job had a bit too much confusion, which has left my mind in a poor state for writing, programming, or blogging.  Tomorrow, I hope, shall be better.  Adieu.

Tuesday, September 13, 2016

Book Review: 1635: The Wars for the Rhine

I recently purchased and read the eARC for 1635: The Wars for the Rhine by Anette Pedersen.  This is a a new volume in the already-voluminous 1632 / Ring of Fire series created by Eric Flint.  This book covers the conflicts erupting from attempts by different factions to control the Rhineland.  It focuses primarily on three sets of characters: the Hatzfeldt family, the Hesse-Kassel family, and Katharina Charlotte, widow of Duke Wolfgang of Jülich-Berg.

While we've seen a little of the Hesse-Kessels and of Archbishop Franz von Hatzfeldt and General Melchior von Hatzfeldt, in other novels and short stories, they've seldom received much "screentime" before.  A number of the other characters from previous stories also make appearances, but most are new.  If you're looking for more Mike Stearns, Gretchen Richter, Gustavus Adolphus, John Simpson, etc. this isn't the book for you.  If you'll enjoy a tale of political and dynastic intrigue that sometimes flair into war, intermixed with a little bit of romance, then you may very well enjoy 1635: The Wars for the Rhine.  I certainly did.

The book is well-written, it flows fairly well, and seems not-improbable.  It has very little reliance upon uptimers or technology; unlike some books of the series, it deals primarily with the impacts to the geopolitical situation resulting from the changes that have already occurred.  If not for the changes to the timeline, and some very limited use of radio, the novel would be a work of historical fiction set in the early modern era, rather than alternate history.  If the lack of lots of shiny new technology, or uptimer characters, is a problem for you, again, this is not the book.  I enjoyed it, though.

There are two things I found slightly annoying.  Before I mention them, let me first say that neither of them is enough to make me not recommend this book.  I do recommend it.  The first of those minor annoyances was keeping straight the various movers and shakers, and their relationships with each other.  The Cast of Characters included with the book helps, but I found myself having to flip back to it several times to make sense of things again.  The other annoyance is that this in some ways serves as a sequel to several earlier short stories in the Grantville Gazette and some of the braided story anthologies, and it makes reference to and builds upon events in them, but with little explanation.  This makes it hard for those who've not read the earlier stories, or not read them recently, to understand fully at a few points.  There's just enough context in the novel at those points not to be completely lost, but no more.  Still, despite these annoyances, I heartily enjoyed the novel, and recommend it.

Monday, September 12, 2016

Rings and craters and pretty colors, oh my!

I made a bit more progress on the planet generator.  Gas giants now have rings, there are different color schemes that may apply that very roughly approximate the colors of the gas giants in our Solar System, and the turbulence level is now variable.  They colors and ring spacing still need tweaking.  Specifically, the colors chosen in some of the schemes are too different from each other; most photos of Neptune and Uranus show shades of blue and green, respectively, that are much more similar than my color schemes. The next three screenshots should give an idea of where things stand.

For the rocky worlds, I attempted to implement the crater algorithm I saw used for Stephen M. Cameron's Spacenerds in Space game.  Basically, it places a "dimple" at the crater site and then
surrounds it with a number of cones in a slightly-irregular near-circle around the perimeter.  Alas, my implementation details need further work, as can be seen.

When looking over my notes on terrestrial planet generation earlier, I realized that I neglected to mention Tectonics.js, a JavaScript + WebGL web program that performs a 3D simulation of plate tectonics.  I've previously mentioned the PlaTec plate tectonics simulator and the Experilous 3D world generator, and that I thought that while they've got some fascinating features, they fall short of what I'm really looking for.  I had hoped Tectonics.js would be a solution, but alas it is as slow or slower than PlaTec, usually lacks the puzzle-piece-like continents (like how Africa and South America fit), seldom produces decent-sized continents, seldom has very many mountains, and has some strange artifacts.  The second and third points may simply be caused by too much subduction.  The fact that unlike PlaTec and the Experilous planet generator it starts with a water world may be a contributing factor as well.  Despite that, it can be fun to watch and does sometimes yield interesting results.

I've begun wondering about combining something to generate fair-to-good initial continent shapes with a solution like the Experilous planet generator.  I have some old 2D code that generates a supercontinent and splits it, spreading the continents out across the world.  That might work.  I'll give it more thought later, once I'm getting into terrestrial planet generation.

Another thought: Most of these approaches produce decent coarse topography, good enough for a view-from-space, but little more.  (Fractals can allow an arbitrary amount of detail, but have major drawbacks of their own.  Everything seems to be a balancing act!)  Perhaps using the coarse topography as an input for something like Ian Parberry's "Design Worlds" approach could work. The type of terrain to be generated in the fine topography could be based upon elevation and slope (derived from elevation of adjacent cells), with appropriate elevation distributions obtained via analysis of several different DEM's (digital elevation models) of appropriate terrain on Earth.

That would still leave rivers and coasts, but Soon Tee Teoh has published an approach that could easily be combined.

And that's probably enough babbling by me for this Monday.  Time to call it a night and get to sleep before the workday.

New transit options in greater Cincinnati

This weekend, the first (and only funded) phase of Cincinnati's new streetcar system opened up. Due to the generosity of corporate sponsors, riding the streetcar was free opening weekend, and swag was being handed out. Actually riding the streetcar was a bit of a problem, though, as every one was packed to the gills. I felt like a sardine when I rode it a few blocks. I doubt the system makes sense in terms of cost-effectiveness, but it will provide a useful downtown circulator. It may even accelerate and extend gentrification of the Over-The-Rhine district. Why do I think it might do so? Because many of its supporters and detractors believe it will do so! Those owning property in the area generally supported it. Those fearing increased rent for the mainly lower-income residents, and those fearing those same residents would be displaced to their neighborhoods as new Section 8 residents, generally opposed it.

Cincinnati streetcar turning eastward onto Central Parkway after coming south on Race Street.

Not to be outdone, the City of Cheviot deployed its new mass transit option: the Barrelzer!

In reality, the Barrelzer is a ride at the Harvest Home Fair which takes place annually, the weekend after Labor Day, in Cheviot, Ohio. Pulled by a riding lawn mower with a barrel over its regular hood section, it pulls what seems like an endless train of barrels on wheels, each of which can seat a child. I had to dodge it a couple times as I walked around the fair.

The more normal fare for here, on books, and planets, and such, will resume tomorrow.

Saturday, September 10, 2016

And I thought SF/F fandom was graying....

On Friday and Saturday, I attended the Hoosier Traction Meet, a gathering of fans of electric railroads of the Midwest.  

It is a small event, averaging about 150 attendees most years.  I was one of maybe twenty people below the age of fifty.  The average age is probably somewhere in the mid-60's.  The youngest person making a presentation was 45.  The children attending with their parents were 50/60-something guys attending with their 70/80-something fathers.  Many of the attendees are old enough to remember WWII - and too old to get one presenter's pub about the man named Shrek not being an ogre.  At least this year no ambulances had to be called because of a person who collapsed in the doorway to the theater.

The organizers clearly recognize the need to attract more young people, based upon a few brief speeches before some of the presentations, but the only plan for doing so that they had was to ask us bring more friends and tell more people.  I'm not sure that'll be enough to save them.  I hope so.  And they encouraged staying at the hotel so that they continue to get enough room nights to avoid having to pay for function space.  Anyway, enough about demographics.  

Much like a science fiction/fantasy convention, the Hooiser Traction Meet featured a room for vendors and displays.  That room wasn't quite filled, unlike the first time I attended, four years ago.   The only other function space was a small theater that was used for the presentations.  Most of the presentations were either (literal) slide shows or PowerPoints.  Some were little more than picture shows with a little narration, while others were more detailed presentations enhanced by they photos and maps.

Whatever its problems, the meet was filled with great presentations, and the vendors had books and models I was interested in. Some were on streetcars, others were on interurbans.  There were also two presentations on buses (which do not interest me, and were the first of the morning each day, so I skipped them) and a brief but interesting presentation on a strangely-routed steam railroad commuter service in the Chicago area.  

Presentations on the Laurel Line interurban in northwest Pennsylvania, Cincinnati's still-born subway, and two of the Detroit United Railway's interurban lines were all excellent.  Eastern Missouri Traction Oddities and Obscurities was also interesting.  The Current Transit Industry News is an perennial feature, even if the commentary would tend to frustrate the politically doctrinaire of any sort.

Given the buckets of rain that were failing from the sky throughout the region, this year I was even more glad than usual that I made the decision to attend.  Amazingly, I managed to miss the rain for most of the drive to and fro.  I also managed an excellent dinner Friday at the Rathskeller in downtown Indianapolis.  Beef rouladen, red cabbage, potato pancake...  yum!

Thursday, September 8, 2016

Playing with planets again

I made some more progress with the planet generation program.  2D (map) and 3D (globe) visualization options are now available.  I've also been reading the eARC for 1635: The Wars for the Rhine by Anette Pederson, which is why I've only made a little progress this evening.

I still need rings for the gas giants, and some sort of color randomization (all bands currently get generated in same order each team). Variable turbulence levels would be nice, too.  Blander gas worlds like Neptune and Uranus may need another approach.

Perlin's marble texture used for a gas giant like Jupiter.
The rocky worlds need craters (at minimum) to seem more realistic, but I'm starting to like the way they look.  I did notice somebody who was working on craters for a space game they were working on, and they've got their C++ implementation available online.

There are still some failures, though.  The cloudy planet like Venus utilizes my implementation of Musgrave's Coriolis algorithm, which is built upon his VLfBm (variable lacunarity fractional Brownian motion) algorithm, which in turn depends upon his VLNoise algorithm, which in turn is dependent upon Ken Perlin's DNoise (derivative of noise) algorithm. . . which I failed to implement properly.  Alas, searching the web reveals few properly working implementations, so it looks like I'll need to do some additional research to understand how to implement an algorithm that calculates the derivative of Perlin noise.

And here are a few interesting failures along the way.

This was due to problems in trigonometry.  This is supposed to resemble a gas giant like Jupiter.
The map of cloudy planet looks more like the opening titles to a vintage episode of Doctor Who.
So, priorities in the near future: craters, rings, acceptable DNoise implementation.

Book Review: Monster Hunter Memoirs: Sinners

Yesterday I purchased and read the eARC for Monster Hunter Memoirs: Sinners, by Larry Correia and John Ringo.  This is the second book in a Monster Hunters Memoirs subseries, and a direct sequel to Monster Hunter Memoirs: Grunge.

I loved this book.  After a particularly dull day at my day job, sitting back and reading this book was a heck of a lot of fun - though I've been paying for it this morning.  It is written in the same first person style as its predecessor, with that slightly-snarky, slightly-blasé attitude that I found amusing.  It is action-packed.  Set in New Orleans, the locale, the characters, and the monsters are as colorful as you would expect.  This isn't a particularly deep novel, but it is a ton of fun, as long as your sense of fun doesn't shrivel up at the occasional bit of blood and gore.

I highly recommend this book to anybody who loves action-packed tales and doesn't mind a small bit of gore.  If you liked the previous book, or liked other books by Correia or Ringo, you'll likely enjoy this one, too.

More playing with planets

I spent a little time continuing with the planets generator, but more time reading, and the only time I spent writing was this blog entry.  The gas giant coloring is a little better, but I need to do some refresher reading on why the gas planets have the colors they do.  Also, the implementation needs adjustments to be a bit less symmetrical in terms of color layout.

I did some sample rocky worlds, but they also need a bit of adjustment.  Impact craters are needed, for example.

My attempts at following F. K. Musgrave's example for a Venus-like world, described in section 5.4 of his dissertation, isn't coming out quite right.  OK, it isn't coming out even remotes right.  I think I shall need to do some additional investigation - this was supposed to be adding horizontally-steaked clouds to a yellowish world!

So what's next?  Making the adjustments and fixes mentioned above, first of all.  The shall come switching to using 3D Cartesian coordinates (via trigonometry) rather than 2D coordinates with an arbitrary Z value.  Wrapping these images around a sphere, like in Globe, will come after that.  But there's more, too - terrestrial worlds!  And rings on the gas giants.

Tuesday, September 6, 2016

Playing with planets

With the bugs worked out of the Globe program, I felt free to begin spending a bit of time on the planets program.  In section 5.5 of his dissertation, F.K. Musgrave documented a good approach for generating colorful gas giants, building upon the Marble texture described in Ken Perlin's foundational paper, "An Image Synthesizer."  Below is an initial failed but interesting attempt at implementing this.  The failure was caused by integer numbers resulting from default conversions resulting from arithmetic operations between different number types (integers, single-precision, and double-precision floating point).  With that problem resolved by some explicit casts, the end result is as you see in the bottom image.  That's much closer to what I was looking for, though I'm not necessarily happy with the color palette I chose - and everything is still just 2D.  Once I get things working right in 2D I'll combine it with the code from Globe and voila, 3D worlds!  (But fractal worlds only go so far, as I've mentioned before.)

A simple digital globe - 3

The digital globe program has been updated with the fix for the distortion where the left and right edges of the image meet when wrapped around the globe - where the "international date line" often is on a map of Earth.  It was simple bug, where one of the UV coordinates was being calculated based upon the wrong vertex.  Oops.  As you can see from the images below, though, I've fixed that, and updated the GitHub repository with the change.

The south polar region (Antarctica) on the map had enough detail it looks decent.  Alas, the northerly polar region was cut off above 80º N, which is bit south of the northern edge of Greenland, Nunavut, and Svalbard - the resultant weirdness and distortion is plain to see.  This is something to consider when trying to apply many map projections like Mercator to the globe - the extreme latitudes may be cut off.  You might need to add some buffer space manually to resolve; you may also have to trim borders around the map.  The source image in this case was a Mercator-projection world map from Wikipedia.

There will probably be another post later, likely on a different topic.


A follow-up post on fixing the distortion can be found here.