Multiple Reflecting Intersect_Ray Laser 3D

Godot Version

4.2

Question

How to get laser to reflects more than once? I got it to reflect just once but it doesn’t reflect again.

var reflects = 0
var max_reflects = 5
var cast_length = 10
#var origin = marker3d.global_position
#var end = marker3d.to_global(Vector3(0,0, -cast_length))

var space_state = get_world_3d().direct_space_state
var from = marker3d.global_position
var to = marker3d.to_global(Vector3(0,0,-cast_length))
var query = PhysicsRayQueryParameters3D.create(from, to, collision_mask, [self])
var result = space_state.intersect_ray(query)

for i in max_reflects:
             # NOTHING HITS > CAST FORWARD
	if !result: 
		
		from = marker3d.global_position
		to = marker3d.to_global(Vector3(0,0,-cast_length))
		line(from, to, Color(1, 0, 0), 1)

         # IF HIT > STOP AT COLLISION > REFLECT
	else : 

		# INITIAL CAST STOP
		to = result["position"]
		line(from, to, Color(1, 0, 0), 1)

		# NEW CAST REFLECT
		var normal = result["normal"]
		var reflect = (from-to).reflect(normal) * cast_length
		from = result["position"]
		to = result["position"] + reflect
		query = PhysicsRayQueryParameters3D.create(from, to, collision_mask, [self])
		line(from, to, Color(1, 0, 0), 1)

So after looking around the internet I finally got it working (tested in gd4.2). Here is the code :


extends CharacterBody3D

func _process(delta):
	var space_state = get_world_3d().direct_space_state
	reflectLaser(space_state)
	
func reflectLaser(space_state):
	var max_reflections :int = 3
	var cast_length = 100
	var from : Vector3
	var to : Vector3
	var query : PhysicsRayQueryParameters3D
	var result : Dictionary
	var normal : Vector3
	var reflect : Vector3
	
	from = marker3d.global_position
	to = marker3d.to_global(Vector3(0,0,-cast_length))
	query = PhysicsRayQueryParameters3D.create(from, to, collision_mask, [self])
	result = space_state.intersect_ray(query)
	
	if result:
		line(from, result["position"], Color(1, 0, 0), 1)
	else:
		line(from, to, Color(1, 0, 0), 1)
	
	if !result:
		return
	
	var incident = to - from
	var cross_vec = incident.cross(result.normal)
	var tangent_vec = result.normal.cross(cross_vec).normalized()
	var reflected_vec = tangent_vec * (incident.dot(tangent_vec)) + result.normal * (-1 * incident.dot(result.normal))
	#line(reflected_vec, result["position"] + reflected_vec, Color(1, 0, 0), 1)

	for i in range(1, max_reflections):
		from = result.position
		to = result.position + reflected_vec.normalized() * cast_length
		query = PhysicsRayQueryParameters3D.create(from, to, collision_mask, [self])
		result = space_state.intersect_ray(query)
		
		if result:
			line(from, result.position, Color(1, 0, 0), 1)
		else:
			line(from, to, Color(1, 0, 0), 1)
			
		if !result:
			return
			
		incident = to - from
		cross_vec = incident.cross(result.normal)
		tangent_vec = result.normal.cross(cross_vec).normalized()
		reflected_vec = tangent_vec * (incident.dot(tangent_vec)) + result.normal * (-1 * incident.dot(result.normal))

		i += 1
		if i >= max_reflections:
			break
			
func line():
	#your draw line function for visual

note: I have a Marker3D for the laser to shoot from.
credits : https://www.reddit.com/r/godot/comments/q8zevk/i_completed_assignments_46_from_freya_holmérs/

Any suggestion for improvement on the code is welcomed. :slightly_smiling_face:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.