Beispiel #1
0
void	render(t_rt *rt)
{
	int			x;
	int			y;
	float		increment_x;
	float		increment_y;
	t_camera	*camera;
	t_ray		ray;
	t_hit		hit;

	if (rt->rendered)
	{
		mlx_update(rt->gfx);
		return ;
	}

	camera = rt->scene->active_camera;

	if (camera == NULL)
		die("No main camera set.");
	
	increment_x = camera->viewplane.width / camera->resolution_width;
	increment_y = camera->viewplane.height / camera->resolution_height;

	vec3_copy(&ray.origin, &camera->position);

	y = 0;
	while (y < rt->height)
	{
		x = 0;
		while (x < rt->width)
		{
			set_ray_direction(&ray, camera, increment_x * x, increment_y * y);
			raycast(&ray, &hit, 2, NULL);

			if (hit.object != NULL)
				draw_pixel(rt->gfx, x, y, vec3_to_color(&hit.color));
			else
				draw_pixel(rt->gfx, x, y, 0x333333);
			x++;
		}
		y++;
	}

	rt->rendered = 1;
	mlx_update(rt->gfx);
}
/* Do the actual raytracing */
void raytrace(Image *src, Camera *camera, BlackHole *blackhole, KerrMetric *kerr) {
    
    // TODO: better to walk across local sky with spherical coordinates? I think this might warp the view because have effectively made the viewing plane curved...
    double arcLengthHoriz = camera->lensAngle;
    double arcLengthVert = ((double)src->rows/(double)src->cols)*arcLengthHoriz;
    
    double horizStep = arcLengthHoriz/src->cols;
    double vertStep = arcLengthVert/src->rows;
    
    double rayPhi, rayTheta;
    
    printf("arcLengthHoriz: %f\n", arcLengthHoriz);
    printf("arcLengthVert: %f\n", arcLengthVert);

    printf("Raytracing...\n\n");

    // walk along the local sky, shooting a ray for each pixel
    for (int row=0;row<src->rows;row++) {
        rayTheta = (M_PI/2) - arcLengthVert/2 + row*vertStep;
        for (int col=0;col<src->cols;col++) {
            
            rayPhi = (M_PI) + arcLengthHoriz/2 - col*horizStep;
            
            Ray ray;
            set_ray_location(&ray, rayTheta, rayPhi);   // direction of incoming ray in camera spherical coord
            set_ray_normal(&ray);                       // direction of incoming ray in camera Cartesian coord
            set_ray_direction(&ray, camera);            // direction of motion of incoming ray in camera Cartesian coord
            set_ray_momenta(&ray, kerr);
            
//            printf("Ray info:\n");
//            printf("    Theta, Phi: (%f, %f)\n", ray.theta, ray.phi);
//            printf("    Nx, Ny, Nz: (%f, %f, %f)\n", ray.Nx, ray.Ny, ray.Nz);
//            printf("    Fx, Fy, Fz: (%f, %f, %f)\n", ray.Fx, ray.Fy, ray.Fz);
//            printf("    Fr, Ftheta, Fphi: (%f, %f, %f)\n", ray.Fr, ray.Ftheta, ray.Fphi);
//            printf("    Pt, Pr, Ptheta, Pphi: (%f, %f, %f, %f)\n", ray.Pt, ray.Pr, ray.Ptheta, ray.Pphi);
//            printf("    Axial angular momentum (b): %f\n", ray.b);
//            printf("    Carter constant (q): %f\n\n", ray.q);

            // check, using the ray constants b and q, whether it came from the horizon or the celestial sphere
            // first though, need to calculate some condition requirements
            double b1, b2 = 0.0;
            double r1, r2 = 0.0;
            double q0 = 0.0;
            double r0 = 0.0;
            // localize some things, also precalculate to keep things pretty & readable
            double b = ray.b;
            double a = kerr->a;
            double q = ray.q;
            double cubeRoot2 = pow(2, 1/3.);    // 1.259921049894873...
            
            // calculate the radius bounds of unstably trapped photons
            r1 = 2.0*(1.0 + cos((2.0/3.0)*acos(-a)));
            r2 = 2.0*(1.0 + cos((2.0/3.0)*acos(a)));
            // printf("Radius interval of unstably trapped photons [r1, r2]: %f, %f\n", r1, r2);
            
            // calculate a constant of motion for photons on the radius bounds
            b2 = -((r1*r1*r1) - 3*r1*r1 + a*a*r1 + a*a) / (a*(r1 - 1));
            b1 = -((r2*r2*r2) - 3*r2*r2 + a*a*r2 + a*a) / (a*(r2 - 1));
            printf("b1, b2: %f, %f\n", b1, b2);
            
            
            // get the value of r0 from parametric equations b(r0) in order to calculate q(r0)
            double tmpQ = (a*a + a*b - 3);
            double tmp = pow(sqrt(108.0*tmpQ*tmpQ*tmpQ + (54 - 54.0*a*a)*(54 - 54.0*a*a)) - 54.0*a*a + 54.0, 1/3.);
            r0 = -(cubeRoot2*tmpQ / tmp) + (tmp / 3.0*cubeRoot2) + 1.0;
            
            // printf("r0: %f\n", r0);
            double r03 = r0*r0*r0;
            
            // calculate another constant of motion
            q0 = -(r03*(r03 - 6.0*r0*r0 + 9.0*r0 - 4.0*a*a)) / (a*a*(b - 1)*(b - 1));
            
            // printf("q0(r0): %f\n", q0);
            
            if ((b1 < b && b < b2) && q < q0) {
                // there are no radial turning points for this {b, q}
                if (ray.Pr > 0) {
                    // ray came from horizon
                    src->data[row][col].rgb[0] = 1.0;
                    src->data[row][col].rgb[1] = 0.0;
                    src->data[row][col].rgb[2] = 0.0;
                } else {
                    // ray came from celestial sphere
                    src->data[row][col].rgb[0] = 0.0;
                    src->data[row][col].rgb[1] = 1.0;
                    src->data[row][col].rgb[2] = 0.0;
//                    src->data[row][col].rgb[0] = 176.0/255;
//                    src->data[row][col].rgb[1] = 196.0/255;
//                    src->data[row][col].rgb[2] = 222.0/255;
                }
                
            } else {
                // there are two radial turning points...
                // need to calculate some roots of equations for a null geodesic
                double rUp = 0.0;
                double delta = kerr->delta;
            
                double P = sqrt(delta*((b-a)*(b-a) + q));
                printf("P: %f\n", P);
                printf("a: %f\n", a);
                // the two positive real roots of R(r) = 0; we want the bigger one
                double rUp1 = -a*a - P + a*b;
                double rUp2 = -a*a + P + a*b;
                
                printf("rUp1: sqrt(%f)\n", rUp1);
                printf("rUp2: sqrt(%f)\n\n", rUp2);
                
                if (rUp1 > rUp2) {
                    rUp = rUp1;
                } else {
                    rUp = rUp2;
                }
                           
                // printf("rUp: %f\n", rUp);
                

                if (camera->location[0] >= rUp) {
                    // ray came from celestial sphere
                    src->data[row][col].rgb[0] = 0.0;
                    src->data[row][col].rgb[1] = 0.0;
                    src->data[row][col].rgb[2] = 1.0;
//                    src->data[row][col].rgb[0] = 176.0/255;
//                    src->data[row][col].rgb[1] = 196.0/255;
//                    src->data[row][col].rgb[2] = 222.0/255;
                } else {
                    // ray came from horizon
                    src->data[row][col].rgb[0] = 0.5;
                    src->data[row][col].rgb[1] = 0.0;
                    src->data[row][col].rgb[2] = 0.5;
                }
            }
            

            
        }
        
    }
  
}