• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    11
  • comments
    28
  • views
    23566

Problems...

Sign in to follow this  
Followers 0
TheChubu

1489 views

Hi! So I wrote a little bit more. And this time I have pictures! Shiny pictures! Have in mind that I might jump around a lot since its kinda hard to summarize everything and have in mind I haven't finished this project so every decision I made it might be subject to change in the future.

Also, sometimes the links look black on my end so it might be hard to distinguish them from normal text.

[font='comic sans ms']

Problems...

[/font]


One of the various things that either the paper doesn't describes properly or I just don't understand them (4 page long paper? It's a trap!) is the secondary ridge line generation.

After some steps (say, 20 advance() method calls), the ridge particles are supposed to spawn two more ridge lines with opposite directions, with half the deviation from the main one in perpendicular direction to the main ridge that spawns them.

Spawning them isn't difficult. If the main ridge direction is (X,Y), their two child ridge particles would have (-Y,X) direction and (Y,-X) direction. They would proceed just like the main ridge particles but with half (one quarter in my case) the deviation of its parent.

This is the heightmap with the main and secondary ridge lines:

gauss.png

The paper mentions "blending" the ridge lines to compute the river network. It doesn't says with what criteria, nor if it means just blending the ridge lines or blurring all the height values, to end up with an image like the paper shows. I choose to do a gaussian blur pass over the heights to blend them all together.

[font='comic sans ms']

Blurry vision

[/font]


Plain ridge lines don't look right and it isn't enough height information for the next steps, we need to spread them around:

gauss_blurred.png

I found a very nice library for image filters Jhlabs.com. It has all sort of filters, though we're interested in the blurring ones.

The Java library operates on top of BufferedImage objects. Which means first and foremost that they're very easy to use. The first blurring passes I did were made with that library by "transforming" the height array into a BufferedImage, blurring it, then bringing out the new height values again to a float array.

It worked pretty well at first but after I while I had some problems. Pixel range is quite... limited. I could go only from 0 to 255 on fixed integer steps. So no matter how detailed were my height calculations, after some integer conversions they looked quite bad.

Say that you want to have 1m resolution, so one pixel is one meter. Thats quite great, you could compute a heightmap with a 2km x 2km surface and have some fun with it in no time. But on the height side, you're limited to 0-255 values (255m tall mountain isn't the definition of scary precisely) if you decide to go for a grayscale heightmap using the previous library.

So in the end I had to knock off my own gaussian blur pass which would work with the float array directly. Turns out not only works quite well, but it also takes half the time to compute than doing a filter pass over the BufferedImage. While integer operations on pixel colors should be quite cheap, there is a lot of bitshifting around plus many integer to float conversions (and viceversa), thus the blurring pass over the float array was a better option.

[font='comic sans ms']

Family, Ridges, and their limits

[/font]


Something that isn't very clear (to me at least) is that if the ridge lines really should stop only when they reach "null" height (I guess the author meant 0.0f ?). See, if the ridges are supposed to reach 0.0f, which would be the lowest point of your heightmap, then the river lines wouldn't be able to carve their way around when you spawn them later. They'd carve their way around the mountain side, then reach 0.0f immediately after and stop since you can't carve a river line anymore.

If you start your heightmap with a middle value, say, your heights go from 0.0f to 1000.0f, and you set all the initial height values to 500.0f. As it is, the ridge lines would carve their way all down to 0.0f before stopping, that is, the mountains would go under your landscape. Which not only looks bad, but it produces plain pools of river particles later on, which isn't helpful. Though I don't discard the possibility of doing canyons this way sometime in the future, it should work with some tweaking I guess.

For now, and as you might see on the previous pictures, I decided to set up an initial height value for all the map, the ridge lines go from their highest points all down until they reach the initial height of the height map instead of the lowest point. This leaves a lot of terrain for the river particles to produce more interesting lines. I made a few helper classes to map back the height values to BufferedImages so I can visualize the results at each stage, only generating the terrain without doing this in the middle should be quite fast.

So for now the ridge particles stop on any of these 3 conditions:

  • They reached the "bottom" of the heightmap, which is an arbitrary value, one quarter of the maximum height in my case.
  • They collided with another ridge particle (first one to discover it has collided stops, the other keeps going). Collisions within the same particle aren't considered.
  • They reached the limits of the heightmap.

    The child ridge line generation follows the same rules. In some rare cases child ridge particles they might collide with their parent's right after their first advance() method invocation since the child particles actually aren't "child" particles. They're normal ridge particles, thus they don't know their parent. Tragic story isn't it?

    Umm...

    So that does it for now biggrin.png There may be some ridge particle stuff that I forgot, I'll add it up to the next journal entry if I remember something valuable. Bye! biggrin.png

0
Sign in to follow this  
Followers 0


7 Comments


Seems like a fairly convoluted algorithm to implement, given that the results aren't really all that fantastic. Have you thought about just doing a basic erosion simulation on a ridged fractal generated terrain? After the erosion pass, you can do a waterflow sim to trace the rivers and fill the lakes, and the results are pretty decent.

0

Share this comment


Link to comment

I think that you are on to the "null value". Not having read the paper, I would assume that it is the baseline for the mountains, not necessarily the lowest point possible. So your "null value" would be added to what ever exists at the current height level, this would give nice smooth hills from a procedurally generated fractal or perlin heightmap, with steeper slopes climbing up from there due to the ridge algorithm. would love to see a finished 3d shot.

0

Share this comment


Link to comment

Seems like a fairly convoluted algorithm to implement, given that the results aren't really all that fantastic. Have you thought about just doing a basic erosion simulation on a ridged fractal generated terrain? After the erosion pass, you can do a waterflow sim to trace the rivers and fill the lakes, and the results are pretty decent.

Hmm... I thought the results from the last page of the paper looked pretty good. Though indeed this part looks quite boring, its the midpoint displacement part that gives it the bling bling needed biggrin.png

I'll try with an erosion algorithm with the ridged terrain, have in mind that the river particle generation (the next stage) is based on an erosion algorithm ("Erosion Based On Velocity Fields" paper I linked in the first journal), except for the sedimentation.

 

If I finish up the river generation process, it shouldn't be too hard I think to adapt that stage to a complete erosion pass on the terrain. I'd need to spawn more particles and add sedimentation to them.

 

I think that you are on to the "null value". Not having read the paper, I would assume that it is the baseline for the mountains, not necessarily the lowest point possible. So your "null value" would be added to what ever exists at the current height level, this would give nice smooth hills from a procedurally generated fractal or perlin heightmap, with steeper slopes climbing up from there due to the ridge algorithm. would love to see a finished 3d shot.

Exactly. I'm actually trying to implement the midpoint displacement stage right now, even if I don't have the river generation finished up (as it is, it traces the river a little then carves a giant hole in the ground). With what I already have, I should be able to get some results at least biggrin.png

 

What is fun about that stage is that if you have the "inverse" midpoint displacement and the midpoint displacement implemented, you can experiment a lot with it, since you just have to fed it with some data, and the algorithm fills the rest for you. Anyway, I'll have to wrap this up before that biggrin.png

0

Share this comment


Link to comment

I took the liberty of rendering out the height map. Looks pretty good.

I had to convert it to a 16 bit image, blur it slightly and add a bit of high frequency noise to get rid of the stair cased look you get when working with 8 bit displacement maps (the down-sampled one you posted).

 

Disp1.jpg

 

Disp2.jpg

1

Share this comment


Link to comment

Sweet! I'd +1 you but it says there is an error registering my vote :D Yep, the 8 bit range is the primary reason why I opted out of ImageBuffers. Hopefully I'll have some format set up at the end. Or I could just convert the values to ints, store them on the 24 bits of an RGB value. Which also works as long as you don't operate on the image as a real image (ie, no per-color operations).

 

I also plan to do some more work with the ridges later, to make them more coherent, like make them follow (mostly) a single direction. As they are its just a bunch of chaotic mountains.

Though everything should be tweakable. Deviation factors, individual ridge particle heights, stepping distance for varying the direction, child particle spawing, etc. Everything can give you a different look. If I play my cards properly, knocking off a map editor shouldn't be to tricky, but I'll have to wait and see for that. 

0

Share this comment


Link to comment

Looks pretty cool. I think it might be interesting to experiment with doing successive layers of the procedure, or going a level or two deeper into the simulation by spawning additional particles from the second-step particles. Real terrain exhibits fractal self-similarity; ie, mountain ridges often have ridges of their own which themselves can have even smaller ridges, something I don't really see being exhibited by a single pass of this algorithm as it stands. But perhaps multiple passes or deeper recursive splits might add the detail you would need. I especially like the potential application of extrapolating detail from data sets derived from real-world sources. Almost makes it a form of explicit sparse convolution noise in that regard.

0

Share this comment


Link to comment

Ah, that would be useful, the problem is that my code is a mess right now, I'd have to put it in shape for doing successive passes. I don't remember right now but there are a few places where it depends on some pre-conditions, for example, river generation can't happen if there are no ridges, since river particles are placed on top of the ridges.

 

I thought about spawning more ridges from the subridges, thing is, that information is only generated for the river network generation. Once the river particles are finished up, all the subridge information and blurred heights are erased and the map re initialized with the river and main ridge lines only.

 

Feeding it some real-world data sounds more involved. Though I guess its just a matter of thinking through it a bit. It would be very nice to have that feature.

 

I'll have to review all the logic once I'm finished.

 

Though I'm not sure if you know, did you see the paper or the previous journal entry? This is the first stage of the algorithm. Later there is a diamond-square pass that should add the missing detail that you're looking for. I'm making a journal entry about it right now biggrin.png

0

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now