Compare commits
4 Commits
ccd46d07a8
...
9d66afaaca
Author | SHA1 | Date | |
---|---|---|---|
9d66afaaca | |||
74b52cb8c2 | |||
aa1091c4d3 | |||
2d7c38365d |
26
Diagrams.org
26
Diagrams.org
@ -1,7 +1,9 @@
|
|||||||
|
# -*- mode: Org; eval: (olivetti-mode 0) -*- #
|
||||||
|
|
||||||
* The topics
|
* The topics
|
||||||
#+begin_src syntree
|
#+begin_src syntree
|
||||||
("Game Programming Fundamentals"
|
("Game Programming Fundamentals"
|
||||||
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra")
|
("Math" "_:Data Structures" "_:Algorithms" "_:Linear Algebra" "_:Geometry")
|
||||||
("Engineering"
|
("Engineering"
|
||||||
("Machine Architecture" "_:CPU Design" "_:Memory Hierarchy" "_:Processes" "_:Concurrency")
|
("Machine Architecture" "_:CPU Design" "_:Memory Hierarchy" "_:Processes" "_:Concurrency")
|
||||||
"_:Networking"
|
"_:Networking"
|
||||||
@ -12,16 +14,26 @@
|
|||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
#+begin_example
|
#+begin_example
|
||||||
Game Programming Fundamentals
|
Game Programming Fundamentals
|
||||||
._________________________________________|_________________________________________.
|
.___________________________________________|___________________________________________.
|
||||||
| |
|
| |
|
||||||
Math Engineering
|
Math Engineering
|
||||||
.______________|_____________. .________________________________._|________._________________________.
|
.______________._____|_______.____________. .________________________________._|________._________________________.
|
||||||
| | | | | | |
|
| | | | | | | |
|
||||||
.______|______. .____|___. .______|_____. Machine Architecture .____|___. .___|___. Operating Systems
|
.______|______. .____|___. .______|_____. .___|__. Machine Architecture .____|___. .___|___. Operating Systems
|
||||||
|_____________| |________| |____________| .______________._____|_______.___________. |________| |_______| .____________.|_____________.
|
|_____________| |________| |____________| |______| .______________._____|_______.___________. |________| |_______| .____________.|_____________.
|
||||||
Data Structures Algorithms Linear Algebra | | | | Networking Compilers | | |
|
Data Structures Algorithms Linear Algebra Geometry | | | | Networking Compilers | | |
|
||||||
.____|___. ._______|______. .___|___. .____|____. .____|___. ._____|____. .______|_____.
|
.____|___. ._______|______. .___|___. .____|____. .____|___. ._____|____. .______|_____.
|
||||||
|________| |______________| |_______| |_________| |________| |__________| |____________|
|
|________| |______________| |_______| |_________| |________| |__________| |____________|
|
||||||
CPU Design Memory Hierarchy Processes Concurrency Scheduling File Systems Virtual Memory
|
CPU Design Memory Hierarchy Processes Concurrency Scheduling File Systems Virtual Memory
|
||||||
|
|
||||||
#+end_example
|
#+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
|
||||||
|
10
Topics.org
Normal file
10
Topics.org
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#+TITLE Topics for Gaming Pads
|
||||||
|
|
||||||
|
* GAIMENPAAADS
|
||||||
|
* List of things to study
|
||||||
|
** Quadtrees (Ongoing)
|
||||||
|
** Triangulation
|
||||||
|
** Bezier Curves
|
||||||
|
** SIMD
|
||||||
|
** Multithreading
|
||||||
|
** Boids
|
19
content/GamingPads.org
Normal file
19
content/GamingPads.org
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
* 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
|
6
content/Geometry.org
Normal file
6
content/Geometry.org
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#+TODO: ⬜ 🟩️ | ✅
|
||||||
|
|
||||||
|
* Geometry
|
||||||
|
** [[file:SpatialPartitioning.org][Spatial Partitioning]]
|
||||||
|
** [[file:Triangulation.org][Triangulation]]
|
||||||
|
** Bezier Curves
|
8
content/KD-Tree.org
Normal file
8
content/KD-Tree.org
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#+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
content/Math.org
Normal file
1
content/Math.org
Normal file
@ -0,0 +1 @@
|
|||||||
|
* Math
|
57
content/Quadtree.org
Normal file
57
content/Quadtree.org
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#+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
|
9
content/SpatialPartitioning.org
Normal file
9
content/SpatialPartitioning.org
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# -*- 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
|
57
content/Triangulation.org
Normal file
57
content/Triangulation.org
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#+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
|
144
quadtree.py
144
quadtree.py
@ -1,13 +1,13 @@
|
|||||||
import pyray as RL
|
import pyray as RL
|
||||||
from pyray import (Rectangle as Rect)
|
from pyray import (Rectangle as Rect, Vector2 as Vec2)
|
||||||
import math
|
import math
|
||||||
import pdb
|
import pdb
|
||||||
import random
|
import random
|
||||||
from typing import Optional, Tuple, List
|
from typing import Optional, Tuple, List
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
screen_width = 1280
|
screen_width = 1200
|
||||||
screen_height = 1024
|
screen_height = 960
|
||||||
|
|
||||||
ball_r = 6
|
ball_r = 6
|
||||||
ball_speed = 3.5
|
ball_speed = 3.5
|
||||||
@ -44,6 +44,10 @@ class World:
|
|||||||
tick = 0
|
tick = 0
|
||||||
paused = False
|
paused = False
|
||||||
mouse_clicks = []
|
mouse_clicks = []
|
||||||
|
nearest_points = []
|
||||||
|
visited_quadrants = []
|
||||||
|
nearest_pairs = []
|
||||||
|
current_visited = 0
|
||||||
|
|
||||||
w = World()
|
w = World()
|
||||||
|
|
||||||
@ -85,79 +89,55 @@ def qt_insert(qt: Quadtree, p):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def qt_find_nearest_point(qt: Quadtree, point) -> Tuple[float, float]:
|
def qt_find_nearest_point(qt: Quadtree, point) -> Tuple[float, float]:
|
||||||
closest_point = None
|
|
||||||
closest_dist = None
|
|
||||||
last_direction = None
|
|
||||||
containing_qt = qt
|
containing_qt = qt
|
||||||
# Find the containing subnode
|
|
||||||
while containing_qt.subdivided:
|
while containing_qt.subdivided:
|
||||||
if RL.check_collision_point_rec(point, qt.nw.node.aabb):
|
if RL.check_collision_point_rec(point, containing_qt.nw.node.aabb):
|
||||||
containing_qt = qt.nw
|
containing_qt = containing_qt.nw
|
||||||
elif RL.check_collision_point_rec(point, qt.ne.node.aabb):
|
elif RL.check_collision_point_rec(point, containing_qt.ne.node.aabb):
|
||||||
containing_qt = qt.ne
|
containing_qt = containing_qt.ne
|
||||||
elif RL.check_collision_point_rec(point, qt.sw.node.aabb):
|
elif RL.check_collision_point_rec(point, containing_qt.sw.node.aabb):
|
||||||
containing_qt = qt.sw
|
containing_qt = containing_qt.sw
|
||||||
elif RL.check_collision_point_rec(point, qt.se.node.aabb):
|
elif RL.check_collision_point_rec(point, containing_qt.se.node.aabb):
|
||||||
containing_qt = qt.se
|
containing_qt = containing_qt.se
|
||||||
|
|
||||||
while containing_qt.parent is not None:
|
def search_for_nearest(qt: Quadtree, direction = ''):
|
||||||
# If it's greater than 1, then we have a point inside we can compare to
|
nonlocal closest_point, closest_dist
|
||||||
if len(containing_qt.node.points) > 1:
|
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:
|
for p in qt.node.points:
|
||||||
if p == point:
|
d = RL.vector_2distance(point, Vec2(p[0], p[1]))
|
||||||
continue
|
if d < closest_dist:
|
||||||
if closest_dist is None or RL.vector_2distance(Vec2(*point), Vec2(*p)) < closest_dist:
|
|
||||||
closest_point = p
|
closest_point = p
|
||||||
last_direction = containing_qt.direction
|
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
|
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
|
return closest_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
|
|
||||||
|
|
||||||
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):
|
def construct_quadtree(points):
|
||||||
@ -185,17 +165,17 @@ def player_input():
|
|||||||
if RL.is_key_pressed(RL.KEY_SPACE):
|
if RL.is_key_pressed(RL.KEY_SPACE):
|
||||||
w.paused = not w.paused
|
w.paused = not w.paused
|
||||||
if RL.is_mouse_button_pressed(0):
|
if RL.is_mouse_button_pressed(0):
|
||||||
print(RL.get_mouse_position())
|
mouse_pos = RL.get_mouse_position()
|
||||||
w.mouse_clicks.append(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
|
||||||
|
|
||||||
def update():
|
def update():
|
||||||
# Recontruct quadtree
|
# Recontruct quadtree
|
||||||
if w.paused:
|
if w.paused:
|
||||||
return
|
return
|
||||||
points = []
|
|
||||||
for b in w.balls:
|
|
||||||
points.append((b.px, b.py))
|
|
||||||
w.qt = construct_quadtree(points)
|
|
||||||
|
|
||||||
for ball in w.balls:
|
for ball in w.balls:
|
||||||
ball.px += ball.vx
|
ball.px += ball.vx
|
||||||
@ -209,6 +189,11 @@ def update():
|
|||||||
ball.py = RL.clamp(ball.py, ball_r + 0.1, screen_height - ball_r - 0.1)
|
ball.py = RL.clamp(ball.py, ball_r + 0.1, screen_height - ball_r - 0.1)
|
||||||
ball.vy *= -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):
|
def draw_qt_dfs(qt: Quadtree):
|
||||||
if not qt:
|
if not qt:
|
||||||
return
|
return
|
||||||
@ -223,10 +208,19 @@ def draw():
|
|||||||
|
|
||||||
RL.clear_background(RL.WHITE)
|
RL.clear_background(RL.WHITE)
|
||||||
draw_qt_dfs(w.qt)
|
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:
|
for ball in w.balls:
|
||||||
RL.draw_circle_lines_v((ball.px, ball.py), ball_r, RL.BLACK)
|
RL.draw_circle_lines_v((ball.px, ball.py), ball_r, RL.BLACK)
|
||||||
for mc in w.mouse_clicks:
|
for mc in w.mouse_clicks:
|
||||||
RL.draw_circle_v(mc, 5, RL.RED)
|
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()
|
RL.end_drawing()
|
||||||
|
|
||||||
|
39
starter.py
39
starter.py
@ -1,5 +1,5 @@
|
|||||||
import pyray as RL
|
import pyray as RL
|
||||||
from pyray import (Rectangle as Rect)
|
from pyray import (Rectangle as Rect, Vector2 as Vec2, Vector3 as Vec3, Camera3D)
|
||||||
import math
|
import math
|
||||||
import pdb
|
import pdb
|
||||||
import random
|
import random
|
||||||
@ -11,29 +11,44 @@ screen_height = 1024
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class World:
|
class World:
|
||||||
|
cam: Camera3D
|
||||||
|
frame_count: int = 0
|
||||||
|
|
||||||
|
def init() -> World:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def init():
|
def player_input(w: World):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def player_input():
|
def update(w: World):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def update():
|
def draw_3d(w: World):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def draw():
|
def draw_2d(w: World):
|
||||||
RL.begin_drawing()
|
pass
|
||||||
RL.clear_background(RL.WHITE)
|
|
||||||
|
|
||||||
RL.end_drawing()
|
|
||||||
|
|
||||||
RL.init_window(screen_width, screen_height, "Starter");
|
RL.init_window(screen_width, screen_height, "Starter");
|
||||||
RL.set_target_fps(60)
|
RL.set_target_fps(60)
|
||||||
|
|
||||||
init()
|
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():
|
while not RL.window_should_close():
|
||||||
player_input()
|
player_input(w)
|
||||||
update()
|
update(w)
|
||||||
draw()
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
73
triangulation.py
Normal file
73
triangulation.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
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
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user