面上の点 ray_start から launch_dir へ光線を飛ばし、box 境界の反射を経て最初に当たる panel を返す。
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(mesh_type), | intent(in) | :: | mesh | |||
| class(photo_raycast_config), | intent(in) | :: | sim | |||
| real(kind=dp), | intent(in) | :: | ray_start(3) | |||
| real(kind=dp), | intent(in) | :: | launch_dir(3) | |||
| logical, | intent(in) | :: | use_periodic2_mode | |||
| real(kind=dp), | intent(out) | :: | hit_pos(3) | |||
| real(kind=dp), | intent(out) | :: | hit_normal(3) | |||
| integer(kind=i32), | intent(out) | :: | hit_elem | |||
| logical, | intent(out) | :: | emitted |
要素に当たったとき |
||
| integer(kind=i32), | intent(out) | :: | collision_status |
衝突照会の status( |
||
| integer(kind=i32), | intent(out) | :: | bounce_count |
衝突照会の status( |
subroutine cast_photo_ray( & mesh, sim, ray_start, launch_dir, use_periodic2_mode, hit_pos, hit_normal, hit_elem, emitted, collision_status, & bounce_count & ) type(mesh_type), intent(in) :: mesh class(photo_raycast_config), intent(in) :: sim real(dp), intent(in) :: ray_start(3), launch_dir(3) logical, intent(in) :: use_periodic2_mode real(dp), intent(out) :: hit_pos(3), hit_normal(3) integer(i32), intent(out) :: hit_elem, collision_status, bounce_count logical, intent(out) :: emitted real(dp), parameter :: eps = 1.0d-12 real(dp) :: ray_pos(3), ray_dir(3), seg_end(3), boundary_probe(3), boundary_dir(3), surf_normal(3) logical :: reached_boundary, alive type(hit_info) :: hit hit_pos = 0.0_dp hit_normal = 0.0_dp hit_elem = -1_i32 emitted = .false. collision_status = collision_query_ok ray_dir = launch_dir ray_pos = ray_start + ray_dir*eps alive = .true. bounce_count = 0_i32 do while (alive .and. bounce_count <= sim%raycast_max_bounce) call step_ray_to_boundary(sim%box_min, sim%box_max, ray_pos, ray_dir, seg_end, reached_boundary) if (.not. reached_boundary) exit call find_first_hit( & mesh, ray_pos, seg_end, hit, sim=sim, box_min=sim%box_min, box_max=sim%box_max, & require_elem_inside=.true., status=collision_status & ) if (collision_status /= collision_query_ok) return if (hit%has_hit) then surf_normal = mesh%normals(:, hit%elem_idx) if (dot_product(surf_normal, ray_dir) > 0.0_dp) surf_normal = -surf_normal if (use_periodic2_mode) then hit_pos = hit%pos_wrapped + surf_normal*eps call canonicalize_periodic_emission_position(sim, hit_pos) else hit_pos = hit%pos + surf_normal*eps end if hit_normal = surf_normal hit_elem = hit%elem_idx emitted = .true. return end if boundary_probe = seg_end + ray_dir*eps boundary_dir = ray_dir call apply_ray_box_boundary(sim, boundary_probe, boundary_dir, alive) if (.not. alive) exit ray_dir = boundary_dir/sqrt(sum(boundary_dir*boundary_dir)) ray_pos = boundary_probe + ray_dir*eps bounce_count = bounce_count + 1_i32 end do end subroutine cast_photo_ray