Remove caching from sf::Transformable and sf::View

This reduces the size of both classes by 130 bytes which has positive
impacts on cache locality. This change also removes all the internal
invariants from both classes allowing them to be converted to
aggregate types in the future.
This commit is contained in:
Chris Thrasher 2024-12-25 19:38:23 -06:00
parent dab1800f61
commit 4c685666c5
No known key found for this signature in database
GPG Key ID: 56FB686C9DFC8E2C
4 changed files with 54 additions and 107 deletions

View File

@ -214,7 +214,7 @@ public:
/// \see `getInverseTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getTransform() const;
[[nodiscard]] Transform getTransform() const;
////////////////////////////////////////////////////////////
/// \brief get the inverse of the combined transform of the object
@ -224,20 +224,16 @@ public:
/// \see `getTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getInverseTransform() const;
[[nodiscard]] Transform getInverseTransform() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f m_origin; //!< Origin of translation/rotation/scaling of the object
Vector2f m_position; //!< Position of the object in the 2D world
Angle m_rotation; //!< Orientation of the object
Vector2f m_scale{1, 1}; //!< Scale of the object
mutable Transform m_transform; //!< Combined transformation of the object
mutable Transform m_inverseTransform; //!< Combined transformation of the object
mutable bool m_transformNeedUpdate{true}; //!< Does the transform need to be recomputed?
mutable bool m_inverseTransformNeedUpdate{true}; //!< Does the transform need to be recomputed?
Vector2f m_origin; //!< Origin of translation/rotation/scaling of the object
Vector2f m_position; //!< Position of the object in the 2D world
Angle m_rotation; //!< Orientation of the object
Vector2f m_scale{1, 1}; //!< Scale of the object
};
} // namespace sf

View File

@ -240,7 +240,7 @@ public:
/// \see `getInverseTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getTransform() const;
[[nodiscard]] Transform getTransform() const;
////////////////////////////////////////////////////////////
/// \brief Get the inverse projection transform of the view
@ -252,21 +252,17 @@ public:
/// \see `getTransform`
///
////////////////////////////////////////////////////////////
[[nodiscard]] const Transform& getInverseTransform() const;
[[nodiscard]] Transform getInverseTransform() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f m_center{500, 500}; //!< Center of the view, in scene coordinates
Vector2f m_size{1000, 1000}; //!< Size of the view, in scene coordinates
Angle m_rotation; //!< Angle of rotation of the view rectangle
FloatRect m_viewport{{0, 0}, {1, 1}}; //!< Viewport rectangle, expressed as a factor of the render-target's size
FloatRect m_scissor{{0, 0}, {1, 1}}; //!< Scissor rectangle, expressed as a factor of the render-target's size
mutable Transform m_transform; //!< Precomputed projection transform corresponding to the view
mutable Transform m_inverseTransform; //!< Precomputed inverse projection transform corresponding to the view
mutable bool m_transformUpdated{}; //!< Internal state telling if the transform needs to be updated
mutable bool m_invTransformUpdated{}; //!< Internal state telling if the inverse transform needs to be updated
Vector2f m_center{500, 500}; //!< Center of the view, in scene coordinates
Vector2f m_size{1000, 1000}; //!< Size of the view, in scene coordinates
Angle m_rotation; //!< Angle of rotation of the view rectangle
FloatRect m_viewport{{0, 0}, {1, 1}}; //!< Viewport rectangle, expressed as a factor of the render-target's size
FloatRect m_scissor{{0, 0}, {1, 1}}; //!< Scissor rectangle, expressed as a factor of the render-target's size
};
} // namespace sf

View File

@ -35,9 +35,7 @@ namespace sf
////////////////////////////////////////////////////////////
void Transformable::setPosition(Vector2f position)
{
m_position = position;
m_transformNeedUpdate = true;
m_inverseTransformNeedUpdate = true;
m_position = position;
}
@ -45,27 +43,20 @@ void Transformable::setPosition(Vector2f position)
void Transformable::setRotation(Angle angle)
{
m_rotation = angle.wrapUnsigned();
m_transformNeedUpdate = true;
m_inverseTransformNeedUpdate = true;
}
////////////////////////////////////////////////////////////
void Transformable::setScale(Vector2f factors)
{
m_scale = factors;
m_transformNeedUpdate = true;
m_inverseTransformNeedUpdate = true;
m_scale = factors;
}
////////////////////////////////////////////////////////////
void Transformable::setOrigin(Vector2f origin)
{
m_origin = origin;
m_transformNeedUpdate = true;
m_inverseTransformNeedUpdate = true;
m_origin = origin;
}
@ -119,44 +110,30 @@ void Transformable::scale(Vector2f factor)
////////////////////////////////////////////////////////////
const Transform& Transformable::getTransform() const
Transform Transformable::getTransform() const
{
// Recompute the combined transform if needed
if (m_transformNeedUpdate)
{
const float angle = -m_rotation.asRadians();
const float cosine = std::cos(angle);
const float sine = std::sin(angle);
const float sxc = m_scale.x * cosine;
const float syc = m_scale.y * cosine;
const float sxs = m_scale.x * sine;
const float sys = m_scale.y * sine;
const float tx = -m_origin.x * sxc - m_origin.y * sys + m_position.x;
const float ty = m_origin.x * sxs - m_origin.y * syc + m_position.y;
const float angle = -m_rotation.asRadians();
const float cosine = std::cos(angle);
const float sine = std::sin(angle);
const float sxc = m_scale.x * cosine;
const float syc = m_scale.y * cosine;
const float sxs = m_scale.x * sine;
const float sys = m_scale.y * sine;
const float tx = -m_origin.x * sxc - m_origin.y * sys + m_position.x;
const float ty = m_origin.x * sxs - m_origin.y * syc + m_position.y;
// clang-format off
m_transform = Transform( sxc, sys, tx,
-sxs, syc, ty,
0.f, 0.f, 1.f);
// clang-format on
m_transformNeedUpdate = false;
}
return m_transform;
// clang-format off
return { sxc, sys, tx,
-sxs, syc, ty,
0.f, 0.f, 1.f};
// clang-format on
}
////////////////////////////////////////////////////////////
const Transform& Transformable::getInverseTransform() const
Transform Transformable::getInverseTransform() const
{
// Recompute the inverse transform if needed
if (m_inverseTransformNeedUpdate)
{
m_inverseTransform = getTransform().getInverse();
m_inverseTransformNeedUpdate = false;
}
return m_inverseTransform;
return getTransform().getInverse();
}
} // namespace sf

View File

@ -48,9 +48,7 @@ View::View(Vector2f center, Vector2f size) : m_center(center), m_size(size)
////////////////////////////////////////////////////////////
void View::setCenter(Vector2f center)
{
m_center = center;
m_transformUpdated = false;
m_invTransformUpdated = false;
m_center = center;
}
@ -58,9 +56,6 @@ void View::setCenter(Vector2f center)
void View::setSize(Vector2f size)
{
m_size = size;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
@ -68,9 +63,6 @@ void View::setSize(Vector2f size)
void View::setRotation(Angle angle)
{
m_rotation = angle.wrapUnsigned();
m_transformUpdated = false;
m_invTransformUpdated = false;
}
@ -152,48 +144,34 @@ void View::zoom(float factor)
////////////////////////////////////////////////////////////
const Transform& View::getTransform() const
Transform View::getTransform() const
{
// Recompute the matrix if needed
if (!m_transformUpdated)
{
// Rotation components
const float angle = m_rotation.asRadians();
const float cosine = std::cos(angle);
const float sine = std::sin(angle);
const float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
const float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
// Rotation components
const float angle = m_rotation.asRadians();
const float cosine = std::cos(angle);
const float sine = std::sin(angle);
const float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
const float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
// Projection components
const float a = 2.f / m_size.x;
const float b = -2.f / m_size.y;
const float c = -a * m_center.x;
const float d = -b * m_center.y;
// Projection components
const float a = 2.f / m_size.x;
const float b = -2.f / m_size.y;
const float c = -a * m_center.x;
const float d = -b * m_center.y;
// Rebuild the projection matrix
// clang-format off
m_transform = Transform( a * cosine, a * sine, a * tx + c,
-b * sine, b * cosine, b * ty + d,
0.f, 0.f, 1.f);
// clang-format on
m_transformUpdated = true;
}
return m_transform;
// Rebuild the projection matrix
// clang-format off
return { a * cosine, a * sine, a * tx + c,
-b * sine, b * cosine, b * ty + d,
0.f, 0.f, 1.f};
// clang-format on
}
////////////////////////////////////////////////////////////
const Transform& View::getInverseTransform() const
Transform View::getInverseTransform() const
{
// Recompute the matrix if needed
if (!m_invTransformUpdated)
{
m_inverseTransform = getTransform().getInverse();
m_invTransformUpdated = true;
}
return m_inverseTransform;
return getTransform().getInverse();
}
} // namespace sf