cast_photo_ray Subroutine

public subroutine cast_photo_ray(mesh, sim, ray_start, launch_dir, use_periodic2_mode, hit_pos, hit_normal, hit_elem, emitted, collision_status, bounce_count)

面上の点 ray_start から launch_dir へ光線を飛ばし、box 境界の反射を経て最初に当たる panel を返す。

Arguments

Type IntentOptional 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

要素に当たったとき .true.。

integer(kind=i32), intent(out) :: collision_status

衝突照会の status(collision_query_ok 以外なら未完了)。

integer(kind=i32), intent(out) :: bounce_count

衝突照会の status(collision_query_ok 以外なら未完了)。 未完了時の bounce index。


Calls

proc~~cast_photo_ray~~CallsGraph proc~cast_photo_ray cast_photo_ray proc~apply_ray_box_boundary apply_ray_box_boundary proc~cast_photo_ray->proc~apply_ray_box_boundary proc~canonicalize_periodic_emission_position canonicalize_periodic_emission_position proc~cast_photo_ray->proc~canonicalize_periodic_emission_position proc~find_first_hit find_first_hit proc~cast_photo_ray->proc~find_first_hit proc~find_first_hit_base find_first_hit_base proc~find_first_hit->proc~find_first_hit_base proc~find_first_hit_periodic2 find_first_hit_periodic2 proc~find_first_hit->proc~find_first_hit_periodic2 proc~initialize_hit initialize_hit proc~find_first_hit->proc~initialize_hit proc~find_first_hit_base->proc~initialize_hit proc~find_first_hit_base_grid find_first_hit_base_grid proc~find_first_hit_base->proc~find_first_hit_base_grid proc~find_first_hit_base_linear find_first_hit_base_linear proc~find_first_hit_base->proc~find_first_hit_base_linear proc~resolve_box_filter_args resolve_box_filter_args proc~find_first_hit_base->proc~resolve_box_filter_args proc~find_first_hit_periodic2->proc~find_first_hit_base proc~find_first_hit_periodic2->proc~initialize_hit proc~point_inside_box_periodic2 point_inside_box_periodic2 proc~find_first_hit_periodic2->proc~point_inside_box_periodic2 proc~prefer_periodic_candidate prefer_periodic_candidate proc~find_first_hit_periodic2->proc~prefer_periodic_candidate proc~find_first_hit_periodic2->proc~resolve_box_filter_args proc~wrap_periodic2_point~2 wrap_periodic2_point proc~find_first_hit_periodic2->proc~wrap_periodic2_point~2 proc~bbox_inside_box bbox_inside_box proc~find_first_hit_base_grid->proc~bbox_inside_box proc~cell_id~2 cell_id proc~find_first_hit_base_grid->proc~cell_id~2 proc~coord_to_cell~2 coord_to_cell proc~find_first_hit_base_grid->proc~coord_to_cell~2 proc~lower_ascii lower_ascii proc~find_first_hit_base_grid->proc~lower_ascii proc~point_inside_box point_inside_box proc~find_first_hit_base_grid->proc~point_inside_box proc~segment_aabb_intersection_t segment_aabb_intersection_t proc~find_first_hit_base_grid->proc~segment_aabb_intersection_t proc~segment_bbox_overlap_precomputed segment_bbox_overlap_precomputed proc~find_first_hit_base_grid->proc~segment_bbox_overlap_precomputed proc~segment_triangle_intersect segment_triangle_intersect proc~find_first_hit_base_grid->proc~segment_triangle_intersect proc~find_first_hit_base_linear->proc~bbox_inside_box proc~find_first_hit_base_linear->proc~point_inside_box proc~find_first_hit_base_linear->proc~segment_bbox_overlap_precomputed proc~find_first_hit_base_linear->proc~segment_triangle_intersect proc~cross~3 cross proc~segment_triangle_intersect->proc~cross~3

Called by

proc~~cast_photo_ray~~CalledByGraph proc~cast_photo_ray cast_photo_ray proc~sample_photo_ray_slot sample_photo_ray_slot proc~sample_photo_ray_slot->proc~cast_photo_ray

Source Code

  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