
Drawing isometric boxes in the correct order - _qc3o
http://shaunlebron.github.io/IsometricBlocks/
======
munchbunny
Great explanation for a generally messy problem!

Just one thought because I spent some time thinking about this type of problem
before deciding to do it a different way in my own work:

If you use an orthographic projection and just actually draw 3-D boxes, this
problem becomes trivial, including the intertwined boxes problem, because the
GPU will take care of it at a per-pixel level with the Z-buffer.

Of course this also means you're suddenly working in 3-D, which complicates
other things. But you can still use 2-D textures by picking the right texture
coordinates for the vertices on the box.

These days it usually makes a lot of sense to be doing 2-D stuff using a 3-D
engine/library anyway, if only for access to hardware accelerated post-
processing and hardware accelerated layering/compositing, in which case using
actual boxes on a tilted camera and using "no projection" for your HUD/UI
works pretty well.

~~~
badlogic
A z-buffer solution will not help as soon as you involve transparency. Which
I'd assume is the case in 99℅ of applications. Unless your application/game is
all boxes :)

~~~
phire
No, transparency is actually quite rare in games, for pretty much this exact
reason, and outside of games is rare to have more than one or two layers of
transparency.

The typical method is to draw all opaque objects first with zbuffering
enabled. Then sort all the remaining trasnparent objects by depth and draw
them from back to front

------
dtf
I was very glad to find this page earlier this week, after scratching my head
while implementing an isometric renderer for a client. I had assumed it would
be a simple back-to-front order, but this page and a few others pointed out
that the partial ordering required to 1) use an intersection test to build
disjoint sets of confused objects, 2) use a pairwise order test to determine
inter-object dependencies, 3 ) use a topological sort to resolve the ultimate
drawing order.

This method was implemented in some fantastic 1980s computer games, and the
developer had named their technique "Filmation". Here's a discussion of that
system, plus a demo of the rendering bug caused by not bothering to break
dependency cycles as discussed in the main article:

[http://bannalia.blogspot.co.uk/2008/02/filmation-
math.html](http://bannalia.blogspot.co.uk/2008/02/filmation-math.html)

(also I just found another with a load more details on the Filmation games:
[http://retrospec.sgn.net/users/nwalker/filmation/](http://retrospec.sgn.net/users/nwalker/filmation/))

~~~
ndr
I'm still reading through the article, but can you give an example of why
rendering all the blocks ordered[0] by (min x, min y, min z) lexicographically
doesn't work[1]? I thought the sophistications is necessary for performance
only, i.e. not drawing anything that doesn't appear in the final result.

[0] Assuming (0, 0, 0) it's in the middle at the top of the screen.

[1] Assuming this is what you meant by "simple back-to-front".

~~~
Jare
Elongated boxes may not be sorted correctly no matter which point you use
(min, max, center).

~~~
ndr
What do you mean by elongated box?

------
tobr
If you're interested in this topic, Andrew Russell recently wrote a blog post
and made a video about how they sort sprites in River City Ransom Underground.
It's even more complicated because the sprites aren't necessarily simple
boxes.

[http://andrewrussell.net/2016/06/how-2-5d-sorting-works-
in-r...](http://andrewrussell.net/2016/06/how-2-5d-sorting-works-in-river-
city-ransom-underground/)

[https://www.youtube.com/watch?v=Ssrkq6_6JYU&t=8m48s](https://www.youtube.com/watch?v=Ssrkq6_6JYU&t=8m48s)

~~~
undershirt
Thanks, this is very interesting! I added it to the article.

The only difference is that bounding boxes are still used for sprites, but he
adds a sort of voxel heightmap inside of it to represent occupied volume.

> heightmap:
> [https://youtu.be/Ssrkq6_6JYU?t=15m21s](https://youtu.be/Ssrkq6_6JYU?t=15m21s)

If you imagine this heightmap as a building with multiple floors (e.g. 1st
floor, 2nd floor) the algorithm takes the lowest common floor of each of these
buildings and performs an intersection test between them and nothing else.
This allows the sprites to interact more fluidly inside the bounding boxes!
Neat.

> heightmap floors:
> [https://youtu.be/Ssrkq6_6JYU?t=16m12s](https://youtu.be/Ssrkq6_6JYU?t=16m12s)

------
mparlane
The way I have seen this commonly solved is to draw each item from back to
front (highest Y value, assuming 0 at bottom of screen and >0 at top). But
every item is the size of one square, or is in fact multiple items the size of
1 square which make up the larger object. It just seems like a simpler and
more efficient solution and you don't need to worry about cycles.

------
Jare
This is pretty much what we did in the Commandos games back in '97\. As
explained in other posts, you can't use some simple depth metric for the
entire box and z-sort them because elongated boxes will cause problems.

One of the reasons to do this instead of Z-buffering is that Zbuffer will not
help with transparency, and most games with these kind of needs will use it,
for antialiasing sprite edges if nothing else.

------
joneholland
What's wrong with naively drawing every box ordered by depth? This seems like
a bunch of extra work for the same result?

~~~
TheCoreh
The boxes are not necessarily cubes, so ordering them by depth of say, a
central point, would not yield correct results for some edge cases (e.g.
elongated boxes)

~~~
thomasahle
From the examples in the article, the boxes can all be broken into fairly few
pieces, which are square when seen from above. Small 'cube towers'.

If you break them up like that, naive painting in order of depth should be
fine.

------
phire
Note, it's only worth going through this trouble if you are drawing boxes with
a CPU only API.

If you have a GPU available, you might as well be using an orthographic
projection and the depth buffer.

~~~
Retr0spectrum
Even on CPU, how much overhead would a depth buffer cost?

~~~
phire
It would basically double the memory bandwidth and cache requirements for
drawing if you used a full 32bit depth buffer.

But it would probably be worth it. A 16 bit buffer would probably be good
enough for isometric drawing and would be faster.

------
joakleaf
I implemented drawing of polygons orthographically quite some time ago. The
output was for PDF, so I couldn't raster + zbuffer. Instead I drew all
polygons back to front.

I ended up creating a BSP tree (1) for the polygons and drawing them in order
according to the tree.

The problem in general with sorted back to front drawing is exactly the
"Conundrum" example. However, a BSP tree will take of that, and divide at
least one of the cubes in that example.

It may feel like overkill, but I would probably have done something similar in
this case. Implementing BSP trees for cubes is very simple, because all planes
are xy, xz, or yz.

[1]
[https://en.wikipedia.org/wiki/Binary_space_partitioning](https://en.wikipedia.org/wiki/Binary_space_partitioning)

------
jaunkst
I worked on an Isometric framework for a flash project in 2009. I remember
coming to an acceptable solution using axis sort and volume data. I would have
killed to have a GPU available then.

------
pjc50
If you're doing isometric, then use a tile system like 90s videogames. It
makes far more sense.

~~~
zyxley
I was just thinking that.

If you really want an isometric look but need more complicated rendering than
layered tiles, it seems like it would be much easier to do 3d rendering but
lock the 'camera' into an orthographic projection mode.

Unity and Unreal Engine both have this as a built-in feature that basically
just takes a checkbox, for examples off the top of my head.

~~~
hcarvalhoalves
Much better approach. Also because it makes rendering particles - or whatever
things that won't align w/ the grid - correctly a non-issue.

------
white-flame
I'm curious as to the first implementation of this. I sat down and solved this
nuisance of a problem in 2008-2009, for as3isolib. I later found a thesis by
Ernir Erlingsson from around the same time period, but with a bit of a
different data structure holding the objects to sort. I'm not aware of any
"classic" games that do a true sort of isometric objects.

The vast majority of actual 2d isometric games use a very naive grid walking,
with uniform tile sized elements. If everything moving is limited to 1 plane,
then varying square footprint tiles can be used with a simple sort. However,
the linked page is the "true" solution to isometric sorting, allowing any size
axis-aligned rectangular solid to exist in any non-interpenetrating location
in 3-space and sort correctly.

------
mclightning
I don't understand why it has to be so complicated. If you position pivot of
your objects on the bottom,lowest corner of its image. Then you can start
drawing them by the order of this position.

Start drawing from highest Z position to the lowest. When you have objects
staying on top of each other, use order of the parent object as the drawing
order for child objects.

1 rule : All buildings are only allowed occupy their own air space only. They
are not allowed to have balconies over reaching to airspace of other X/Y area.

------
chad-autry
Seems just break all boxes into cubes, then draw in z index order is the best.

Also as some say, just throwing it into 3D and locking the perspective is
waaaay easier on the math. For example, 2 of my own projects.

[http://chad-autry.github.io/hex-grid-map/#/demo](http://chad-
autry.github.io/hex-grid-map/#/demo) vs [http://chad-autry.github.io/hex-grid-
map-3D/#/demo](http://chad-autry.github.io/hex-grid-map-3D/#/demo)

------
efnx
I may be naive but I do have some experience with isometric games and my
solution was to set the index origin of each box as the top back corner (the
top of the hexagon if flattened), and then order bottom-to-top, back-to-front.
Then draw in order.

[http://blog.efnx.com/wp-
content/uploads/2007/10/fpsExample.s...](http://blog.efnx.com/wp-
content/uploads/2007/10/fpsExample.swf)

------
fao_
Wouldn't a 'painter's algorithm'-style solution of:

    
    
      break all the shapes into boxes that can occupy only 1 space
      
      for height = 0 .. n:
    
        for <however many boxes can be displayed in a column>
      
          for <however many boxes can be displayed in a row>
      
            draw box, step to next box (x+1, y+1)
    

solve these problems? I'm not sure how fast it would be in practice.

~~~
munchbunny
The way you would do this in practice would be:

1\. Start with the abstraction that every shape is actually a group of one or
more sub-shapes. (Well-understood and pretty much universally applied
abstraction.)

2\. Pre-process all of your geometry so that you won't get cycles of
occlusion, which is the corner case the author mentioned. If you do have a
cycle, then subdivide and group as mentioned in #1.

3\. Use some fast but crude algorithm to preemptively reject non-visible
shapes.

4\. Apply painter's algorithm. to "probably visible" shapes.

------
resist_futility
Unless you take the voxel draw every cube approach, I can't see how you can
account for every possible shape and position. Taking the last example further
what if the red box continued below the purple box. The next best thing I
could think of, without going 3D, was to split each box into layers.

~~~
Retra
This only works on rectangular prisms (which is the definition given for 'box'
in the article.) If the red box continued below the purple one, it wouldn't be
such a box anymore.

------
steaminghacker
why not draw the individual polygons as a single batch?

