mirror of
https://git.allpurposem.at/mat/WiggleWobble.git
synced 2025-12-23 21:11:29 +01:00
perf: avoid useless copy of particle positions in renderpass
This commit is contained in:
parent
4885426233
commit
e0475aa880
@ -17,7 +17,9 @@ class CWobblyWindow {
|
|||||||
static inline float s_dampingStrength = 12.f;
|
static inline float s_dampingStrength = 12.f;
|
||||||
static inline float s_drag = 0.4f;
|
static inline float s_drag = 0.4f;
|
||||||
|
|
||||||
std::vector<SParticle> m_particles;
|
std::vector<float> m_particlePositions;
|
||||||
|
std::vector<Vector2D> m_particleVelocities;
|
||||||
|
|
||||||
std::vector<Vector2D> m_targetPositions;
|
std::vector<Vector2D> m_targetPositions;
|
||||||
std::optional<Vector2D> m_grabPosition {std::nullopt};
|
std::optional<Vector2D> m_grabPosition {std::nullopt};
|
||||||
Vector2D m_windowMovement;
|
Vector2D m_windowMovement;
|
||||||
@ -25,5 +27,7 @@ class CWobblyWindow {
|
|||||||
CWobblyWindow();
|
CWobblyWindow();
|
||||||
|
|
||||||
bool step(Time::steady_tp time);
|
bool step(Time::steady_tp time);
|
||||||
|
|
||||||
|
void applyMovement(const Vector2D& movement);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -73,10 +73,7 @@ void hkRenderWindow(
|
|||||||
wobble.m_grabPosition = std::nullopt;
|
wobble.m_grabPosition = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
wobble.m_windowMovement = (pos - g_windowPositions[pWindow]) / windowSize;
|
wobble.applyMovement((pos - g_windowPositions[pWindow]) / windowSize);
|
||||||
for (auto&& particle : wobble.m_particles) {
|
|
||||||
particle.position -= wobble.m_windowMovement;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update last pos
|
// update last pos
|
||||||
g_windowPositions[pWindow] = pos;
|
g_windowPositions[pWindow] = pos;
|
||||||
|
|||||||
@ -165,16 +165,13 @@ void CRenderWobblyWindowPassElement::draw(const CRegion& damage) {
|
|||||||
// TODO: these should never be nan
|
// TODO: these should never be nan
|
||||||
// if (not std::isnan(wobble.m_particles[0].position.x)) {
|
// if (not std::isnan(wobble.m_particles[0].position.x)) {
|
||||||
|
|
||||||
// TODO: we need the particle positions in their own vec, to avoid this copy
|
|
||||||
std::vector<float> verts;
|
|
||||||
verts.reserve(vertsPerRow * vertsPerRow * 2);
|
|
||||||
for (auto&& particle : wobble.m_particles) {
|
|
||||||
verts.push_back(particle.position.x);
|
|
||||||
verts.push_back(particle.position.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, s_VBO));
|
||||||
GLCALL(glBufferSubData(GL_ARRAY_BUFFER, 0, verts.size() * sizeof(float), verts.data()));
|
GLCALL(glBufferSubData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
0,
|
||||||
|
wobble.m_particlePositions.size() * sizeof(float),
|
||||||
|
wobble.m_particlePositions.data()
|
||||||
|
));
|
||||||
// }
|
// }
|
||||||
} else {
|
} else {
|
||||||
// restore default verts
|
// restore default verts
|
||||||
|
|||||||
@ -5,11 +5,15 @@
|
|||||||
|
|
||||||
CWobblyWindow::CWobblyWindow() {
|
CWobblyWindow::CWobblyWindow() {
|
||||||
auto&& verts = CRenderWobblyWindowPassElement::s_baseVerts;
|
auto&& verts = CRenderWobblyWindowPassElement::s_baseVerts;
|
||||||
m_particles.reserve(verts.size() / 2);
|
|
||||||
m_targetPositions.reserve(verts.size() / 2);
|
|
||||||
|
|
||||||
|
// copy directly
|
||||||
|
m_particlePositions = verts;
|
||||||
|
|
||||||
|
// init empty
|
||||||
|
m_particleVelocities.resize(verts.size() / 2);
|
||||||
|
|
||||||
|
m_targetPositions.reserve(verts.size() / 2);
|
||||||
for (unsigned int i {}; i < verts.size(); i += 2) {
|
for (unsigned int i {}; i < verts.size(); i += 2) {
|
||||||
m_particles.push_back(SParticle {Vector2D {verts[i], verts[i + 1]}, {}});
|
|
||||||
m_targetPositions.push_back(Vector2D {verts[i], verts[i + 1]});
|
m_targetPositions.push_back(Vector2D {verts[i], verts[i + 1]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,42 +26,44 @@ bool CWobblyWindow::step(Time::steady_tp time) {
|
|||||||
|
|
||||||
Vector2D totalVel {};
|
Vector2D totalVel {};
|
||||||
|
|
||||||
for (unsigned int i {}; i < m_particles.size(); i++) {
|
for (unsigned int i {}; i < m_particlePositions.size() / 2; i++) {
|
||||||
auto&& particle = m_particles[i];
|
// TODO: avoid float -> double promotion
|
||||||
auto&& particlePositon = particle.position;
|
const auto& pos = Vector2D {m_particlePositions[i * 2], m_particlePositions[i * 2 + 1]};
|
||||||
|
auto&& vel = m_particleVelocities[i];
|
||||||
auto&& targetPosition = m_targetPositions[i];
|
auto&& targetPosition = m_targetPositions[i];
|
||||||
|
|
||||||
const Vector2D directionToTarget = targetPosition - particlePositon;
|
const Vector2D directionToTarget = targetPosition - pos;
|
||||||
|
|
||||||
if (m_grabPosition.has_value()) {
|
if (m_grabPosition.has_value()) {
|
||||||
const float distanceToDragPosition = m_grabPosition.value().distance(particlePositon);
|
const float distanceToDragPosition = m_grabPosition.value().distance(pos);
|
||||||
const float dragStrength = std::clamp(distanceToDragPosition, 0.f, 1.f);
|
const float dragStrength = std::clamp(distanceToDragPosition, 0.f, 1.f);
|
||||||
|
|
||||||
particle.position += m_windowMovement * dragStrength;
|
m_particlePositions[i * 2] += m_windowMovement.x * dragStrength;
|
||||||
|
m_particlePositions[i * 2 + 1] += m_windowMovement.y * dragStrength;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector2D springForce =
|
const Vector2D springForce = directionToTarget * s_springStrength - vel * s_dampingStrength;
|
||||||
directionToTarget * s_springStrength - particle.velocity * s_dampingStrength;
|
vel += springForce * dt;
|
||||||
particle.velocity += springForce * dt;
|
|
||||||
|
|
||||||
// Apply drag
|
// Apply drag
|
||||||
const Vector2D dragForceVector = (particle.velocity * particle.velocity) * -s_drag;
|
const Vector2D dragForceVector = (vel * vel) * -s_drag;
|
||||||
|
|
||||||
// * Area
|
// * Area
|
||||||
auto dir = particle.velocity;
|
auto dir = vel;
|
||||||
float magnitude = dir.normalize();
|
float magnitude = dir.normalize();
|
||||||
|
|
||||||
if (magnitude != 0)
|
if (magnitude != 0)
|
||||||
particle.velocity += (dragForceVector * dir) * dt;
|
vel += (dragForceVector * dir) * dt;
|
||||||
|
|
||||||
// Apply velocity
|
// Apply velocity
|
||||||
particle.position += particle.velocity * dt;
|
m_particlePositions[i * 2] += vel.x * dt;
|
||||||
|
m_particlePositions[i * 2 + 1] += vel.y * dt;
|
||||||
|
|
||||||
totalVel += particle.velocity;
|
totalVel += vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool shouldEnd =
|
const bool shouldEnd = m_windowMovement.size() == 0
|
||||||
m_windowMovement.size() == 0 and totalVel.size() / m_particles.size() < .001f;
|
and totalVel.size() / (m_particlePositions.size() / 2.f) < .001f;
|
||||||
|
|
||||||
// std::println(
|
// std::println(
|
||||||
// "Top left: {}, totalVel: {}",
|
// "Top left: {}, totalVel: {}",
|
||||||
@ -68,3 +74,12 @@ bool CWobblyWindow::step(Time::steady_tp time) {
|
|||||||
|
|
||||||
return shouldEnd;
|
return shouldEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWobblyWindow::applyMovement(const Vector2D& movement) {
|
||||||
|
m_windowMovement = movement;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < m_particlePositions.size() / 2; i++) {
|
||||||
|
m_particlePositions[i * 2] -= movement.x;
|
||||||
|
m_particlePositions[i * 2 + 1] -= movement.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user