Enhancing terrain rendering engine
by Dave Myers · in Torque Game Engine · 02/05/2002 (11:46 am) · 19 replies
I've seen multiple threads in the forums wondering about how to either (a) increase the size of the map beyond 256x256 or (b) allowing multiple maps to be loaded. Apparently T1 supported the latter at least, but was not used so was dropped when it came time for T2. I thought I'd start a thread here to see if we can't figure out how to enhance the engine to do the above. I have some experience with graph theory and algorithms, so things like quadtrees are very interesting to me.
Starting with (b), I took a preliminary glance at the terrData.cc and terrData.h files to see what are the principle actors here. I am concerned, though, that there are places in the engine/editor that assume a size of 256x256, but I haven't dug in enough to determine if that's true.
After reviewing my references on quadtrees, it looks like the TerrainBlock contains most of the variables we need to look at first pertaining to size of the map. Examples include BlockSize, BlockShift, GridMapSize.
Things I think I know about TerrainFile and TerrainBlock:
o We will want a larger heightmap now - 512x512 let's say as an example, and the values below are based on that.
o It looks like the TerrainFile, which is responsible for building the GridMap is all set to go to support larger maps, as I see no hard-coded reference to size of heightmap or GridMap.
o TerrainBlock::squareSize should be 9 now - though I'm wondering about it's use elsewhere like the editor (terrainActions.cc) - haven't dug in enough yet to see how it's using this size
o TerrainBlock::GridMapSize is now 349525 or 0x55555.
o TerrainBlock::BlockSize should be 512 - this is the root node's width/height in the quadtree
o TerrainBlock::BlockShift should be 9 - our BlockSize is 2^n, and now we have 2^9 = 512
o TerrainBlock::BlockSquareWidth should be 512
o TerrainBlock::BlockMask should be 511
That's a start at least. Hopefully a couple others out there will join in on the fun. And maybe our gracious hosts, too. ;)
Dave Myers
21-6 Productions
Starting with (b), I took a preliminary glance at the terrData.cc and terrData.h files to see what are the principle actors here. I am concerned, though, that there are places in the engine/editor that assume a size of 256x256, but I haven't dug in enough to determine if that's true.
After reviewing my references on quadtrees, it looks like the TerrainBlock contains most of the variables we need to look at first pertaining to size of the map. Examples include BlockSize, BlockShift, GridMapSize.
Things I think I know about TerrainFile and TerrainBlock:
o We will want a larger heightmap now - 512x512 let's say as an example, and the values below are based on that.
o It looks like the TerrainFile, which is responsible for building the GridMap is all set to go to support larger maps, as I see no hard-coded reference to size of heightmap or GridMap.
o TerrainBlock::squareSize should be 9 now - though I'm wondering about it's use elsewhere like the editor (terrainActions.cc) - haven't dug in enough yet to see how it's using this size
o TerrainBlock::GridMapSize is now 349525 or 0x55555.
o TerrainBlock::BlockSize should be 512 - this is the root node's width/height in the quadtree
o TerrainBlock::BlockShift should be 9 - our BlockSize is 2^n, and now we have 2^9 = 512
o TerrainBlock::BlockSquareWidth should be 512
o TerrainBlock::BlockMask should be 511
That's a start at least. Hopefully a couple others out there will join in on the fun. And maybe our gracious hosts, too. ;)
Dave Myers
21-6 Productions
About the author
Considerable experience developing with Torque-based technologies and produced the first third-party game using any Torque technology (Orbz). Game designer, programmer, and producer, and credits include the innovative title Orbz and the colorful BuggOut.
#2
The rest looks right to me. I spent some time on this until I realized I was in over my head. It is possible I had all the right changes, but then I had to actually generate a 512x512 terrain to test my changes with. This turned out to be the killer for me (doh) since the function that will do this is not up to speed with the current terrain file format apparently. Mebbe I can find the code I altered for that (pretty sure I saved it)...
02/05/2002 (3:45 pm)
Quote:o TerrainBlock::squareSize should be 9 now - though I'm wondering about it's use elsewhere like the editor (terrainActions.cc) - haven't dug in enough yet to see how it's using this sizeTerrainBlock::squareSize is the size in meters of each square. You can alter that in a .mis file and it simply stretches the terrain, so I think this is a red herring.
The rest looks right to me. I spent some time on this until I realized I was in over my head. It is possible I had all the right changes, but then I had to actually generate a 512x512 terrain to test my changes with. This turned out to be the killer for me (doh) since the function that will do this is not up to speed with the current terrain file format apparently. Mebbe I can find the code I altered for that (pretty sure I saved it)...
#3
Would it be possible to treat the heightmap data as a set of triangle strips and our view of them as a window onto the strips? Such a window would allow us to limit the amount that could be seen to a reasonable amount for the system to handle and the nature of the strips would provide a way to rapidly search mathematically thru the file to get a strip in the direction a person is traveling. Think of it as a piano roll. Not too wide but you could make it very long. Or if you turned it not too tall but very long. The idea would be to have very large areas bordered by water or something to make it reasonable - Think North and South America- while still having a huge arena to play in. The paging would be a strip at a time in the direction the player moves.
02/05/2002 (7:23 pm)
One thing I was thinking of. I got the idea from something mentioned in another thread. Would it be possible to treat the heightmap data as a set of triangle strips and our view of them as a window onto the strips? Such a window would allow us to limit the amount that could be seen to a reasonable amount for the system to handle and the nature of the strips would provide a way to rapidly search mathematically thru the file to get a strip in the direction a person is traveling. Think of it as a piano roll. Not too wide but you could make it very long. Or if you turned it not too tall but very long. The idea would be to have very large areas bordered by water or something to make it reasonable - Think North and South America- while still having a huge arena to play in. The paging would be a strip at a time in the direction the player moves.
#4
Back to large pages. Sorry for the digression.
02/06/2002 (5:55 am)
Bad idea. While triangle strips would be incredibly easy to store, very, very fast and a window on the world could be rapidly generated, there would be a lot of disk paging and it would be really difficult to work with the editors and the lighting would be difficult to generate in real-time.Back to large pages. Sorry for the digression.
#5
I'm hoping to dig out (a) all hard-coded references that affect resizing the map and (b) how each of the constants in TerrainBlock and family need to be adjusted in order to support the resizing. I started that above and continued some below.
Some more things that I think I know (and some I don't) about the terrain renderer and the constants found in TerrainBlock:
o constructTerrainFile seems to be fine - this function actually reads in the terrain file and populates the TerrainFile object, which includes the mHeightMap, mMaterialMap, mBaseMaterialMap, and mMaterialAlphaMap. It then calls to buildGridMap(), which builds our quadtree.
o I'm not clear yet on why there is BlockSquareWidth and then BlockSize, both of which are currently 256. If they are truly interchangeable, then obviously we should set it to 512, also. Someone wanting to volunteer to dig a little on that would be helpful.
o I've been digging a little on the concept behind chunks and the mChunkMap found in the TerrainFile. mChunkMap is a (ChunkSquareWidth x ChunkSquareWidth) array, where ChunkSquareWidth = 64 currently. There is a dependency between the chunks and our block, which is the TerrainBlock::ChunkShift = BlockShift - ChunkDownShift. So, if we change BlockShift to 9, I think we can leave ChunkDownShift at 2, but we need to change ChunkSquareWidth = 128 in order for methods like TerrainFile::buildChunkDeviance to be able to calculate correctly what it needs. For instance, the first step that method performs grabs the GridChunk that corresponds to the passed-in (x,y) location:
Now, as an example, if we are passing in (1,0), the GridChunk = mChunkMap + 1 + (0 << 7) = mChunkMap + 1. Pretty simple. If we pass in (1, 1), though, we get GridChunk = mChunkMap + 1 + (1 << 7) = mChunkMap + 129 (the next row in our mChunkMap, as it is 128x128 now). This seems right at first glance, but I welcome any thoughts.
o TerrainBlock::ChunkSize - the only place I see this being used in the engine is in TerrainBlock::setHeight. This in turn is only called from TerrainEditor::setGridHeight, so it's obviously an editor function only for now. I'm not clear why the ChunkSize is set to 4 yet, however. It looks like it is fine to leave it as that at first glance.
Looking for hard-coded references to current map size:
o TerrainBlock::buildMaterialMap has some hard-coded references to 256, but there are in essence commented out with an #if 0, so we don't need to worry about those.
o fluid::SetInfo contains hard-coded references to a quarter of a terrain block (which is 128x128 currently). However, I'm thinking this is fine.
o GuiTerrPreviewCtrl::onRender has set mTerrainSize = 8*256, which doesn't look good, until you notice that it is simply a default value. It actually uses our nice TerrainBlock constants to initialize the terrain size for this control.
o However, a little further down it has a nested loop for rendering the '+' at the center of the block that uses hard-coded references to 256. This seems like it needs to use one of our constants.
o Terraformer::Terraformer() also has a default value of 256 for block size (among others) that seems like it should be using on of our constants.
o Terraformer::setTerrain has a line of code that looks like it should use a constant, also.
Whew, okay, that's enough for that post.
Dave Myers
21-6 Productions
02/06/2002 (11:01 am)
Ok, Tim, that helps - wasn't sure what that field was exactly. And if you've already done some work, maybe you can dig into it and post what your direction was and any thoughts.I'm hoping to dig out (a) all hard-coded references that affect resizing the map and (b) how each of the constants in TerrainBlock and family need to be adjusted in order to support the resizing. I started that above and continued some below.
Some more things that I think I know (and some I don't) about the terrain renderer and the constants found in TerrainBlock:
o constructTerrainFile seems to be fine - this function actually reads in the terrain file and populates the TerrainFile object, which includes the mHeightMap, mMaterialMap, mBaseMaterialMap, and mMaterialAlphaMap. It then calls to buildGridMap(), which builds our quadtree.
o I'm not clear yet on why there is BlockSquareWidth and then BlockSize, both of which are currently 256. If they are truly interchangeable, then obviously we should set it to 512, also. Someone wanting to volunteer to dig a little on that would be helpful.
o I've been digging a little on the concept behind chunks and the mChunkMap found in the TerrainFile. mChunkMap is a (ChunkSquareWidth x ChunkSquareWidth) array, where ChunkSquareWidth = 64 currently. There is a dependency between the chunks and our block, which is the TerrainBlock::ChunkShift = BlockShift - ChunkDownShift. So, if we change BlockShift to 9, I think we can leave ChunkDownShift at 2, but we need to change ChunkSquareWidth = 128 in order for methods like TerrainFile::buildChunkDeviance to be able to calculate correctly what it needs. For instance, the first step that method performs grabs the GridChunk that corresponds to the passed-in (x,y) location:
GridChunk &gc = *(mChunkMap + x + (y << TerrainBlock::ChunkShift))
Now, as an example, if we are passing in (1,0), the GridChunk = mChunkMap + 1 + (0 << 7) = mChunkMap + 1. Pretty simple. If we pass in (1, 1), though, we get GridChunk = mChunkMap + 1 + (1 << 7) = mChunkMap + 129 (the next row in our mChunkMap, as it is 128x128 now). This seems right at first glance, but I welcome any thoughts.
o TerrainBlock::ChunkSize - the only place I see this being used in the engine is in TerrainBlock::setHeight. This in turn is only called from TerrainEditor::setGridHeight, so it's obviously an editor function only for now. I'm not clear why the ChunkSize is set to 4 yet, however. It looks like it is fine to leave it as that at first glance.
Looking for hard-coded references to current map size:
o TerrainBlock::buildMaterialMap has some hard-coded references to 256, but there are in essence commented out with an #if 0, so we don't need to worry about those.
o fluid::SetInfo contains hard-coded references to a quarter of a terrain block (which is 128x128 currently). However, I'm thinking this is fine.
o GuiTerrPreviewCtrl::onRender has set mTerrainSize = 8*256, which doesn't look good, until you notice that it is simply a default value. It actually uses our nice TerrainBlock constants to initialize the terrain size for this control.
o However, a little further down it has a nested loop for rendering the '+' at the center of the block that uses hard-coded references to 256. This seems like it needs to use one of our constants.
o Terraformer::Terraformer() also has a default value of 256 for block size (among others) that seems like it should be using on of our constants.
o Terraformer::setTerrain has a line of code that looks like it should use a constant, also.
shift *= 256.0/(TerrainBlock::BlockSize*terrBlock->getSquareSize());
Whew, okay, that's enough for that post.
Dave Myers
21-6 Productions
#6
Well, if you want a terrain that's just a little bigger than the terrain supported by torque, changing the size to 512x512 would probably be the easiest course.
But, if you want to have incredibly large worlds, you'll need to go multi-block at some point... for these, I'd keep the TerrainBlock size the way it is and just use multiple TerrainBlock objects that stitch together. The terrain render code is already essentially set up to do this, but it always uses the same block. In terrRender.cc:renderBlock in the section started with PROFILE_START(TerrainRenderRecurse), the terrain engine computes which squares on the infinite terrain grid are potentially visible (based on the vis distance), and then recurses the heightfield on each visible block.
So, one way to add multi-block support would be:
Create a new TerrainManager class that has an initial transform and an array of terrain blocks/grid positions for those blocks.
Move the prepRenderImage and renderObject calls from TerrainBlock into TerrainManager.
Change TerrainRender::renderBlock to take a TerrainManager object, and iterate through its blocks. In the heightfield recurse set mCurrentBlock to the current terrain block within the TerrainManager.
Add a currentBlock field to the AllocatedTexture object, then change the buildBlendMap function to use the texture's block's blender object to generate the texture.
Remove ghosting functionality from TerrainBlock and move it into TerrainManager. This will just transfer the TerrainManager object to the client.
Initially have the TerrainManager construct and intiailize all the TerrainBlocks that it has registered. Once this works, experiment with streaming blocks in as they become visible.
The terrain editor only works on individual blocks, but that shouldn't be a problem... make it so that edits outside the current block change which block is being edited.
Hmm... could be a bit of work :)
02/06/2002 (11:02 am)
Ok, where to start...Well, if you want a terrain that's just a little bigger than the terrain supported by torque, changing the size to 512x512 would probably be the easiest course.
But, if you want to have incredibly large worlds, you'll need to go multi-block at some point... for these, I'd keep the TerrainBlock size the way it is and just use multiple TerrainBlock objects that stitch together. The terrain render code is already essentially set up to do this, but it always uses the same block. In terrRender.cc:renderBlock in the section started with PROFILE_START(TerrainRenderRecurse), the terrain engine computes which squares on the infinite terrain grid are potentially visible (based on the vis distance), and then recurses the heightfield on each visible block.
So, one way to add multi-block support would be:
Create a new TerrainManager class that has an initial transform and an array of terrain blocks/grid positions for those blocks.
Move the prepRenderImage and renderObject calls from TerrainBlock into TerrainManager.
Change TerrainRender::renderBlock to take a TerrainManager object, and iterate through its blocks. In the heightfield recurse set mCurrentBlock to the current terrain block within the TerrainManager.
Add a currentBlock field to the AllocatedTexture object, then change the buildBlendMap function to use the texture's block's blender object to generate the texture.
Remove ghosting functionality from TerrainBlock and move it into TerrainManager. This will just transfer the TerrainManager object to the client.
Initially have the TerrainManager construct and intiailize all the TerrainBlocks that it has registered. Once this works, experiment with streaming blocks in as they become visible.
The terrain editor only works on individual blocks, but that shouldn't be a problem... make it so that edits outside the current block change which block is being edited.
Hmm... could be a bit of work :)
#7
On a seperate (but quirkily related) subject Mark, where is the heuristic to calculate the tesselation depth of a particular part of the terrain? I'd like to have a fiddle with it to lower the polycount on my terrains (right now the polycount for the terrain is higher than I need and slows my machine a little, plus I want to see how much speed difference i get on my TNT2 to see if its worth doing some optimisation (and see if it effects the collision speeds)).
I can dig it out, but if you know off the top of your head it'd help.
Thanks.
Phil.
02/06/2002 (11:38 am)
Hehehe.. naaah, sure its just a 5 minute job :))On a seperate (but quirkily related) subject Mark, where is the heuristic to calculate the tesselation depth of a particular part of the terrain? I'd like to have a fiddle with it to lower the polycount on my terrains (right now the polycount for the terrain is higher than I need and slows my machine a little, plus I want to see how much speed difference i get on my TNT2 to see if its worth doing some optimisation (and see if it effects the collision speeds)).
I can dig it out, but if you know off the top of your head it'd help.
Thanks.
Phil.
#8
So, the question is: is it feasible (read this as not impossible but is it practical) to have more control (more tesselations) in designated local areas? In other words, if I'm building a terrain that has a couple areas that need finer shape control, could I localize it to that square without the fps killer of doing this to the entire terrain?
02/06/2002 (12:49 pm)
OK, two more cents...given the default squareSize = 8, we have a terrain that's a bit over a square mile. At that resolution though, its difficult to marry up the terrain with difs in certain situations. When faced with this problem, i've reduced the squareSize and the waterblock size--works fine. But I'd still like the larger area.So, the question is: is it feasible (read this as not impossible but is it practical) to have more control (more tesselations) in designated local areas? In other words, if I'm building a terrain that has a couple areas that need finer shape control, could I localize it to that square without the fps killer of doing this to the entire terrain?
#9
I'm off to be a wizard...
a wonderful, wizard like id...
I hear I is, a wiz of a wiz...
If ever a wiz there wuz...
His hat slips down suddenly over his nose. Unable to see he stumbles and falls flat on his face.
"Damn terrain!", he mumbles. Reaching out in the darkness he feels a sharp paper thin point.
"Hmmm, could this be the edge of the universe? I'd better take a look"
He leans forward blindly groping for the elusive unknown and is last seen falling down thru an endless series of quirky planes, muttering.
"So far, so good."
"I think I need some coffee."
02/06/2002 (2:13 pm)
Sounds like Desmond could use Phil's answer to raise the polycount for his terrain. Cool two birds with one stone. Thanks for the roadmap Mark. I'm sure that it's no yellow brick road, but I'm off to be a wizard...
a wonderful, wizard like id...
I hear I is, a wiz of a wiz...
If ever a wiz there wuz...
His hat slips down suddenly over his nose. Unable to see he stumbles and falls flat on his face.
"Damn terrain!", he mumbles. Reaching out in the darkness he feels a sharp paper thin point.
"Hmmm, could this be the edge of the universe? I'd better take a look"
He leans forward blindly groping for the elusive unknown and is last seen falling down thru an endless series of quirky planes, muttering.
"So far, so good."
"I think I need some coffee."
#10
02/06/2002 (2:29 pm)
ROFL
#11
You mentioned that you had trouble building a new 512x512 terrain file to test your changes. If it's any help, I believe you can just create it in VC++ if that's what you're using. I created one real quick that way by dragging and dropping a pretty blank terrain file (flat, one material) into the editor and then copy and pasting the sections I needed according to the file format. I haven't tested it (will try tonight), but let me know if you'd like it.
Dave Myers
21-6 Productions
02/07/2002 (9:47 am)
Tim,You mentioned that you had trouble building a new 512x512 terrain file to test your changes. If it's any help, I believe you can just create it in VC++ if that's what you're using. I created one real quick that way by dragging and dropping a pretty blank terrain file (flat, one material) into the editor and then copy and pasting the sections I needed according to the file format. I haven't tested it (will try tonight), but let me know if you'd like it.
Dave Myers
21-6 Productions
#12
02/07/2002 (11:55 am)
Help me understand exactly what the goal here is: you're trying to double the worldsize (importing a 512x512 heightmap to produce a terrain that is 4096 world units on a side) but keep the squareSize at 8? Which would mean that instead of 256 terrain squares on a side there would be 512? And of course, this could be varied by changing the squareSize variable.
#13
David: I looked and looked and I can't find the code I know I saved. I was some time ago, so it may be archived to CD, in which case I may never find it (doh) since they are not particularly organized (hell, half of them are stuck between books on the bookshelf - I can't even find them all). So much for useful backups...
02/07/2002 (12:40 pm)
Desmond: I believe that is what we are after, yes.David: I looked and looked and I can't find the code I know I saved. I was some time ago, so it may be archived to CD, in which case I may never find it (doh) since they are not particularly organized (hell, half of them are stuck between books on the bookshelf - I can't even find them all). So much for useful backups...
#14
www.garagegames.com/index.php?sec=mg&mod=resource&page=result&qtm=Terrain%20LOD
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=258
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=321
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3319
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3414
(shameless self-promotion)
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=482
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=445
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1821
(no GG stuff, but usefull)
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=4029
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3312
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2471
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2341
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1670
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1100
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2293
--Bryan
03/31/2002 (7:59 pm)
Stitching together a 'fabric' of terrain posts... These are posts which contain significant responses from the GG crew:www.garagegames.com/index.php?sec=mg&mod=resource&page=result&qtm=Terrain%20LOD
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=258
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=321
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3319
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3414
(shameless self-promotion)
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=482
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=445
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1821
(no GG stuff, but usefull)
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=4029
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=3312
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2471
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2341
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1670
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=1100
www.garagegames.com/index.php?sec=mg&mod=forums&page=result.thread&qt=2293
--Bryan
#15
Who's seriously working on this? How much headway has everyone made? I'm getting to the point where I need the functionality of larger terrains and if nobody has made any progress then I'll tackle it.
04/01/2002 (8:49 am)
Hrm... haven't I read this somewhere else? heh... again, thanks for the compilation, Bryan.Who's seriously working on this? How much headway has everyone made? I'm getting to the point where I need the functionality of larger terrains and if nobody has made any progress then I'll tackle it.
#16
Something else that would be great on the terrain renderer: bump mapped texture support for G3/4 and ATI...
David
04/01/2002 (11:43 pm)
Hi,Something else that would be great on the terrain renderer: bump mapped texture support for G3/4 and ATI...
David
#17
Thanks for all the great work everyone has done here!!
08/20/2003 (2:58 pm)
Hi, I'm new to TGE as of this week (yay! what a great engine!!) and am just wondering whether anyone has taken off yet in the direction of stitching together blocks of terrain, as per Mark Frohnmayer's post? I'm interested in using TGE for real world simulations implementing USGS DEM data, so repeated terrain is not an option. Thanks for all the great work everyone has done here!!
#18
08/20/2003 (3:18 pm)
Do a search for Terrain Manager, there is a lot of interest in making bigger worlds there.
#19
I too am very interested in this concept, but I think it needs a major overhaul.
09/01/2003 (12:57 pm)
All progress on this seems to have stopped. As far as I can find, there is not a working version of the Terrain Manager for HEAD anymore. All conversations seemed to stop a few months ago and most of the links are dead.I too am very interested in this concept, but I think it needs a major overhaul.
Torque Owner David Dougher
Pariah Games
This was one reason I had hoped that Tim and Mark would do this for us. Tim did the original T1 terrain and Mark did the T2 terrain and the most recent editor changes. However, as long as somebody at GG is willing to tell us where we are messing up I'm willing to poke around.