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