Well, it's been a busy October for OpenSimEarth!
We're still totally under construction and not ready for business yet, of course, but this seemed like a pretty good time to report back. If you're interested in checking out the repos, see my last post on the subject for URLs.
The quick summary, as hinted in the title: I now have a somewhat functional system for paging streets (mesh roads) and forests as you travel around the world.
The streets are a further development from this post, and they follow directly from the work I did with the forests.
Torque has a very nice forest rendering system, capable of rendering impressive numbers of trees at very low cost... but at some point, even it will become unusable if you just keep stuffing trees into it forever. Since my goal is an open and virtually infinite world, I needed to have a way to control the forested area and keep it centered on the player.
My (somewhat predictable) solution was to subdivide my terrain tiles into a grid of forest cells, and load and drop them as the player moves around the map.
I needed to paint the forest procedurally, of course, so I copied the random forest painting technique from the forest brush tool into a function designed to fill a single cell, and then worked up a little logic to keep track of which cells around the player had been filled already and keep filling and dropping them as we move.
Oh, before I forget, I did some things that could be of general interest here. First, if you ever get tired of painting forest with brushes arbitrarily limited to 150m in radius, the fix for that is in forestBrushTool.cpp, line 307:
void ForestBrushTool::setSize( F32 val )
mSize = mClampF( val, 0.0f, 15000.0f );//150.0f
Con::executef( this, "syncBrushToolbar" );
I'm not using the brush tool anymore, but that really annoyed me for a while, thought it might help somebody.
Second, I added a couple of functions that I think really ought to be included in stringFunctions.h. I'll be glad to submit it as a PR, but if anyone on the steering committee just wants to copy and paste them from here, that would be fine too, they're quite trivial. But unless I missed something there didn't seem to be a "Torque way" to convert char strings to long or double values:
inline long dAtol(const char *str)
return strtol(str, NULL, 10);
inline double dAtod(const char *str)
return strtod(str, NULL);
Anyway, once I got my forests paging around the map with me, I moved on to the next step, which was filling different areas with different types of forest. So far I've only accomplished the first part of this process, which was differentiating forest cover based on terrain texture. For my ultimate solution I intend to do this in addition to having arbitrary landcover polygons that I can place anywhere, but... one thing at a time.
Since I was already scheming about how to incrementally load both street nodes and other placed objects, this forest cell system led me right on to other things. However, the first thing I had to figure out was how to make sure the forest didn't get placed in the roads. (I was actually a little surprised Torque didn't do this already.) I'm still unsure about the best way to handle decal roads, but with meshroads it was possible to get a different object type from a castray function, so I added the following line to my getGroundAt function stolen from forestBrushTool:
if ( !hit || strcmp(rinfo.object->getClassName(),"TerrainBlock"))
If you want the same behavior with your forestBrushTool, you can go there (forestBrushTool.cpp, line 673) and do the same thing. (Does this want to be pulled into the main trunk as well?) In addition to roads, it also keeps forests from growing on rocks or houses or any other static object. Not sure if a lot of people need contradictory behavior or not, for me this seems to work pretty well.
Along the way here I lost a couple of days getting very excited about something called SpatiaLite, which is an add-on for SQLite to support GIS logic. I'm still hoping I get to move there sooner or later, because it sounds like THE way to do what I'm trying to do on my own here, but I found a large number of obstacles involved in compiling and using it with Visual Studio and ended up backing away in defeat with my tail between my legs. My primary goal was to be able to do efficient regional searches of a potentially very large geographic database, and what I ended up doing was inventing a lat/long based cell tag for all of my street nodes (looking like "123d0834W_44d0566N"), and then creating an index on that tag to make it search faster. It wastes a little memory, and it's still too slow, but it definitely helped.
There's still a lot of work to do, of course, in many different directions. I'm setting road widths and (to the extent I have textures available, which is very little) road textures based on the highway type specified in the OpenStreetMap data. I hope to extend the same logic to rivers and streams, but I'll need to do terrain modification for them, and of course that would also help a lot with roads, to flatten the terrain underneath them.
Finally, as mentioned above, I'd love to find an easy way to detect decal roads with a raycast, anybody got any ideas on that? I'm using all mesh roads right now just because they're the only ones I can detect to keep the forests out of them.
Oh, also, I don't expect any magic help here for this one, but I'm running into a really annoying render glitch with my forests... at times, they seem to just not work at all, but when I raise my camera up a bit in free camera mode, they pop back in. You can see an example around the 0:21 point in this video, which demonstrates the current system: