Editor’s note: [I originally wrote this as an Appendix to the documentation for Z3D Engine, but I think it’s interesting enough to deserve a slightly wider audience.]
I have to preface this section by saying that I have no idea what I’m talking about here, but am trying to learn. I like math, but I didn’t go to school primarily for it, and that was decades ago. I haven’t studied 3D geometry, or optics, or computer graphics in any formal sense. I’m figuring this out more or less by myself, learning as I teach myself.
So if someone who knows more than I do wants to explain this stuff better than I can, I’d love to hear from you. You can send me an email at the Contact page, or tweet at me @csanyk, or just comment on this article.
Thanks in advance!
I’ve called Z3D Engine a “Fake 3D” engine and “2.5D” engine, because those are fairly vague terms that I don’t have to worry about being right about. Someone asked me what type of view it is, and I couldn’t tell them. That bothered me, so I started reading a bit. I still don’t really know for sure.
- a method of projection in which an object is depicted or a surface mapped using parallel lines to project its shape onto a plane.
- a drawing or map made using orthographic projection.
I think this is sortof close to what Z3D is… maybe. What I can tell you about Z3D is this: You can see the full front side and the full top side of (most) objects. These do not foreshorten.
gerund or present participle: foreshortening
- portray or show (an object or view) as closer than it is or as having less depth or distance, as an effect of perspective or the angle of vision.
- “seen from the road, the mountain is greatly foreshortened”
The blue rectangle that represents the “player” in the demo is intended to show the player as a side view only, with no pixels in the sprite representing the top surface of the player. This is because I’m intending Z3D to be used for games drawn in a visual style similar to the top-down Legend of Zelda games, and in those games, no matter which way Link is facing, you can only see pixels in his sprite that represent his side, and nothing that represents the top of him, even though you’re viewing most of the rest of the terrain in the room from this weird view where you can see both the top and side of things like blocks and chests, and for other things like bushes you can only see the side.
Things in Z3D do not appear to get smaller as they recede into the background, or get bigger as they get closer to the foreground. As well, the tops of objects (that have tops), the top is drawn 1 visual pixel “deep” (in the Y-dimension) for every pixel of distance.
This doesn’t look correct, strictly speaking; if you’re looking for “correct” visuals this engine likely isn’t for you. But it is visually easy to understand for the player, and it is very simple.
What I’m doing in Z3D Engine is showing the top of everything (that has a top) as though you’re looking at it’s top from a vantage point that is exactly perpendicular to the top, while at the same time you’re also seeing the side of everything as though you’re looking at the side from a vantage point that is exactly perpendicular to the side. This is an impossible perspective in real life, but it works in 2D graphics that are trying to create a sort of “fake” 3D look, which is what Z3D does.
Imagine you’re looking at this cube:
At most, assuming the cube is opaque, you can see only three faces of the cube from any given vantage point outside the cube; the other three faces are occluded on the other side of the cube.
(That image above is properly called Isometric, by the way. Z3D is not isometric).
If you were looking at the cube from a vantage point where you were perpendicular to one of the faces, you could only see that one face, and it would look like a square:
(Since the faces of this cube are all nondescript, we can’t tell if we’re looking at the side or the top of the cube.)
Now, if it were possible to be at a vantage point that is exactly perpendicular to the both the side and the top of the cube simultaneously, the cube would look like this:
This is weird and wrong, but yet it is easy to understand, and it turns out that it is also very easy to compute the position and movement along 3 dimensional axes if you allow this wrong way of drawing. This is view is (or perhaps is similar to) a method of visualization known as a oblique projection.
More properly, if you were positioned at a vantage point somewhere between the two points that are perfectly perpendicular to the top and side faces, the cube would look like this:
Here, obviously, we are looking at the cube mostly from the side, but our eye is slightly above, so we can see the top of the cube as well. But notice, since we are not viewing the top face of the cube from a perpendicular vantage point, it does not appear to be a square any longer — it foreshortens, so that the far end of the top of the cube appears narrower than the closer end.
This is perhaps obvious, because we’re using to seeing it, because we see it every day, because that’s what real life looks like. But it’s because we see this every day that we take it for granted, and when we have to explicitly understand what’s going on visually with geometry, we have to unpack a lot of assumptions and intuitions that we don’t normally think consciously about.
If we were to put our eye at the exact middle point between the points that are perpendicular to the side face and the top face, the cube should look to us like this:
Notice that both the bottom of the side face and the far edge of the top face are foreshortened due to perspective.
This is how they “should” look in a “correct” 3D graphics system, but Z3D “cheats” to show both the side and top faces without doing any foreshortening, which means that it can draw an instance as it moves through any of the three dimensions using extremely simple math.
Visually moving 1 pixel left or right is always done at a hspeed of -1 or 1, regardless of whether the object is near (at a high y position) or far away (at a low y position). Likewise, moving near or far is also always done at a rate of one distance pixel per apparent visual pixel. And moving up and down in the z-dimension is also always done at a rate of 1 distance pixel per apparent visual pixel.
If we wanted to draw more convincingly realistic 3D graphics, we need to understand what’s going on with the eye, with perspective, and things at a distance.
The same object viewed in Z3D’s perspective is something like this:
(We’ve omitted the occluded faces on the back end of the cube relative to the viewer, for simplicity.)
These two “apparent” perspectives are combined at the point where the player’s real eye is, resulting in something like this fake-3D perspective:
So, in conclusion I’m not 100% sure that my terminology is correct, but I think we can call this perspective “flattened orthographic bi-perspective” or perhaps “oblique projection”.
(From this, we can begin to see how a corrected view might be possible, using trigonometry to calculate the amount of foreshortening/skew a given position in the Z3D space would need in order to appear correct for a single-POV perspective. But this is something well beyond what I am planning to do with the engine; if you wanted this, you would be far better off creating your game with a real 3D engine.)
It gets weirder when you realize that for certain objects, such as the player, we’re going to draw only the side view, meaning that the player will be drawn a flat 2D representation in a fake 3D space. Yet the player’s “footprint” collision box will likely have some y-dimension height to it.