Sunday, October 30, 2016

Where'd everything go?

A tiny bit of progress was made later in the day, after my last post.  I met a friend for dinner, than came home and slept - I am still getting over whatever cold or other bug I caught that has been plaguing me the past few week.  So the only progress to report is that the very basic image-on-button GUI code is in place, and the code for basic camera movement is coming along.

Also, I'd forgotten, but the memory leak was tracked down and resolved.  It involved a set of minor logic errors resulting in repeated calls to a GDI+ function and a an OpenGL function that somehow were causing memory to leak.  The GDI+ calls were being made far too frequently and the wrong OpenGL function was being used; with that fixed the leak disappeared or was at least severely reduced in severity.

A functional menu in the test program.  Note buttons for menu, help, and full screen along the top.

View of the terrain from a small ways up.  Where'd all the trees go?

If you've been following my blog, you know that just a few days ago, there were trees and things in the screenshots.  You may be wondering where everything went.  Therein lies the tale of the next hurdle to jump over.

The tutorial I was following implemented a very simple loader for 3D models in the Wavefront OBJ file format.  Unfortunately, it was so simple more than half of the models I found in that format failed to load through it.  The main problems were with models utilizing multiple textures, or that had no textures at all but supplied material information (colors, shine, etc.) instead.  

The new Model/Patch classes I've created can handle that, but the OBJ loader needs to, as well, so I am in the process of porting over an OBJ reader/writer class I'd written years ago.  Until then, no models.  I ported over the basic image-based terrain loader already, so there's height map-based terrains, but not models of trees, shrubs, etc.  And since I'm hoping to be healthy enough to get up and go to work in the morning, I shall leave it where it is for now.

Once I've got the rendering and controls back to where they were (but better) I'll look at getting the outstanding GUI items completed.  As it stands, I've only been addressing them as I encounter them while using the GUI in the test application..

GUI + Rendering = Awesome!

After lunch, I spent a bit of time working on the rendering engine.  I've reorganized it a bit into a new project, AwesomeWorlds.Engine.  It combines code from the tutorial I was following with new code I've written and a bit of old code I've had sitting around.  It also now integrates the GUI code I mentioned in my previous two blog posts.

Menu shown over (rather lame) rendering

I'm refactoring a bit of the input code, which had previously been a bit awkward.  I'm creating classes that mediate between OpenTK.GameWindow and the engine, rather than having all the mouse and keyboard code directly in one or the other.  It is cleaner and more portable that way.  Then it'll be back to either wrapping up the GUI work or getting the code I wrote while following the tutorial to integrate properly into my architecture.

Render at night, with dialog box and button shown.
OK, I'll admit it.  Awesome may have been overselling things a bit.  But I think its cool I now have a GUI in my OpenGL apps.  Now if I could just track down that pernicious memory leak that only happens when I combine the GUI code and the rendering code...


I may have a book review later, and/or another status update.  Or not.  We'll see.

Saturday, October 29, 2016

More GUI, less gooey

More progress was made on the GUI (graphical user interface) work I had done yesterday.  There are now rounded corners (when desired), text boxes, check boxes, and picture boxes.  The captioned panel can now be expanded and collapsed, and simple a menu mechanism now exists.  So what's left in the near term?  Small images (icons/glyphs) need to be supported for buttons, and the ones for the captioned panel for collapsing/expanding, and possibly for closing, need to be added. The gradient fill hasn't been implemented. Total development time elapsed is about eight hours.  I'd guess another four hours to finish off the items I noted above, and do some cleanup and reorganization of the code, and that will be it for phase 1.


See the check box toward the lower left?

Not the dialog box collapsed and moved into another position.

See the text box at bottom center, and the rounded edges of dialog box and exit button.
A very simple menu.  An application can call up a menu in a single line of code.





A gooey, er, GUI mess

One of the things I'd like to have in my OpenGL-based graphics applications is some sort of graphical user interface (GUI, pronounced gooey).  I guess you could consider the mouse selection I showed in a previous post an example of a GUI, but that's not enough.  I've also shown simple text output overlaid on the graphics in the flight simulator port.  Neither is sufficient.  I want at least some basic buttons, textboxes, etc. that can be displayed and interacted with when appropriate.

There are a few approaches I could take.  There are a lot of frameworks out there for doing this, particularly if I were working in C/C++.  There are even a few C# wrappers to such frameworks, and a very small number of C# only libraries (see Empty Keys, for instance).  Or I could use WPF or Windows Forms, btu that ties me to Windows.  There are some cross-platform C#/.NET GUI libraries (like Avalonia), but few have good OpenGL integration, or they're such beasts I won't bother.  (If anybody knows of a good one, do please post in comments.)

So I decided to take a stab at my own GUI.  Its not currently integrated with my OpenGL code, but is stand alone.  (The background image is one of the samples Microsoft includes in the default Windows 7 install, not an awesome desert rendering I created - wouldn't it be awesome if it was?) Nevertheless, with about 5 hours work this evening I have something that's starting to work.  It consists of my own code and uses the System.Drawing library (for which the Mono Project has an equivalent for Unix-y systems), so is reasonably cross-platform.  I've got a bit more work to do on it, but you can see it in all its non-glory below.

A basic GUI
Buttons, labels, and panels are the only controls that exist right now, but they're more or less working. In the immediate future I envision creating text box and check box controls, but not the full panoply of different controls/widgets from Windows Forms, WPF, Qt, Gtk, etc.  Also, being able to display images would be very nice, and should be fairly simple, but mixing them with text on the same control (i.e. text and image on a button) is something a bit more complex (for the layout and clipping calculations) so that will wait until tomorrow.  The other effort would be making the panel control a bit fancier.

The one panel seen here in the center is emulating a dialog box, but not doing the world's best job of it.  The title bar at the top is optional, but when turned on it looks rather lame. It needs to be improved.  In the prototype, it appears whenever I click the big red "Do NOT click" button, and disappears again when its OK button is pressed.  Options and features for dragging, resizing, and collapsing/expanding would be nice - but I'm not sure I want to spend too much time on this.  I'm not looking to create something to let me build full-blown applications like I do in my day job, I'm looking to provide some minimal UI in places where user input is required.

Anchoring is one of the features that's complete and in place.  You can resize the window and the buttons in those corners will stay anchored as they've been set.  I don't have percentage-based locations/sizes like some GUI systems provide, which would be nice.  everything is in pixels, but they're specified relative to the edges.  So if anchored to the right edge, and the control has a right value of 10, it will appear 10 pixels to the left of the right edge, regardless of window resizing.

A couple other nice-to-haves that I may omit in the short term are rounded corners, gradient fill, and background images.  There's all nice features, but not essential.  Windows Forms-style docking would be another cool feature, but again not critical.  A persistence mechanism, so the layout could be edited on screen and saved, would be really need, but again not something I plan to address right now.

I've got a few more miscellaneous points to bring up, and then I'm calling it a night.  First, there's a nice set of modern (i.e. black and white) icons available free under the Apache license, apparently the end result of a project started by Google.  I may end up using them, or not, but thought I'd call them out in case anybody who reads this blog has need of such.  The other point is.... I can't remember. Maybe I should finish up and get some sleep.  Goodnight, world!


Friday, October 28, 2016

Function Junction

Due to still being ill, I've not made demonstrable progress on much of anything that I can show you. And between tiredness and illness, I can't really apply my mind to writing reviews on any of the books I've recently finished, although I shall mention that I've recent started reading Arch Whitehouse's The Zeppelin Fighters and find it engrossing.

One thing I did manage to complete was a very small program for function graphing.  I had some thoughts on using trigonemetric and other math functions, and combinations thereof, for various simulation or generation purposes.  Light levels and sun elevation for day/night cycles, terrain generation, and waves can all be modified with functions.

Absolute value of sine: y = abs(sin(x))
Sawtooth function: too messy for including in the caption, so see below.


private double Sawtooth(double x)

{

double a = 2;
double t = x;
double toa = t / a;
double y = 2 * ((toa) - Floor(toa + 0.5));
return y;
}


private double Clamp(double value, double low, double high)

{
if (value < low) return low;
if (value > high) return high;
return value;
}


Clamped sine:  y = clamp(sin(x), 0, 1)

None of these are likely to be original ideas, as I'm aware of some use of them for such purposes.For example, cosine is used for mountain ranges in the "River and Coastal Action" article I've mentioned before.  This tiny little program is helping me do a little visualization of how these functions work. There are math programs that can do this, I think (my TI calculator can do some of it), but whatever functions I come up with will have to be expressed in code anyway so I can use them in other code, so being able to quickly prototype is nice.

Some of the functions are useful in and of themselves, while otherwise would need to be combined with other techniques (such as noise) to be of use.  For now, though, I shall bid the world a fond goodnight and get some sleep.


Wednesday, October 26, 2016

Night and Day

I was home sick today, but that didn't mean I had much time to do anything.  Between sleeping much of the day, general sicky-ness, and lack of concentration, it was evening before I could even try to work one of the tutorials, and it nearly four hours for something that should have taken maybe an hour.  (This was part of why I was home sick.)

But I did complete that one tutorial.  I made it through the Day/Night tutorial before bed yesterday, and completed Tutorial 29: Mouse Picking today.  So now the skybox (but not the actual light) changes.

It is a cloudy day.  There is a box on the field ahead.
Night has fallen, and the box has been selected using the mouse.
Is that lady getting tired?  She's been standing there all day.
Yay!  Something was accomplished.  Now I shall go get some sleep and see if I can drag myself into work in the morning.



A Better Sky

As those who follow this blog may be aware, I've been following a series of tutorials on developing a simple game engine using OpenGL.  I'm already familiar with basic OpenGL programming, WPF 3D, and know a little bit about the Unity game engine.  Unfortunately, a full-blown game engine like Unity is so high level that it gets in the way of some of the things I want to experiment with.  Total overkill. WPF 3D doesn't support a number of rendering techniques (no support for normal or bump maps.  Again, too high level; no shader-level work.  OpenGL in and of itself is fine, but I wanted to see a way to fits bits and pieces together better.  There are also a few techniques I've never tried before.

The point of this exercise, therefore, is to learn enough to assemble a very simple OpenGL game engine that will let me wander around, fly over, etc. terrains generated via the techniques I'm experimenting with.  I figure another day or two will bring me to the point where I know enough to do that, and that I've learned the additional techniques I need.  Today has brought me closer to that point.

A woman standing on a hillside, with a cloudy sky behind.

The terrain is no longer flat.  The basic skybox is in place with clouds anyway you look.  The blocky man from yesterday has been replaced by a woman who doesn't quite render properly (texture mapping problem) but is still less freaky than the box man.  The woman and one of the tree models were free models I downloaded online.

Alas, that brings me to one of the major limitations of the game engine as it stands.  It only supports OBJ models that are textured by one and only one texture file.  Untextured OBJ models, or those with multiple textures, are not properly supported.  There's a lot of good free models, at least for a demo/experiment like this, but I can't load most of them, even after converting them to OBJ via Blender, because of the poor support.

At first glance that sounds like a simple thing to resolve.  It actually is with respect to reading the file format.  But efficient data structures for rendering, on the other hand, I am still considering.  At this point, I think the likely solution in my eventual engine (as opposed to what is emerging from the tutorial) is that a model may actually become a list of paired geometries and materials.  When rendering multiple instances of a model (as with the trees, ferns, flowers, etc.) I'd iterate over the list of instances once per paired geometry/material.  So if a model had geometry/material A, B and we had instances 1, 2, 3, 4 of the model, we'd render 1A, 2A, 3A, 4A, 1B, 2B, 3B, 4B so there would only be one state change, between 4A and 1B.

I'm also considering how to deal with non-textured models.  Models with simple color can still be very useful.  Perhaps auto-generating a texture map with all the used colors on it, and assigning texture coordinates to vertices such that they map to the correct color block of the texture map, may be the answer.  That would let the same shader handle both types of models.

Anyhow, I'm going to finish out at least three more of the tutorials (day/night cycle, normal mapping, and mouse picking) before I start creating my own, limited engine.  I'm not trying to create a major game, nor sell an engine, but some of this experimental stuff is just more easily implemented using lower level graphics programming - but alas at a slightly higher level than OpenGL itself provides.  I don't think running out and using a full blown scene graph or game engine is the solution, so I shall continue.




Tuesday, October 25, 2016

All Too Square

I'm continuing down the tutorial path I mentioned in yesterday's post.  There's now more types of objects in the scene, there's an absurdly boxy model of a person who moves through it (his body isn't animated, it just shifts position).  The camera perspective can be adjusted via the mouse (zooming, angle adjustment, etc.).  The character can jump - but he makes crazy leaps like he's Captain America or something - and there's no physics behind his non-vertical movement.  He can change his direction and speed in mid-air with the greatest of ease!


Absurdly boxy character walking through a cartoonish world.

I'm not sure how much farther I shall follow the tutorials.  At least through the next four or so.  I may try to hunt down some better models, as well - the ones I'm using were included with the tutorial, and are useful for development/testing purposes.  However, unless I'm aiming for a cartoon-like or surrealistic effect, I need better models.  I supposed I shall be searching online in the near future, regardless of how far I go with the tutorials.

Sunday, October 23, 2016

Trees and mountains and bright colors!

I'm still hitting some snags with the wind code, so I decided to take a break and work on something else for a bit.  First, I spent a short while porting to C# a very simple OpenGL flight simulator written in C.  It was on a college website and appears to be a starting point for future assignments.  It served as a useful starting point, but it is quite limited.


Flight sim, unsmoothed
I experimented with a few modifications, but the program is really quite limited, and is written for old-school OpenGL (OpenGL 1.1 or so) so extensive terrain display would be difficult due to the fundamental constraints, without writing a lot of code to compensate.  Still, it was a nice bit of fun.  Alas, the terrain looked too harshly faceted, but my attempt to resolve this through calculating normals to smooth the terrain left it looking bland instead.  Oh, well.

It looks worse with smoothing.



The other thing I messed around with is a series of OpenGL game tutorials.  Though the tutorials are aimed at building a Java-based game engine, it is serving quite well at helping me experiment with modern OpenGL using C# and the OpenTK library.  I just completed tutorial 14, which creates (flat) terrain and populates the land with a large number of trees.  I'd played around with OpenGL 3.3 and later using C++ and examples from the OpenGL SuperBible Fifth Edition, and via various graphics and gaming engines, but I'm liking this approach better so far.  I'm not sure I agree with some aspects of the engine design, and will likely only be using it as a starting point or reference for further work. Regardless, it is an excellent tutorial and suitable for some basic games.  Personally, my plan is to get far enough to have walking and flying navigation modes available and be able to load up terrain from file or generate it on the fly.  I have no specific game idea in mind, mostly just want to be able to look at the terrains I'm generating from other programs.  We'll see what happens.


At the end of tutorial 14, you too can run through the randomly-arranged instances of the tree model!



Out and About on Saturday

I spent most of yesterday afternoon evening out and about.  My afternoon started with a late lunch, or very later breakfast depending upon your perspective, at a local BBQ joint called Pit To Plate.  Instead of the beef brisket or chicken I'd had before, I order the turkey breast, with mashed potatoes and green beans and piece of their delicious jalapeno cornbread.  It was rather like an early Thanksgiving meal, without the family or the desserts.  The lack of dessert was due to discretion on my part, not because their Reeses pie isn't awesome.

Afterwards I took a short walk, then met a friend and went hiking for a bit.  Despite several days of rain a few days earlier, the trails in the park were almost entirely dry.  Whether that was due to the weather, good drainage along the trail, or a combination, I do not know, but I was glad that torrential downpours only two days earlier had few muddy spots on the trail.  The weather was a bit cooler than seasonal, but perfectly comfortable with a light jacket.

Somehow we then ended up spending the rest of the afternoon stopping at little pumpkin festivals at what seemed like every little farmers market along the lower Great Miami River.  I enjoyed some nice spiced cider and saw more pumpkins than I can every recall seeing before.

Finally, heading back toward the northwestern suburbs of Cincinnati, we saw a sign for winery and restaurant down a side road.  Neither of us are big fans of alcohol, but food sounded very inviting just about then, and the road ahead was home almost exclusively to chain restaurants.

If you do enjoy wine, the meal the Vinoklet Winery may be a good deal for you.  If you don't, it may be a pricey option you might still enjoy once in a rare while.  For about $40 they offer a wine tasting, a bottle of wine per couple, and the meal.  The meal consists of an all-you-can-eat buffet of soup, salad, vegetables, potatoes, rolls, and dessert.

For the main course, they offer a number of meat and seafood options, but the catch is that it's grill your own.  They have large indoor grilling area, with a charcoal grill and a (mostly-effective) ventilation system.  You season your meat or fish, toss it on the grill, wait, flip it, grill it some more, then take it back to your table.  That's the only part of the food that isn't all-you-can-eat, but the portion size is reasonable - and if you're still hungry there's always the option of more soup, salad, veggies, or dessert.  Alas, my grilling skills are a bit rusty, and I while intending to grill my steak to medium I ended up with marts of it ranging from medium-rare to just shy of well done.

I expect I'll visit again periodically, but not often.  Its rather pricey for the non-drinker, and a lot of work compared to a normal restaurant or buffet meal, but the food was good and the whole environment is neat.

The restaurant sits atop a hill, and the vineyard stretches down the hillside until it reaches a wooded area. Beyond the woods ultimately lies the valley of the Great Miami River, not quite visible due to the wooded nature of most of the hills, and the hills across the valley. The view roughly faces west-by-southwest, and as the sun began to sink the sky was lit in shades of orange and bright red.  There's little major development visible in the valley or the hills, so as the light faded further the only signs of civilization beyond the vineyard were the blinking red lights atop a few antennas and water towers.

After I dropped my friend at her house, I returned home.  I was full but not stuffed.  And I sat down at my computer and went back to the work at hand.  I hope to post more on that in the near future.


Saturday, October 22, 2016

using static

First off, let me mention the concept of namespaces in programming languages.  Programming languages allow users to define variables, functions, classes, etc. with names (identifiers).  For example, there may be variables named x and userName, functions named CalculateVolume and PrintDetailsand a class named File.  In any program of sufficient complexity, there is the potential for the same identifier to be used in multiple places.  Some potential complexity is resolved simply by the concept of scope.  For instance, the identifier for a variable defined inside a function only applies within that function.  Scope isn't sufficient to fully resolve the problem in a complex program though, particularly when third-party code is involved.  You may have a function named CalculateVolume and a class named User in your own source code, but you may also be utilizing libraries, one of which contains a function named CalculateVolume and another which has a class named User.  How does this potential ambiguity of sorts get resolved?

Classes and/or namespaces, depending upon the language in question.  Namespaces provide a way of placing a set of classes, functions, variables, etc. into a named context such that they can be qualified. For example, the vector class in the C++ Standard Template Library is a type of list structure that exists in the namespace std, and so may be qualified as std::vector.  There may also be a vector class defined elsewhere for purposes of linear algebra; assuming it existing in the algebra namespace it would be algebra::vector.  Classes can also be used to help resolve the potential conflicts between identifiers.

The identifier of function defined within a class exists within the scope of the class, and so can be qualified by the name of the class.  Assume there is a class User which has a function named GetLastLoginTime,  If the function is an instance method of the User class, and there is an instance of the User class named aUser, then the function would be called as aUser.GetLastLoginTime().  On the other hand, not all functions contained within a class are instance methods.  Some are what are known as static methods.  Static methods have a variety of purposes, but one of the purposes is to simply group conceptually-related functions into a common place.

An example of this use can be found in the C# and Java programming languages, with the Math class.  A number of useful mathematical functions such as the trigonometric functions (sine, cosine, tangent, and their inverses), exponentiation, logarithms, square roots, etc. are static methods within a class named Math.  To use these functions, they must be qualified with the class name .  For exmaple, in C# to make a call to the function to calculate cosine for an angle of 1.2 radians you would call Math.Cos(1.2).  Simple enough, but long formulas and complex equations often become longer and less readable than they otherwise must be.

Starting with C# 6.0, there is a new language construct known as using static.  Since its inception, C# had a language construct known as using which allowed programmers to bypass the need to qualify class names with the namespace.  For example, rather than referring to calling System.IO.File.Exists, if using System.IO; was specified at the top of the file, File.Exists could be called without the additional qualification.  The using static construct extends that concept to static methods of classes.

I've only been using this feature for a short time, and I like it.  Calculations that involved lots of common math functions used to be far longer and are now shorter and easier to read, since I simply add a using static System.Math; statement at the top of any C# file where there are lots of calculations.  In projects where I've got a bunch of common utility functions that are widely used, it also very handy at simplifying code.  In some of my experimental code where a strict object-oriented approach is either not a good fit or simply premature because structure is an open question until technique is understood, it allows me to organize and modularize code into classes while keeping the the individual code statements clean.  On the other hand, it can lead to the very same ambiguities due to identifier conflicts that namespaces, classes, and qualifications helped to resolve, so it should be used with care.

You'll probably be able to see some more examples of this once I get the planet generator finished and released.  Until then, I hope you find some use for using static, or at least found this post interesting.  Good bye for now.

Thursday, October 20, 2016

The Winds of Hell

Rainfall is now looking a bit better - the tight banding is gone - but it still isn't correct yet.  Part of the problem is the winds, which are proving positively devilish to get right.


Rainfall map



Enlarged view of portion of the rainfall map.  Intense blue indicates high rainfall.
(Colors were unintentionally shifted in the above image.)

Note the correspondence between the higher amount of rainfall (above) with the mountains (below). That's exactly as should be.

Enlarged view of portion of elevation map.  Black is low level ground, gray are mountains.

As you can see, the winds go kind of crazy after encountering the mountains.  Mountains can, in fact, perturb, divert, or even outright block wind.  But I shouldn't be ending up with the zig-zag pattern seen below, I don't think.
Enlarged view portion of wind direction map.  Lines point from center of cell toward direction winds are blowing.
Looks like I need to spend some more time on the winds algorithm.  Something is still clearly not right.  I may have misunderstood something from the article I based this on (it was a bit unclear on a few points), or I may simply have some bugs in the implementation.

I also think that the algorithm fundamentally needs a second pass.  Once rivers are flowing through an area, evaporation from the rivers (and any lakes) would increase moisture in the air, leading to more rainfall.  Rivers come down from mountains even in many areas that are dry due to the rain shadow effect, but travel far enough away from the mountains and the air slowly gets moist again.  I think that's from evaporation of the river and lake waters.

Or maybe I misunderstand the origins of the moisture in the Midwestern air.  I may have to break down and do a little investigation online and maybe pull up one of the geology/meteorology/geography books from the basement.  It could be flow of moist air from elsewhere.  Or a combination.  In any case the extensive river system east of the Rocky Mountains would not form with the model I'm using; only a few rivers originating in the mountains would form.

Something to consider after the wind model is working properly, and rivers are forming at all.


Wednesday, October 19, 2016

Too cute for words

This is too cute and funny for words.

http://circa.com/whoa/humor/check-out-this-new-vending-machine-that-dispenses-cats

Banding together

I've been implementing the wind and rainfall model for the tectonic-based terrain generation program, and found that it had developed bands.  This is based upon the algorithm described by Soon Tee Teoh in "River and Coastal Action in Automatic Terrain Generation."  Alas, as implemented by mean it is leading to bands of absolutely arid land (white portion at left) interspersed with bands of average rainfall.  I suspect the problem lies with my implementation, not in the algorithm as described.

Rainfall from moisture carried on winds from the east
The more intensely blue portions in the image above indicate a higher amount of rainfall in those cells.  This is the result of a simple algorithm to emulate orographic rain.  You can see corresponding mountain range in the terrain image below.  What seems to be happening is that the wind is pushing moisture westward over the mountains, during which the higher peaks result in more rain at those points and less to the west.  In some cases, the amount of rain was sufficient that the rain "runs out" a bit west of the mountains.  Where the wind pushed over lower portions of the mountain range, enough moisture was left that it "rained" all the way across the continent.

In essence, I'm getting a banded, displaced rain shadow effect.  That's not all bad.  The banding definitely needs to be resolved, whether through tweaks to the constants or through changes to the algorithm - maybe just adding a smoothing algorithm at the end.  We'll see.  The rain shadow being displaced from the mountain range I'm not so sure about.  That may or may not represent a true problem.  Perhaps the mountain range is merely not tall enough for a sharp rain shadow.


Terrain for the area above
In any case, all of this represents progress of sorts.  I need to get these issues resolved a bit further before I can start implementing the rest of the river generation algorithm.  That's because river generation is dependent upon the rainfall data to calculate water flows that ultimately lead to rivers.

That can wait until Wednesday evening.  For now, I am signing off.  Good night, world!

Tuesday, October 18, 2016

Continent images

I'm currently doing some code cleanup before starting working on the river and erosion code. Since that yields no interesting pictures, I though I'd share a couple examples of other output I'd produced during some testing since my last post on the topic.


First off, while erosion is upcoming work, I did implement a basic elevation smoothing algorithm. After the elevation map is generated based upon the plate pseudo-motions at boundaries, three iterations of smoothing are applied to the elevation, and then a "max" operation is applied between the elevation results pre-smoothing and post-smoothing.  That max operation restores the peaks and tiny islands, but leaves them with sloped land around them.  Some of the results can be seen below.

Three iterations of smoothing applied

Enlarged image of smoothing applied.

I also experimented with increasing the allowable range of motion for the hinge rotate operation.  I'm not really happy with the results generally speaking, but they did result in a nice mountain chain down the middle of the eastern land mass.  This led me to some more thoughts on how to manipulate the land plates before applying the elevation based upon plate pseudo-motion.


Experiments with "hinge rotate"


Enlarged view of altered "hinge rotate" results, showing two plates rotating into each other.

Sunday, October 16, 2016

The West is the Best

This is neither a discussion of the 1967 hit song "The End" by the classic rock group The Doors, nor an observation on claims of cultural superiority.  Instead, it is just an observation that I had a lot of fun attending the final day of this year's Old West Festival in Williamsburg, Ohio.  Willamsburg is a tiny town about 25 miles east of Cincinnati, in the next county east, Clermont.  However, the actual site of the Old West Festival is just east of Williamsburg proper, over the next county line in Brown County.  It is, in essence, in the middle of nowhere. . . aside from being immediately adjacent to Ohio 32, a major highway.

Front Street, the main street of the "town"

What is the Old West Festival?  Well, if you know what a Renaissance Festival is, it is a lot like that, only the setting/theme is the American West of 1878 - and you can skip to the next paragraph.  The Old West Festival has a bunch of people wondering about in Old West costumes, an Old West style main street with shops, so-called saloons offering corny but amusing entertainment ("magic" tricks, comedy, song and dance, etc.), horseback riding shows, gunfights, and miscellaneous booths with games.  And slightly overpriced food and drink, of course.  It runs on weekends, they charge admission, and it can be a diverting way to spend an afternoon or the bulk of the day. . . once a year or so.  A friend wanted to go, so we went, and had some fun.

Wagon ride at the festival
On the way back, we stopped for dinner at a restaurant in Milford called Roney's.  Roney's is in a new location, a new building off of Chamber Drive.  They used to be located on Roney Lane in Mount Carmel, and have been around in one form or another since 1969, owned and operated by the same family.  They used to be a Roy Rogers franchise; in fact, they were the last such franchise in Ohio.  Now they're independent, but serving up almost the same food.  In fact, their new building looks much like their old building did, and their largest sign is simply the old Roy Rogers wagon sign with the Roy plated over and the "g" and "r" from "Rogers" replaced with an "n" and "y".

So why am I writing about it?  Because it was a nice change.  Roy Rogers had a wide menu compared to most fast food places, with variety of sandwiches, roast beef, burgers, fried chicken, etc. plus sides. Roney's is missing some of the sides, but the meat of the menu is very similar.  I had a nice roast beef sandwich with cole slaw, my friend had a ham and Swiss sandwich with fries, and we were in and out quite quick.  There's nothing particularly special about the food, but it is good solid fare for a decent price, and it is neat that it has been in operation for nearly a half century.  They've even kept some of the old Roy Rogers (the cowboy singer/actor) memorabilia and a few other western-themed items, making the stop their a thematic continuation of the day's outing.

If I'm passing through the area I'd definitely consider going back, although there are a number of other dining options in that area I've yet to try, so who knows.

On another topic: Work on the tectonics-based terrain generation continues.  I have a basic smoothing algorithm that has what I consider a positive impact on the terrain quality.  I've learned a few new (to me) words in the process (not four letter ones, either) that I may bring up in a future post.  Also, I think I know where to go from here with an algorithm to generate better land forms, but I think I have other fish to fry first (river generation and proper erosion, plains at the foot of mountains, etc.).  I'll have more updates in the future.



Saturday, October 15, 2016

Colorful continents from plate tectonics

In yesterday's post, I wrote that I'd abandoned calculations of pseudo-motion at each point on the plate boundary, and used plate-by-plate collision data along with distance from plate boundary to generate elevation from pseudo-collisions.

I went back to the pseudo-motion calculations, removed the code for finding distance to border, and sped things up by about 3-4 times.  Its still not as fast as I'd like, but I'm getting results I'm happier with.  I simply iterate through every border point and evaluate the points in a radius around the border point, the radius based upon a effect factor in the range 0..1 that is based upon the pseudo-collisions.  That effect factor is multiplied by a distance factor (falls off farther from border point), then my a peak elevation, and then the result is mixed with three octaves of fBm based upon Perlin noise.  The result is some decent mountains and island arcs of variable density along the boundaries of oceanic plates.

Elevation map with new technique
Enlarged view of elevation map, showing mountains and islands

Resolutions under 1024 x 512 typically complete in under a minute, and an 1800 x 900 map took less than two minutes.  A 3600 x 1800 map took under seven minutes.  Alas, 7200 x 3600 took well over forty minutes, mostly in dividing the ocean into plates.  That step seems to scale up poorly.

I've also incorporated the terrestrial world coloring code from the earlier planet generator into this code.  The results are a pleasant mix of colors that vary based upon elevation and latitude. 


Map with color!

There's still more I'd like to tweak, but I think its really coming along nicely now.  For example, I think some smoothing or proper erosion algorithms would enhance the look of the maps.  Perhaps some river generation techniques could be applied.  In particular, I'm thinking of using ideas from Soon Tee Teoh's paper "River and Coastal Action in Automatic Terrain Generation" for rivers and possibly for river deltas.  My planetary-scale maps are likely too coarse for the rest of the techniques in that paper, such as more-detailed mountains, or beaches and headlands.

I may also take the output from the program and load it into the digital globe program.  The source code should ultimately get incorporated into the Planets generator, as should the Star System generator.  


Enlarged view of map with colors applied.  Colors vary by latitude and elevation.


Other thoughts: A higher degree of freedom for the hinge rotate operation should be incorporated, based upon the available map space (don't let parts rotate off-map).  Investigate better resolution independence - only the basic land shapes and their splitting remain consistent for the same seed number; changing resolution alters other aspects such as the oceanic plate partitioning and their pseudo-motions (and hence topography).  Oceanic trenches?  Split off small parts of continents sometimes to create giant islands like New Zealand, Madagascar, or Greenland.


Another world, created using a seed value of 8.  The ones above used a seed of 2.


Another world, created using a seed value of 9.



Getting continents into shape

I've got a reliable, effective algorithm for finding the nearest plate boundary.  Alas, it is slow as molasses.  It works, but about 70% of the time the program spends generating the world is spent on nothing but finding the nearest boundary for each cell on the map.  I'll have to revisit it later and develop a more optimal algorithm.

Still, it works.  That's enough to move forwards on getting the first real elevation onto the map.  In the the first try, it was simply supposed to slope from the plate boundaries to the center of the plate, with the high (white) part being near the plate boundaries and the lower (black) part being away from the boundaries.  It was definitely not supposed to result in land masses that resemble zebras.

My continents look like zebras!


A bit of of investigation and some trial and error led to a slightly different algorithm.  It was better, but not complete.  The continents are almost right for how the initial code was supposed to work, but all oceanic plate boundaries were turned into trenches, again with a (narrower) striping pattern.

Correct, but incomplete
That got fixed soon enough, but there was still something missing.  What was missing?  Tectonics! As I explained back on October 5, simulated collisions at the borders need to be calculated based upon pseudo-motion vectors.I was generating mountains at the edges of continental plates and trenches between oceanic plates, but I needed to take those collisions into account.

With collisions calculated at each border (boundary) cell

This turned out to be not as effective as desired.  The effects were utterly discontinuous, with gaps everywhere.  So I replaced precise calculates with a plate vs. plate decision upon what the effect would be via a couple calls to the pseudo-random number generator (PRNG) for each plate combination.  That proved much better, but was too uniform, and the "colliding" oceanic plates generated long islands that look like worms.


Worms!



To deal with the uniformity I added some Perlin noise.  You can see the impact of that below.

Plates with noise


Islands, not worms!
This left me with island chains rather than island chains rather than long, worm-like islands (mostly). However, the noise was a little too blurry when it came to the mountains, so switched from simple Perlin noise to fractal Brownian motion (fBm) with Perlin noise as basis.  I'm still experimenting with that.  I'll likely post more on that tomorrow.

Until then, good night.








Thursday, October 13, 2016

Book Review: 1636: The Ottoman Onslaught

Today say the release of the electronic Advanced Reader Copy (eArc) for Eric Flint's latest novel, 1636: The Ottoman Onslaught.  This is the latest mainline release of his hugely popular 1632 series. By mainline novel, I mean it focuses on some of the core characters from the first few novels, such as Mike Stearns, Rebecca Arabanel, Jeff Higgins, and Gretchen Richter.  It also includes a whole slew of the characters who first appeared in later works of the series, and many of the leading historical figures of Central Europe at the time.

I thoroughly enjoyed this novel.  In some respects, this has been a lot more fun of a read than some of the novels I've read in recent years.  I've enjoyed reading all of the books in the 1632 series, but some have a more light-hearted, fun-filled tone than others, even against a backdrop of war.  This one was filled with fun.  There's romance, adventure, airships, battles, airship battles, sieges, cavalry actions, and women in disguise.  There's random acts of kindness, and some just desserts are served.

WARNING: Extremely minor spoilers follow in the next two paragraphs.

One thing I particularly enjoyed was the steampunk-like nature of the Ottoman force itself, which nevertheless was all explicable and feasible, unlike the situation in many steampunk tales.  This extends to the airships; their existence and use by both sides is both easily explained, and practical.  It is not all about the coolness factor.

I have few complaints or criticisms, and they are fairly minor.  First, I'm still not fully convinced that American attitudes would have penetrated quickly as far, wide, and deeply as they have in the series, particularly that as many autocratic monarch have been willing to accommodate as much sociopolitical changes as they have.  Second, and it is a very minor thing, is that the Saxony/Silesia thread is something of a distraction; I suspect its presence in this novel was necessary to help keep the series moving along on some degree of synchronization.

These complaints should not keep you from rushing out to purchase a copy when it becomes available - or from purchasing the eArc now.  As an eARC, it is of course not yet proofed, and as a result contains one of my favorite typos of all times: "Alexandra the Great".  :) (EDIT: Strike that last part - not a typo.  It was correct in context.) I highly recommend this novel.  It was great fun and well worthy every dollar I spent.




I know how far it is to the border

I was trying to sleep when the answer came to me.  It's not fully correct yet, but almost.  There's a few implementation details I hope to clear up tomorrow evening.

Almost there!
I've more or less implemented Bresenham's algorithm (line drawing / digital difference analyzer). Once I get the last details ironed out, I can go on to the next steps and stop abusing what is supposed to be a crude elevation-based visualization mechanism to show plate boundaries and percentage distance from plate boundary (border) to centroid.

The key change to make is to follow the line all the way from centroid to the first border beyond the point we're trying to compute the nearest border of.  That way if we're dealing with concave shapes (like above) we can pick better select the nearest border, which may be between the centroid and the border.  It still won't always be correct for portions of some complex concave shapes, but it shall come close enough in most cases.

And now, back to bed.  Now that its not bugging me I can hopefully sleep.

Wednesday, October 12, 2016

How Far to the Border?

"How far to the border?"  When dealing with a raster-based set of plates, I need to know where the closest border is for each point on a tectonic plate.  Alas, creating code that answers that question in a timely manner has proven difficult.

Not right


This attempt was reasonably fast, but had only a parting resemblance to the correct result.  The plate boundaries and the centroid of the continental plates should be white, while the rest of the continental plates should be a gradient from black near the boundary to white near the centroid.  Clearly, that's not happening.  So I shall go back to it.

Good night, y'all.

Tuesday, October 11, 2016

Too Fried to Think

I'm too fried to think up much of a post today.  I'll just post a few pictures of approaches toward planet-wide terrain generation I've tried in past, but haven't liked the results of.  They started with a blobby (multiple, overlapping, roughly-circular shapes) supercontinent.

Split and plates moved randomly

Split and move plates toward "points of attraction" using a vaguely gravity-like model
Random movement with overlap limitations

Movement after splitting was random forced not to overlap.
Patterned movement (toward four corners) worked but produced results that were too similar each time

The next batch had a similar approach as the above examples, but added islands.  Again, I wasn't happy with the results.


Nearly-random movement, with overlap constraints, and islands
Another example with nearly-random movement, with overlap constraints, and islands

The next batch added simple mountain ranges along (roughly) the medial axis of the larger landmasses, and had smaller numbers of randomly-placed individual islands, but added island arcs.  I event attempted to simulate Aleutian-like archipelagos extending from continental mountains ranges into the sea. I think that worked out. . . poorly.

With island arcs and mountains
Another planet-wide map with island arcs, mountains, etc.