feat: updated for documentation and testing

This commit is contained in:
Sara Gerretsen 2025-10-28 22:22:12 +01:00
parent 5c67286175
commit 0affb60ae1
3 changed files with 23 additions and 5 deletions

15
CHANGES.md Normal file
View file

@ -0,0 +1,15 @@
# Optimalizaties
## Spatial Hashing
In 2d, de meest efficiente spatial-hashing strategie is vlakkenverdeling. Het is simpel voor hashing en hash searches om een ruimte op te delen in gelijkmatige vlakken.
Voor hashing moet een datastructuur worden teruggebracht naar een nummer. Mijn implementatie verdeeld een 8-bit unsigned int over 2 delen, de meest significante 4 bits worden gebruikt door de x coordinaat, en de minst significante 4 de y coordinaat.
Het systeem waar deze coordinaten naar verwijzen is de het vlak in de vlakkenverdeling waarin een positie zich bevind.
> Met 8 bits hebben we 255 mogelijke opties, dit betekend dat de grootste vlakkenverdeling mogelijk 16x16 is.
## Performance
De performance-verbetering door deze hashing-strategie is redelijk hoog. Gemiddelde frametime valt van `0.08...` naar `0.03...` gemiddeld op mijn AMD Ryzen AI 9 HX 370 met `2500` particles (de standaard hoeveelheid waarmee de voorbeeldimplementatie is aangeleverd).

View file

@ -32,7 +32,7 @@ void setup() {
ImGui::GetIO().ConfigFlags |= (ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_DockingEnable); ImGui::GetIO().ConfigFlags |= (ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_DockingEnable);
sf::View view{get_window().getView()}; sf::View view{get_window().getView()};
set_render_view(view); set_render_view(view);
v2::initialize(2500, {{50,50}, {1000, 1000}}); v2::initialize(2500, {{50,50}, {3000, 2000}});
} }
void handle_input_event(sf::Event const &event) { void handle_input_event(sf::Event const &event) {

View file

@ -15,8 +15,8 @@
#include <ranges> #include <ranges>
#include <set> #include <set>
#define HASH_BUCKETS 10 #define HASH_BUCKETS 24
#define HASH_GRID_DIVISIONS 2 #define HASH_GRID_DIVISIONS 18
namespace v2 { namespace v2 {
typedef uint8_t PointHash; typedef uint8_t PointHash;
@ -67,7 +67,8 @@ void initialize(size_t particleCount, sf::FloatRect bounds) {
worldBounds = bounds; worldBounds = bounds;
std::mt19937 rng{std::mt19937()}; std::mt19937 rng{std::mt19937()};
std::uniform_real_distribution<float> positionDist{std::uniform_real_distribution<float>(5.0f, 795.0f)}; std::uniform_real_distribution<float> xPositionDist{std::uniform_real_distribution<float>(bounds.position.x, bounds.position.x + bounds.size.x)};
std::uniform_real_distribution<float> yPositionDist{std::uniform_real_distribution<float>(bounds.position.y, bounds.position.y + bounds.size.y)};
std::uniform_real_distribution<float> velocityDist{std::uniform_real_distribution<float>(-200.0f, 200.0f)}; std::uniform_real_distribution<float> velocityDist{std::uniform_real_distribution<float>(-200.0f, 200.0f)};
std::uniform_int_distribution<uint8_t> colorDist{std::uniform_int_distribution<uint8_t>(0, 255)}; std::uniform_int_distribution<uint8_t> colorDist{std::uniform_int_distribution<uint8_t>(0, 255)};
std::uniform_real_distribution<float> radiusDist{std::uniform_real_distribution<float>(2.5f, 2.5f)}; std::uniform_real_distribution<float> radiusDist{std::uniform_real_distribution<float>(2.5f, 2.5f)};
@ -77,7 +78,7 @@ void initialize(size_t particleCount, sf::FloatRect bounds) {
sf::CircleShape(radiusDist(rng)), sf::CircleShape(radiusDist(rng)),
sf::Vector2f{0, 0}); sf::Vector2f{0, 0});
Particle &particle{particles[particles.size() - 1]}; Particle &particle{particles[particles.size() - 1]};
particle.shape.setPosition({positionDist(rng), positionDist(rng)}); particle.shape.setPosition({xPositionDist(rng), yPositionDist(rng)});
particle.velocity = {velocityDist(rng), velocityDist(rng)}; particle.velocity = {velocityDist(rng), velocityDist(rng)};
particle.spatialHash = hashParticlePosition(particle); particle.spatialHash = hashParticlePosition(particle);
particle.shape.setFillColor({colorDist(rng), colorDist(rng), colorDist(rng), 255}); particle.shape.setFillColor({colorDist(rng), colorDist(rng), colorDist(rng), 255});
@ -160,6 +161,7 @@ void tick(double delta) {
} }
void draw(sf::RenderTarget *target) { void draw(sf::RenderTarget *target) {
#if 0
sf::RectangleShape rect{worldBounds.size}; sf::RectangleShape rect{worldBounds.size};
rect.setPosition(worldBounds.position); rect.setPosition(worldBounds.position);
rect.setFillColor(sf::Color::Transparent); rect.setFillColor(sf::Color::Transparent);
@ -167,6 +169,7 @@ void draw(sf::RenderTarget *target) {
rect.setOutlineThickness(3); rect.setOutlineThickness(3);
target->draw(rect); target->draw(rect);
sf::Vertex polygon[2]; sf::Vertex polygon[2];
#endif
for (Particle &particle : particles) { for (Particle &particle : particles) {
if (particle.active) { if (particle.active) {
target->draw(particle.shape); target->draw(particle.shape);