Rotating objects »
Sometimes you need to rotate not only an image, but also the images location. Then
the rotate() method of CL_Sprite and CL_Surface is not enough.
Rotation math »
To rotate a point around (0, 0), you'll need to apply the following transformation.
x' = x cosŲ - y sinŲ
y' = x sinŲ + y cosŲ
Simple rotation
float new_x = old_x * ::cos(fi_rad) - old_y * ::sin(fi_rad);
float new_y = old_x * ::sin(fi_rad) + old_y * ::cos(fi_rad);
To rotate around an arbitrary point in the plane, the point needs first be translated to (0, 0), rotated, and finally translated back to the original position.
Rotation around arbitrary point
CL_Pointf the_point(230.f, 480.f);
CL_Pointf rotate_around_me(230.f, 480.f);
float rotation_angle_degrees = 45.f;
float rotation_angle_radians = rotation_angle_degrees * M_PI / 180;
CL_Pointf new_pos(the_point);
new_pos -= rotate_around_me;
the_point.x = new_pos.x * ::cos(rotation_angle_radians) -
new_pos.y * ::sin(rotation_angle_radians);
the_point.y = new_pos.x * ::sin(rotation_angle_radians) +
new_pos.y * ::cos(rotation_angle_radians);
the_point += rotate_around_me;
Now that we know how to do it we can optimise the code.
There is no point in calculating the cosŲ and sinŲ twice for each calculation. The value should be cached. And what if we need to rotate
multiple points at the same time?
Final solution »
rotation2dcalculator.h
class Rotation2DCalculator
{
public:
Rotation2DCalculator(const CL_Pointf& rotation_hotspot, float angle_deg)
: hotspot(rotation_hotspot), angle(angle_deg)
{
float angle_rad = angle_deg * M_PI / 180;
sin_fi = ::sin(angle_rad);
cos_fi = ::cos(angle_rad);
}
inline void rotate(CL_Pointf &p) const;
protected:
CL_Pointf hotspot;
float angle, sin_fi, cos_fi;
};
inline void Rotation2DCalculator::rotate(CL_Pointf &p) const
{
CL_Pointf new_pos(p);
new_pos -= hotspot;
p.x = new_pos.x * cos_fi - new_pos.y * sin_fi;
p.y = new_pos.x * sin_fi + new_pos.y * cos_fi;
p += hotspot;
}
Now it's possible to use a Rotation2DCalculator object for multiple transformations. Supplying getters and setters for the rotation hotspot and the rotation angle will complete the class.
Note: This functionality can also be acheived using CL_Vector::rotate(). But if speed is
an issue, this here idea is the way to go. It can be extended to three dimensions for those in need.
Back
|