test_raycasting.gd 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. extends Test
  2. const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside"
  3. var _hit_from_inside = false
  4. var _do_raycasts = false
  5. @onready var _raycast_visuals = ImmediateMesh.new()
  6. @onready var _material = StandardMaterial3D.new()
  7. func _ready():
  8. var options = $Options
  9. options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false)
  10. options.option_changed.connect(self._on_option_changed)
  11. _material.flags_unshaded = true
  12. _material.vertex_color_use_as_albedo = true
  13. var raycast_mesh_instance = MeshInstance3D.new()
  14. raycast_mesh_instance.mesh = _raycast_visuals
  15. add_child(raycast_mesh_instance)
  16. move_child(raycast_mesh_instance, get_child_count())
  17. await start_timer(0.5).timeout
  18. if is_timer_canceled():
  19. return
  20. _do_raycasts = true
  21. func _physics_process(delta):
  22. super._physics_process(delta)
  23. if not _do_raycasts:
  24. return
  25. _do_raycasts = false
  26. Log.print_log("* Start Raycasting...")
  27. _raycast_visuals.clear_surfaces()
  28. _raycast_visuals.surface_begin(Mesh.PRIMITIVE_LINES)
  29. for shape in $Shapes.get_children():
  30. var body = shape as PhysicsBody3D
  31. var space_state = body.get_world_3d().direct_space_state
  32. Log.print_log("* Testing: %s" % body.name)
  33. var center = body.global_transform.origin
  34. # Raycast entering from the top.
  35. var res = _add_raycast(space_state, center + Vector3(0.0, 2.0, 0.0), center)
  36. Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
  37. # Raycast exiting from inside.
  38. center.x -= 0.2
  39. res = _add_raycast(space_state, center, center - Vector3(0.0, 3.0, 0.0))
  40. Log.print_log("Raycast out: %s" % ("HIT" if res else "NO HIT"))
  41. # Raycast all inside.
  42. center.x += 0.4
  43. res = _add_raycast(space_state, center, center - Vector3(0.0, 0.8, 0.0))
  44. Log.print_log("Raycast inside: %s" % ("HIT" if res else "NO HIT"))
  45. _raycast_visuals.surface_end()
  46. _raycast_visuals.surface_set_material(0, _material)
  47. func _on_option_changed(option, checked):
  48. match option:
  49. OPTION_TEST_CASE_HIT_FROM_INSIDE:
  50. _hit_from_inside = checked
  51. _do_raycasts = true
  52. func _add_raycast(space_state, pos_start, pos_end):
  53. var params = PhysicsRayQueryParameters3D.new()
  54. params.from = pos_start
  55. params.to = pos_end
  56. params.hit_from_inside = _hit_from_inside
  57. var result = space_state.intersect_ray(params)
  58. if result:
  59. _raycast_visuals.surface_set_color(Color.GREEN)
  60. else:
  61. _raycast_visuals.surface_set_color(Color.RED.darkened(0.5))
  62. # Draw raycast line.
  63. _raycast_visuals.surface_add_vertex(pos_start)
  64. _raycast_visuals.surface_add_vertex(pos_end)
  65. # Draw raycast arrow.
  66. _raycast_visuals.surface_add_vertex(pos_end)
  67. _raycast_visuals.surface_add_vertex(pos_end + Vector3(-0.05, 0.1, 0.0))
  68. _raycast_visuals.surface_add_vertex(pos_end)
  69. _raycast_visuals.surface_add_vertex(pos_end + Vector3(0.05, 0.1, 0.0))
  70. return result