SFML Views setCenter vs rotation

2019-07-21 04:36发布

问题:

I have a view with same dimensions of original window (500,300)

I apply view.zoom(2) to leave the view at half the size.

Now the view is centered. I want to move the view to the upper left corner of the original window. So I put view.setCenter(500,300);

The view is now correctly positioned in the upper corner of the original window. But now I want to rotate the view, making the center of the view its own top left corner, ie (0,0): view.setRotation(5);

As you can see, the center of the axis of rotation should be 0.0 but not respected. The problem is that if I do view.setCenter (0,0), the whole view returns to the middle of the original window.

How to solve this?

回答1:

Instead of using view.setCenter(500,300); move it via view.move(x_offset, y_offset);. Then applying setCenter(...) won't redefine the center and it won't get reset.

I recommend consulting the API reference of View for further reading.

You might also be interested in void sf::View::setViewport(const FloatRect& viewport) or void sf::View::reset(const FloatRect& rectangle).



回答2:

This code, kindly provided by Geheim, solves the problem and also teaches a more practical approach to SFML.

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window({500, 300}, "SFML Views", sf::Style::Close);
    window.setFramerateLimit(120);
    bool useViewPort {true};        // change this to false to see the other version

    sf::View camera {{0, 0}, static_cast<sf::Vector2f>(window.getSize())};
    if (useViewPort)
    {
        camera.setViewport({-0.5f, -0.5f, 1, 1});
        camera.rotate(5);
    }
    else
        camera.setCenter(camera.getSize());

    camera.zoom(2);
    window.setView(camera);

    sf::RectangleShape background {camera.getSize()};
    sf::RectangleShape square {{50, 50}};
    square.setFillColor(sf::Color::Red);

    sf::RenderTexture texture;
    texture.create(window.getSize().x, window.getSize().y);

    while (window.isOpen())
    {
        for (sf::Event event; window.pollEvent(event);)
            if (event.type == sf::Event::Closed)
                window.close();

        window.clear();

        if (useViewPort)
        {
            window.draw(background);
            window.draw(square);
        }
        else
        {
            texture.clear();
            texture.draw(background);
            texture.draw(square);
            texture.display();

            sf::Sprite content {texture.getTexture()};
            content.rotate(-5);     // you have to rotate in the other disquareion here, do you know why?
            window.draw(content);
        }

        window.display();
    }

    return EXIT_SUCCESS;
}


回答3:

I'm glad you got the result you wanted by applying viewports using Geheim's code.

However, if you don't want to be using viewports to clip areas of the window and such, you can still rotate a view around a specific point other than its centre. You just need a little bit of mathematics...

Take the different between the target point (in the view's co-ordinate system) and the view's centre and rotate that point by the amount you wish to rotate the view and around the view's centre. Then, calculate the difference between those points (the target point and the rotated point). Once you have this difference, simply rotate the view (around its centre as normal) but then move the view by that difference.

It might sound complicated so you might want to just use this free function that I made that does it all automatically; it's on the SFML Wiki: RotateViewAt



标签: c++ sfml