LargeScreen/scripts/traffic_light_mesh.gd

195 lines
8.1 KiB
GDScript3
Raw Normal View History

2025-01-13 14:39:58 +08:00
extends MeshInstance3D
var traffic_light_recognition = TrafficLights.new()
var traffic_light_group_map: Array
@export var light_bulb_offset = 0.0
func _ready():
traffic_light_recognition.subscribe("/perception/traffic_light_recognition/traffic_signals", false)
# Function to generate a light bulb, setting up its mesh and material
func generate_light_bulb(light_bulb) -> MeshInstance3D:
var plane_mesh = PlaneMesh.new()
plane_mesh.size = Vector2(light_bulb["radius"] * 2, light_bulb["radius"] * 2)
# Creating mesh instance
var mesh_instance = MeshInstance3D.new()
# Creating ArrayMesh
var array_mesh = ArrayMesh.new()
array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, plane_mesh.get_mesh_arrays())
# Setting material
var material = StandardMaterial3D.new()
material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
if light_bulb["color"] == "red":
material.albedo_texture = load("res://TrafficLight/traffic_light_red.png")
elif light_bulb["color"] == "yellow":
material.albedo_texture = load("res://TrafficLight/traffic_light_yellow.png")
elif light_bulb["color"] == "green":
if light_bulb["arrow"] == "none":
material.albedo_texture = load("res://TrafficLight/traffic_light_green.png")
elif light_bulb["arrow"] == "right":
material.albedo_texture = load("res://TrafficLight/traffic_light_green_right.png")
elif light_bulb["arrow"] == "left":
material.albedo_texture = load("res://TrafficLight/traffic_light_green_left.png")
elif light_bulb["arrow"] == "up":
material.albedo_texture = load("res://TrafficLight/traffic_light_green_up.png")
elif light_bulb["arrow"] == "down":
material.albedo_texture = load("res://TrafficLight/traffic_light_green_down.png")
mesh_instance.material_override = material
# Setting mesh
mesh_instance.mesh = array_mesh
# Setting mesh instance transformation and position
var target_normal = light_bulb["normal"].normalized()
var angle_y = atan2(target_normal.x, target_normal.z)
var rotation_y = Transform3D(Basis().rotated(Vector3.UP, angle_y), Vector3.ZERO)
var angle_z = atan2(target_normal.y, Vector2(target_normal.x, target_normal.z).length()) + PI * 0.5
var rotation_z = Transform3D(Basis().rotated(Vector3.LEFT, angle_z), Vector3.ZERO)
var rotation_flip = Transform3D(Basis().rotated(Vector3.UP, PI), Vector3.ZERO)
# Applying final transformation
mesh_instance.transform = Transform3D().translated(light_bulb["position"]) * rotation_y * rotation_z * rotation_flip * Transform3D().translated(Vector3(0,light_bulb_offset,0))
return mesh_instance
func set_traffic_light_map(traffic_light_group_list):
traffic_light_group_map = traffic_light_group_list
# Function to generate the visuals for light bulbs
func visualize():
mesh.clear_surfaces()
var boards_arr = []
boards_arr.resize(Mesh.ARRAY_MAX)
var boards_verts = PackedVector3Array()
var boards_normals = PackedVector3Array()
var boards_colors = PackedColorArray()
# Boards
for traffic_light_group in traffic_light_group_map:
for traffic_light in traffic_light_group["traffic_lights"]:
boards_verts.append(traffic_light["board"]["left_top_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_verts.append(traffic_light["board"]["right_top_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_verts.append(traffic_light["board"]["right_bottom_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_verts.append(traffic_light["board"]["left_bottom_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_verts.append(traffic_light["board"]["left_top_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_verts.append(traffic_light["board"]["right_bottom_position"])
boards_normals.append(traffic_light["board"]["normal"])
boards_colors.append(Color(0.1, 0.1, 0.1, 1.0))
boards_arr[Mesh.ARRAY_VERTEX] = boards_verts
boards_arr[Mesh.ARRAY_NORMAL] = boards_normals
boards_arr[Mesh.ARRAY_COLOR] = boards_colors
# Light Bulbs
var light_bulbs_arr = []
light_bulbs_arr.resize(Mesh.ARRAY_MAX)
var light_bulbs_verts = PackedVector3Array()
var light_bulbs_normals = PackedVector3Array()
var light_bulbs_colors = PackedColorArray()
var segments = 16 # Number of segments to form a circle. Increase this number for a smoother circle.
var angle_step = 2.0 * PI / segments # Angle per segment
for traffic_light_group in traffic_light_group_map:
for traffic_light in traffic_light_group["traffic_lights"]:
for light_bulb in traffic_light["light_bulbs"]:
var center = light_bulb["position"] # Center of the circle
var radius = light_bulb["radius"] # Radius of the circle
var normal = light_bulb["normal"].normalized() # Normal vector of the circle
var angle_y = atan2(normal.x, normal.z)
var rotation_y = Transform3D(Basis().rotated(Vector3.UP, angle_y), Vector3.ZERO)
var angle_z = atan2(normal.y, Vector2(normal.x, normal.z).length()) + PI * 0.5
var rotation_z = Transform3D(Basis().rotated(Vector3.LEFT, angle_z), Vector3.ZERO)
for i in range(segments):
# Calculate two points (current point and next point)
var current_angle = angle_step * i
var next_angle = angle_step * (i + 1)
var current_point_local = Vector3(cos(current_angle), 0.0, sin(current_angle)) * radius
var next_point_local = Vector3(cos(next_angle), 0.0, sin(next_angle)) * radius
# Apply rotation and transform to world coordinates
var current_point = center + rotation_y * rotation_z * current_point_local
var next_point = center + rotation_y * rotation_z * next_point_local
# Add vertices
light_bulbs_verts.append(center)
light_bulbs_verts.append(current_point)
light_bulbs_verts.append(next_point)
# Add normals
light_bulbs_normals.append(normal)
light_bulbs_normals.append(normal)
light_bulbs_normals.append(normal)
# Add colors
light_bulbs_colors.append(Color(0.0, 0.0, 0.0, 1.0))
light_bulbs_colors.append(Color(0.0, 0.0, 0.0, 1.0))
light_bulbs_colors.append(Color(0.0, 0.0, 0.0, 1.0))
light_bulbs_arr[Mesh.ARRAY_VERTEX] = light_bulbs_verts
light_bulbs_arr[Mesh.ARRAY_NORMAL] = light_bulbs_normals
light_bulbs_arr[Mesh.ARRAY_COLOR] = light_bulbs_colors
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, light_bulbs_arr)
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, boards_arr)
func _process(_delta):
if !traffic_light_recognition.has_new():
return
var traffic_light_status_list = traffic_light_recognition.get_traffic_light_status()
# Dictionary to mark existing meshes
var existing_meshes = {}
for child in get_children():
if child is MeshInstance3D:
existing_meshes[child.name] = child
for traffic_light_group in traffic_light_group_map:
for traffic_light_status in traffic_light_status_list:
if traffic_light_status["group_id"] != traffic_light_group["group_id"]:
continue
for traffic_light_status_element in traffic_light_status["status_elements"]:
for traffic_light in traffic_light_group["traffic_lights"]:
for light_bulb in traffic_light["light_bulbs"]:
if light_bulb["color"] != traffic_light_status_element["color"]:
continue
if light_bulb["arrow"] != traffic_light_status_element["arrow"]:
continue
var mesh_name = "Mesh_" + str(traffic_light_status["group_id"]) + "_" + light_bulb["color"] + "_" + light_bulb["arrow"]
var mesh_instance
if mesh_name in existing_meshes:
mesh_instance = existing_meshes[mesh_name]
else:
mesh_instance = generate_light_bulb(light_bulb)
mesh_instance.name = mesh_name
add_child(mesh_instance)
# Exclude this mesh from the deletion list since it's being reused
existing_meshes.erase(mesh_name)
# Delete meshes that were not used
for mesh_instance in existing_meshes.values():
remove_child(mesh_instance)
mesh_instance.queue_free()
traffic_light_recognition.set_old()