Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Need real corner coordinates of rotated rectangle  (Read 6665 times)

0 Members and 2 Guests are viewing this topic.

freesoul

  • Newbie
  • *
  • Posts: 19
    • View Profile
Need real corner coordinates of rotated rectangle
« on: August 11, 2013, 04:12:24 pm »
I want to apply SAT collision detection to my 2D game. As I understood, getGlobalBounds retrieves the bigger box that contains the rotated rectangle, but it isnt what i need. getLocalBounds gives the sprite without transformation, which I could use to get the rotated coords, but I actually dont know how to apply maths to, set an origin and an angle, get the coords ¿is there a way to get the real coordinates of the rotated sprite? thanks.

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re: Need real corner coordinates of rotated rectangle
« Reply #1 on: August 11, 2013, 04:56:20 pm »
use the object's inner transform (getTransform() ) and its member transformPoint() to pass any local point in the rect to the global position :)

freesoul

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Need real corner coordinates of rotated rectangle
« Reply #2 on: August 11, 2013, 05:56:42 pm »
Ok thanks. I set origin on centre, but I got rare results.

I got an image sized 223 x 75 px

I put the origin on the middle of the sprite, then rotate it 45º.

I make a point transform to a point (0, 75) and the result is

+      point   {x=-105.35892 y=-51.618793 }   sf::Vector2<float>


Why? -105 on x axis??

My expected result should be like (-10, 10) or so

I guess it has to do with origin. So, how can I rotate at that origin but have the input (0, 75), and the output from normal (0, 0) coord? thanks
« Last Edit: August 11, 2013, 06:04:18 pm by freesoul »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need real corner coordinates of rotated rectangle
« Reply #3 on: August 11, 2013, 08:24:01 pm »
At best write a minimal example with the transformation and post it here, thus we can directly point at the mistake and explain the solution. :)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re: Need real corner coordinates of rotated rectangle
« Reply #4 on: August 11, 2013, 09:29:06 pm »
How hard can it be?

sf::RectangleShape rect;
rect.setOrigin(25,25);
rect.setSize(50,50);
rect.setPosition(500,500);
rect.setRotation(120);

Global coordinates:
vec2 topLeft = rect.getTransform().transformPoint(vec2(0,0));
vec2 topRight = rect.getTransform().transformPoint(vec2(rect.getSize().x,0));
vec2 bottomLeft = rect.getTransform().transformPoint(vec2(0,rect.getSize().y));
vec2 bottomRight = rect.getTransform().transformPoint(vec2(0rect.getSize().x,rect.getSize().y));

Go for it :D

freesoul

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Need real corner coordinates of rotated rectangle
« Reply #5 on: August 11, 2013, 10:30:56 pm »
Finally I finished my little collision check for rotated rectangles, thanks you. Code below

sat.h
#ifndef SAT_
#define SAT_

#include <SFML/Graphics.hpp>


        struct rectangle {
                sf::Vector2f vertex[4];
        };

class SAT {
public:
        bool collision(sf::Sprite* s1, sf::Sprite* s2);
private:
        void  SAT::project(sf::Vector2f& axis, rectangle* _rectangle, float &min, float &max);
        void normalize(sf::Vector2f& vector);
        float dot(sf::Vector2f& vector1, sf::Vector2f& vector2);
        float SAT::distance(float minA, float maxA, float minB, float maxB) ;
};


#endif


#include <math.h>
#include "SATcollision.h"


void SAT::normalize(sf::Vector2f& vector) {
        const float length = sqrt(vector.x * vector.x + vector.y * vector.y);
        if(length==0)
                return;
        vector.x = vector.x / length;
        vector.y = vector.y / length;
}

float SAT::dot(sf::Vector2f& vector1, sf::Vector2f& vector2)
{
        return vector1.x*vector2.x + vector1.y*vector2.y;
}

float SAT::distance(float minA, float maxA, float minB, float maxB) // Positive return = no hit
{
        if(minB > maxA) return minB-maxA;
        else return minA-maxB;
}




void  SAT::project(sf::Vector2f& axis, rectangle* _rectangle, float &min, float &max)
{
        float _dot = dot(axis, _rectangle->vertex[0]);

        min=_dot;
        max=_dot;

        for(short i=1; i<4; i++)
        {
                _dot = dot(_rectangle->vertex[i], axis);

                if(_dot<min)
                        min=_dot;
                else if(_dot>max)
                        max=_dot;
        }
}


bool SAT::collision(sf::Sprite* s1, sf::Sprite* s2)
{
        rectangle one;
        rectangle two;

        sf::Transform transform = s1->getTransform();
        sf::FloatRect rect = s1->getLocalBounds();

        one.vertex[0]=transform.transformPoint(sf::Vector2f(rect.left, rect.top));
        one.vertex[1]=transform.transformPoint(sf::Vector2f(rect.left+rect.width, rect.top));
        one.vertex[2]=transform.transformPoint(sf::Vector2f(rect.left+rect.width, rect.top+rect.height));
        one.vertex[3]=transform.transformPoint(sf::Vector2f(rect.left, rect.top+rect.height));

        transform = s2->getTransform();
        rect = s2->getLocalBounds();

        two.vertex[0]=transform.transformPoint(sf::Vector2f(rect.left, rect.top));
        two.vertex[1]=transform.transformPoint(sf::Vector2f(rect.left+rect.width, rect.top));
        two.vertex[2]=transform.transformPoint(sf::Vector2f(rect.left+rect.width, rect.top+rect.height));
        two.vertex[3]=transform.transformPoint(sf::Vector2f(rect.left, rect.top+rect.height));

        sf::Vector2f axis;
        float minA;
        float minB;
        float maxA;
        float maxB;
       

        // Test one
        axis.x = one.vertex[1].x - one.vertex[0].x;
        axis.y = one.vertex[1].y - one.vertex[0].y;
        SAT::normalize(axis);

        project(axis, &one, minA, maxA);
        project(axis, &two, minB, maxB);

        if(distance(minA,maxA,minB,maxB)>0.f)
                return false;


        // Test two
        axis.x = one.vertex[3].x - one.vertex[0].x;
        axis.y = one.vertex[3].y - one.vertex[0].y;
        SAT::normalize(axis);

        project(axis, &one, minA, maxA);
        project(axis, &two, minB, maxB);

        if(distance(minA,maxA,minB,maxB)>0.f)
                return false;


        // Test three
        axis.x = two.vertex[1].x - two.vertex[0].x;
        axis.y = two.vertex[1].y - two.vertex[0].y;
        SAT::normalize(axis);

        project(axis, &one, minA, maxA);
        project(axis, &two, minB, maxB);

        if(distance(minA,maxA,minB,maxB)>0.f)
                return false;


        // Test four
        axis.x = two.vertex[3].x - two.vertex[0].x;
        axis.y = two.vertex[3].y - two.vertex[0].y;
        SAT::normalize(axis);

        project(axis, &one, minA, maxA);
        project(axis, &two, minB, maxB);

        if(distance(minA,maxA,minB,maxB)>0.f)
                return false;

        return true;

}
« Last Edit: August 11, 2013, 11:07:57 pm by freesoul »