feat: updated for documentation and testing
This commit is contained in:
		
							parent
							
								
									5c67286175
								
							
						
					
					
						commit
						0affb60ae1
					
				
							
								
								
									
										15
									
								
								CHANGES.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								CHANGES.md
									
									
									
									
									
										Normal 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).
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue