renderer: implement window wobble (#14920)

Adds a new window transformer, and wobble framework.
This commit is contained in:
Vaxry
2026-07-31 19:11:53 +02:00
committed by GitHub
parent 8668a53921
commit e8a6164298
27 changed files with 1195 additions and 93 deletions
+91
View File
@@ -0,0 +1,91 @@
#include <helpers/DeformableMesh.hpp>
#include <gtest/gtest.h>
#include <algorithm>
#include <cmath>
TEST(Helpers, deformableMeshSetSizeClamps) {
CDeformableMesh mesh;
mesh.setSize(1);
EXPECT_EQ(mesh.size(), 2u);
mesh.setSize(64);
EXPECT_EQ(mesh.size(), 32u);
}
TEST(Helpers, deformableMeshNoopUpdateKeepsExtents) {
CDeformableMesh mesh(4);
CBox box = {10, 20, 100, 50};
mesh.onPositionUpdate(box, box, 1.F);
const auto EXTENTS = mesh.transformedExtents(box);
EXPECT_DOUBLE_EQ(EXTENTS.x, box.x);
EXPECT_DOUBLE_EQ(EXTENTS.y, box.y);
EXPECT_DOUBLE_EQ(EXTENTS.w, box.w);
EXPECT_DOUBLE_EQ(EXTENTS.h, box.h);
EXPECT_TRUE(mesh.stable(0.F, 0.F));
}
TEST(Helpers, deformableMeshPositionUpdateExpandsExtents) {
CDeformableMesh mesh(4);
const CBox PREVIOUS = {0, 0, 100, 50};
const CBox CURRENT = {10, 0, 100, 50};
mesh.onPositionUpdate(PREVIOUS, CURRENT, 1.F);
const auto EXTENTS = mesh.transformedExtents(CURRENT);
EXPECT_LT(EXTENTS.x, CURRENT.x);
EXPECT_GE(EXTENTS.x + EXTENTS.w, CURRENT.x + CURRENT.w);
EXPECT_FALSE(mesh.stable(0.F, 0.F));
}
TEST(Helpers, deformableMeshGrabPointAnchorsNearestVertices) {
CDeformableMesh mesh(3);
const CBox PREVIOUS = {0, 0, 100, 100};
const CBox CURRENT = {0, 0, 100, 120};
mesh.onPositionUpdate(PREVIOUS, CURRENT, 1.F, Vector2D{0.5, 0.0});
const auto VERTICES = mesh.verticesForBox(CURRENT, CURRENT, {100, 120});
const auto TOPCENTER = std::ranges::find_if(VERTICES, [](const auto& v) { return v.u == 0.5F && v.v == 0.F; });
const auto CENTER = std::ranges::find_if(VERTICES, [](const auto& v) { return v.u == 0.5F && v.v == 0.5F; });
ASSERT_NE(TOPCENTER, VERTICES.end());
ASSERT_NE(CENTER, VERTICES.end());
EXPECT_LT(std::abs(TOPCENTER->y - TOPCENTER->v), std::abs(CENTER->y - CENTER->v));
}
TEST(Helpers, deformableMeshPositionUpdateClampsDisplacement) {
CDeformableMesh mesh(4);
const CBox PREVIOUS = {0, 0, 100, 50};
const CBox CURRENT = {1000, 1000, 100, 50};
mesh.onPositionUpdate(PREVIOUS, CURRENT, 2.F);
const auto EXTENTS = mesh.transformedExtents(CURRENT);
EXPECT_GE(EXTENTS.x, CURRENT.x - 16.001);
EXPECT_GE(EXTENTS.y, CURRENT.y - 16.001);
EXPECT_LE(EXTENTS.x + EXTENTS.w, CURRENT.x + CURRENT.w + 16.001);
EXPECT_LE(EXTENTS.y + EXTENTS.h, CURRENT.y + CURRENT.h + 16.001);
}
TEST(Helpers, deformableMeshVerticesForBoxBuildsTriangles) {
CDeformableMesh mesh(2);
const auto VERTICES = mesh.verticesForBox({0, 0, 100, 50}, {0, 0, 100, 50}, {100, 50});
ASSERT_EQ(VERTICES.size(), 6u);
EXPECT_FLOAT_EQ(VERTICES.front().x, 0.F);
EXPECT_FLOAT_EQ(VERTICES.front().y, 0.F);
EXPECT_FLOAT_EQ(VERTICES.front().u, 0.F);
EXPECT_FLOAT_EQ(VERTICES.front().v, 0.F);
EXPECT_FLOAT_EQ(VERTICES.back().x, 1.F);
EXPECT_FLOAT_EQ(VERTICES.back().y, 1.F);
EXPECT_FLOAT_EQ(VERTICES.back().u, 1.F);
EXPECT_FLOAT_EQ(VERTICES.back().v, 1.F);
}
+62
View File
@@ -0,0 +1,62 @@
#include <render/transformer/TransformerList.hpp>
#include <gtest/gtest.h>
class CTestDamageTransformer : public Render::IWindowTransformer {
public:
CTestDamageTransformer(int priority, double scale, double add, bool active = true) : m_priority(priority), m_scale(scale), m_add(add), m_active(active) {
;
}
virtual SP<Render::IFramebuffer> transform(SP<Render::IFramebuffer> in, const Render::SWindowTransformContext& context) {
(void)context;
return in;
}
virtual int priority() const {
return m_priority;
}
virtual bool active() const {
return m_active;
}
virtual CBox transformBoxForDamage(const CBox& currentBox) const {
CBox box = currentBox;
box.x = box.x * m_scale + m_add;
box.w *= m_scale;
return box;
}
private:
int m_priority = 0;
double m_scale = 1.0;
double m_add = 0.0;
bool m_active = true;
};
TEST(Render, transformerListDamageBoxFollowsPriorityOrder) {
Render::CWindowTransformerList list;
list.emplace<CTestDamageTransformer>(20, 2.0, 0.0);
list.emplace<CTestDamageTransformer>(10, 1.0, 3.0);
const CBox BOX = {1, 2, 10, 20};
const auto OUT = list.transformBoxForDamage(BOX);
EXPECT_DOUBLE_EQ(OUT.x, 8.0);
EXPECT_DOUBLE_EQ(OUT.y, 2.0);
EXPECT_DOUBLE_EQ(OUT.w, 20.0);
EXPECT_DOUBLE_EQ(OUT.h, 20.0);
}
TEST(Render, transformerListDamageBoxSkipsInactiveTransformers) {
Render::CWindowTransformerList list;
list.emplace<CTestDamageTransformer>(10, 2.0, 0.0, false);
list.emplace<CTestDamageTransformer>(20, 1.0, 3.0);
const CBox BOX = {1, 2, 10, 20};
const auto OUT = list.transformBoxForDamage(BOX);
EXPECT_DOUBLE_EQ(OUT.x, 4.0);
EXPECT_DOUBLE_EQ(OUT.w, 10.0);
}