Mapping a Landscape
The Super Nintendo (SNES) offered a graphics mode which allowed hardware rotation and scaling of a playfield. Programmers soon realised that by adjusting the rotation and scaling factors on each scan line, the Mode 7 display could be "perspectivized" or flattened, and look like a landscape. Unfortunately, over the years this effect has become synonomous with the term "Mode 7" which is properly just the ability to rotate/scale a playfield. I will use the term "Mode 7 landscape" to refer to the perspectivized version.
The Nintendo Gameboy Advance (GBA) offers a similar mode to that of the SNES. The principle of mode 7 landscaping is the same, and this document is an attempt to explain how to correctly calculate the scaling and rotation parameters required. This document deals more with the theory of mode 7 landscaping, rather than the hardware-related settings. Now, I'm a programmer not a technical writer. If you see errors, they are mine. Please take the time to write and correct them.
How it Works!
We need to understand exactly what we're doing, and how we 'trick' the machine into displaying a mode 7 landscape. We descend into the technical world of stick-figures to make our visualisation easier...
Fig. 1 Conceptual view of Mode 7 Landscaping
This is a side-view of what the systems are doing. We are considering the display of a single scanline on the screen. The guy standing at the left is you. The almost horizontal line is supposed to be dead-flat. Just to the right of the guy is a vertical line representing the screen, his window on the world. Everything he sees is through that screen. The line sloping downward from his feet is the ground he is standing on, so he's on a bit of a downslope in this diagram.
The dotted line projecting from his eye, through the screen at C1 and intersecting the ground at C shows us what part of the playfield (PF) the guy will see on his screen at that point. The distance from EYE to C tells us what scaling to use for the playfield on the line we're currently calculating (that is, how BIG the pixels are). The actual scaling values we use is up to us - it depends on how big we want a pixel to be - a pixel could be 1cm, 1m or 0.01mm... it's up to us. As long as we keep our calculations consistent, all will be OK. So all of our discussions about scaling are relative values; the actual value used is up to you. The pixel C is what we want to see on the screen at C1, and our scaling calculation tells us just how big we want that pixel/line on the screen to be.
Calculating EYE-C
Adjusting the Center of Rotation
All is hunky-dory until we look at how the hardware rotation/scaling actually operates on the SNES and GBA. In these machines, we have the ability to set (albeit indirectly on the GBA) a center of rotation and a scale. The hardware then proceeds to calculate what pixels of the playfield constitute each scanline as it is drawing the screen. In the GBA, though, the centerpoint and scaling are entangled in a weird way, so it's not as easy as just setting the center point and rotation. Please look elsewhere for more detailed explanations of the GBA rotation/zooming calculations - as noted, this document is a discussion of theory more than implementation.
Since we know how big the pixels are (from our calculation of EYE-C), that's the scaling value we use when setting our hardware parameters. But if we do that, the pixel we would see would be the one at X. That's where the length along the line A-PF is the same as EYE-C. That's not what we want. So we need to adjust things so that instead of X we see C. The only way to do that without affecting the size of the pixels is to shift the origin (A) - which is the center of rotation - backward. And that's exactly what we do!
Hills!
It is not possible (at least, I don't think it is) to use mode 7 effects to generate true hills. But we can work with pseudo-hills, which are effectively hill-like ripples in terrain in front of you. Consider the following...
Fig. 2 Hill Calculations
Instead of a flat landscape, our playfield is now a curvy line representing hills. Like before, we have a screen through which our stick-man sees the world. In this diagram, the dotted line intersects a hill at point C. The distance from EYE-C again gives us our scaling (how big the pixels are), but this time it is clearly a shorter distance than the actual walking-distance from A-C. So if we were to use the scaling to set our hardware parameters, we'd see point C1 instead of C. What we need is to adjust the center point of rotation (as explained above) so that we will see point C at the calculated scaling factor.
The very tricky point is knowing exactly what point C actually is! That can be calculated by the walking-distance along A-C (that is, the length of the curve). I know this is tricky and potentially very time consuming, however the methods described here can in principle be implemented as a general-purpose solution to allow hills, flat land, and slopes, to be implemented with the one piece of code.
Pitch!
This is where you look up/down, and your view changes accordingly. I'll write this up if there's any interest.
Conclusion
This document has been concerned with correctness as opposed to practicality. In particular, some of the calculations might be more tricky than is warranted. For example, for most purposes EYE-C is very close to A-B (especially if the ground is flat, and C is a reasonable distance away). It's only recently I realised that a mode 7 game I wrote did just this, yet still it looked fine.
|