Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Psudeo 3D (Sprite positions in mode 7 games)
#1
I actually understand how Mode 7 3D works - it's actually a scrolling & rotating 2D background, which scales each line wider as you move down the screen, to create a fake perspective effect.

If I was to make a Mario Kart clone, I'd make the "track" as a simple background layer in Tiled, and then I'd make a new layer and place tiles that will represent the "sprites" on the track, eg. the green pipes that stick up as obstacles. This would give those sprites a position on the 2D map.

I could probably guess at how to make them appear to move in perspective - the scaling is easy, just use a bigger sprite the closer to the bottom of the screen they are.  Same with the perspective effect, just scale their X position further away from the center of the screen the closer to the bottom of the screen they are.

The part I haven't learned yet, is how to rotate all those objects together, so they stay with the map when it rotates.  I think this may have to do with "matrixes", something I'm only aware of the existence of, but not used before.

Am I on the right track with my understanding of Mode 7, and do you have any suggestions about where to go from here?
Reply
#2
Ah it's probably simple enough when I put the time into it. I just need to go get the code for it. From what I understand, I can store the rotation of the background in a matrix, and then all the sprites have their own matrix, which is just their position relative to the world. Then when I rotate the background matrix, to get the final positions of the sprites, I just add the sprites matrix to the background matrix to get the final (rotated) position of the sprite.

Maybe I should even be coming at it from the other end - using the matrix properly and have a projection matrix so everything has a 3D position in space, and just using the z somehow to set the scaling of each scanline.
Reply
#3
Hi,
Interesting subject, but this one goes beyond Tilengine itself. I recommend you a good tutorial about linear algebra and affine transformations. It's not really that hard, you don't need to understand the math itself, just how to apply some basic receipes:
  • Grab a simple linear math library that supports points, vectors, and matrices,
  • There are 3 basic linear transformations: rotation, translation and scale,
  • Each of these transformations has a standard "template" where you encode the desired values,
  • Multiple transformations can be chained by multiplying two matrices (order matters: it's not the same translate and then rotate, than first rotate and then translate)
  • To apply a transformation to a point, you multiply the source point by the transformation matrix that encodes your desired composite transformation,
That's all! Tilengine itself does it internally, you may check the source code to get inspiration if you want, but I guess there are better examples out there
Reply
#4
Thanks! I'm going to start experimenting.  I found Eigen as a recommendation for a straightforward "linear algebra matrix library", I hope it's simple enough to use for what I need - I'm sure there will be options out there that are overkill.  But it even supports "fixed sizes" (eg. Matrix4f) for small simple calculations, and I see you're also using your own implementation of fixed point calculations.

I just had a quick look to see how you're doing fixed point calculations in Mode7.c.  I assume this is because it's more efficient than using floats?  (Although I found a page saying calculation speed between ints and floats vary between processors - in some cases, floats are faster!) But is this mainly to stay true to how it would have been done back then?
Reply
#5
Inside tilengine I do the matrix calculations of edge points using floating point arithmetic, but then interpolated across using fixed point.

Classic systems lack floating point hardware so fixed point was a must, because emulating floating point using integers is very expensive. But there's another reason: floating point suffers precision loss because of accumulative rounding errors, whereas fixed point is stable and deterministic. Unless the extended range of floating point is required (the ability to merge very large and very small numbers), I'd rather recommend fixed point arithmetic when performing incremental calculations.
Reply
#6
(08-05-2018, 05:21 PM)megamarc Wrote: ...floating point suffers precision loss because of accumulative rounding errors, whereas fixed point is stable and deterministic. Unless the extended range of floating point is required (the ability to merge very large and very small numbers), I'd rather recommend fixed point arithmetic when performing incremental calculations.

Ah of course. I'm going to take that advice on board.

It seems  like every time I post here and you reply, I learn something!  I knew that about floating point, but I've never been in a situation where fixed point was the solution to a problem I had, so I never thought about it like that - but it makes sense when you put it that way. 

The only situation I've been in where floating point inaccuracy was a problem, was when you travel too far away from 0,0,0.  In my voxel game, when the player position was greater than around 10,000 in any direction, all the meshes would start to render with cracks between them, and I had no idea what was going on! I programmed them to line up perfectly, why was my math suddenly off?  That day, I learned about how floating point inaccuracy affects mesh rendering when the position values are too large, and ALL open world games (Skyrim, GTA, etc. etc.) periodically move every mesh, and the player, back towards 0,0,0 when you go too far in any one direction, for this reason!  I implemented a system like that in my game and it solved the problem!
Reply


Forum Jump:


Users browsing this thread: 5 Guest(s)