Compare commits

..

No commits in common. "9d66afaacaa5756d1f1e93f82569d55b474060c2" and "ccd46d07a8f5d479d8df7a98ba09abb6a0a20300" have entirely different histories.

12 changed files with 106 additions and 367 deletions

View File

@ -1,9 +1,7 @@
# -*- mode: Org; eval: (olivetti-mode 0) -*- #
* The topics
#+begin_src syntree
("Game Programming Fundamentals"
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra" "_:Geometry")
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra")
("Engineering"
("Machine Architecture" "_:CPU Design" "_:Memory Hierarchy" "_:Processes" "_:Concurrency")
"_:Networking"
@ -13,27 +11,17 @@
#+RESULTS:
#+begin_example
Game Programming Fundamentals
.___________________________________________|___________________________________________.
| |
Math Engineering
.______________._____|_______.____________. .________________________________._|________._________________________.
| | | | | | | |
.______|______. .____|___. .______|_____. .___|__. Machine Architecture .____|___. .___|___. Operating Systems
|_____________| |________| |____________| |______| .______________._____|_______.___________. |________| |_______| .____________.|_____________.
Data Structures Algorithms Linear Algebra Geometry | | | | Networking Compilers | | |
.____|___. ._______|______. .___|___. .____|____. .____|___. ._____|____. .______|_____.
|________| |______________| |_______| |_________| |________| |__________| |____________|
CPU Design Memory Hierarchy Processes Concurrency Scheduling File Systems Virtual Memory
Game Programming Fundamentals
._________________________________________|_________________________________________.
| |
Math Engineering
.______________|_____________. .________________________________._|________._________________________.
| | | | | | |
.______|______. .____|___. .______|_____. Machine Architecture .____|___. .___|___. Operating Systems
|_____________| |________| |____________| .______________._____|_______.___________. |________| |_______| .____________.|_____________.
Data Structures Algorithms Linear Algebra | | | | Networking Compilers | | |
.____|___. ._______|______. .___|___. .____|____. .____|___. ._____|____. .______|_____.
|________| |______________| |_______| |_________| |________| |__________| |____________|
CPU Design Memory Hierarchy Processes Concurrency Scheduling File Systems Virtual Memory
#+end_example
#+begin_src syntree
("Graphics"
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra")
("Engineering"
("Machine Architecture" "_:CPU Design" "_:Memory Hierarchy" "_:Processes" "_:Concurrency")
"_:Networking"
"_:Compilers"
("Operating Systems" "_:Scheduling" "_:File Systems" "_:Virtual Memory")))
#+end_src

View File

@ -1,10 +0,0 @@
#+TITLE Topics for Gaming Pads
* GAIMENPAAADS
* List of things to study
** Quadtrees (Ongoing)
** Triangulation
** Bezier Curves
** SIMD
** Multithreading
** Boids

View File

@ -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

View File

@ -1,6 +0,0 @@
#+TODO: ⬜ 🟩️ | ✅
* Geometry
** [[file:SpatialPartitioning.org][Spatial Partitioning]]
** [[file:Triangulation.org][Triangulation]]
** Bezier Curves

View File

@ -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:

View File

@ -1 +0,0 @@
* Math

View File

@ -1,57 +0,0 @@
#+TEST: [[file:SpatialPartitioning.org][Spacial Partitioning]]
* 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:
** Resources
[[http://ericandrewlewis.github.io/how-a-quadtree-works/][Visualize a Quadtree]]
[[http://donar.umiacs.umd.edu/quadtree/][Academic Interactive Demo]]
** Notes
// 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) {
return best;
}
I don't know how to explain but I get it. Because of the euclidian distance and the fact that we're dealing with rectangles, the closest distance to a rectangle is a straight line in one of the x or y axis
So if the point we're checking is farther away from the rectangle on either axis, then it cannot possible be the case that it is closer
I still can't visualize or understand it intuitively, I more just trust that it works, maybe if I see it in action it'll click better
JosephFerano
Today at 4:15 PM
This is some clever math shit this guy is doing
Or that he picked up
https://gist.github.com/patricksurry/6478178
Gist
D3JS quadtree nearest neighbor algorithm
D3JS quadtree nearest neighbor algorithm. GitHub Gist: instantly share code, notes, and snippets.
D3JS quadtree nearest neighbor algorithm
// check if kid is on the right or left, and top or bottom
// and then recurse on most likely kids first, so we quickly find a
// nearby point and then exclude many larger rectangles later
var kids = node.nodes;
var rl = (2*x > x1 + x2), bt = (2*y > y1 + y2);
if (kids[bt*2+rl]) best = nearest(x, y, best, kids[bt*2+rl]);
if (kids[bt*2+(1-rl)]) best = nearest(x, y, best, kids[bt*2+(1-rl)]);
if (kids[(1-bt)*2+rl]) best = nearest(x, y, best, kids[(1-bt)*2+rl]);
if (kids[(1-bt)*2+(1-rl)]) best = nearest(x, y, best, kids[(1-bt)*2+(1-rl)]);
That's kinda neat, estimating probability with some math and then going into the index of the array where the point is more likely to be
No idea why this works
But I think I'm done with this
Interesting, he doesn't even check if any of the rects contain the point
Hmmm
Oh I see
It's because he's tracking whether a node is visited or not, and I'm putting in a lot of work to make sure you don't revisit the same node twice, but I don't do it with a "visited" bool, which I intentionally avoided but now seeing his solution, I realize it may have been a mistake
JosephFerano
Today at 4:27 PM
Actually I don't think adding "visited" is a good idea, because you have to walk through the whole thing again once you're done to uncheck all the visited bools. That's a linear walk through all the nodes, which might not be much, but it's certainly making things slower
I'll have to investigate further

View File

@ -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

View File

@ -1,57 +0,0 @@
#+TEST: [[file:Geometry][Geometry]]
* 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:
** Resources
[[http://ericandrewlewis.github.io/how-a-quadtree-works/][Visualize a Quadtree]]
[[http://donar.umiacs.umd.edu/quadtree/][Academic Interactive Demo]]
** Notes
// 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) {
return best;
}
I don't know how to explain but I get it. Because of the euclidian distance and the fact that we're dealing with rectangles, the closest distance to a rectangle is a straight line in one of the x or y axis
So if the point we're checking is farther away from the rectangle on either axis, then it cannot possible be the case that it is closer
I still can't visualize or understand it intuitively, I more just trust that it works, maybe if I see it in action it'll click better
JosephFerano
Today at 4:15 PM
This is some clever math shit this guy is doing
Or that he picked up
https://gist.github.com/patricksurry/6478178
Gist
D3JS quadtree nearest neighbor algorithm
D3JS quadtree nearest neighbor algorithm. GitHub Gist: instantly share code, notes, and snippets.
D3JS quadtree nearest neighbor algorithm
// check if kid is on the right or left, and top or bottom
// and then recurse on most likely kids first, so we quickly find a
// nearby point and then exclude many larger rectangles later
var kids = node.nodes;
var rl = (2*x > x1 + x2), bt = (2*y > y1 + y2);
if (kids[bt*2+rl]) best = nearest(x, y, best, kids[bt*2+rl]);
if (kids[bt*2+(1-rl)]) best = nearest(x, y, best, kids[bt*2+(1-rl)]);
if (kids[(1-bt)*2+rl]) best = nearest(x, y, best, kids[(1-bt)*2+rl]);
if (kids[(1-bt)*2+(1-rl)]) best = nearest(x, y, best, kids[(1-bt)*2+(1-rl)]);
That's kinda neat, estimating probability with some math and then going into the index of the array where the point is more likely to be
No idea why this works
But I think I'm done with this
Interesting, he doesn't even check if any of the rects contain the point
Hmmm
Oh I see
It's because he's tracking whether a node is visited or not, and I'm putting in a lot of work to make sure you don't revisit the same node twice, but I don't do it with a "visited" bool, which I intentionally avoided but now seeing his solution, I realize it may have been a mistake
JosephFerano
Today at 4:27 PM
Actually I don't think adding "visited" is a good idea, because you have to walk through the whole thing again once you're done to uncheck all the visited bools. That's a linear walk through all the nodes, which might not be much, but it's certainly making things slower
I'll have to investigate further

View File

@ -1,13 +1,13 @@
import pyray as RL
from pyray import (Rectangle as Rect, Vector2 as Vec2)
from pyray import (Rectangle as Rect)
import math
import pdb
import random
from typing import Optional, Tuple, List
from dataclasses import dataclass, field
screen_width = 1200
screen_height = 960
screen_width = 1280
screen_height = 1024
ball_r = 6
ball_speed = 3.5
@ -44,10 +44,6 @@ class World:
tick = 0
paused = False
mouse_clicks = []
nearest_points = []
visited_quadrants = []
nearest_pairs = []
current_visited = 0
w = World()
@ -89,55 +85,79 @@ def qt_insert(qt: Quadtree, p):
return True
def qt_find_nearest_point(qt: Quadtree, point) -> Tuple[float, float]:
containing_qt = qt
while containing_qt.subdivided:
if RL.check_collision_point_rec(point, containing_qt.nw.node.aabb):
containing_qt = containing_qt.nw
elif RL.check_collision_point_rec(point, containing_qt.ne.node.aabb):
containing_qt = containing_qt.ne
elif RL.check_collision_point_rec(point, containing_qt.sw.node.aabb):
containing_qt = containing_qt.sw
elif RL.check_collision_point_rec(point, containing_qt.se.node.aabb):
containing_qt = containing_qt.se
def search_for_nearest(qt: Quadtree, direction = ''):
nonlocal closest_point, closest_dist
contains_point = RL.check_collision_point_rec(point, qt.node.aabb)
if not contains_point:
px, py = point.x, point.y
dx, dy = 0,0
if px < qt.node.aabb.x:
dx = qt.node.aabb.x - px
elif px > qt.node.aabb.x + qt.node.aabb.width:
dx = px - (qt.node.aabb.x + qt.node.aabb.width)
if py < qt.node.aabb.y:
dy = qt.node.aabb.y - py
elif py > qt.node.aabb.y + qt.node.aabb.height:
dy = py - (qt.node.aabb.y + qt.node.aabb.height)
dist = RL.vector2_length(Vec2(dx, dy))
if dist >= closest_dist:
return
if qt.subdivided:
if direction != 'NW': search_for_nearest(qt.nw)
if direction != 'NE': search_for_nearest(qt.ne)
if direction != 'SW': search_for_nearest(qt.sw)
if direction != 'SE': search_for_nearest(qt.se)
w.visited_quadrants.append(qt)
for p in qt.node.points:
d = RL.vector_2distance(point, Vec2(p[0], p[1]))
if d < closest_dist:
closest_point = p
closest_dist = d
closest_point = None
closest_dist = float('inf')
previous_direction = ''
while containing_qt is not None:
search_for_nearest(containing_qt, previous_direction)
previous_direction = containing_qt.direction
containing_qt = containing_qt.parent
closest_dist = None
last_direction = None
containing_qt = qt
# Find the containing subnode
while containing_qt.subdivided:
if RL.check_collision_point_rec(point, qt.nw.node.aabb):
containing_qt = qt.nw
elif RL.check_collision_point_rec(point, qt.ne.node.aabb):
containing_qt = qt.ne
elif RL.check_collision_point_rec(point, qt.sw.node.aabb):
containing_qt = qt.sw
elif RL.check_collision_point_rec(point, qt.se.node.aabb):
containing_qt = qt.se
while containing_qt.parent is not None:
# If it's greater than 1, then we have a point inside we can compare to
if len(containing_qt.node.points) > 1:
for p in qt.node.points:
if p == point:
continue
if closest_dist is None or RL.vector_2distance(Vec2(*point), Vec2(*p)) < closest_dist:
closest_point = p
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
else:
# If there aren't any other points in here, then we can't create a
# closest_point or a closest_dist. We would have to handle that later on
if not containing_qt.subdivided:
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
else:
# def search_for_nearest(child_qt: Quadtree):
# We have to generalize this code, most likely, because it feels like
# we have to do this recursively until we have exhausted all quadrants
px, py = point
# This is where we check the surrounding nodes and try to discard nodes
if last_direction == 'NW':
xse, yse = containing_qt.se.node.aabb.x, containing_qt.se.node.aabb.y
return closest_point
ne_dist = containing_qt.ne.node.aabb.x - px
if ne_dist < closest_dist:
closest_dist = True
# Now we have to search inside, but we would have to do recursively
pass
sw_dist = containing_qt.sw.node.aabb.y - py
se_dist = RL.vector_2distance(Vec2(*point), Vec2(xse, yse))
assert se_dist >= 0, 'ITS LESS THAN 0!!!!'
if last_direction == 'NE':
xsw, ysw = containing_qt.sw.node.aabb.x, containing_qt.sw.node.aabb.y
nw_dist = px - containing_qt.nw.node.aabb.x
sw_dist = RL.vector_2distance(Vec2(xsw, ysw), Vec2(*point))
assert sw_dist >= 0, 'ITS LESS THAN 0!!!!'
se_dist = containing_qt.se.node.aabb.y - py
if last_direction == 'SW':
xne, yne = containing_qt.ne.node.aabb.x, containing_qt.ne.node.aabb.y
nw_dist = px - containing_qt.nw.node.aabb.x
ne_dist = RL.vector_2distance(Vec2(xne, yne), Vec2(*point))
assert ne_dist >= 0, 'ITS LESS THAN 0!!!!'
se_dist = containing_qt.se.node.aabb.x - px
if last_direction == 'SE':
xnw, ynw = containing_qt.nw.node.aabb.x, containing_qt.nw.node.aabb.y
nw_dist = RL.vector_2distance(Vec2(xnw, ynw), Vec2(*point))
ne_dist = py - containing_qt.nw.node.aabb.y
assert ne_dist >= 0, 'ITS LESS THAN 0!!!!'
sw_dist = px - containing_qt.se.node.aabb.x
last_direction = containing_qt.direction
containing_qt = containing_qt.parent
def construct_quadtree(points):
@ -165,17 +185,17 @@ def player_input():
if RL.is_key_pressed(RL.KEY_SPACE):
w.paused = not w.paused
if RL.is_mouse_button_pressed(0):
mouse_pos = RL.get_mouse_position()
nearest = qt_find_nearest_point(w.qt, mouse_pos)
w.nearest_pairs.append((mouse_pos, nearest))
w.paused = True
if RL.is_key_pressed(RL.KEY_ENTER):
w.current_visited += 1
print(RL.get_mouse_position())
w.mouse_clicks.append(RL.get_mouse_position())
def update():
# Recontruct quadtree
if w.paused:
return
points = []
for b in w.balls:
points.append((b.px, b.py))
w.qt = construct_quadtree(points)
for ball in w.balls:
ball.px += ball.vx
@ -189,11 +209,6 @@ def update():
ball.py = RL.clamp(ball.py, ball_r + 0.1, screen_height - ball_r - 0.1)
ball.vy *= -1
points = []
for b in w.balls:
points.append((b.px, b.py))
w.qt = construct_quadtree(points)
def draw_qt_dfs(qt: Quadtree):
if not qt:
return
@ -208,19 +223,10 @@ def draw():
RL.clear_background(RL.WHITE)
draw_qt_dfs(w.qt)
for i in range(w.current_visited):
RL.draw_rectangle_rec(w.visited_quadrants[i].node.aabb, RL.LIGHTGRAY)
for ball in w.balls:
RL.draw_circle_lines_v((ball.px, ball.py), ball_r, RL.BLACK)
for mc in w.mouse_clicks:
RL.draw_circle_v(mc, 5, RL.RED)
for np in w.nearest_points:
RL.draw_circle_lines_v(Vec2(np[0], np[1]), ball_r, RL.GREEN)
for mc,(px,py) in w.nearest_pairs:
pos = Vec2(px, py)
RL.draw_circle_v(mc, 5, RL.RED)
RL.draw_circle_lines_v(pos, ball_r, RL.GREEN)
RL.draw_line_v(mc, pos, RL.BLUE)
RL.end_drawing()

View File

@ -1,5 +1,5 @@
import pyray as RL
from pyray import (Rectangle as Rect, Vector2 as Vec2, Vector3 as Vec3, Camera3D)
from pyray import (Rectangle as Rect)
import math
import pdb
import random
@ -11,44 +11,29 @@ screen_height = 1024
@dataclass
class World:
cam: Camera3D
frame_count: int = 0
def init() -> World:
pass
def player_input(w: World):
def init():
pass
def update(w: World):
def player_input():
pass
def draw_3d(w: World):
def update():
pass
def draw_2d(w: World):
pass
def draw():
RL.begin_drawing()
RL.clear_background(RL.WHITE)
RL.end_drawing()
RL.init_window(screen_width, screen_height, "Starter");
RL.set_target_fps(60)
init()
cam = Camera3D(Vec3(0, 0, 10), RL.vector3_zero(), Vec3(0, 1, 0), 60, 1)
w = World(cam)
while not RL.window_should_close():
player_input(w)
update(w)
# Drawing
RL.begin_drawing()
RL.clear_background(RL.WHITE)
RL.begin_mode_3d(w.cam)
draw_3d(w)
RL.end_mode_3d()
draw_2d(w)
RL.end_drawing()
w.frame_count += 1
player_input()
update()
draw()

View File

@ -1,73 +0,0 @@
import pyray as RL
from pyray import (Rectangle as Rect, Vector2 as Vec2, Vector3 as Vec3, Camera3D, BoundingBox)
import math
import pdb
import random
from typing import Optional, Tuple, List
from dataclasses import dataclass, field
screen_width = 1280
screen_height = 1024
grid_slices = 100
grid_spacing = 0.2
@dataclass
class World:
cam: Camera3D
floor_bb: BoundingBox
rotate_cam: bool = True
frame_count: int = 0
vertices: List[Vec3] = field(default_factory=list)
def init() -> World:
cam = Camera3D(Vec3(0, 10, 10), Vec3(0, 0, 0), Vec3(0, 1, 0), 45, RL.CAMERA_PERSPECTIVE)
half_grid = grid_slices * grid_spacing * 0.5
floor_bb = BoundingBox(Vec3(-half_grid, -0.01, -half_grid), Vec3(half_grid, 0.01, half_grid))
return World(cam, floor_bb)
def player_input(w: World):
if RL.is_key_pressed(RL.KEY_SPACE):
w.rotate_cam = not w.rotate_cam
if RL.is_mouse_button_pressed(0):
mouse_pos = RL.get_mouse_position()
ray = RL.get_mouse_ray(mouse_pos, w.cam)
collision = RL.get_ray_collision_box(ray, w.floor_bb)
if collision.hit:
p = collision.point
w.vertices.append(Vec3(p.x, 0, p.z))
def update(w: World):
pass
def draw_3d(w: World):
RL.draw_grid(grid_slices, grid_spacing)
RL.draw_bounding_box(w.floor_bb, RL.GREEN)
for vert in w.vertices:
RL.draw_sphere(vert, 0.1, RL.GREEN)
def draw_2d(w: World):
pass
RL.init_window(screen_width, screen_height, "Starter");
RL.set_target_fps(60)
w = init()
while not RL.window_should_close():
player_input(w)
update(w)
# Drawing
if w.rotate_cam:
RL.update_camera(w.cam, RL.CameraMode.CAMERA_ORBITAL)
RL.begin_drawing()
RL.clear_background(RL.WHITE)
RL.begin_mode_3d(w.cam)
draw_3d(w)
RL.end_mode_3d()
draw_2d(w)
RL.end_drawing()
w.frame_count += 1