AdamsLair / duality

a 2D Game Development Framework
https://adamslair.github.io/duality
MIT License
1.41k stars 288 forks source link

Add ability to get the viewport of a camera in world coordinates #681

Closed ChristianGreiner closed 6 years ago

ChristianGreiner commented 6 years ago

Summary

As the title says it would be nice to get the world viewport coordinates of a camera.

For example it could be useful to figure out if objects are in the viewport of the camera.

Example: randomcontrol_af3_camera_object

ilexp commented 6 years ago

API suggestion: public Rect GetWorldViewport(float z);

SirePi commented 6 years ago

Can I haz for next month? Maybe have it return a Vector2[] instead of Rect to be able to also take into account situations where the camera is rotated.

ilexp commented 6 years ago

Can I haz for next month?

Sure! Assigned you. This should branch off of develop-3.0, as I'm trying to close down master as we slowly approach v3 release.

Maybe have it return a Vector2[] instead of Rect to be able to also take into account situations where the camera is rotated.

That's a very good point. Though a Vector2 array is a lot less useful than a rect in probably most cases where the camera isn't rotated, and it's also one allocation per call - maybe we can find another way?

There's also another issue I hadn't thought about earlier, which is that the rendered image size is unknown - we can't assume DualityApp.TargetViewSize in the general case, as anyone calling Render manually could just specify any value. So we should probably expose this as an optional parameter, which falls back to the target view size.

So here's my proposal: Let's change this to

public Rect GetWorldViewportBounds(float z, Vector2 imageSize = default(Vector2))

where the default imageSize is interpreted as a fallback to DualityApp.TargetViewSize, and the returned rect is the axis-aligned bounding rectangle that incorporates all four corners of a the viewport. In the usual, unrotated case, this will be equal to the actual viewport rect. In the rotated case, we still get useful information from the bounds rect. In cases where people want the actual rotated four corners, they can still call GetWorldPos four times.

ilexp commented 6 years ago

Actually, doesn't hurt to have both methods. Let's do something like this:

public Rect GetWorldViewportBounds(float z, Vector2 imageSize = default);
public void GetWorldViewportCorners(Vector2[] corners, float z, Vector2 imageSize = default);

The bounds variant could use the corners one with an internal Vector2[] temp field to avoid the allocation on every call, and just do the bounding rectangle around that.

SirePi commented 6 years ago

So if I understand correctly, the void one would fill the corners parameter? what if the array is not big enough?

ilexp commented 6 years ago

So if I understand correctly, the void one would fill the corners parameter?

Yep.

what if the array is not big enough?

Argument check and throw an exception if null or too small.

SirePi commented 6 years ago

Starting to think about this.. would it make sense to also have the z parameter optional, and if not set assume it's this.GameObj.Transform.Pos.Z + this.FocusDist where this is the Camera?

ilexp commented 6 years ago

Starting to think about this.. would it make sense to also have the z parameter optional, and if not set assume it's this.GameObj.Transform.Pos.Z + this.FocusDist where this is the Camera?

Hmm.. the default might as well be the Z-0 plane, but I'd say both make a similar amount of sense. It's probably ambiguous enough to not have a default / optional z.

ilexp commented 6 years ago

Implemented by SirePi in #688. Closing this.