Poisson-disk sampling, new org-roam content
This commit is contained in:
		
							parent
							
								
									c5096cf3f9
								
							
						
					
					
						commit
						c2309066e3
					
				
							
								
								
									
										2
									
								
								.dir-locals.el
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.dir-locals.el
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| ((nil . ((org-roam-directory . "/home/joe/Development/gaming-pads/content") | ||||
|          (org-roam-db-location . "/home/joe/Development/gaming-pads/org-roam.db")))) | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| /org-roam.db | ||||
							
								
								
									
										12
									
								
								content/20240813113042-gaming_pads.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								content/20240813113042-gaming_pads.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       6793b3f2-32d1-46dc-b104-e2d446c9a66e | ||||
| :END: | ||||
| #+title: Gaming Pads | ||||
| 
 | ||||
| It's how the acronym GAIMENPAAADS sounds, but that's a crappy acronym. Here is | ||||
| a hierarchical overview of the topics | ||||
| 
 | ||||
| * [[id:f2b91852-e931-4026-a9a4-cc4188eecbb0][Math for Game Programmers]] | ||||
| * [[id:bdba2433-f92c-48cc-a401-a9d8f777df8f][Graphics]] | ||||
| * [[id:f548e57e-3d8e-4fe4-a5eb-5ebd338b1825][Artificial Intelligence]] | ||||
| 
 | ||||
| @ -1,24 +1,26 @@ | ||||
| #+TEST: [[file:SpatialPartitioning.org][Spacial Partitioning]] | ||||
| :PROPERTIES: | ||||
| :ID:       4f3f07d3-a05e-40ad-94f9-cb35dad69ef1 | ||||
| :END: | ||||
| #+title: Quadtree | ||||
| 
 | ||||
| * Quadtree | ||||
| Recursively subdivide an AABB into 4 regions, hence Quad. They are usually | ||||
| denoted as North West, North East, South West, and South East (NW, NE, SW, SE). | ||||
| Several things can be created with this; | ||||
| ** Linked Implementation                                     :datastructure: | ||||
| ** Array Implementation                                      :datastructure: | ||||
| ** Insertion                                                     :algorithm: | ||||
| ** Query                                                         :algorithm: | ||||
| ** Find Nearest Neighbor                                         :algorithm: | ||||
| ** Morton codes | ||||
| * Linked Implementation                                       :datastructure: | ||||
| * Array Implementation                                        :datastructure: | ||||
| * Insertion                                                       :algorithm: | ||||
| * Query                                                           :algorithm: | ||||
| * Find Nearest Neighbor                                           :algorithm: | ||||
| * Morton codes | ||||
| This is a technique that allows us to convert coordinates into an array index, | ||||
| allowing us to pack them contiguously in memory | ||||
| http://johnsietsma.com/2019/12/05/morton-order-introduction/ | ||||
| ** Resources | ||||
| * Resources | ||||
| [[http://ericandrewlewis.github.io/how-a-quadtree-works/][Visualize a Quadtree]] | ||||
| [[http://donar.umiacs.umd.edu/quadtree/][Academic Interactive Demo]] | ||||
| [[https://codepen.io/_bm/pen/ExPBMrW][Codepen (Js example)]] | ||||
| [[https://gist.github.com/patricksurry/6478178][D3.js Example]] | ||||
| ** Notes | ||||
| * Notes | ||||
| #+begin_src js | ||||
| // exclude node if point is farther away than best distance in either axis | ||||
| if (x < x1 - best.d || x > x2 + best.d || y < y1 - best.d || y > y2 + best.d) { | ||||
							
								
								
									
										6
									
								
								content/20240813113150-math_for_game_programmers.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								content/20240813113150-math_for_game_programmers.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       f2b91852-e931-4026-a9a4-cc4188eecbb0 | ||||
| :END: | ||||
| #+title: Math for Game Programmers | ||||
| 
 | ||||
| * [[id:42583e83-bc7d-4428-8228-c1c04f91806f][Geometry]] | ||||
							
								
								
									
										7
									
								
								content/20240813113239-geometry.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								content/20240813113239-geometry.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       42583e83-bc7d-4428-8228-c1c04f91806f | ||||
| :END: | ||||
| #+title: Geometry | ||||
| 
 | ||||
| * [[id:62ab48ad-9a26-4fb7-a41b-dd341165cdec][Spatial Partitioning]] | ||||
| * [[id:729ccfcc-8015-4438-b0c6-3097f311e505][Triangulation]] | ||||
							
								
								
									
										8
									
								
								content/20240813113258-spatial_partitioning.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								content/20240813113258-spatial_partitioning.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       62ab48ad-9a26-4fb7-a41b-dd341165cdec | ||||
| :END: | ||||
| #+title: Spatial Partitioning | ||||
| 
 | ||||
| * [[id:4f3f07d3-a05e-40ad-94f9-cb35dad69ef1][Quadtree]] | ||||
| * [[id:9d793370-5e77-4ae6-bf7a-6f3e6377a79c][KD-Tree]] | ||||
| * [[id:137d9b32-c670-4b30-89ff-4b2da47006db][Poisson-disk sampling]] | ||||
							
								
								
									
										10
									
								
								content/20240813113355-kd_tree.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								content/20240813113355-kd_tree.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       9d793370-5e77-4ae6-bf7a-6f3e6377a79c | ||||
| :END: | ||||
| #+title: KD-Tree | ||||
| 
 | ||||
| Info about a KD-Tree | ||||
| * Linked Implementation                                       :datastructure: | ||||
| * Array Implementation                                        :datastructure: | ||||
| * Insertion                                                       :algorithm: | ||||
| * Find Nearest Neighbor                                           :algorithm: | ||||
| @ -1,12 +1,14 @@ | ||||
| #+TEST: [[file:Geometry][Geometry]] | ||||
| :PROPERTIES: | ||||
| :ID:       729ccfcc-8015-4438-b0c6-3097f311e505 | ||||
| :END: | ||||
| #+title: Triangulation | ||||
| 
 | ||||
| * Triangulation | ||||
| Generate triangles from points | ||||
| ** Convex Hull Jarvis March (Gift wrapping)                      :algorithm: | ||||
| * Convex Hull Jarvis March (Gift wrapping)                        :algorithm: | ||||
| [[file:~/Development/gaming-pads/convexhull-jarvismarch.py][Python Code]] | ||||
| ** Resources | ||||
| * Resources | ||||
| https://www.youtube.com/watch?v=Vu84lmMzP2o | ||||
| https://www.habrador.com/tutorials/math/8-convex-hull/ | ||||
| https://www.youtube.com/watch?v=B2AJoQSZf4M | ||||
| https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf | ||||
| ** Notes | ||||
| * Notes | ||||
							
								
								
									
										9
									
								
								content/20240813113634-procedural_generation.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								content/20240813113634-procedural_generation.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       98eb9900-fead-478c-8db4-29310ced82fb | ||||
| :END: | ||||
| #+title: Procedural Generation | ||||
| 
 | ||||
| These are used to divide a space in either a 2D or 3D world into smaller spaces | ||||
| that can make operations like searching and filtering more efficient. | ||||
| 
 | ||||
| * [[id:137d9b32-c670-4b30-89ff-4b2da47006db][Poisson-disk sampling]] | ||||
							
								
								
									
										5
									
								
								content/20240813113652-poisson_disk_sampling.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								content/20240813113652-poisson_disk_sampling.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       137d9b32-c670-4b30-89ff-4b2da47006db | ||||
| :END: | ||||
| #+title: Poisson-disk sampling | ||||
| 
 | ||||
							
								
								
									
										7
									
								
								content/20240813114155-graphics.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								content/20240813114155-graphics.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       bdba2433-f92c-48cc-a401-a9d8f777df8f | ||||
| :END: | ||||
| #+title: Graphics | ||||
| 
 | ||||
| * [[id:98eb9900-fead-478c-8db4-29310ced82fb][Procedural Generation]] | ||||
| * [[id:729ccfcc-8015-4438-b0c6-3097f311e505][Triangulation]] | ||||
							
								
								
									
										6
									
								
								content/20240813114306-artificial_intelligence.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								content/20240813114306-artificial_intelligence.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| :PROPERTIES: | ||||
| :ID:       f548e57e-3d8e-4fe4-a5eb-5ebd338b1825 | ||||
| :END: | ||||
| #+title: Artificial Intelligence | ||||
| 
 | ||||
| * [[id:98eb9900-fead-478c-8db4-29310ced82fb][Procedural Generation]] | ||||
| @ -1,19 +0,0 @@ | ||||
| * Gaming Pads | ||||
| It's how the acronym GAIMENPAAADS sounds, but that's a crappy acronym. Here is | ||||
| a hierarchical overview of the topics | ||||
| ** Math | ||||
| *** Trigonometry | ||||
| *** Data Structures | ||||
| *** Algorithms | ||||
| *** Linear Algebra | ||||
| *** Geometry | ||||
| **** Bezier Curves | ||||
| **** Triangulation | ||||
| **** Spatial Partitioning | ||||
| #+transclude: [[file:Quadtree.org]] :level 5 :exclude-elements "keyword" | ||||
| #+transclude: [[file:KD-Tree.org]] :level 5 :exclude-elements "keyword" | ||||
| ** Engineering | ||||
| *** Machine Architecture | ||||
| *** Networking | ||||
| *** Compilers | ||||
| *** Operating Systems | ||||
| @ -1,6 +0,0 @@ | ||||
| #+TODO: ⬜ 🟩️ | ✅ | ||||
| 
 | ||||
| * Geometry | ||||
| ** [[file:SpatialPartitioning.org][Spatial Partitioning]] | ||||
| ** [[file:Triangulation.org][Triangulation]] | ||||
| ** Bezier Curves | ||||
| @ -1,8 +0,0 @@ | ||||
| #+NAVIGATION_UP: [[file:SpatialPartitioning.org][Spacial Partitioning]] | ||||
| 
 | ||||
| * KD-Tree | ||||
| Info about a KD-Tree | ||||
| ** Linked Implementation                                     :datastructure: | ||||
| ** Array Implementation                                      :datastructure: | ||||
| ** Insertion                                                     :algorithm: | ||||
| ** Find Nearest Neighbor                                         :algorithm: | ||||
| @ -1 +0,0 @@ | ||||
| * Math | ||||
| @ -1,9 +0,0 @@ | ||||
| # -*- mode: Org; eval: (org-transclusion-mode 0) -*- # | ||||
| #+NAVIGATION-UP: [[file:Geometry.org][Geometry]] | ||||
| 
 | ||||
| * Spatial Partitioning | ||||
| These are used to divide a space in either a 2D or 3D world into smaller spaces | ||||
| that can make operations like searching and filtering more efficient. | ||||
| 
 | ||||
| #+transclude: [[file:Quadtree.org]] :level 2 | ||||
| #+transclude: [[file:KD-Tree.org]] :level 2 | ||||
							
								
								
									
										151
									
								
								poisson-disk-sampling.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								poisson-disk-sampling.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,151 @@ | ||||
| import pyray as RL | ||||
| from pyray import (Rectangle as Rect, Vector2 as Vec2, Vector3 as Vec3, Camera3D, BoundingBox, Color) | ||||
| import math | ||||
| import pdb | ||||
| import random | ||||
| from typing import Optional, Tuple, List | ||||
| from dataclasses import dataclass, field | ||||
| 
 | ||||
| def dump(struct): | ||||
|     s = f"{RL.ffi.typeof(struct)}: (".replace('<ctype ', '').replace('>', '') | ||||
|     for field in dir(struct): | ||||
|         data = struct.__getattribute__(field) | ||||
|         if str(data).startswith("<cdata"): | ||||
|             data = dump(data) | ||||
|         s += f"{field}:{data} " | ||||
|     s += ")" | ||||
|     return s | ||||
| 
 | ||||
| screen_width = 1024 | ||||
| screen_height = 512 | ||||
| r = 10 | ||||
| k = 30 | ||||
| cell_size = r / math.sqrt(2) | ||||
| cols = int(screen_width // cell_size) | ||||
| rows = int(screen_height // cell_size) | ||||
| 
 | ||||
| @dataclass | ||||
| class World: | ||||
|     grid: List[Vec2] | ||||
|     points: List[Vec2] | ||||
|     active: List[Vec2] | ||||
|     pidx = 0 | ||||
|     start = False | ||||
|     point_count = 0 | ||||
|     frame_count: int = 0 | ||||
|     debug_draw: bool = False | ||||
| 
 | ||||
| def init() -> World: | ||||
|     grid = [None] * rows * cols | ||||
|     points = [Vec2(screen_width // 2, screen_height // 2)] | ||||
|     # points = [] | ||||
|     active = points.copy() | ||||
|     for p in points: | ||||
|         idx = int(p.y // cell_size * cols + p.x // cell_size) | ||||
|         grid[idx] = p | ||||
|     return World(grid, points, active) | ||||
| 
 | ||||
| def player_input(w: World): | ||||
|     if RL.is_mouse_button_pressed(0): | ||||
|         p = RL.get_mouse_position() | ||||
|         w.points.append(p) | ||||
|         idx = int(p.y // cell_size * cols + p.x // cell_size) | ||||
|         if idx < len(w.grid): | ||||
|             w.grid[idx] = 1 | ||||
|     if RL.is_key_pressed(RL.KEY_SPACE): | ||||
|         w.debug_draw = not w.debug_draw | ||||
|     if RL.is_key_pressed(RL.KEY_ENTER): | ||||
|         w.start = True | ||||
| 
 | ||||
| def update(w: World): | ||||
|     # if w.frame_count % 1 != 0: | ||||
|     #     return | ||||
|     if not w.start or not w.points or not w.active: | ||||
|         return | ||||
|     for _ in range(25): | ||||
|         if not w.active: | ||||
|             break | ||||
|         point = w.active[-1] | ||||
|         w.pidx = (w.pidx + 1) % len(w.points) | ||||
|         found = False | ||||
|         for i in range(k): | ||||
|             r_angle = random.random() * math.pi * 2 | ||||
|             r_dist = random.uniform(r, 2 * r) | ||||
|             new_point = Vec2(point.x + math.cos(r_angle) * r_dist, point.y + math.sin(r_angle) * r_dist) | ||||
|             new_point_idx = int(new_point.y // cell_size * cols + new_point.x // cell_size) | ||||
|             if (new_point_idx >= len(w.grid) or w.grid[new_point_idx] is not None | ||||
|                 or new_point.x < 0 or new_point.x > cell_size * cols | ||||
|                 or new_point.y < 0 or new_point.y > cell_size * rows): | ||||
|                 continue | ||||
|             new_point_row = new_point_idx // cols | ||||
|             new_point_col = new_point_idx % cols | ||||
|             collides = False | ||||
|             for i in range(-2, 3): | ||||
|                 for j in range(-2, 3): | ||||
|                     if collides: | ||||
|                         break | ||||
|                     row = new_point_row + i | ||||
|                     col = new_point_col + j | ||||
|                     if row < 0 or row >= rows or col < 0 or col >= cols: | ||||
|                         continue | ||||
|                     idx = row * cols + col | ||||
|                     if w.grid[idx] is not None: | ||||
|                         # Check distance | ||||
|                         dist_sqr = RL.vector_2distance_sqr(w.grid[idx], new_point) | ||||
|                         if dist_sqr < r * r: | ||||
|                             collides = True | ||||
| 
 | ||||
|             if collides: | ||||
|                 continue | ||||
|             w.grid[new_point_idx] = new_point | ||||
|             w.points.append(new_point) | ||||
|             w.point_count += 1 | ||||
|             w.active.append(new_point) | ||||
|             found = True | ||||
|             break | ||||
|         if not found: | ||||
|             w.active.pop() | ||||
| 
 | ||||
| 
 | ||||
| def draw_2d(w: World): | ||||
|     # for p in w.points: | ||||
|     #     prx = p.x // cell_size * cell_size | ||||
|     #     pry = p.y // cell_size * cell_size | ||||
|     #     rect = Rect(prx, pry, cell_size, cell_size) | ||||
|     #     RL.draw_rectangle_rec(rect, Color(230, 230, 230, 255)) | ||||
|     if w.debug_draw: | ||||
|         for i,c in enumerate(w.grid): | ||||
|             if c != -1: | ||||
|                 cell_x = (i % cols) * cell_size | ||||
|                 cell_y = (i // cols) * cell_size | ||||
|                 rect = Rect(cell_x, cell_y, cell_size, cell_size) | ||||
|                 RL.draw_rectangle_rec(rect, Color(230, 230, 230, 255)) | ||||
| 
 | ||||
|         for i in range(int((screen_width // cell_size) + 1) - 1): | ||||
|             for j in range(int((screen_height // cell_size) + 1) - 1): | ||||
|                 rect = Rect(cell_size * i, cell_size * j, cell_size, cell_size) | ||||
|                 RL.draw_rectangle_lines_ex(rect, 2, RL.GREEN) | ||||
|     for i,p in enumerate(w.points): | ||||
|         red = min(200, i % 255) | ||||
|         green = min(200, i * 2 % 255) | ||||
|         blue = min(200, i * 3 % 255) | ||||
|         RL.draw_circle_v(p, 2, Color(red, green, blue, 255)) | ||||
| 
 | ||||
| 
 | ||||
| RL.init_window(screen_width, screen_height, "Poisson-disk Sampling"); | ||||
| RL.set_target_fps(60) | ||||
| 
 | ||||
| w = init() | ||||
| while not RL.window_should_close(): | ||||
|     player_input(w) | ||||
|     update(w) | ||||
| 
 | ||||
|     # Drawing | ||||
|     RL.begin_drawing() | ||||
|     RL.clear_background(RL.WHITE) | ||||
| 
 | ||||
|     draw_2d(w) | ||||
| 
 | ||||
|     RL.end_drawing() | ||||
|     w.frame_count += 1 | ||||
|      | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user