コード例 #1
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
/* @param t t distance
 * @return 1 means hit, otherwise 0
 */
static int raySphereIntersection(const point3 ray_e,
                                 const point3 ray_d,
                                 const sphere *sph,
                                 intersection *ip, double *t1)
{
    point3 l;
    subtract_vector(sph->center, ray_e, l);
    double s = dot_product(l, ray_d);
    double l2 = dot_product(l, l);
    double r2 = sph->radius * sph->radius;

    if (s < 0 && l2 > r2)
        return 0;
    float m2 = l2 - s * s;
    if (m2 > r2)
        return 0;
    float q = sqrt(r2 - m2);
    *t1 = (l2 > r2) ? (s - q) : (s + q);
    /* p = e + t1 * d */
    multiply_vector(ray_d, *t1, ip->point);
    add_vector(ray_e, ip->point, ip->point);

    subtract_vector(ip->point, sph->center, ip->normal);
    normalize(ip->normal);
    if (dot_product(ip->normal, ray_d) > 0.0)
        multiply_vector(ip->normal, -1, ip->normal);
    return 1;
}
コード例 #2
0
void spacing_simulator_step(spacing_simulator *ss) {
    linked_list* vertices = ss->vg->vertices;
    linked_list* edges = ss->vg->edges;
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        v1->sim_data.speed = subtract_vector(make_vector_2d(400, 300), v1->position);
        v1->sim_data.speed = multiply_vector(normalize(v1->sim_data.speed), ss->origin_point_force);
        //debug_vector2d(v1->position, "POSITION");
        //debug_vector2d(v1->sim_data.speed, "SPEED");
        //debug("VVVVVVVVVV\n");
    }
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        for(node* j = i->next;j != NULL;j = j->next){
            visual_vertex* v2 = (visual_vertex*)j->element;
            vector_2d speed1 = subtract_vector(v1->position, v2->position);
            vector_2d speed2 = subtract_vector(v2->position, v1->position);
            float distance = calculate_distance(v1->position, v2->position);
            float force_factor = 100-distance;
            force_factor = (force_factor > 0 ? force_factor : 0)*2;
            speed1 = normalize(speed1);
            speed2 = normalize(speed2);
            speed1 = multiply_vector(speed1, force_factor);
            speed2 = multiply_vector(speed2, force_factor);
            v1->sim_data.speed = add_vector(v1->sim_data.speed, speed1);
            v2->sim_data.speed = add_vector(v2->sim_data.speed, speed2);
            //debug_vector2d(speed1, "SPEED1");
            //debug_vector2d(speed2, "SPEED2");
        }
    }
    for(node* i = edges->first;i != NULL;i = i->next){
        visual_edge* e = (visual_edge*)i->element;
        vector_2d pos1 = e->v1->position;
        vector_2d pos2 = e->v2->position;
        float distance = calculate_distance(pos1, pos2);
        vector_2d direction1 = normalize(subtract_vector(pos2, pos1));
        vector_2d direction2 = normalize(subtract_vector(pos1, pos2));
        vector_2d speed1 = multiply_vector(direction1, distance*distance/500);
        vector_2d speed2 = multiply_vector(direction2, distance*distance/500);
        e->v1->sim_data.speed = add_vector(e->v1->sim_data.speed, speed1);
        e->v2->sim_data.speed = add_vector(e->v2->sim_data.speed, speed2);
    }
    for(node* i = vertices->first; i != NULL;i = i->next){
        visual_vertex* v1 = (visual_vertex*)i->element;
        v1->sim_data.speed = multiply_vector(v1->sim_data.speed, ss->friction_factor);
        v1->position = add_vector(v1->position, v1->sim_data.speed);
    }
}
コード例 #3
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
/* @param d direction of ray
 * @param w basic vectors
 */
static void rayConstruction(point3 d, const point3 u, const point3 v,
                            const point3 w, unsigned int i, unsigned int j,
                            const viewpoint *view, unsigned int width,
                            unsigned int height)
{
    double xmin = -0.0175;
    double ymin = -0.0175;
    double xmax =  0.0175;
    double ymax =  0.0175;
    double focal = 0.05;

    point3 u_tmp, v_tmp, w_tmp, s;

    double w_s = focal;
    double u_s = xmin + ((xmax - xmin) * (float) i / (width - 1));
    double v_s = ymax + ((ymin - ymax) * (float) j / (height - 1));

    /* s = e + u_s * u + v_s * v + w_s * w */
    multiply_vector(u, u_s, u_tmp);
    multiply_vector(v, v_s, v_tmp);
    multiply_vector(w, w_s, w_tmp);
    add_vector(view->vrp, u_tmp, s);
    add_vector(s, v_tmp, s);
    add_vector(s, w_tmp, s);

    /* p(t) = e + td = e + t(s - e) */
    subtract_vector(s, view->vrp, d);
    normalize(d);
}
コード例 #4
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
/* @param d direction of the ray into intersection
 * @param l direction of intersection to light
 * @param n surface normal
 */
static void compute_specular_diffuse(double *diffuse,
                                     double *specular,
                                     const point3 d, const point3 l,
                                     const point3 n, double phong_pow)
{
    point3 d_copy, l_copy, middle, r;

    /* Calculate vector to eye V */
    COPY_POINT3(d_copy, d);
    multiply_vector(d_copy, -1, d_copy);
    normalize(d_copy);

    /* Calculate vector to light L */
    COPY_POINT3(l_copy, l);
    multiply_vector(l_copy, -1, l_copy);
    normalize(l_copy);

    /* Calculate reflection direction R */
    double tmp = dot_product(n, l_copy);
    multiply_vector(n, tmp, middle);
    multiply_vector(middle, 2, middle);
    subtract_vector(middle, l_copy, r);
    normalize(r);

    /* diffuse = max(0, dot_product(n, -l)) */
    *diffuse = MAX(0, dot_product(n, l_copy));

    /* specular = (dot_product(r, -d))^p */
    *specular = pow(MAX(0, dot_product(r, d_copy)), phong_pow);
}
コード例 #5
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
/* reference: https://www.opengl.org/sdk/docs/man/html/refract.xhtml */
static void refraction(point3 t, const point3 I, const point3 N,
                       double n1, double n2)
{
    double eta = n1 / n2;
    double dot_NI = dot_product(N,I);
    double k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
    if (k < 0.0 || n2 <= 0.0)
        t[0] = t[1] = t[2] = 0.0;
    else {
        point3 tmp;
        multiply_vector(I, eta, t);
        multiply_vector(N, eta * dot_NI + sqrt(k), tmp);
        subtract_vector(t, tmp, t);
    }
}
コード例 #6
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
/* @return 1 means hit, otherwise 0; */
static int rayRectangularIntersection(const point3 ray_e,
                                      const point3 ray_d,
                                      rectangular *rec,
                                      intersection *ip, double *t1)
{
    point3 e01, e03, p;
    subtract_vector(rec->vertices[1], rec->vertices[0], e01);
    subtract_vector(rec->vertices[3], rec->vertices[0], e03);

    cross_product(ray_d, e03, p);

    double det = dot_product(e01, p);

    /* Reject rays orthagonal to the normal vector.
     * I.e. rays parallell to the plane.
     */
    if (det < 1e-4)
        return 0;

    double inv_det = 1.0 / det;

    point3 s;
    subtract_vector(ray_e, rec->vertices[0], s);

    double alpha = inv_det * dot_product(s, p);

    if ((alpha > 1.0) || (alpha < 0.0))
        return 0;

    point3 q;
    cross_product(s, e01, q);

    double beta = inv_det * dot_product(ray_d, q);
    if ((beta > 1.0) || (beta < 0.0))
        return 0;

    *t1 = inv_det * dot_product(e03, q);

    if (alpha + beta > 1.0f) {
        /* for the second triangle */
        point3 e23, e21;
        subtract_vector(rec->vertices[3], rec->vertices[2], e23);
        subtract_vector(rec->vertices[1], rec->vertices[2], e21);

        cross_product(ray_d, e21, p);

        det = dot_product(e23, p);

        if (det < 1e-4)
            return 0;

        inv_det = 1.0 / det;
        subtract_vector(ray_e, rec->vertices[2], s);

        alpha = inv_det * dot_product(s, p);
        if (alpha < 0.0)
            return 0;

        cross_product(s, e23, q);
        beta = inv_det * dot_product(ray_d, q);

        if ((beta < 0.0) || (beta + alpha > 1.0))
            return 0;

        *t1 = inv_det * dot_product(e21, q);
    }

    if (*t1 < 1e-4)
        return 0;

    COPY_POINT3(ip->normal, rec->normal);
    if (dot_product(ip->normal, ray_d)>0.0)
        multiply_vector(ip->normal, -1, ip->normal);
    multiply_vector(ray_d, *t1, ip->point);
    add_vector(ray_e, ip->point, ip->point);

    return 1;
}
コード例 #7
0
ファイル: raytracing.c プロジェクト: TempoJiJi/raytracing
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

/* @param background_color this is not ambient light */
void raytracing(void* args)
{
    arg *data = (arg*) args;
    point3 u, v, w, d;
    color object_color = { 0.0, 0.0, 0.0 };

    const viewpoint *view = (*data).View;
    color back = { 0.0 , 0.1 , 0.1 };
    uint8_t *pixels = data->pixels;
    int start_j,end_j;

    /*	Separate to count the pixels  */
    if(pthread_equal(pthread_self(),THREAD[0])) {
        start_j = 0;
        end_j = 128;
    } else if(pthread_equal(pthread_self(),THREAD[1])) {
        start_j = 128;
        end_j = 256;
    } else if(pthread_equal(pthread_self(),THREAD[2])) {
        start_j = 256;
        end_j = 384;
    } else if(pthread_equal(pthread_self(),THREAD[3])) {
        start_j = 384;
        end_j = 512;
    }

    /* calculate u, v, w */
    calculateBasisVectors(u, v, w, view);

    idx_stack stk;

    int factor = sqrt(SAMPLES);

    #pragma omp parallel for num_threads(64)	\
    private(stk), private(d),	\
    private(object_color)
    for (int j = start_j ; j < end_j; j++) {
        for (int i = 0 ; i < (*data).row; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, u, v, w,
                                i * factor + s / factor,
                                j * factor + s % factor,
                                view,
                                (*data).row * factor, (*data).col * factor);
                if (ray_color(view->vrp, 0.0, d, &stk,(*data).rectangulars,
                              (*data).spheres, (*data).lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += back[0];
                    g += back[1];
                    b += back[2];
                }
                pixels[((i + (j * (*data).row)) * 3) + 0] = r * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 1] = g * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
}
コード例 #8
0
ファイル: raytracing.c プロジェクト: oiz5201618/raytracing
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

static void *parallel (void* range1)
{
    Thread_range *range = (Thread_range *)range1;

    point3 d;
    idx_stack stk;
    color object_color = { 0.0, 0.0, 0.0 };

    for (int j = range->height1; j < range->height2; j++) {
        for (int i = 0; i < range->ptr->width; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, range->ptr->u,
				range->ptr->v, range->ptr->w,
                                i * range->ptr->factor + s / range->ptr->factor,
                                j * range->ptr->factor + s % range->ptr->factor,
                                range->ptr->view,
                                range->ptr->width * range->ptr->factor, 
				range->ptr->height * range->ptr->factor);
                if (ray_color(range->ptr->view->vrp, 0.0, d,
			      &(stk), range->ptr->rectangulars,
			      range->ptr->spheres,
                              range->ptr->lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += range->ptr->background_color[0];
                    g += range->ptr->background_color[1];
                    b += range->ptr->background_color[2];
                }
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 0] = r * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 1] = g * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
	return NULL;
}