Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you rotate and zoom GPU_Camera around camera's current center point? #198

Open
seanballais opened this issue Aug 11, 2020 · 16 comments

Comments

@seanballais
Copy link
Contributor

When GPU_Camera is at (0, 0), the camera rotates and zooms correctly. However, when the camera is not at (0, 0), its rotation and zoom is anchored at (window_width / 2, window_height / 2). I was expecting that the camera will rotate and zoom around its new center point, (camera_x + (camera_viewport_width / 2), camera_y + (camera_viewport_height / 2)).

On that note, how do you rotate and zoom the camera around camera's current center point?

@albertvaka
Copy link
Contributor

This patch should fix the issue, can you give it a try and confirm it works for you? #206

@seanballais
Copy link
Contributor Author

Hey, @albertvaka! I've just tested it. The camera now rotates around the camera center. However, zoom still does not.

@albertvaka
Copy link
Contributor

❤️ Thanks for your test @seanballais! Can you give it another try with my latest changes to the same PR? I think I got it right this time :D

@seanballais
Copy link
Contributor Author

seanballais commented Oct 12, 2020

Hey, @albertvaka! Works great! The zoom now runs perfectly. Good job.

@grimfang4, I would recommend merging this PR.

One issue I did notice was that, when moving the camera when it is rotated, the camera moves along the rotated axes, instead of the window axes. It's a bit disorientating and counter-intuitive. But, I think it's a different issue from this one.

@albertvaka
Copy link
Contributor

Thanks a lot for your testing!

Good point about the camera movement when rotated. Currently the camera coordinates are always in world coordinates. I agree there are some use cases (eg: an RTS like Battle for Wesnoth) where you want up/down to move "towards the top/bottom of the window" and not "in the Y axis". This is a use case I didn't think about, so thanks for bringing it up!

Supporting both modes, however, would likely need a bool/enum somewhere, thus increasing the complexity of SDL_gpu. Given it should be simple enough to implement this in game code, we could want to leave this out of the library. But that's something we can discuss, in any case.

@seanballais
Copy link
Contributor Author

Since the camera is part of SDL_gpu, I think it is best that we have it as an option. I can imagine limited use cases where the camera can be moved in world coordinates, rather than screen coordinates. But, I think it's more intuitive and natural to have the camera move in screen coordinates. We should probably have that option be the default instead.

@grimfang4
Copy link
Owner

I'm not against building in both paths. The complexity of this piece of the library is isolated to the camera system, which is an optional system anyhow and can be disabled to give you full control of the view matrix instead.

I feel like the default should be translation in window coordinates, as that is probably what someone will expect when positioning a camera in their world. The other way is useful for 2D follow cameras in a free-moving topdown game, but seems to me to be the less common case.

@grimfang4
Copy link
Owner

By the way, I'm looking to put together a 1.0.0 release and this is the last significant semantic change that I expect to go into it. Don't fret over the small details, since I'm realistic about version numbers and while 1.0.0 sounds like a big deal, it shouldn't be.

@albertvaka
Copy link
Contributor

I've added a small demo that tests the camera, so we have a common thing to visualize the changes we make: #208

@albertvaka
Copy link
Contributor

I've created a branch that contains:

  • The camera demo I just wrote about
  • My previous camera fix
  • A boolean to toggle between the old behavior and the behavior in my PR

You can try it out here:
master...albertvaka:albertvaka/awesome-camera

What I found is that the old behavior already does what was being discussed here: it rotates and zooms around the center point while moving along the window axis... so I'm not sure there's anything that needs fixing. I'll await your input :)

@seanballais
Copy link
Contributor Author

Hey, @albertvaka! Sorry for the late reply. I discovered something with your fix (#206): The origin became the center of the window, rather than the top-left corner. This affected drawing graphics. What used to be rendered on the top-left corner gets rendered now on the centre. This doesn't occur in the current master commit. Shouldn't we keep the origin at the top-left for rendering like it has always been?

@albertvaka
Copy link
Contributor

albertvaka commented Oct 26, 2020

Yes, that's the case when use_centered_origin is true. That was my interpretation of what that boolean was meant to do. You can disable it, but then the rotation is also done from the top left corner, which is probably not what you want (ever?). So, there are two options:

  • Keep (0,0) always at the top left regardless of use_centered_origin and make use_centered_origin only change where we scale/rotate from.
  • Keep (0,0) at the top left only if use_centered_origin is false, or center it otherwise.

Also I'm not sure we ever want to rotate from anywhere other than the center of the screen, so maybe use_centered_origin shouldn't affect rotation. In that case we should decide whether it affects only where we scale from or both the scale and wether (0,0) is the center or the top-left.

@grimfang4 Which of the two respects the intended behavior of use_centered_origin?
@seanballais If setting use_centered_origin to false still rotated the camera from the center of the screen, would that suit your use case? (Note zoom would still happen from the top-left in that case)

@seanballais
Copy link
Contributor Author

seanballais commented Oct 27, 2020

The way I interpret use_centered_origin is that it only affects the camera, not the origin of everything. A justification to my interpretation could be seen by checking how the Camera struct is defined, where we have the use_centered_origin attribute. Additionally, traditionally, the origin was always kept at the top left corner, so I don't think it makes sense for the origin to be changed to the centre. As such, I'd vouch for the first option you mentioned, and having the attribute affect the scale and rotation only.

I think there are uses for rotating the camera somewhere else other than the center. For example, a top down shooter where we rotate the player and the camera as a result to set the aim. This would be akin to one top down level in a Contra game for the SNES. So, I think use_centered_origin should also affect rotation. Similarly, I think there are cases where scaling needs to be done not from the center, like in cutscenes, but I think cases like these can be solved by just moving the camera and zooming it at the same time.

As for my use case, I still need the zoom to happen from the center. So, I would still set use_centered_origin to true. But, if I didn't need the scaling, I would find it weird that the camera is being rotated from the centre yet use_centered_origin is false for reasons I've said earlier.

On another note, considering most cases, I think it is best if we set use_centered_origin to true by default. @grimfang4, what do you think?

@grimfang4
Copy link
Owner

That's how I feel, generally. A centered origin is for the camera's view to be offset so it shows the region (-w/2, -h/2, w/2, h/2) and rotates and zooms about the center of the screen. I still think use_centered_origin should default to false because the expected default drawing region should be (0, 0, w, h). use_centered_origin turns the traditional computer graphics view into something more suitable for a follow-style "game camera".

@seanballais
Copy link
Contributor Author

seanballais commented Oct 28, 2020

@grimfang4, I see. So, when we set use_centered_origin to true, the world-space origin will now initially be located in the screen-space center, right?

@albertvaka, given @grimfang4's opinion, I now think your implementation is spot on, and I just forgot to separate screen-space and world-space. I guess what's left to do is deciding whether the translation of the camera should be done in screen space or world space by default.

@albertvaka
Copy link
Contributor

@grimfang4 friendly ping :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants