refactor: eh gonna rewrite it in rust
This commit is contained in:
parent
b970959e65
commit
54a01c2ecc
@ -10,12 +10,14 @@ var velocity := Vector2.ZERO
|
|||||||
# this is assigned by the flock, if this boid is a child of it
|
# this is assigned by the flock, if this boid is a child of it
|
||||||
var flock: Flock
|
var flock: Flock
|
||||||
|
|
||||||
|
var last_processed_in: int = 0
|
||||||
|
|
||||||
## applies some force to this boid.
|
## applies some force to this boid.
|
||||||
func apply_force(spatial_force: Vector3) -> void:
|
func apply_force(spatial_force: Vector3) -> void:
|
||||||
var force := Vector2(spatial_force.x, spatial_force.y)
|
var force := Vector2(spatial_force.x, spatial_force.y)
|
||||||
velocity += force
|
velocity += force
|
||||||
velocity = velocity.limit_length(properties.max_speed)
|
velocity = velocity.limit_length(properties.max_speed)
|
||||||
position += velocity * BoidManager.SIMULATION_RATE
|
position += velocity
|
||||||
|
|
||||||
func _get_boid_position() -> Vector3:
|
func _get_boid_position() -> Vector3:
|
||||||
return Vector3(position.x, position.y, 0.0)
|
return Vector3(position.x, position.y, 0.0)
|
||||||
|
@ -10,11 +10,13 @@ var velocity := Vector3.ZERO
|
|||||||
# this is assigned by the flock, if this boid is a child of it
|
# this is assigned by the flock, if this boid is a child of it
|
||||||
var flock: Flock
|
var flock: Flock
|
||||||
|
|
||||||
|
var last_processed_in: int = 0
|
||||||
|
|
||||||
## applies some force to this boid.
|
## applies some force to this boid.
|
||||||
func apply_force(force: Vector3) -> void:
|
func apply_force(force: Vector3) -> void:
|
||||||
velocity += force
|
velocity += force
|
||||||
velocity = velocity.limit_length(properties.max_speed)
|
velocity = velocity.limit_length(properties.max_speed)
|
||||||
position += velocity * BoidManager.SIMULATION_RATE
|
position += velocity
|
||||||
|
|
||||||
func _get_boid_position() -> Vector3:
|
func _get_boid_position() -> Vector3:
|
||||||
return position
|
return position
|
||||||
|
@ -4,8 +4,6 @@ extends Node
|
|||||||
# this seems to help with 1000 boids in a single flock from 400ms to 180ms (before quadtrees)
|
# this seems to help with 1000 boids in a single flock from 400ms to 180ms (before quadtrees)
|
||||||
const PARALLELIZATION_RATE: int = 50 # 50 seems to be the best value?
|
const PARALLELIZATION_RATE: int = 50 # 50 seems to be the best value?
|
||||||
const EPSILON: float = 0.00001
|
const EPSILON: float = 0.00001
|
||||||
# simulate per n physics frame ticks
|
|
||||||
var SIMULATION_RATE: int = 1
|
|
||||||
|
|
||||||
var flocks: Dictionary = {}
|
var flocks: Dictionary = {}
|
||||||
var total_boid_count: int = 0:
|
var total_boid_count: int = 0:
|
||||||
@ -17,6 +15,7 @@ var total_boid_count: int = 0:
|
|||||||
# create our arrays for parallel processing
|
# create our arrays for parallel processing
|
||||||
var args_array: Array[Dictionary] = []
|
var args_array: Array[Dictionary] = []
|
||||||
var forces_array: PackedVector3Array = []
|
var forces_array: PackedVector3Array = []
|
||||||
|
#var grids: Dictionary = {}
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
get_tree().node_added.connect(_register_flock)
|
get_tree().node_added.connect(_register_flock)
|
||||||
@ -34,18 +33,20 @@ func _init_register_flock(node: Node = get_tree().root) -> void:
|
|||||||
|
|
||||||
func _register_flock(maybe_flock: Node) -> void:
|
func _register_flock(maybe_flock: Node) -> void:
|
||||||
if maybe_flock is not Flock: return
|
if maybe_flock is not Flock: return
|
||||||
flocks[maybe_flock.get_instance_id()] = maybe_flock
|
var flock_id := maybe_flock.get_instance_id()
|
||||||
|
flocks[flock_id] = maybe_flock
|
||||||
|
#grids[flock_id] = Grid.new()
|
||||||
print_verbose("[BoidManager] flock ", maybe_flock, " registered")
|
print_verbose("[BoidManager] flock ", maybe_flock, " registered")
|
||||||
|
|
||||||
func _unregister_flock(maybe_flock: Node) -> void:
|
func _unregister_flock(maybe_flock: Node) -> void:
|
||||||
if maybe_flock is not Flock: return
|
if maybe_flock is not Flock: return
|
||||||
flocks.erase(maybe_flock.get_instance_id())
|
var flock_id := maybe_flock.get_instance_id()
|
||||||
|
flocks.erase(flock_id)
|
||||||
|
#grids.erase(flock_id)
|
||||||
print_verbose("[BoidManager] flock ", maybe_flock, " unregistered")
|
print_verbose("[BoidManager] flock ", maybe_flock, " unregistered")
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
# run the simulation at a given rate
|
_process_boids()
|
||||||
if Engine.get_physics_frames() % SIMULATION_RATE == 0:
|
|
||||||
_process_boids()
|
|
||||||
|
|
||||||
func _process_boids() -> void:
|
func _process_boids() -> void:
|
||||||
var total_parallel_tasks := total_boid_count / PARALLELIZATION_RATE
|
var total_parallel_tasks := total_boid_count / PARALLELIZATION_RATE
|
||||||
@ -55,8 +56,10 @@ func _process_boids() -> void:
|
|||||||
# organize the work into tasks
|
# organize the work into tasks
|
||||||
for flock: Flock in flocks.values():
|
for flock: Flock in flocks.values():
|
||||||
var flock_args := _pack_calc_args_flock(flock)
|
var flock_args := _pack_calc_args_flock(flock)
|
||||||
for boid in flock.boids.values():
|
var boids := flock.boids.values()
|
||||||
var args := _pack_calc_args_boid(boid, flock_args.duplicate())
|
#grids.get(flock.get_instance_id()).build(Vector3.ONE * 1000.0, 30.0, boids)
|
||||||
|
for boid in boids:
|
||||||
|
var args := _pack_calc_args_boid(flock, boid, flock_args.duplicate())
|
||||||
args_array[boid_count] = args
|
args_array[boid_count] = args
|
||||||
forces_array[boid_count] = Vector3.ZERO
|
forces_array[boid_count] = Vector3.ZERO
|
||||||
boid_count += 1
|
boid_count += 1
|
||||||
@ -97,7 +100,17 @@ func _pack_calc_args_flock(flock: Flock) -> Dictionary:
|
|||||||
flock_args['target_position'] = flock.target.global_position
|
flock_args['target_position'] = flock.target.global_position
|
||||||
return flock_args
|
return flock_args
|
||||||
|
|
||||||
func _pack_calc_args_boid(boid, args: Dictionary) -> Dictionary:
|
func _pack_calc_args_boid(flock: Flock, boid, args: Dictionary) -> Dictionary:
|
||||||
|
#var nearby_boids: Array[Node] = grids.get(flock.get_instance_id()).get_nearby_boids(boid)
|
||||||
|
#var others_pos := PackedVector3Array([]); others_pos.resize(nearby_boids.size())
|
||||||
|
#var others_vel := PackedVector3Array([]); others_vel.resize(nearby_boids.size())
|
||||||
|
#var idx := 0
|
||||||
|
#for aboid in nearby_boids:
|
||||||
|
#others_pos.set(idx, aboid._get_boid_position())
|
||||||
|
#others_vel.set(idx, aboid._get_boid_velocity())
|
||||||
|
#idx += 1
|
||||||
|
#args['others_pos'] = others_pos
|
||||||
|
#args['others_vel'] = others_vel
|
||||||
args['boid'] = boid
|
args['boid'] = boid
|
||||||
args['self_props'] = boid.properties
|
args['self_props'] = boid.properties
|
||||||
args['self_vel'] = boid._get_boid_velocity()
|
args['self_vel'] = boid._get_boid_velocity()
|
||||||
@ -109,7 +122,7 @@ func _calculate_boid_parallel(idx: int) -> void:
|
|||||||
var end_at := mini(start_from + PARALLELIZATION_RATE, total_boid_count)
|
var end_at := mini(start_from + PARALLELIZATION_RATE, total_boid_count)
|
||||||
var arg_idx := start_from
|
var arg_idx := start_from
|
||||||
while arg_idx < end_at:
|
while arg_idx < end_at:
|
||||||
var force = _calculate_boid(args_array[arg_idx])
|
var force := _calculate_boid(args_array[arg_idx])
|
||||||
forces_array[arg_idx] = force
|
forces_array[arg_idx] = force
|
||||||
arg_idx += 1
|
arg_idx += 1
|
||||||
|
|
||||||
|
122
addons/boids/grid.gd
Normal file
122
addons/boids/grid.gd
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
extends RefCounted
|
||||||
|
class_name Grid
|
||||||
|
|
||||||
|
var _cells: Dictionary
|
||||||
|
var _scale: float
|
||||||
|
var size: Vector3
|
||||||
|
var scaled_points: Dictionary
|
||||||
|
|
||||||
|
func build(unscaled_size: Vector3, scale: float, boids: Array):
|
||||||
|
_scale = scale
|
||||||
|
size = Vector3(_scale_axis(unscaled_size.x), _scale_axis(unscaled_size.y), _scale_axis(unscaled_size.z))
|
||||||
|
_cells.clear()
|
||||||
|
scaled_points.clear()
|
||||||
|
|
||||||
|
var idx := 0
|
||||||
|
for boid in boids:
|
||||||
|
var scaled_point := _scale_point(boid._get_boid_position())
|
||||||
|
_add_body(boid, scaled_point)
|
||||||
|
scaled_points[boid.get_instance_id()] = scaled_point
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
|
||||||
|
func _scale_axis(point: float) -> float:
|
||||||
|
return floorf(point / _scale)
|
||||||
|
|
||||||
|
|
||||||
|
func _scale_point(vector: Vector3) -> Vector3:
|
||||||
|
var scaled_point = (vector / _scale).floor()
|
||||||
|
scaled_point.x = minf(maxf(scaled_point.x, 0), size.x)
|
||||||
|
scaled_point.y = minf(maxf(scaled_point.y, 0), size.y)
|
||||||
|
scaled_point.z = minf(maxf(scaled_point.z, 0), size.z)
|
||||||
|
return scaled_point
|
||||||
|
|
||||||
|
|
||||||
|
func _add_body(body: Node, scaled_point: Vector3) -> void:
|
||||||
|
var boids := _cells.get(scaled_point, [])
|
||||||
|
boids.append(body)
|
||||||
|
_cells[scaled_point] = boids
|
||||||
|
|
||||||
|
func _get_cell(x: float, y: float, z: float, write_to: Array[Node]) -> void:
|
||||||
|
write_to.append_array(_cells.get(Vector3(x, y, z), []))
|
||||||
|
|
||||||
|
func get_nearby_boids(boid: Node) -> Array[Node]:
|
||||||
|
var scaled_point: Vector3 = scaled_points[boid.get_instance_id()]
|
||||||
|
|
||||||
|
# keep the points in bounds
|
||||||
|
var x := minf(maxf(scaled_point.x, 0), size.x)
|
||||||
|
var y := minf(maxf(scaled_point.y, 0), size.y)
|
||||||
|
var z := minf(maxf(scaled_point.z, 0), size.z)
|
||||||
|
|
||||||
|
var results: Array[Node] = []
|
||||||
|
var gb := func(x, y, z): _get_cell(x, y, z, results)
|
||||||
|
gb.call(x, y, z)
|
||||||
|
|
||||||
|
var up := y - 1
|
||||||
|
var down := y + 1
|
||||||
|
var left := x - 1
|
||||||
|
var right := x + 1
|
||||||
|
var forwards := z - 1
|
||||||
|
var backwards := z + 1
|
||||||
|
|
||||||
|
# up
|
||||||
|
if up > 0:
|
||||||
|
gb.call(x, up, z)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, up, z)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, up, z)
|
||||||
|
if forwards > 0:
|
||||||
|
gb.call(x, up, forwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, up, forwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, up, forwards)
|
||||||
|
if backwards <= size.z:
|
||||||
|
gb.call(x, up, backwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, up, backwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, up, backwards)
|
||||||
|
# down
|
||||||
|
if down <= size.y:
|
||||||
|
gb.call(x, down, z)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, down, z)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, down, z)
|
||||||
|
if forwards > 0:
|
||||||
|
gb.call(x, down, forwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, down, forwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, down, forwards)
|
||||||
|
if backwards <= size.z:
|
||||||
|
gb.call(x, down, backwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, down, backwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, down, backwards)
|
||||||
|
|
||||||
|
# forwards
|
||||||
|
if forwards > 0:
|
||||||
|
gb.call(x, y, forwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, y, forwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, y, forwards)
|
||||||
|
|
||||||
|
if backwards <= size.z:
|
||||||
|
gb.call(x, y, backwards)
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, y, backwards)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, y, backwards)
|
||||||
|
|
||||||
|
# left and right
|
||||||
|
if left > 0:
|
||||||
|
gb.call(left, y, z)
|
||||||
|
if right <= size.x:
|
||||||
|
gb.call(right, y, z)
|
||||||
|
|
||||||
|
return results
|
@ -2,7 +2,7 @@ extends Node2D
|
|||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
for flock in get_children():
|
for flock in get_children():
|
||||||
for i in 1000: spawnBoid(flock)
|
for i in 100: spawnBoid(flock)
|
||||||
|
|
||||||
func spawnBoid(flock: Flock) -> void:
|
func spawnBoid(flock: Flock) -> void:
|
||||||
var boid: Boid2D = preload("../example_boid.tscn").instantiate()
|
var boid: Boid2D = preload("../example_boid.tscn").instantiate()
|
||||||
|
Loading…
Reference in New Issue
Block a user