refactor: eh gonna rewrite it in rust
This commit is contained in:
parent
059eb4dc2f
commit
e72bce410d
@ -10,12 +10,14 @@ var velocity := Vector2.ZERO
|
||||
# this is assigned by the flock, if this boid is a child of it
|
||||
var flock: Flock
|
||||
|
||||
var last_processed_in: int = 0
|
||||
|
||||
## applies some force to this boid.
|
||||
func apply_force(spatial_force: Vector3) -> void:
|
||||
var force := Vector2(spatial_force.x, spatial_force.y)
|
||||
velocity += force
|
||||
velocity = velocity.limit_length(properties.max_speed)
|
||||
position += velocity * BoidManager.SIMULATION_RATE
|
||||
position += velocity
|
||||
|
||||
func _get_boid_position() -> Vector3:
|
||||
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
|
||||
var flock: Flock
|
||||
|
||||
var last_processed_in: int = 0
|
||||
|
||||
## applies some force to this boid.
|
||||
func apply_force(force: Vector3) -> void:
|
||||
velocity += force
|
||||
velocity = velocity.limit_length(properties.max_speed)
|
||||
position += velocity * BoidManager.SIMULATION_RATE
|
||||
position += velocity
|
||||
|
||||
func _get_boid_position() -> Vector3:
|
||||
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)
|
||||
const PARALLELIZATION_RATE: int = 50 # 50 seems to be the best value?
|
||||
const EPSILON: float = 0.00001
|
||||
# simulate per n physics frame ticks
|
||||
var SIMULATION_RATE: int = 1
|
||||
|
||||
var flocks: Dictionary = {}
|
||||
var total_boid_count: int = 0:
|
||||
@ -17,6 +15,7 @@ var total_boid_count: int = 0:
|
||||
# create our arrays for parallel processing
|
||||
var args_array: Array[Dictionary] = []
|
||||
var forces_array: PackedVector3Array = []
|
||||
#var grids: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
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:
|
||||
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")
|
||||
|
||||
func _unregister_flock(maybe_flock: Node) -> void:
|
||||
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")
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
# run the simulation at a given rate
|
||||
if Engine.get_physics_frames() % SIMULATION_RATE == 0:
|
||||
_process_boids()
|
||||
_process_boids()
|
||||
|
||||
func _process_boids() -> void:
|
||||
var total_parallel_tasks := total_boid_count / PARALLELIZATION_RATE
|
||||
@ -55,8 +56,10 @@ func _process_boids() -> void:
|
||||
# organize the work into tasks
|
||||
for flock: Flock in flocks.values():
|
||||
var flock_args := _pack_calc_args_flock(flock)
|
||||
for boid in flock.boids.values():
|
||||
var args := _pack_calc_args_boid(boid, flock_args.duplicate())
|
||||
var boids := flock.boids.values()
|
||||
#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
|
||||
forces_array[boid_count] = Vector3.ZERO
|
||||
boid_count += 1
|
||||
@ -97,7 +100,17 @@ func _pack_calc_args_flock(flock: Flock) -> Dictionary:
|
||||
flock_args['target_position'] = flock.target.global_position
|
||||
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['self_props'] = boid.properties
|
||||
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 arg_idx := start_from
|
||||
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
|
||||
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:
|
||||
for flock in get_children():
|
||||
for i in 1000: spawnBoid(flock)
|
||||
for i in 100: spawnBoid(flock)
|
||||
|
||||
func spawnBoid(flock: Flock) -> void:
|
||||
var boid: Boid2D = preload("../example_boid.tscn").instantiate()
|
||||
|
Loading…
Reference in New Issue
Block a user