Compare commits

..

No commits in common. "swarm_engine" and "develop" have entirely different histories.

16 changed files with 76 additions and 33879 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bcsjr6kydgdqy"
path="res://.godot/imported/result.gltf-fa6e7d401ecc486ebc1efbad267cda09.scn"
[deps]
source_file="res://assets/spider/result.gltf"
dest_files=["res://.godot/imported/result.gltf-fa6e7d401ecc486ebc1efbad267cda09.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={
"meshes": {
"result_Cube": {
"generate/lightmap_uv": 0,
"generate/lods": 0,
"generate/shadow_meshes": 1,
"lods/normal_merge_angle": 60.0,
"lods/normal_split_angle": 25.0,
"save_to_file/enabled": true,
"save_to_file/path": "res://assets/spider/spider_mesh.res"
}
},
"nodes": {
"PATH:RootNode/SpiderArmature/Skeleton3D": {
"rest_pose/external_animation_library": null
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1

Binary file not shown.

View File

@ -17,9 +17,6 @@ var not_dead := true
@export_multiline var death_message : Array[String]
#@onready var color_rect: ColorRect = $CanvasLayer/ColorRect
func _process(delta: float) -> void:
DebugDraw3D.draw_sphere(position, .5)
func handle_dying():
not_dead = false
#weapon_slot_2.queue_free()

View File

@ -1,7 +0,0 @@
extends Resource
class_name ColorHelper
static func get_direction_color(direction: Vector3) -> Color:
var angle = atan2(direction.z, direction.x)
var hue = (angle / (2.0 * PI)) + 0.5
return Color.from_hsv(hue, 1.0, 1.0)

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,11 @@
extends Resource
class_name FlowFieldCell
var position:Vector3 = Vector3(0.0, 0.0, 0.0)
var flow_direction:Vector3 = Vector3(randf(), 0.0, randf())
func debug_process() -> void:
if flow_direction.length() > 0.0:
DebugDraw3D.draw_arrow(position, position + flow_direction, Color(1,1,1,1), 0.1)
else:
DebugDraw3D.draw_sphere(position, .05)

View File

@ -1,34 +0,0 @@
#[compute]
#version 450
// Speicher für FlowField-Daten
layout(std430, set = 0, binding = 0) buffer FlowFieldBuffer {
vec2 flow_field[];
};
// Zielposition und Grid-Daten
layout(push_constant) uniform Params {
vec2 target_pos;
float cell_size;
int grid_size_x;
int grid_size_z;
};
void main(){
uint x = gl_GlobalInvocationID.x;
uint z = gl_GlobalInvocationID.y;
if (x >= grid_size_x || z >= grid_size_z) return;
int index = int(z * grid_size_x + x);
// Zellzentrum berechnen
vec2 cell_center = vec2(x, z) * cell_size + vec2(cell_size * 0.5);
// Richtung zum Ziel berechnen
vec2 direction = normalize(target_pos - cell_center);
// Ergebnis in FlowField speichern
flow_field[index] = direction;
}

View File

@ -1,14 +0,0 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bf4mkjohkqpox"
path="res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res"
[deps]
source_file="res://swarm_engine/flow_field_navigation/flow_field_compute.glsl"
dest_files=["res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res"]
[params]

View File

@ -1,234 +1,71 @@
extends Node3D
class_name FlowFieldNav
# https://docs.godotengine.org/cs/4.x/tutorials/shaders/compute_shaders.html#create-a-local-renderingdevice
# Das Updaten der flow richtung kann auf der grafikkarte gemacht werden mit compute shader
@export_group("Debug")
@export var debugVisu: bool = true
@export var line_color: Color = Color(1, 1, 1, 1)
@export_category("Debug Visualization")
@export_group("Grid Center")
@export var show_grid_center: bool = false
@export_color_no_alpha var grid_center_color: Color = Color(1, 1, 1, 1)
@export var grid_center_size: float = 0.5
@export_group("Border")
@export var show_border: bool = false
@export_color_no_alpha var border_color: Color = Color(1, 1, 1, 1)
@export_group("Cells")
@export_subgroup("X Lines")
@export var show_x_lines: bool = false
@export_color_no_alpha var x_lines_color: Color = Color(1, 1, 1)
@export_subgroup("Z Lines")
@export var show_z_lines: bool = false
@export_color_no_alpha var z_lines_color: Color = Color(1, 1, 1)
@export_group("Arrows")
@export var show_arrows: bool = false
@export var arrows_size: float = 0.1
@export_color_no_alpha var cell_center_color: Color = Color(1, 1, 1)
@export var cell_center_size: float = 0.2
@export_category("Grid")
@export_group("Grid")
@export var grid_size: int = 10
@export var cell_size: float = 1.0
@export_group("Grid Size", "grid_size_")
@export var grid_size_x: int = 2
@export var grid_size_z: int = 5
@export var target: Node3D = null
var flow_direction_list: Array[Vector2] = []
var half_size_x: float
var half_size_z: float
var rd: RenderingDevice
var shader: RID
var pipeline: RID
var flow_field_buffer: RID
var flow_field_data: PackedVector2Array
var _cells: Dictionary
var grid_offset: Vector3
func _ready() -> void:
#var rendering_device := RenderingServer.create_local_rendering_device()
#var shader_file := load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl")
#var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
#var shader_RID := rendering_device.shader_create_from_spirv(shader_spirv)
#
#var center_array: PackedVector3Array
#for x in range(grid_size_x):
#for z in range(grid_size_z):
#center_array.append(_get_cell_center_with_coordinates(x,z))
#
#var center_byte_array = center_array.to_byte_array()
#var storage_buffer_RID = rendering_device.storage_buffer_create(center_byte_array.size(), center_byte_array)
#
#var uniform := RDUniform.new()
#uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
#uniform.binding = 0
#uniform.add_id(storage_buffer_RID)
#var uniform_set_RID := rendering_device.uniform_set_create([uniform], shader_RID, 0)
#
#var pipeline_RID := rendering_device.compute_pipeline_create(shader_RID)
#var compute_list_id := rendering_device.compute_list_begin()
#
#rendering_device.compute_list_bind_compute_pipeline(compute_list_id, pipeline_RID)
#rendering_device.compute_list_bind_uniform_set(compute_list_id, uniform_set_RID, 0)
#rendering_device.compute_list_dispatch(compute_list_id, 1, 1, 1)
#rendering_device.compute_list_end()
#rendering_device.submit()
var half_size = (grid_size * cell_size) * 0.5
grid_offset = Vector3(-half_size + (cell_size * 0.5), 0, -half_size + (cell_size * 0.5))
create_grid()
#rd = RenderingServer.get_rendering_device()
#
## Compute Shader laden
#var shader_file = load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl")
#shader = rd.shader_create_from_spirv(shader_file.get_spirv())
#pipeline = rd.compute_pipeline_create(shader)
#
## Speicher für FlowField erstellen
#var buffer_size = grid_size_x * grid_size_z * 8 # Vector2 -> 2 floats = 8 Bytes pro Eintrag
#flow_field_buffer = rd.storage_buffer_create(buffer_size)
#flow_field_data.resize(grid_size_x * grid_size_z)
#
func create_grid() -> void:
_cells.clear()
for x in range(grid_size):
for z in range(grid_size):
var cell = FlowFieldCell.new()
var world_x = x * cell_size + grid_offset.x
var world_z = z * cell_size + grid_offset.z
cell.position = Vector3(world_x, 0, world_z)
_cells[Vector3(x, 0, z)] = cell # Dictionary mit Grid-Koordinaten als Key
for x in range(grid_size_x):
for z in range(grid_size_z):
flow_direction_list.append(Vector2(0.0, 0.0))
half_size_x = (grid_size_x * cell_size) * 0.5
half_size_z = (grid_size_z * cell_size) * 0.5
func _process(delta: float) -> void:
if debugVisu:
_debug_draw_grid()
for cell in _cells.values():
cell.debug_process()
#_update_gpu_flow_field()
_update_flow_field()
_draw_debug()
func _debug_draw_grid() -> void:
for x in range(grid_size + 1):
var pos_x = x * cell_size + grid_offset.x - (cell_size * 0.5)
DebugDraw3D.draw_line(Vector3(pos_x, 0, grid_offset.z - (cell_size * 0.5)), Vector3(pos_x, 0, grid_offset.z + grid_size * cell_size - (cell_size * 0.5)), line_color)
func _update_gpu_flow_field():
if not target:
return
# Push-Constants für Shader setzen
var push_constants = PackedByteArray()
push_constants.append_array(PackedByteArray([
target.position.x,
target.position.z,
cell_size,
float(grid_size_x),
float(grid_size_z)
]))
# GPU Command erstellen
var compute_list = rd.compute_list_begin()
rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
rd.compute_list_bind_storage_buffer(compute_list, flow_field_buffer, 0, 0)
rd.compute_list_set_push_constant(compute_list, push_constants, 0)
rd.compute_list_dispatch(compute_list, grid_size_x, grid_size_z, 1)
rd.compute_list_end()
# GPU Berechnung starten
rd.submit()
rd.sync()
# Daten von der GPU zurückholen
var buffer_data = rd.buffer_get_data(flow_field_buffer)
var output = buffer_data.to_float32_array()
# 2D-Array für FlowField initialisieren
flow_direction_list = []
for x in range(grid_size_x):
flow_direction_list.append([]) # Erstellt leere Arrays für jede X-Spalte
# Konvertiere die 1D-GPU-Daten in ein 2D-Array
for z in range(grid_size_z):
for x in range(grid_size_x):
var index = (z * grid_size_x + x) * 2 # 2 Floats pro Vector2
var flow_vector = Vector2(output[index], output[index + 1])
flow_direction_list[index] = flow_vector
func _update_flow_field():
if target != null:
for x in range(grid_size_x):
for z in range(grid_size_z):
var index = z * grid_size_x + x
var flow_direction = (target.position - _get_cell_center_with_coordinates(x,z)).normalized() * (cell_size/2)
flow_direction_list[index] = Vector2(flow_direction.x, flow_direction.z)
var target_index = _get_index_from_position(target.position)
flow_direction_list[target_index] = Vector2(0, 0)
for z in range(grid_size + 1):
var pos_z = z * cell_size + grid_offset.z - (cell_size * 0.5)
DebugDraw3D.draw_line(Vector3(grid_offset.x - (cell_size * 0.5), 0, pos_z), Vector3(grid_offset.x + grid_size * cell_size - (cell_size * 0.5), 0, pos_z), line_color)
func _draw_debug():
if show_grid_center:
DebugDraw3D.draw_sphere(position, grid_center_size, grid_center_color)
if show_border:
_draw_border()
# Gibt die Zelle basierend auf einer Weltposition zurück
func get_cell_from_pos(world_pos: Vector3) -> FlowFieldCell:
var grid_x = int((world_pos.x - grid_offset.x) / cell_size)
var grid_z = int((world_pos.z - grid_offset.z) / cell_size)
var cell_pos = Vector3(grid_x, 0, grid_z)
if show_x_lines:
_draw_x_lines()
return _cells.get(cell_pos, null)
if show_z_lines:
_draw_z_lines()
if show_arrows:
_draw_arrows()
# Raycast zur Bestimmung der Zelle unter dem Mauszeiger
func _input(event):
if event is InputEventMouseButton and event.pressed:
var camera = get_viewport().get_camera_3d()
var from = camera.project_ray_origin(get_viewport().get_mouse_position())
var to = from + camera.project_ray_normal(get_viewport().get_mouse_position()) * 1000
func _draw_border():
var top_left = position - Vector3(half_size_x, 0 , half_size_z)
var top_right = position + Vector3(half_size_x, 0, -half_size_z)
var bottom_left = position - Vector3(half_size_x, 0, -half_size_z)
var bottom_right = position + Vector3(half_size_x, 0, half_size_z)
var space_state = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(from, to)
var result = space_state.intersect_ray(query)
var lines: PackedVector3Array
lines.append_array(PackedVector3Array([top_left, top_right]))
lines.append_array(PackedVector3Array([top_right, bottom_right]))
lines.append_array(PackedVector3Array([bottom_right, bottom_left]))
lines.append_array(PackedVector3Array([bottom_left, top_left]))
DebugDraw3D.draw_lines(lines, border_color)
func _draw_x_lines():
var lines: PackedVector3Array
for x in range(grid_size_x - 1):
var start = position - Vector3(half_size_x - ((x + 1) * cell_size), 0, half_size_z)
var end = position - Vector3(half_size_x - ((x + 1) * cell_size), 0, -half_size_z)
lines.append_array(PackedVector3Array([start, end]))
DebugDraw3D.draw_lines(lines, x_lines_color)
func _draw_z_lines():
var lines: PackedVector3Array
for z in range(grid_size_z - 1):
var start = position - Vector3(half_size_x, 0, half_size_z - ((z + 1) * cell_size))
var end = position - Vector3(-half_size_x, 0, half_size_z - ((z + 1) * cell_size))
lines.append_array(PackedVector3Array([start, end]))
DebugDraw3D.draw_lines(lines, z_lines_color)
func _draw_arrows():
var points: PackedVector3Array
for x in range(grid_size_x):
for z in range(grid_size_z):
var cell_center = _get_cell_center_with_coordinates(x,z)
var index = z * grid_size_x + x
if flow_direction_list[index].length() > 0.0:
var direction = Vector3(flow_direction_list[index].x, 0, flow_direction_list[index].y).normalized()
var arrow_end = cell_center + direction * (cell_size * 0.4)
DebugDraw3D.draw_arrow(cell_center, arrow_end, ColorHelper.get_direction_color(direction), arrows_size)
if result.has("position"):
var cell = get_cell_from_pos(result["position"])
if cell:
print("Zelle an", cell.position, ":", cell.flow_direction)
else:
points.append(cell_center)
DebugDraw3D.draw_points(points, DebugDraw3D.POINT_TYPE_SQUARE, cell_center_size, cell_center_color)
func _get_cell_center_with_coordinates(x:int, z:int) -> Vector3:
return position + Vector3(
(-half_size_x + (x * cell_size) + (cell_size * 0.5)),
0,
(-half_size_z + (z * cell_size) + (cell_size * 0.5)))
func _get_coordinates_from_position(pos: Vector3) -> Vector2i:
return Vector2i(int((pos.x - position.x + half_size_x) / cell_size),
int((pos.z - position.z + half_size_z) / cell_size))
func _get_index_from_position(pos: Vector3) -> int:
var pos_coord = _get_coordinates_from_position(pos)
if _is_coordinate_valid(pos_coord):
return -1
return pos_coord.y * grid_size_x + pos_coord.x
func _is_coordinate_valid(coord: Vector2i) -> bool:
return coord.x < 0 or coord.x >= grid_size_x or coord.y < 0 or coord.y >= grid_size_z
func get_direction_from_position(position: Vector3) -> Vector3:
var index = _get_index_from_position(position)
return Vector3(flow_direction_list[index].x, 0, flow_direction_list[index].y)
print("Keine Zelle gefunden!")

View File

@ -0,0 +1 @@
extends Node3D

View File

@ -1,71 +1,20 @@
[gd_scene load_steps=6 format=3 uid="uid://bwo12me8h21q5"]
[gd_scene load_steps=3 format=3 uid="uid://bwo12me8h21q5"]
[ext_resource type="Script" path="res://swarm_engine/swarm_engine_debug_level.gd" id="1_f0ttr"]
[ext_resource type="PackedScene" uid="uid://cn2xvs2g7box5" path="res://swarm_engine/flow_field_navigation/flow_field_navigation.tscn" id="1_xwcpn"]
[ext_resource type="PackedScene" uid="uid://cdau7qryen3uq" path="res://swarm_engine/swarm_unit/swarm_unit.tscn" id="3_6kohq"]
[ext_resource type="PackedScene" uid="uid://dycbdcrwsm6wu" path="res://experimente/felox/player.tscn" id="6_wayso"]
[sub_resource type="PlaneMesh" id="PlaneMesh_3dwe5"]
size = Vector2(400, 400)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_vtddf"]
points = PackedVector3Array(-200, 0, -200, -200, 0, 200, 200, 0, -200, 200, 0, 200)
[node name="World" type="Node3D"]
script = ExtResource("1_f0ttr")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
shadow_enabled = true
[node name="FlowFieldNavigation" parent="." node_paths=PackedStringArray("target") instance=ExtResource("1_xwcpn")]
unique_name_in_owner = true
show_grid_center = true
grid_center_color = Color(0, 0.0833333, 1, 1)
show_border = true
show_x_lines = true
x_lines_color = Color(1, 0.45, 0, 1)
show_z_lines = true
z_lines_color = Color(1, 0, 0.0166664, 1)
show_arrows = true
cell_center_color = Color(0.702375, 0.0507974, 0.96251, 1)
cell_size = 4.0
grid_size_x = 50
grid_size_z = 50
target = NodePath("../player")
[node name="FlowFieldNavigation" parent="." instance=ExtResource("1_xwcpn")]
grid_size = 100
cell_size = 2.0
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("PlaneMesh_3dwe5")
[node name="CSGSphere3D" type="CSGSphere3D" parent="FlowFieldNavigation"]
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConvexPolygonShape3D_vtddf")
[node name="player" parent="." instance=ExtResource("6_wayso")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3.50529)
[node name="Camera3D" type="Camera3D" parent="player"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 10, 8)
[node name="Node3D" type="Node3D" parent="."]
[node name="SwarmUnit" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0338392, 0, -41.7085)
move_speed = 4
flow_field_navigation = NodePath("../../FlowFieldNavigation")
[node name="SwarmUnit2" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17.4426, 0, -41.7085)
move_speed = 4
flow_field_navigation = NodePath("../../FlowFieldNavigation")
[node name="SwarmUnit3" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0338392, 0, -58.7671)
move_speed = 4
flow_field_navigation = NodePath("../../FlowFieldNavigation")
[node name="SwarmUnit4" parent="Node3D" node_paths=PackedStringArray("flow_field_navigation") instance=ExtResource("3_6kohq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17.4426, 0, -58.7671)
move_speed = 4
flow_field_navigation = NodePath("../../FlowFieldNavigation")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.331371, 0.943501, 0, -0.943501, 0.331371, 0, 13.203, 5.65752)

View File

@ -1,36 +0,0 @@
extends MultiMeshInstance3D
@export var move_speed = 2
@export var number: int = 100
@export var stretch: int = 2
@onready var flow_field_navigation: FlowFieldNav = %FlowFieldNavigation
@onready var player: Player = %player
func _ready() -> void:
for x in range(number):
for z in range(number):
var index = z * number + x
self.multimesh.set_instance_transform(index, Transform3D(Basis(), Vector3(x * stretch, 0.0, -z * stretch)))
func _process(delta: float) -> void:
for x in range(number):
for z in range(number):
var index = z * number + x
var current_trans = self.multimesh.get_instance_transform(index)
var cell = flow_field_navigation.get_cell_from_pos(current_trans.origin)
if cell != null and cell.flow_direction.length() > 0.0:
var movement = cell.flow_direction.normalized() * move_speed * delta
current_trans.origin += movement
var direction_to_player = (player.position - current_trans.origin).normalized()
var target_rotation_y = Quaternion(Vector3.UP, atan2(-direction_to_player.x, -direction_to_player.z))
var fix_rotation_x = Quaternion(Vector3.RIGHT, deg_to_rad(-90))
var fix_rotation_y_180 = Quaternion(Vector3.UP, deg_to_rad(180))
var final_rotation = fix_rotation_y_180 * target_rotation_y * fix_rotation_x
current_trans.basis = Basis(final_rotation)
self.multimesh.set_instance_transform(index, current_trans)

View File

@ -1,10 +0,0 @@
extends CharacterBody3D
@export var move_speed = 2
@export var flow_field_navigation: FlowFieldNav
func _physics_process(delta: float) -> void:
var flow_direction = flow_field_navigation.get_direction_from_position(position)
if flow_direction.length() > 0.0:
var movement = flow_direction.normalized() * move_speed * delta
position += movement

View File

@ -1,11 +0,0 @@
[gd_scene load_steps=3 format=3 uid="uid://cdau7qryen3uq"]
[ext_resource type="Script" path="res://swarm_engine/swarm_unit/swarm_unit.gd" id="1_eynce"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o8sb1"]
[node name="SwarmUnit" type="CharacterBody3D"]
script = ExtResource("1_eynce")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_o8sb1")