Tell HN: My 3D terrain in Flash just went online
Flash Player 10 required. Allow for some delays in loading because our servers are in Russia.
Controls: drag to move, mousewheel to tilt. Secret tips for fellow hackers here: i toggles stats, m toggles mesh, t shows textures, s shows strips.
The location is Russian Caucasus, images are from IRS satellite, heightmaps are SRTM.
Actually we (my employer http://kosmosnimki.ru, a Russian online map) have covered the whole land area of the world below the 60th parallel. Changing the x and y parameters in the URL bar allows you to go elsewhere. Numbers are in meters, Mercator projection, WGS84 datum. I especially recommend the Himalayas, the Andes and Kilimanjaro, if you're smart enough to figure out the right numbers :-)
The code was written by me alone from scratch during this week. Two days of scribbling in a notebook until it got clear, then two days of frantic coding. No existing 3D engines like Papervision were used, it's all pure AS3 (well, haXe). About 1000 lines in total.
Any questions are welcome, especially questions about algorithms!
39 comments
[ 3.1 ms ] story [ 82.8 ms ] threadBarcelona, where I live :)
for ideas on how to solve it.
Personally, I think it's a bit of overkill for a specific problem (and I don't know if it actually occurred in practice, or it was only predicted that it would occur). Maybe the HN community can be trusted to not abuse linkified links? OTOH, it's an extremely minor niggle, and I agree that pg's time is better spent on preventing spam and keeping the community civil etc. That's way more important.
Meta-discussion like this is frowned upon, but I wanted to answer your question and also offer a solution: I solve this problem with a customable dictionary lookup addon for firefox, by adding a rule that just opens the highlighted string directly. I come across unlinkified URLs quite often.
1. Draw a big rectangle of flat-shaded ground (no textures, no heightmaps) tiled into triangles of equal size. Mouse navigation to fly over it.
2. Move the vertices vertically according to a formula - a procedural heightmap - e.g. a sine wave.
3. Add subdivision of triangles into smaller triangles as needed, like in ROAM (http://www.llnl.gov/graphics/ROAM/roam.pdf).
4. Solve hidden surface removal. This is easy because the triangles form a bintree-like structure, treat it as a BSP and draw back to front.
5. Implement loading of texture tiles. (Do you have those?) The scale of the texture to load for each triangle depends on its transformed Z value.
6. Implement loading of heightmaps in your preferred format.
7. Debug, optimize, debug, optimize, debug, optimize.
Did you try it with more naive mesh code? Meaning, applying a fixed triangle count, not varying the triangles based off the underlying elevation variation? My implementation with a fixed triangle count just bogs down like crazy when I add enough to get good detail in the mountains, and I never got around to a more intelligent method like yours.
Do you have any good links for me to read up, or is this just a large background of computer graphics? I have little computer graphics background, which made implementing a 3D terrain map a two week process for me.
I do have a large background in computer graphics. If I lost the knowledge and had to reconstruct it again, I would begin by writing simple demos in the lowest level environment I could find. Forget Papervision, try making a spinning textured cube by assigning colors to individual pixels using C code. This way you pick up the background awfully fast.
You gave me some hope now :)
Anyway, nice job. When I implemented ROAM and then Lindstrom/Pascucci's algo 8 years ago it ran like a dog on an antiquated SGI - I never would have dreamed something like this would run on the browser some day :)
Edit: Ah - never mind, I see you reference ROAM another comment. If you haven't read the paper referenced above you may enjoy it: http://www.pascucci.org/pdf-papers/vis2001.pdf
The basic data structure is taken from ROAM: a bintree of right triangles. It is regenenerated from scratch on every frame, recursively, starting from several top-level triangles. (So it's technically a multi-tree, I guess.) A triangle is split if the midpoint of the hypotenuse has a screen-space error of more than 10 pixels. Each triangle knows its children and neighbors, so each split can cause neighboring triangles to split to avoid T-junctions. (This was by far the trickiest part of the code, similar in difficulty to balancing a red-black tree.) I also take many not-quite-correct shortcuts, like stopping the splitting process if the triangle lies completely behind the camera or outside the screen bounds.
I believe the main reason my engine looks so good is because it uses satellite photos for textures - they hint at a lot of 3D detail that isn't expressed by the triangles. I render only 1 or 2 thousand triangles per frame, but they pretend to be a lot more, if you don't look at the ridges too closely. Try the m and i keys to look under the hood.