* @brief Returns an rgb image containing the raytraced black hole from the * camera rays, spacetime metric, objects living in the space, and background * * @param initial_pos initial position from where the rays are launched * @param initial_vel initial velocities (directions) the rays have * @param objects the objects the rays can collide with * @param background the background of the scene
| 915 | * @return af::array |
| 916 | */ |
| 917 | af::array generate_image(const af::array& initial_pos, |
| 918 | const af::array& initial_vel, |
| 919 | const std::vector<std::unique_ptr<Object> >& objects, |
| 920 | const Background& background, uint32_t width, |
| 921 | uint32_t height, double time, double tol, |
| 922 | uint32_t checks = 10) { |
| 923 | uint32_t lines = initial_pos.dims()[1]; |
| 924 | |
| 925 | auto def_step = 0.5 * pow(tol, 0.25); |
| 926 | auto dt = af::constant(def_step, 1, lines, f64); |
| 927 | auto t = af::constant(0.0, 1, lines, f64); |
| 928 | auto index = af::iota(lines); |
| 929 | auto selected = t < time; |
| 930 | |
| 931 | auto result = af::constant(0, lines, 3, f32); |
| 932 | |
| 933 | auto pos = initial_pos; |
| 934 | auto vel = initial_vel; |
| 935 | |
| 936 | af::Window window{(int)width, (int)height, "Black Hole Raytracing"}; |
| 937 | |
| 938 | af::array bg_col = af::constant(0.f, lines, 3); |
| 939 | af::array begin_pos, end_pos; |
| 940 | af::array bh_nohit; |
| 941 | |
| 942 | if (scene != Scene::ROTATE_BH) |
| 943 | begin_pos = sph_to_cart_position(pos(af::seq(1, 3), af::span)); |
| 944 | else |
| 945 | begin_pos = oblate_to_cart_position(pos(af::seq(1, 3), af::span)); |
| 946 | end_pos = begin_pos; |
| 947 | |
| 948 | int i = 0; |
| 949 | |
| 950 | while (t.dims()[1] != 0 && af::anyTrue<bool>(t < time) && |
| 951 | af::anyTrue<bool>(dt != 0.0)) { |
| 952 | // Displays the current progress and approximate time needed to finish |
| 953 | // it |
| 954 | status_bar((lines - t.dims()[1]) * time + |
| 955 | af::sum<double>(af::clamp(t, 0.0, time)), |
| 956 | time * lines, "Progress:"); |
| 957 | |
| 958 | // RK34 method for second order differential equation |
| 959 | auto dt2 = dt * dt; |
| 960 | auto k1 = geodesics(pos, vel); |
| 961 | auto k2 = geodesics(pos + vel * dt / 4.0 + k1 * dt2 / 32.0, |
| 962 | vel + k1 * dt / 4.0); |
| 963 | auto k3 = geodesics(pos + vel * dt / 2.0 + (k1 + k2) * dt2 / 16.0, |
| 964 | vel + k2 * dt / 2.0); |
| 965 | auto k4 = geodesics(pos + vel * dt + (k1 - k2 + k3 * 2.0) * dt2 / 4.0, |
| 966 | vel + (k1 - k2 * 2.0 + 2.0 * k3) * dt); |
| 967 | |
| 968 | auto diff4 = (k1 + k2 * 8.0 + k3 * 2.0 + k4) / 24.0; |
| 969 | auto diff3 = (k2 * 8.0 + k4) / 18.0; |
| 970 | |
| 971 | auto err = (af::max)(af::abs(diff4 - diff3), 0) * dt2; |
| 972 | auto maxerr = tol * (1.0 + (af::max)(af::abs(pos), 0)); |
| 973 | |
| 974 | auto rdt = af::constant(0, 1, dt.dims()[1], f64); |
no test coverage detected