Author Topic: Terrain Brushes  (Read 3417 times)

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« on: September 10, 2006, 03:17:10 PM »
Well, this weekend I was able to implement basic terrain brushes in OP2Mapper 3. That is, a point and click way to place terrain and have the mapper do the edges for you, like most map editors.



As you can see it's pretty primitive right now, due to the way the OP2 transitions work.

My brush system works by dividing each tile into 4 pieces / corners. Each corner is assigned a value which corresponds to a certain brush / terrain type.

When the user places a tile, the mapper fills in the top, left, right, and bottom edges with transition pieces that match up (matching is determined by comparing pieces that touch on tile edges). It then fills in the other corners as well based on the edge pieces already placed. Example:

Code: [Select]
+--+--+
|ab|ef|
|cd|gh|
+--+--+

The numeric value assigned to piece 'b' must equal that of 'e', likewise 'd' must equal 'g' to match the two tiles left to right. If they don't match, a tile is selected on the left side that would match. If a match still isn't found, the mapper doesn't modify that tile (the mapper can't continue since it can't 'guess' what tile should go there, it has to use a list of definitions).

The problem is, in the tileset there are various transition pieces that work, but have to match up correctly with each other to look right (for example, two top to bottom grey->orange transitions. One has more orange than the other. Placed side by side they wouldn't look right). Thus I need to find out a reasonable way to do this (I want to keep the quarters system because it's simple to implement and use). Perhaps by using some sort of exclusion list, i.e. Tile A cannot appear next to Tile B.

Programming a more complex system (i.e. something that divides a tile into 1/16ths) isn't hard to do. The problem lies in the definition of the tile pieces themselves; that is, it would place a lot more work on the person writing the definitions / the tileset designer.

Currently, it stores the terrain type definitions in a "terrains.ini" file, with a format like so:

Code: [Select]
;Header section describing the terrains. The names are just used by humans, the mapper doesn't know or care about them.
[TerrainInfo]
;Number of terrain types
NumTerrains=2
0=Lava Flow
1=Rocky Terrain

;Now come the tile definitions. They have a format:
;tileID=nw,ne,sw,se
;where nw/ne/sw/se are the terrain IDs (0 or 1 as defined above) assigned to each corner of the tile
;There are sections for each tileset name, as you can see
[well0001]
0=1,1,1,1
;so on...

[well0006]
;This set contains some transition pieces
6=1,0,1,0
;This would specify that the left half of the tile is rocky terrain, the right half is lava terrain.

Adding more pieces (16ths as in the example before) would make it even more complex. Even when creating datasets for only about 30 transition pieces, it was a nerve-wracking experience, with lots of mistakes and backtracking.

I have plans to change the file format as well (I kinda like INI with the sections and all, but there are a few features I want to add, such as C/C++ #include type statements, maybe defines / symbolic constants like ROCKY=1, etc. Also, the built in windows INI reading functions are _very_ slow).

Kudos goes to Sirbomber for encouraging me to look at the code of another map editor (where I got the quarters idea from).

If you have any creative ideas on how I can solve the matching problem without making a lot of work / mess for both myself / the person editing terrains.ini, let me know. Same goes for any suggestions / wanted features on the terrain editor.

-- op2hacker

Offline dm-horus

  • Hero Member
  • *****
  • Posts: 1047
    • Division 32 Community
Terrain Brushes
« Reply #1 on: September 10, 2006, 07:22:54 PM »
Very nice work, Hacker!!! Im getting excited about this version of the mapper. Im sure the whole community appreciates all your hard work. Keep it up!
Always outnumbered. Never outgunned.

Offline Freeza-CII

  • Administrator
  • Hero Member
  • *****
  • Posts: 2323
Terrain Brushes
« Reply #2 on: September 10, 2006, 09:49:31 PM »
Of course we like his work because we dont want to do it HEHEHEHEHEHEHE

Offline TH300

  • Hero Member
  • *****
  • Posts: 1425
    • http://op3game.net
Terrain Brushes
« Reply #3 on: September 11, 2006, 04:02:35 AM »
I'd prefer a system with 1/16s. We will need the accuracy.

one tile might look like this:
Code: [Select]
+----+
|abcd|
|efgh|
|ijkl|
|mnop|
+----+

We could leave out f,g,j,k , because they are not at the edge.

Now, when trying to find a tile that fits at the right edge, e.g.
Code: [Select]
+----+
|qrst|
|u  v|
|w  x|
|yzzz|
+----+
d must equal q, h must equal u and so on.

And here comes my idea:
store 4 lists in the ini-file, one for every edge, e.g.
Code: [Select]
[LEFT]
....
[TOP]
....
[RIGHT]
....
[BOTTOM]
....
And in more detail (with random values):
Code: [Select]
[LEFT]
0,0,0,0=2,3,4,5,...
1,1,0,0=10,16,33,37,40,84,...
1,1,1,0=15,32,39,56,62,...
...

following the scheme "Terrain types at this edge = list of tiles that have them".
This way the mapper won't have to search for the right tile. - The mapper knows that a tile with a certain left edge (e.g. 1,1,0,0) has to be found, thus looks at the
list (which is sorted and probably in array form, internally), then picks one of 10,16,33,37,40,84.


There's still lots of work to be done to create those lists. I could help with that.
 

Offline Leviathan

  • Hero Member
  • *****
  • Posts: 4115
Terrain Brushes
« Reply #4 on: September 11, 2006, 05:04:51 AM »
Great work :)

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #5 on: September 25, 2006, 12:58:24 PM »
Well, I worked on this recently and the 16-tile system (well, really 12 since the middle tiles don't matter) is working pretty nicely.

A lot more accuracy is possible (but again, it's only as accurate as the terrain definitions in the ini file).

I also changed the way data is entered into terrains.ini, and I think this method makes it a lot more reasonable for people to type in (i.e. faster and less error-prone).

Rather than dividing a tile into a grid like I did before, I now use 6 pieces of information to determine the 12 cells in a tile:
Code: [Select]
[tileset name]
tile_id=terrain1,terrain2,percentN,percentS,percentW,percentE

terrain1 and terrain2 are terrain type ID's, simple enough.

The percent[N/S/W/E] are simply ratios of terrain1 to the total terrain on the given edge expressed as a percent, starting from the top left corner going to the bottom right. So, for example, if you have a tile which is a vertical grey/black transition, with grey on the left side of the tile, black on the right, and assuming it is exactly 50/50 (split right down the center of the tile vertically), you would have the following definition (assuming it is tile ID 0, black is terrain type 0, grey is terrain type 2):
Code: [Select]
0=2,0,50,50,100,0

To recap, the definition literally means:
There are two terrains in the tile, grey (2) and black (0). On the north and south edges, starting from the left corner, the first 50% is grey, the rest is black. On the west side, it is entirely grey (100% terrain1). On the east side, it is entirely black (0% terrain1).

I know some of you are saying that there is some problem. What if you wanted to say that the RIGHT part of the north edge is terrain1? Well, for that I just use negative percent values. The negative just forces the engine to start at the bottom/right corner of an edge when evaluating the percent data. For 0 and 100 it doesn't make sense (since interpreting in this manner, 100 is the 'negative' of zero in this case, if you get my drift).

There are 5 magnitudes possible for the percents: 0, 25, 50, 75, and 100 (since internally tiles are divided into 1/16ths, minus the middle 4 pieces).

Hopefully all of this makes sense. It took me a while to come up with it but it makes defining tile data so much easier.

Let me know any suggestions/comments you have.
« Last Edit: September 25, 2006, 01:01:10 PM by op2hacker »

Offline Sirbomber

  • Hero Member
  • *****
  • Posts: 3172
Terrain Brushes
« Reply #6 on: September 25, 2006, 01:50:03 PM »
Show us pictures of the new system.
"As usual, colonist opinion is split between those who think the plague is a good idea, and those who are dying from it." - Outpost Evening Star

Outpost 2 Coding 101 Tutorials

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #7 on: September 25, 2006, 02:15:45 PM »
There aren't really any pictures... it still looks the same, but with less errors.

And I still have to finish up the code that generates corners (NW, NE, SW, SE of the tiles). Right now it doesn't look correct until that is completed. Then I will get a picture (again won't look too much different).

Offline TH300

  • Hero Member
  • *****
  • Posts: 1425
    • http://op3game.net
Terrain Brushes
« Reply #8 on: September 26, 2006, 08:44:30 AM »
how does that work for tiles with three terrain types?

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #9 on: September 28, 2006, 01:31:30 PM »
Right now there's no way to handle 3 terrain types. (I don't believe OP2 has any tiles with 3 terrain types?)

What I will probably do however to make this possible, is just check to see if 12 comma-delimited values are entered instead of 6. (12 values = terrain type at each cell in the tile). This way most tiles can be represented using a simpler method, where tiles that can't be represented that way can be represented the 'conventional' way.

Offline TH300

  • Hero Member
  • *****
  • Posts: 1425
    • http://op3game.net
Terrain Brushes
« Reply #10 on: October 07, 2006, 12:43:42 PM »
Quote
Right now there's no way to handle 3 terrain types. (I don't believe OP2 has any tiles with 3 terrain types?)

What I will probably do however to make this possible, is just check to see if 12 comma-delimited values are entered instead of 6. (12 values = terrain type at each cell in the tile). This way most tiles can be represented using a simpler method, where tiles that can't be represented that way can be represented the 'conventional' way.
Sounds good.

And there is at least one tile with 3 terrain types in the original tileset.

Offline Mcshay

  • Administrator
  • Sr. Member
  • *****
  • Posts: 405
Terrain Brushes
« Reply #11 on: October 08, 2006, 04:13:52 AM »
I just looked though the tiles, and couldn't find a single tile that uses three types. However you can combine two tiles ingame to make something that might be mistaken for a tile with three terrain types.

Offline TH300

  • Hero Member
  • *****
  • Posts: 1425
    • http://op3game.net
Terrain Brushes
« Reply #12 on: October 09, 2006, 08:41:09 AM »
You are probably right. I didn't use the mapper for some time (and can't right now). So my memory might very well be wrong.

Nontheless the mapper should support 12 terrain types on a tile.

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #13 on: October 09, 2006, 01:07:04 PM »
Quote
You are probably right. I didn't use the mapper for some time (and can't right now). So my memory might very well be wrong.

Nontheless the mapper should support 12 terrain types on a tile.
Yes, that will be possible. As I recall the mapper uses signed 16 bit integers to store terrain type values (which should mean 16,384 possible terrains) -- which doesn't make a lot of sense anyway since there is a 2048-mapping limit on the map.

There are no other internal limitations that would prevent the mapper from being able to use 12 different terrain types on a tile.

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #14 on: October 18, 2006, 05:07:01 PM »
Well, I went at it and changed the system again.

After writing the 1/16ths code I realized a problem: Some tiles still won't fit perfectly into the grid. There are some tiles which look much like this:


Imagine what would happen if it was divided into a 4x4 grid. There would be ambiguity in interpreting, say the upper left corner (consider it to be (0,0) on the 4x4 grid). If the tile was placed below the main / base tile it would have to be considered as 'black' in relation to that tile (since the main tile is adjacent to the black part). However, if it was placed to the right of the main tile then that piece would have to be 'white' in relation to the main tile.

Thus, I changed it so the percents system is used completely in code, this way the mapper looks at the tile in terms of a percentage of terrain covering each edge instead of a 4x4 grid. The only issue with this is the fact that it completely eliminates the possibility of there being more than 2 terrain types on a single tile. (Not that OP2 actually has 3 terrain types on a single tile anywhere in the tileset AFAIK)

However, there are still major issues with the terrain matching up. This prompted me to change the code so when placing a tile at the north, south, west, or east position, it will throw away possible matches with 100% of any one terrain covering the edges perpendicular to the base tile edge. (i.e. for the north position, the west and east edges must contain a transition; they cannot be fully one terrain or the other).

This helped a little bit but it's still very, very rough:


Not much of an improvement over the 2x2 system (possibly even a step backwards).

Looking at the generated terrain, the conclusion I am coming to is that it is placing tiles for the cardinal directions (N/S/W/E) which cannot be matched up to on the intermediate directions (NW/NE/SW/SE). The intermediate tiles are determined based on the cardinal-direction tiles (i.e. for the southwest tile to fit, it must perfectly match the south edge of the west tile, and the west edge of the south tile).
For example an unusual transition such as what you see in the middle of the picture below:


There are no tiles that could suitably match to the left and right of those pieces so they are filled in with "bad" pieces.

The reason for this is because the mapper has no sort of "memory" or way of checking for tiles already there when the mouse is being dragged. It does the following:

1. Location where user clicks is filled in with solid tile.
2. North, south, east, and west are filled in with transitions which will match up to to the middle tile.
3. NW/NE/SW/SE are filled in based off of the tiles placed for N/S/W/E.

I am probably going to change this so the mapper looks at surrounding tiles, and tries to match up with the existing tiles to make smoother transitions. I also might scan the tiles and have it generate some sort of 'exclusion set' which would prevent it from using certain tiles except in cases (i.e. corners).

If you have any good ideas for improving the system other than what I've mentioned here please let me know.

Offline White Claw

  • Hero Member
  • *****
  • Posts: 598
Terrain Brushes
« Reply #15 on: October 22, 2006, 06:47:05 PM »
I don't know how the terrain in OP2 is organized, but when I built my own terrain editor I used a bitwise mask scheme. On a 3x3 grid, each grid location had a value. That value was a 4-bit (16) value that was assigned to the tile type subset.

A transition tile set that was dirt to lava would have all the variations of tiles laid out to do bit wise math. Tile 0 (0000) is all dirt. Tile 15 (1111) is all lava. Tile 1 (0001) is 3/4 dirt and 1/4 lava in the bottom right corner (or whatever). All the tiles repeat this way in the grid. So each bit position corresponds to a quadrant of the tile and it's level of lava shading. This way you can simply bit wise AND the values around the tile you change and they will automatically "add up" to the appropriate transition. (So if there was already some lava there, it would take that into account) This eliminates the need for a bunch of special tile specific coding.

The only thing that is special is you have to actually know what tile type the neighbor tile is to choose the appropriate transition set (which can also be done bitwise if set up properly).

Anyway, like I said, I haven't investigated how OP2 is organized, but when I make my own tile based games, that's how I organize it for ease of coding.

So you have to figure out if the OP coders did the same and how it is based. (Minimum I can figure is 4 bit (16 tiles) to get a full transition set.)

Edit: Reading this again, I think it's important to realize that the 16 tiles I am referring to are not the tiles you are actively editing. The 16 tiles are the subset of transitions. The tiles you are actively editing work in a 3x3 grid.

-----
|abc|
|def|
|ghi|
-----

I found it was t's too much of a hassle to "edit" a 4x4 grid (or larger). I would edit on a 3x3 grid (corresponding to a 1x1 edit brush) and recurse if you want to have a larger "paintbrush" in the editor. I found that I had to create more special code for a 2x2, 3x3 brush (etc...)
« Last Edit: October 22, 2006, 06:57:02 PM by White Claw »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 3969
Terrain Brushes
« Reply #16 on: October 22, 2006, 07:06:56 PM »
OP2 is slightly more complicated. The reason is that there is more than one transition tile of any given type.

Ex: Let the numbers represent the different terrain types
111
122
122


The top left 1 would be a corner piece, the 1 to the right is an edge piece, as is the 1 below, but in a different orientation. One of the problems is that not all corner pieces that can be places in the top left will fit with all edges pieces to teh right or below it based on this simple diagram.

It might be a tight corner where all the terrain type 2 graphics are close to the corner, or it might have mostly terrain type 2 graphics covering the whole tile, or somewhere in between. If an appropriate edge is not selected to the right or below it, then these edge transitions don't occur along the same line. (They don't occur with the same proximity to the side of the tile).

I'm sure you're method can be extended to cover this too, but it's gonna require a few more bits and it's a lot more to think about. I'm not exactly sure what all possible transitions are. It seems like you have different transition sets. I suppose you could choose one and stick with it, but there might also be transitions from the edges in one transition set to the edges in another transition set.
 

Offline White Claw

  • Hero Member
  • *****
  • Posts: 598
Terrain Brushes
« Reply #17 on: October 22, 2006, 07:15:17 PM »
It sounds like what I was getting at with extending out to 5 or 6 bits. 5 bits would give you two transition subsets and 6 would give four (for dirt to lava for example). Tile set one has small shades of lava while tile set two has larger shades.

But I suppose you would then need to have transitions for the transitions...

Edit: I think we're saying the same thing...   :P  
« Last Edit: October 22, 2006, 07:16:36 PM by White Claw »

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #18 on: October 23, 2006, 12:58:17 PM »
Yes, that's the problem I was having.

The place I originally got the whole idea of splitting a tile up into a grid was from the editor in the Stratagus game engine. (They split it into a 2x2 grid). This works fine if you are using simple tilesets (Stratagus was originally written as an opensource WC2 compatible engine, so the tileset is rather simple). As Hooman stated already in a simple case like this all corners should line up with the appropriate edge pieces in any situation.

My method is different because I use percentage coverage of each edge of the tile, I don't use bitfields at all. (The original 2x2 grid code I used didn't use a bitfield either, it just used an array of 4 integer values which indicated each terrain type in that quadrant. A bit field would limit you to at most 2 terrain types per tile, which is fine for the original OP2 tileset but could be problems for any future tilesets).

So my problem is, I would have to create some sort of list that tells what transition pieces are able to fit together. (The other option as I already stated would be to modify the map more than one tile away from the mouse click, that way it would allow for more accurate transitions).

To put it simply, some transitions require multiple tiles in a specific configuration to look correct. You can't just take any edge and any corner out of the tileset and just stick them next to each other and expect it to work properly.

Hopefully I'm making sense. I've looked for other possible solutions to this problem, and I haven't found a whole lot of code out there (other than ways to handle the simple WC2-style transitions).

Offline White Claw

  • Hero Member
  • *****
  • Posts: 598
Terrain Brushes
« Reply #19 on: October 23, 2006, 03:19:26 PM »
Again, I haven't looked at the OP2 tiles, but when you extend beyond a 2x2 set (to the 4x4 set I was talking about) the transitions sets begin to look a little more random by themselves. And if you add two or four groups of transition sets I can see it ending up in the situation you have.

From the sound of it, you guys have  been working a variation of this theory already. I guess what I'm really getting at is that if we've all thought of some sort of method like this I bet the programmers back then did too. So I'm sure there's a rhyme to their reason. Just need to figure out what it is.

Unless it's like the mapper for Command and Conquer. The tile sets were asymmetric and seemingly random (even in the mapper). Every tile had to be matched by hand. It was crap...

Of course, before I ramble on too long, you can tell this n00b to shove it and go look at the files myself...  :P (which I will eventually...)

Offline Mcshay

  • Administrator
  • Sr. Member
  • *****
  • Posts: 405
Terrain Brushes
« Reply #20 on: October 23, 2006, 04:19:04 PM »
Quote
Unless it's like the mapper for Command and Conquer. The tile sets were asymmetric and seemingly random (even in the mapper). Every tile had to be matched by hand. It was crap...
Bingo.

Offline White Claw

  • Hero Member
  • *****
  • Posts: 598
Terrain Brushes
« Reply #21 on: October 23, 2006, 04:42:38 PM »
Are the tiles in the mapper extracted in the order they appear in the artwork files?

Offline Mcshay

  • Administrator
  • Sr. Member
  • *****
  • Posts: 405
Terrain Brushes
« Reply #22 on: October 23, 2006, 05:25:45 PM »
Yes, they are arranged in the order the devs had them. You should download the mapper and look at it for yourself.

Offline White Claw

  • Hero Member
  • *****
  • Posts: 598
Terrain Brushes
« Reply #23 on: October 23, 2006, 05:34:16 PM »
I did (download the mapper) and it looks awesome. Kudos to the developer...

I was just wondering if the tiles were in order (before I started killing brain cells trying to figure it out).

I have a hard time believing the transition sets can all be identical but yet there is no pattern to the work. Of course, I've only been looking at it for an hour and you've been doing it for a while...


The other thing that makes me wonder is why would you want to have twelve terrain types on one tile? That sorta defeats the purpose of having tiles if you have to create a tile for every possible situation. (12!)
« Last Edit: October 23, 2006, 05:40:35 PM by White Claw »

Offline BlackBox

  • Administrator
  • Hero Member
  • *****
  • Posts: 3103
Terrain Brushes
« Reply #24 on: October 23, 2006, 06:00:43 PM »
Well, the way the OP2 tilesets work is a bit strange.

You can have multiple tilesets (bitmap files). Each has N number of tiles indexed 0..n (as you should expect).
The tilesets are also indexed 0..n in the order they appear in the tileset table inside the map file.

In each .map file, there is a table (we refer to it as the Mapping Table), basically it maps a tileset and tile index to a virtual index in the map. (Referred to by us as the mapping index). There is a max of 2048 mapping indexes (because OP2 only uses 11 bits to store the mapping index for each tile). So this imposes a limit of 2048 different tiles on the map at any time.

The mapping index, not the tileset/tile index, is what is used to identify the contents of each tile.

If you want more details see
http://wiki.outpostuniverse.net/Using_Advanced_Edit

Anyway, to answer your question, the mapping indexes are usually contiguous (i.e. index 901 might correspond to set 5 tile 3, 902 corresponds to set 5 tile 4, so on) but they don't have to be. The game itself imposes no limits on the ordering of entries in the mapping table, you could easily have 901 correspond to set 1 tile 0 and 902 correspond to set 8 tile 27, or anything you wanted.

Thus mapping 900 might not be the same tileset/tile pair as 900 in another map. The only failsafe way to identify a specific tile is to go by tileset name and tile index in that set.

If you want to see the set of transition tiles, have a look at (well0006 I believe it is). As for the way the mapper figures out the transitions on each tile, it parses an ini file with information for each tileset name / tile index, telling it what pieces of each tile contain what terrain definition. The mapper doesn't know anything about the terrain definitions themselves other than that they are discrete terrains (i.e. terrain ID's 1 and 2 are not the same). For all other purposes they are there just for the user's convenience (since they are assigned a textual name).

And yes, there isn't a lot of sense to using 12 types per tile; the capability is however there since 3 or 4 on a tile seems reasonable / possible. (for example 4 areas, all different terrains, intersect at one tile).

Oh, btw, thanks for the compliment on the mapper :) It was mostly the work of Hooman and myself.