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

camera viewport DOES affect camera space #732

Open
PSteinhaus opened this issue Jun 4, 2024 · 1 comment
Open

camera viewport DOES affect camera space #732

PSteinhaus opened this issue Jun 4, 2024 · 1 comment

Comments

@PSteinhaus
Copy link

PSteinhaus commented Jun 4, 2024

This is on master at 4e27d18
Slightly related to #171

expected behavior

The docs state that

Viewport do not affect camera space, just the render position on the screen.

observed behavior

I modified the rustaceanmark example minimally to try out the macroquad camera. During this I stumbled upon the fact that specifying a viewport does alter your cameras space. As you can see here specifying a viewport has the effect of zooming in:

native (Ubuntu 23.10, Nvidia GTX 1060):
grafik

wasm (Firefox and Chromium):
grafik

Code:

use macroquad::prelude::*;

struct Rustaceane {
    pos: Vec2,
    speed: Vec2,
    color: Color,
}

#[macroquad::main("Rustaceanmark")]
async fn main() {
    let mut rustaceanes: Vec<Rustaceane> = Vec::new();
    let rustacean_tex = load_texture("examples/rustacean_happy.png").await.unwrap();
    rustacean_tex.set_filter(FilterMode::Nearest);

    let mut cam = Camera2D::default();
    cam.viewport = Some((0, 0, 200, 200));

    loop {
        clear_background(Color::default());
        set_camera(&cam);

        if macroquad::input::is_mouse_button_down(MouseButton::Left) {
            for _i in 0..100 {
                rustaceanes.push(Rustaceane {
                    pos: Vec2::from(macroquad::input::mouse_position()),
                    speed: Vec2::new(
                        rand::gen_range(-250., 250.) / 60.,
                        rand::gen_range(-250., 250.) / 60.,
                    ),
                    color: Color::from_rgba(
                        rand::gen_range(50, 240),
                        rand::gen_range(80, 240),
                        rand::gen_range(100, 240),
                        255,
                    ),
                })
            }
        }

        for rustaceane in &mut rustaceanes {
            rustaceane.pos += rustaceane.speed;

            if ((rustaceane.pos.x + rustacean_tex.width() / 2.) > screen_width())
                || ((rustaceane.pos.x + rustacean_tex.width() / 2.) < 0.)
            {
                rustaceane.speed.x *= -1.;
            }
            if ((rustaceane.pos.y + rustacean_tex.height() / 2.) > screen_height())
                || ((rustaceane.pos.y + rustacean_tex.height() / 2.) < 0.)
            {
                rustaceane.speed.y *= -1.;
            }

            draw_texture(
                &rustacean_tex,
                rustaceane.pos.x,
                rustaceane.pos.y,
                rustaceane.color,
            );
        }

        draw_text(format!("FPS: {}", get_fps()).as_str(), 0., 16., 32., WHITE);
        draw_text(
            format!("Rustaceanes: {}", rustaceanes.len()).as_str(),
            0.,
            32.,
            32.,
            WHITE,
        );

        next_frame().await
    }
}

experiment with from_display_rect camera configuration

I can get the right space back though, if I also set the zoom and target accordingly by using from_display_rect with the same dimensions as the viewport:

native (and wasm looks the same):
grafik

Code:

use macroquad::prelude::*;

struct Rustaceane {
    pos: Vec2,
    speed: Vec2,
    color: Color,
}

#[macroquad::main("Rustaceanmark")]
async fn main() {
    let mut rustaceanes: Vec<Rustaceane> = Vec::new();
    let rustacean_tex = load_texture("examples/rustacean_happy.png").await.unwrap();
    rustacean_tex.set_filter(FilterMode::Nearest);

    const WORLD_WIDTH: f32 = 200.;
    const WORLD_HEIGHT: f32 = 200.;

    let mut cam = Camera2D::from_display_rect(Rect::new(0., 0., WORLD_WIDTH, WORLD_HEIGHT));
    cam.zoom = Vec2::new(cam.zoom.x, -cam.zoom.y); // workaround for https:/not-fl3/macroquad/issues/171
    cam.viewport = Some((0, 0, WORLD_WIDTH as i32, WORLD_HEIGHT as i32));

    loop {
        clear_background(Color::default());
        set_camera(&cam);

        if macroquad::input::is_mouse_button_down(MouseButton::Left) {
            for _i in 0..100 {
                rustaceanes.push(Rustaceane {
                    pos: Vec2::from(macroquad::input::mouse_position()),
                    speed: Vec2::new(
                        rand::gen_range(-250., 250.) / 60.,
                        rand::gen_range(-250., 250.) / 60.,
                    ),
                    color: Color::from_rgba(
                        rand::gen_range(50, 240),
                        rand::gen_range(80, 240),
                        rand::gen_range(100, 240),
                        255,
                    ),
                })
            }
        }

        for rustaceane in &mut rustaceanes {
            rustaceane.pos += rustaceane.speed;

            if ((rustaceane.pos.x + rustacean_tex.width() / 2.) > screen_width())
                || ((rustaceane.pos.x + rustacean_tex.width() / 2.) < 0.)
            {
                rustaceane.speed.x *= -1.;
            }
            if ((rustaceane.pos.y + rustacean_tex.height() / 2.) > screen_height())
                || ((rustaceane.pos.y + rustacean_tex.height() / 2.) < 0.)
            {
                rustaceane.speed.y *= -1.;
            }

            draw_texture(
                &rustacean_tex,
                rustaceane.pos.x,
                rustaceane.pos.y,
                rustaceane.color,
            );
        }

        draw_text(format!("FPS: {}", get_fps()).as_str(), 0., 16., 32., WHITE);
        draw_text(
            format!("Rustaceanes: {}", rustaceanes.len()).as_str(),
            0.,
            32.,
            32.,
            WHITE,
        );

        next_frame().await
    }
}

experiments with multiple cameras

If we try to go one step further and restore the default camera (using set_default_camera) after drawing the sprites but before drawing the text we get this:
grafik

As you can see, now the text is being scaled down.

If we do something like this instead:

let mut def_cam = Camera2D::default();
def_cam.viewport = Some((0, 0, screen_width() as i32, screen_height() as i32));
set_camera(&def_cam);

we get no text drawn at all (or probably somewhere we can't see):
grafik

@PSteinhaus
Copy link
Author

What does work though to get something like a functioning viewport is using the clipping functionality in macroquad:

const WORLD_WIDTH: f32 = 200.;
const WORLD_HEIGHT: f32 = 200.;

let mut cam = Camera2D::from_display_rect(Rect::new(0., 0., WORLD_WIDTH, WORLD_HEIGHT));
cam.zoom = Vec2::new(cam.zoom.x, -cam.zoom.y); // workaround for https:/not-fl3/macroquad/issues/171
set_camera(&cam);
unsafe {
    window::get_internal_gl().quad_gl.scissor(Some((0, 0, WORLD_WIDTH as i32, WORLD_HEIGHT as i32)));
}

// ... draw sprites

unsafe {
    window::get_internal_gl().quad_gl.scissor(None);
}
set_default_camera();

grafik

Now I even get the camera space that I asked for! :D

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

1 participant