arcade icon indicating copy to clipboard operation
arcade copied to clipboard

Camera2D unexpected results in simple case

Open cdeil opened this issue 10 months ago • 5 comments

I'm trying to use Camera2D for the first time (x-ref #2557) and wanted to have a solar system with sun at world position (0, 0) and earth at world position (1, 0) etc, but then have it displayed on a larger window e.g. with 800 x 600 pixels.

I tried to create a Camera2D for this that does this world to screen pixel mapping like this:

>>> import arcade
>>> window = arcade.Window(width=800, height=600)
>>> window
Window=(width=800, height=600)
>>> rect = arcade.XYWH(x=0, y=0, width=8, height=6)
>>> camera = arcade.camera.Camera2D(projection=rect)
>>> camera.projection
Rect(left=-4.0, right=4.0, bottom=-3.0, top=3.0, width=8.0, height=6.0, x=0.0, y=0.0)
>>> camera.viewport
Rect(left=0, right=800, bottom=0, top=600, width=800, height=600, x=400.0, y=300.0)

My understanding from the docs is that camera.projection should be the Rect in world coordinates and camera.viewport the Rect in screen pixel coordinates. So far it looks good to me, what I expected.

However then when I try to use this to draw it doesn't do what I expected, to put the sun from world position (0, 0) to the screen center at pixel position (400, 300).

I see this is what project and unproject gives:

>>> camera.project((0, 0))
Vec2(x=-39600.0, y=-29700.0)
>>> camera.unproject((400, 300))
Vec3(x=400.0, y=300.0, z=0.0)
>>> camera.unproject((0, 0))
Vec3(x=396.0, y=297.0, z=0.0)

This is not what I expected. Is this a bug? Or probably I'm simply not grokking yet how cameras work?

cdeil avatar Feb 10 '25 14:02 cdeil

I see now, the issue is that camera.position is set to the viewport center:

>>> camera.position
Vec2(x=400.0, y=300.0)

https://github.com/pythonarcade/arcade/blob/f4f4521d4cd263e0e5f82e791bc475044bb35c77/arcade/camera/camera_2d.py#L138-L139

I had expected that when I pass projection it's auto-set to the projection center.

If I change to this everything works as expected:

>>> camera = arcade.camera.Camera2D(projection=rect, position=rect.center)
>>> camera.position
Vec2(x=0.0, y=0.0)
>>> camera.project((0, 0)))
Vec2(x=400.0, y=300.0)

Does it make sense to init position as now or should it be changed to init based on projection center?

Maybe at least the docstring could be clarified what "XY plane" means?

https://github.com/pythonarcade/arcade/blob/f4f4521d4cd263e0e5f82e791bc475044bb35c77/arcade/camera/camera_2d.py#L61-L62

Either way, I'm happy that I have a working solution with a camera. :-)

cdeil avatar Feb 10 '25 15:02 cdeil

One more issue I ran into is that arcade.draw_circle_filled will only use four points now.

Is this something that should be improved that to compute how many points to use for the screen render first the transform to screen pixel coordinates is applied?

As workaround I now use num_segments=30 at the moment. ( my script so far: https://gist.github.com/cdeil/8fa5dab682ee4fea0e561f52b9764c11 )

Image

cdeil avatar Feb 10 '25 15:02 cdeil

@DragonMoffon

einarf avatar Feb 10 '25 19:02 einarf

Okay, Github initially hid the extra messages, so my first response wasn't helpful.

The reason it sits in the center of the viewport is to mimic Arcade's default behavior of having (0.0, 0.0) in the bottom left corner. Maybe this should be changed if you set the projection. However, the center of the projection doesn't really make sense either.

The documentation for cameras is very lacking at the moment as I depriortised it to get 3.0 out. It's on my todo list.

DragonMoffon avatar Feb 11 '25 00:02 DragonMoffon

I'm reviewing issues because there are so many things I want to do before 4.0 comes out. Getting this working nice is on the list. I think this may be solved already. If it isn't, for future me, the camera should always position itself in the init so that (0.0, 0.0) is the bottom left corner of the screen so it matches the default behavior of arcade. This wouldn't solve this person's issue since they want 0.0, 0.0 to be the center of the screen, but I think matching arcade's default behavior is more important.

DragonMoffon avatar Oct 08 '25 02:10 DragonMoffon