Home > front end >  Algorithm to fill arbitrary marked/selected tiles on a square grid with the smallest number of recta
Algorithm to fill arbitrary marked/selected tiles on a square grid with the smallest number of recta

Time:01-13

What I am asking here is an algorithm question. I'm not asking for specifics of how to do it in the programming language I'm working in or with the framework and libraries I'm currently using. I want to know how to do this in principle.

As a hobby, I am working on an open source virtual reality remake of the 1992 first-person shooter game Wolfenstein 3D. My program will support classic mods and map packs for WOLF3D made in the original format from the 90s. This means that my program will not know in advance what the maps are going to be. They are loaded in at runtime from user provided files.

A Wolfenstein 3D map is a 2D square grid of normally 64x64 tiles. let's assume I have a 2D array of bools which return true if a particular tile can be traversed by the player and false if the tile will never be traversable no matter what happens in the game.

I want to generate rectangular collision objects for a modern game engine which will prevent collisions into non traversable tiles on the map. Right now, I have a small collision object on each surface of each wall tile with a traversible tile next to it and that is very inefficient because it makes way more collision objects than necessary. What I should have instead is a smaller number of large rectangles which fill all of the squares on the grid where that 2D array I mentioned has a false value to indicate non-traversible.

When I search for any algorithms or research that might have been done for problems similar to this, I find lots of information about rectangle packing for the purposes of making texture atlases for games, which packs rectangles into a square, but I haven't found anything that tries to pack the smallest number of rectangles into an arbitrary set of selected / marked square tiles.

The naive approach which occurs to me is to first make 64 rectangles representing 64 rows and then chop out whatever squares are traversible. but I suspect that there's got to be an algorithm which can do better, meaning that it can fill the same spaces with a smaller number of rectangles. Maybe something that starts with my naive approach and then checks each rectangle for adjacent rectangles which it could merge with? But I'm not sure how far to take that approach or if it will even truly reduce the number of rectangles.

The result doesn't have to be perfect. I am just fishing here to see if anyone has any magic tricks that could take me even a little bit beyond the naive approach.

Has anyone done this before? What is it called? Just knowing what some of the vocabulary words I would need to even talk about this are would help. Thanks!

(later edit)

Here is some sample input as comma-separated values. The 1s represent the area that must be filled with the rectangles while the 0s represent the area that should not be filled with the rectangles.

I expect that the result would be a list of sets of 4 integers where each set represents a rectangle like this:

  1. First integer would be the x coordinate of the left/western edge of the rectangle.
  2. Second integer would be the y coordinate of the top/northern edge of the rectangle.
  3. Third integer would be the width of the rectangle.
  4. Fourth integer would be the depth of the rectangle.

My program is in C# but I'm sure I can translate anything in a normal mainstream general purpose programming language or psuedocode.

CodePudding user response:

Mark all tiles as not visited
For each tile:
    skip if the tile is not a top-left corner or was visited before
    # now, the tile is a top-left corner
    expand right until top-right corner is found
    expand down
    save the rectangle
    mark all tiles in the rectangle as visited

However simplistic it looks, it will likely generate minimal number of rectangles - simply because we need at least one rectangle per pair of top corners.

For faster downward expansion, it makes sense to precompute a table holding sum of all element top and left from the tile (aka integral image).

For non-overlapping rectangles, worst case complexity for an n x n "image" should not exceed O(n^3). If rectangles can overlap (would result in smaller number of them), integral image optimization is not applicable and the worst case will be O(n^4).

  •  Tags:  
  • Related