raycaster with top-left origin - problems with trigonometry

Started by
3 comments, last by jacmoe 3 years, 2 months ago

The project I am working on is very simple. It's just a raycaster similar to the one used in Wolfenstein 3D. I'm using just the standard Win32 graphics capabilities (not GDI, see below). However, I'm running into issues with directional programming and math given that my screen coordinate system uses top-left as the origin. As such, x increases when going right to left (like usual), but y increases going top to bottom. Therefore, considering all the functions required for movement and rotation using a raycaster, the unit circle for my raycaster looks like:

         180
	  |
    270---|---90
	  |
	  0

It's not that the coordinate system is rotated, it's that it's flipped over the Y axis. One obvious issue (among many others I'm sure) is that if you attempt to rotate clockwise, your direction angle DECREASES in degrees, so you actually rotate counterclockwise.

I struggle with simple math enough as it is, so even a standard coordinate system with 0 pointing “up” would be challenging enough for me, but this just throws in a cruel twist.

Most graphics systems seem to use top-left origin, and I'm sure there has been more than 1 person out there who wanted to goof around with building a raycaster, so I imagine this problem has been discussed quite a bit. I've found a few articles online, but maybe I'm just not searching with the correct terms because I don't come up with much.

It seems that there are 3 basic solutions:

  1. Change the graphics system to use bottom-left as the origin. This is something I could do. My graphics “system” (strong word) is basically just drawing to the memory of an offscreen bitmap, then blitting the bitmap to the Win32 window. I have control over whether my system is top-left or bottom-left. But if you were using a graphics library where the origin was fixed at top-left, this wouldn't be an option.
  2. Convert the player attributes (xPos, yPos, direction, etc) from top-left to bottom-left coordinates at the beginning of the game loop after updating position but before running all the trigonometry. It would seem that you would basically need two sets of variables, e.g. xPos, yPos, and dir, PLUS xPosCorrected, yPosCorrected, dirCorrected. The first 3 store the information on your player based on the top-left coordinate system being used. So if you move your player “down”, the yPos will become larger, if you rotate clockwise, your player angle will decrease, etc. Then, convert these variables to a bottom-left coordinate system. So if your screen height is 100, and your player is at yPos = 80, you convert that to yPosCorrected = 20. And for the direction, you take the y-component and make it negative to flip it back over the y-axis and store it in dirCorrected. And then when you do your math, you use xPosCorrected, yPosCorrected, and dirCorrected instead.
  3. You just live with the messed up unit circle situation. For example, if your player presses the rotate clockwise button, you subtract from the angle. Even though that is counterintuitive. But, are there other issues besides a simple rotation problem that would come up eventually?

Like with everything, I'm sure there are hidden problems with some or all of these that may not be immediately apparent. But I just wanted some advice on different ways to handle this issue. I would prefer to design it the best way from the start rather than have to switch gears midstream.

Advertisement

@docyoung83 You're right about clockwise needing the angle to be reverse when an axis is flipped, but I can't see the relation to your wolfie-style raycaster, where there is only one ray per column, and “up” and “down” has no meaning before you colour in the ceiling, floor and apply textures.

As for the rays on the map, I'd say keep what you feel works best. I use a coordinate system like that in my project and have lots of homemade geometry stuff all using that; so the angle around my Z axis would increase when I rotate right, and decrease when I rotate left, but my sin() just returns a negated value. It's probably not as elegant as just saying your coordinate system is classic, and let the angle decrease when you rotate right, though.

Thank you! I appreciate the feedback.

@docyoung83 What did you end up doing?

I am writing a raycaster and recreating all the Wolfenstein levels from the first episode, but I find it annoying that it flips the Y axis. I know the wolf3d levels by heart and that the levels are flipped bugs me.

EDIT:

I ended up converting the level data when I load it. I basically reverse each row of the data, and then I need to figure out how to convert the start position. I am working on it ?

ANOTHER EDIT:

It was a simple matter of subtracting the map width from the X coordinate of player start. Now I only need to fix the minimap!

FINAL EDIT:

Minimap rendering simply uses the original, not reversed level data. Job done! :D

Too many projects; too much time

This topic is closed to new replies.

Advertisement