/* * Returns the normal vector of a cone on a given position. The vector is * already normalized. * * posn: Position at which the intersection occured * cone_ptr: Pointer to a cone figure. */ Vector get_cone_normal_vector(Vector posn, void* cone_ptr) { Cone cone = *((Cone*) cone_ptr); Vector border, normal_vec; border = subtract_vectors(posn, cone.anchor); long double distance = normalize_vector(&border); if(do_dot_product(border, cone.direction) < 0) distance *= -1; normal_vec = multiply_vector(1.0/ fabsl(distance), subtract_vectors(posn, get_ray_position(cone.anchor, cone.direction, distance * sqrt(2)))); normalize_vector(&normal_vec); return normal_vec; }
static void dye_fun(double const coords[3], double* v) { double x[3]; double const l[3] = {.25, .5, 0}; double const r[3] = {.75, .5, 0}; double dir = 1; subtract_vectors(coords, l, x, 3); if (vector_norm(x, 3) > .25) { dir = -1; subtract_vectors(coords, r, x, 3); } if (vector_norm(x, 3) > .25) { v[0] = 0; return; } v[0] = 4 * dir * (.25 - vector_norm(x, 3)); }
static void warp_fun(double const* coords, double* v) { double x[3]; double const mid[3] = {.5, .5, 0}; subtract_vectors(coords, mid, x, 3); double polar_a = atan2(x[1], x[0]); double polar_r = vector_norm(x, 3); double rot_a = 0; if (polar_r < .5) rot_a = the_rotation * (2 * (.5 - polar_r)); double dest_a = polar_a + rot_a; double dst[3]; dst[0] = cos(dest_a) * polar_r; dst[1] = sin(dest_a) * polar_r; dst[2] = 0; subtract_vectors(dst, x, v, 3); }
/* * Returns a pointer to the intersection between a cone and a ray. * * eye: Position from which the ray is thrown. * dir_vec: Direction towards which the ray is thrown. Must be normalized. * object_ptr: Pointer to the Object struct that represents the cone. * length: Output parameter for the number of intersections found. */ void* get_cone_intersection(Vector eye, Vector dir_vec, void* object_ptr, int *length) { Cone* cone_ptr = (Cone*) ((Object*)object_ptr)->figure; long double termQD, termQE; Vector varD, varE, anchor_to_anchor; anchor_to_anchor = subtract_vectors(eye, cone_ptr->anchor); termQD = do_dot_product(cone_ptr->direction, dir_vec); termQE = do_dot_product(cone_ptr->direction, anchor_to_anchor); varD = subtract_vectors(multiply_vector(termQD, cone_ptr->direction), dir_vec); varE = get_ray_position(cone_ptr->anchor, subtract_vectors(multiply_vector(termQE, cone_ptr->direction), eye), 1); long double a = pow(varD.x, 2) + pow(varD.y, 2) + pow(varD.z, 2) - pow(cone_ptr->radius, 2) * pow(termQD, 2); long double b = 2 * (do_dot_product(varE, varD) - pow(cone_ptr->radius, 2) * termQD * termQE); long double c = pow(varE.x, 2) + pow(varE.y, 2) + pow(varE.z, 2) - pow(cone_ptr->radius, 2) * pow(termQE, 2); return get_cyl_cone_intersection(a, b, c, eye, dir_vec, object_ptr, length); }
void calculate_intensity(struct vector *c, struct constants *k, color ambient, struct light *light, struct vector *p, struct vector *n, struct vector *v) { /* I = Ke + Ia Ka + Ip Kd (->L * ->N) + Ip Ks [(2->N(->L * ->N)- ->L) * ->V] */ double dotd, dots; struct vector l, tmp; l = *p; subtract_vectors(&l, &light->l); normalize(&l); dotd = dot(&l, n); if (dotd < 0) { dotd = dots = 0; goto add_terms; } tmp = *n; scalar_mult(2 * dotd, &tmp); subtract_vectors(&tmp, &l); dots = dot(&tmp, v); if (dots < 0) dots = 0; add_terms: ctov(c, k->e); ctov(&tmp, ambient); tmp.x *= k->r[Ka]; tmp.y *= k->g[Ka]; tmp.z *= k->b[Ka]; add_vectors(c, &tmp); ctov(&tmp, light->c); tmp.x *= k->r[Kd] * dotd + k->r[Ks] * dots; tmp.y *= k->g[Kd] * dotd + k->g[Kd] * dots; tmp.z *= k->b[Kd] * dotd + k->b[Ks] * dots; add_vectors(c, &tmp); }
roots intersection_with_ray(sphere s, ray r) { // We need r in sphere-coordinates ray r_sphere_coordinates; matrix s_transform_inverse = inverse_of_matrix(s.transform); r_sphere_coordinates.point = transform_point(s_transform_inverse, r.point); r_sphere_coordinates.direction = transform_ray(s_transform_inverse, r.direction); vector point_minus_center = subtract_vectors(r_sphere_coordinates.point, s.center); float polynomials[3]; polynomials[2] = square_of_magnitude_of_vector(r_sphere_coordinates.direction); polynomials[1] = 2 * dot_product(point_minus_center, r_sphere_coordinates.direction); polynomials[0] = square_of_magnitude_of_vector(point_minus_center) - s.radius * s.radius; roots quad_roots; quad_roots = quadratic(polynomials[2], polynomials[1], polynomials[0]); return quad_roots; }
/* * Adds the effect of the given light over the given intersection. * * light: Light that is being applied. * inter: Intersection over which the light is being applied. * normal_vec: Normal vector of the intersection point. It is passed by as a * parameter for optimization purposes. * rev_dir_vec: Reverse vector of the direction of the ray that comes from the * eye. It is passed by as a parameter for optimization purposes. * all_lights_color: Accumulated amount of light sources effect. The effect of * the given light is added to this total. * all_lights_color: Accumulated amount of the specular light effect. The * specular effect of the given light is added to this total. * conf: Configuration of the scene. */ void apply_light_source(Light light, Intersection inter, Vector normal_vec, Vector rev_dir_vec, Color *all_lights_color, long double *all_spec_light, SceneConfig conf) { Vector light_vec; long double light_distance, illum_cos, att_factor, spec_cos; Color light_filter; Intersection* shadow_inter; int shadow_i, shadow_inter_length; Object shadow_obj; // Find the vector that points from the intersection point to the light // source, and normalize it light_vec = subtract_vectors(light.anchor, inter.posn); light_distance = normalize_vector(&light_vec); // We check for any object making a shadow from that light light_filter = (Color){ .red = 1.0, .green = 1.0, .blue = 1.0 };; shadow_inter = get_intersections(inter.posn, light_vec, &shadow_inter_length, conf); // If the intersection is beyond the light source, we ignore it if(shadow_inter) { // Object(s) is/are actually behind the light for(shadow_i = 0; shadow_i < shadow_inter_length && !is_color_empty(light_filter); shadow_i++) { if(shadow_inter[shadow_i].distance < light_distance) { shadow_obj = shadow_inter[shadow_i].obj; if(shadow_obj.translucency_material) { light_filter = multiply_color(shadow_obj.translucency_material, multiply_colors(light_filter, shadow_obj.color)); } else { light_filter = get_empty_color(); } } } if(!is_color_empty(light_filter)) { free(shadow_inter); shadow_inter = NULL; } } // If there aren't any shadows if(!shadow_inter) { illum_cos = do_dot_product(normal_vec, light_vec); // We only take it into account if the angle is lower than 90 degrees if(illum_cos > 0) { Vector light_mirror_vec = subtract_vectors(multiply_vector(2 * illum_cos, normal_vec), light_vec); // Attenuation factor, reduces the light energy depending on the distance att_factor = get_attenuation_factor(light, light_distance); spec_cos = do_dot_product(rev_dir_vec, light_mirror_vec); // We add the light source effect light_filter = multiply_color(illum_cos * inter.obj.light_material * att_factor, light_filter); *all_lights_color = add_colors(*all_lights_color, multiply_colors(light_filter, light.color)); // The specular light, is the white stain on the objects if(spec_cos > 0) { *all_spec_light += pow(spec_cos * inter.obj.specular_material * att_factor, inter.obj.specular_pow); } } } else free(shadow_inter); } /* * Gets the color of the intersection by calculating light intensity, * (which includes specular light, shadows, transparency, etc) * * light: Light for which the attenuation factor is calculated. * distance: Distance between the light and an illuminated spot. * mirror_level: Current level of reflection. * conf: Configuration of the scene. */ Color get_intersection_color(Vector eye, Vector dir_vec, Intersection *inter_list, int inter_length, int mirror_level, int transparency_level, SceneConfig conf) { Intersection inter; int light_index; long double spec_light_factor, mirror_factor, transparency_factor; Vector normal_vec, rev_dir_vec, reflection_vec; Light light; Color all_lights_color, color_found, reflection_color, transparency_color, final_color; inter = inter_list[transparency_level]; // Light intensity all_lights_color = (Color){ .red = 0.0, .green = 0.0, .blue = 0.0 }; // Specular light intensity spec_light_factor = 0.0; normal_vec = get_normal_vector(&inter); // Pick up the normal vector that is pointing to the eye if(do_dot_product(normal_vec, dir_vec) > 0) normal_vec = multiply_vector(-1, normal_vec); // Initialize reverse direction vector for mirrors and specular light rev_dir_vec = multiply_vector(-1, dir_vec); for(light_index = 0; light_index < conf.lights_length; light_index++) { light = conf.lights[light_index]; apply_light_source(light, inter, normal_vec, rev_dir_vec, &all_lights_color, &spec_light_factor, conf); } // We add the environmental light of the scene all_lights_color = add_colors(all_lights_color, multiply_color(inter.obj.light_ambiental, conf.environment_light)); if(spec_light_factor > 1.0) spec_light_factor = 1.0; color_found = multiply_colors(all_lights_color, inter.obj.color); // Specular light gives a color between enlightened color and the light color. color_found.red += (1 - color_found.red) * spec_light_factor; color_found.green += (1 - color_found.green) * spec_light_factor; color_found.blue += (1 - color_found.blue) * spec_light_factor; // Get transparency color transparency_factor = inter.obj.transparency_material; if (transparency_level < conf.max_transparency_level && transparency_factor > 0.0) { if(transparency_level + 1 < inter_length) { transparency_color = get_intersection_color(eye,dir_vec,inter_list,inter_length,0,transparency_level+1, conf); } else { transparency_color = conf.background; } } else { transparency_factor = 0.0; transparency_color = get_empty_color(); } // Get reflection color mirror_factor = inter.obj.mirror_material; if (mirror_level < conf.max_mirror_level && mirror_factor > 0.0) { reflection_vec = subtract_vectors(multiply_vector(2 * do_dot_product(normal_vec, rev_dir_vec), normal_vec), rev_dir_vec); reflection_color = get_color(inter.posn, reflection_vec, mirror_level + 1, conf); } else { mirror_factor = 0; reflection_color = get_empty_color(); } // Calculate final color transparency_color = multiply_color(transparency_factor, transparency_color); reflection_color = multiply_color((1.0-transparency_factor) * mirror_factor, reflection_color); color_found = multiply_color((1.0-transparency_factor) * (1.0-mirror_factor), color_found); final_color = add_colors(transparency_color, add_colors(reflection_color, color_found)); return final_color; } /* * Returns the color that is seen from the position 'eye' when looking at the * tridimensional scene towards the direction 'dir_vec'. * * eye: Position from which the scene is seen. * dir_vec: Direction at which the eye is looking. This vector must be normalized. * mirror_level: Current level of reflection. * conf: Configuration of the scene. */ Color get_color(Vector eye, Vector dir_vec, int mirror_level, SceneConfig conf) { Intersection *inter_list; Color color; // Get intersections on the given direction. Intersections are ordered from the nearest to the farthest. int inter_list_length; inter_list = get_intersections(eye, dir_vec, &inter_list_length, conf); // If we don't find an intersection we return the background, otherwise we check for the intersections's color. if (!inter_list) return conf.background; color = get_intersection_color(eye, dir_vec, inter_list, inter_list_length, mirror_level, 0, conf); free(inter_list); return color; }
void horizontal_convert(polygon poly, struct screen *s, enum shading_t type, struct constants *k, color ambient, struct light *l, struct vector norm[3], struct vector *v) { const double y0 = poly[0]->y, y1 = poly[1]->y, y2 = poly[2]->y; int ib, im, it; int dy_bt, dy_bm, dy_mt; double dx; struct vector pb, pm, pt; struct vector dp_dy_bt, dp_dy_bm, dp_dy_mt; struct vector p0, p1; edge e = {&p0, &p1}; struct vector p; double dz_dx; struct vector cb, cm, ct; struct vector dc_dy_bt, dc_dy_bm, dc_dy_mt; struct vector c0, c1; struct vector c; struct vector dc_dx; struct vector dn_dy_bt, dn_dy_bm, dn_dy_mt; struct vector n0, n1; struct vector n; struct vector dn_dx; if (y0 <= y1 && y1 <= y2) { ib = 0; im = 1; it = 2; } else if (y0 <= y2 && y2 <= y1) { ib = 0; im = 2; it = 1; } else if (y1 <= y0 && y0 <= y2) { ib = 1; im = 0; it = 2; } else if (y1 <= y2 && y2 <= y0) { ib = 1; im = 2; it = 0; } else if (y2 <= y0 && y0 <= y1) { ib = 2; im = 0; it = 1; } else { ib = 2; im = 1; it = 0; } pb = *poly[ib]; pm = *poly[im]; pt = *poly[it]; pb.y = (int)pb.y; pm.y = (int)pm.y; pt.y = (int)pt.y; dy_bt = pt.y - pb.y; dy_bm = pm.y - pb.y; dy_mt = pt.y - pm.y; p0 = pb; p1 = pb.y != pm.y? pb : pm; dp_dy_bt = pt; subtract_vectors(&dp_dy_bt, &pb); scalar_div(dy_bt, &dp_dy_bt); dp_dy_bm = pm; subtract_vectors(&dp_dy_bm, &pb); scalar_div(dy_bm, &dp_dy_bm); dp_dy_mt = pt; subtract_vectors(&dp_dy_mt, &pm); scalar_div(dy_mt, &dp_dy_mt); switch (type) { case FLAT: calculate_centroid(&p, poly); calculate_intensity(&c, k, ambient, l, &p, norm, v); for (p.y = pb.y; p.y <= pt.y; p.y++) { p0.y = p1.y = p.y; draw_line(e, s, vtoc(&c) ); add_vectors(&p0, &dp_dy_bt); add_vectors(&p1, (p.y < pm.y? &dp_dy_bm : &dp_dy_mt) ); } break; case GOROUD: calculate_intensity(&cb, k, ambient, l, poly[ib], norm + ib, v); calculate_intensity(&cm, k, ambient, l, poly[im], norm + im, v); calculate_intensity(&ct, k, ambient, l, poly[it], norm + it, v); c0 = cb; c1 = (pb.y != pm.y? cb : cm); dc_dy_bt = ct; subtract_vectors(&dc_dy_bt, &cb); scalar_div(dy_bt, &dc_dy_bt); dc_dy_bm = cm; subtract_vectors(&dc_dy_bm, &cb); scalar_div(dy_bm, &dc_dy_bm); dc_dy_mt = ct; subtract_vectors(&dc_dy_mt, &cm); scalar_div(dy_mt, &dc_dy_mt); for (p.y = pb.y; p.y <= pt.y; p.y++) { dx = p1.x - p0.x; dc_dx = c1; subtract_vectors(&dc_dx, &c0); scalar_div(dx, &dc_dx); dz_dx = (p1.z - p0.z) / dx; p.x = p0.x; p.z = p0.z; c = c0; while (1) { plot(s, vtoc(&c), &p); if (p0.x < p1.x) { p.z += dz_dx; add_vectors(&c, &dc_dx); p.x++; if (p.x > p1.x) break; } else { p.z -= dz_dx; subtract_vectors(&c, &dc_dx); p.x--; if (p.x < p1.x) break; } } add_vectors(&p0, &dp_dy_bt); add_vectors(&c0, &dc_dy_bt); if (p.y < pm.y) { add_vectors(&p1, &dp_dy_bm); add_vectors(&c1, &dc_dy_bm); } else { add_vectors(&p1, &dp_dy_mt); add_vectors(&c1, &dc_dy_mt); } } break; case PHONG: n0 = norm[ib]; n1 = norm[pb.y != pm.y? ib : im]; dn_dy_bt = norm[it]; subtract_vectors(&dn_dy_bt, norm + ib); scalar_div(dy_bt, &dn_dy_bt); dn_dy_bm = norm[im]; subtract_vectors(&dn_dy_bm, norm + ib); scalar_div(dy_bm, &dn_dy_bm); dn_dy_mt = norm[it]; subtract_vectors(&dn_dy_mt, norm + im); scalar_div(dy_mt, &dn_dy_mt); for (p.y = pb.y; p.y <= pt.y; p.y++) { dx = p1.x - p0.x; dn_dx = n1; subtract_vectors(&dn_dx, &n0); scalar_div(dx, &dn_dx); dz_dx = (p1.z - p0.z) / dx; p = p0; n = n0; while (1) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); if (p0.x < p1.x) { p.z += dz_dx; add_vectors(&n, &dn_dx); p.x++; if (p.x > p1.x) break; } else { p.z -= dz_dx; subtract_vectors(&n, &dn_dx); p.x--; if (p.x < p1.x) break; } } add_vectors(&p0, &dp_dy_bt); add_vectors(&n0, &dn_dy_bt); if (p.y < pm.y) { add_vectors(&p1, &dp_dy_bm); add_vectors(&n1, &dn_dy_bm); } else { add_vectors(&p1, &dp_dy_mt); add_vectors(&n1, &dn_dy_mt); } } break; } }
void draw_shaded_edge(int x, polygon poly, struct screen *s, enum shading_t type, struct constants *k, color ambient, struct light *l, struct vector norm[3], struct vector *v) { int i, j, tmp; struct vector p, *p1, dp; int d; double derz; /* derz: derivative of z */ struct vector n, dern; struct vector c; switch (x) { case 0: i = 0; j = 1; break; case 1: i = 1; j = 2; break; case 2: i = 2; j = 0; break; } //swap points so we're always draing left to right if (poly[i]->x > poly[j]->x) { tmp = i; i = j; j = tmp; } p = *poly[i]; p1 = poly[j]; dp = *p1; subtract_vectors(&dp, &p); //positive slope: Octants 1, 2 (5 and 6) if (dp.y > 0 ) { //slope < 1: Octant 1 (5) if (dp.x > dp.y) { d = 2 * dp.y - dp.x; derz = dp.z / dp.x; n = norm[i]; dern = norm[j]; subtract_vectors(&dern, &n); scalar_div(dp.x, &dern); for (; p.x <= p1->x; p.x++) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); p.z += derz; add_vectors(&n, &dern); if ( d < 0 ) d += 2 * dp.y; else { p.y++; d += 2 * (dp.y - dp.x); } } } //slope > 1: Octant 2 (6) else { d = dp.y - 2 * dp.x; derz = dp.z / dp.y; n = norm[i]; dern = norm[j]; subtract_vectors(&dern, &n); scalar_div(dp.y, &dern); for (; p.y <= p1->y; p.y++) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); p.z += derz; add_vectors(&n, &dern); if ( d > 0 ) d -= 2 * dp.x; else { p.x++; d += 2 * (dp.y - dp.x); } } } } //negative slope: Octants 7, 8 (3 and 4) //slope > -1: Octant 8 (4) else { if ( dp.x > fabs(dp.y) ) { d = 2 * dp.y + dp.x; derz = dp.z / dp.x; n = norm[i]; dern = norm[j]; subtract_vectors(&dern, &n); scalar_div(dp.x, &dern); for (; p.x <= p1->x; p.x++) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); p.z += derz; add_vectors(&n, &dern); if ( d > 0 ) d += 2 * dp.y; else { p.y--; d += 2 * (dp.y + dp.x); } } } //slope < -1: Octant 7 (3) else { d = dp.y + 2 * dp.x; derz = dp.z / dp.y; n = norm[i]; dern = norm[j]; subtract_vectors(&dern, &n); scalar_div(dp.y, &dern); for (; p.y >= p1->y; p.y--) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); p.z -= derz; subtract_vectors(&n, &dern); if ( d < 0 ) d += 2 * dp.x; else { p.x++; d += 2 * (dp.y + dp.x); } } } } }
void vertical_convert(polygon poly, struct screen *s, enum shading_t type, struct constants *k, color ambient, struct light *l, struct vector norm[3], struct vector *v) { const double x0 = poly[0]->x, x1 = poly[1]->x, x2 = poly[2]->x; int il, im, ir; int dx_lr, dx_lm, dx_mr; double dy; struct vector pl, pm, pr; struct vector dp_dx_lr, dp_dx_lm, dp_dx_mr; struct vector p0, p1; edge e = {&p0, &p1}; struct vector p; double dz_dy; struct vector cl, cm, cr; struct vector dc_dx_lr, dc_dx_lm, dc_dx_mr; struct vector c0, c1; struct vector c; struct vector dc_dy; struct vector dn_dx_lr, dn_dx_lm, dn_dx_mr; struct vector n0, n1; struct vector n; struct vector dn_dy; if (x0 <= x1 && x1 <= x2) { il = 0; im = 1; ir = 2; } else if (x0 <= x2 && x2 <= x1) { il = 0; im = 2; ir = 1; } else if (x1 <= x0 && x0 <= x2) { il = 1; im = 0; ir = 2; } else if (x1 <= x2 && x2 <= x0) { il = 1; im = 2; ir = 0; } else if (x2 <= x0 && x0 <= x1) { il = 2; im = 0; ir = 1; } else { il = 2; im = 1; ir = 0; } pl = *poly[il]; pm = *poly[im]; pr = *poly[ir]; pl.x = (int)pl.x; pm.x = (int)pm.x; pr.x = (int)pr.x; dx_lr = pr.x - pl.x; dx_lm = pm.x - pl.x; dx_mr = pr.x - pm.x; p0 = pl; p1 = pl.x != pm.x? pl : pm; dp_dx_lr = pr; subtract_vectors(&dp_dx_lr, &pl); scalar_div(dx_lr, &dp_dx_lr); dp_dx_lm = pm; subtract_vectors(&dp_dx_lm, &pl); scalar_div(dx_lm, &dp_dx_lm); dp_dx_mr = pr; subtract_vectors(&dp_dx_mr, &pm); scalar_div(dx_mr, &dp_dx_mr); switch (type) { case FLAT: calculate_centroid(&p, poly); calculate_intensity(&c, k, ambient, l, &p, norm, v); for (p.x = pl.x; p.x <= pr.x; p.x++) { p0.x = p1.x = p.x; draw_line(e, s, vtoc(&c) ); add_vectors(&p0, &dp_dx_lr); add_vectors(&p1, (p.x < pm.x? &dp_dx_lm : &dp_dx_mr) ); } break; case GOROUD: calculate_intensity(&cl, k, ambient, l, poly[il], norm + il, v); calculate_intensity(&cm, k, ambient, l, poly[im], norm + im, v); calculate_intensity(&cr, k, ambient, l, poly[ir], norm + ir, v); c0 = cl; c1 = (pl.x != pm.x? cl : cm); dc_dx_lr = cr; subtract_vectors(&dc_dx_lr, &cl); scalar_div(dx_lr, &dc_dx_lr); dc_dx_lm = cm; subtract_vectors(&dc_dx_lm, &cl); scalar_div(dx_lm, &dc_dx_lm); dc_dx_mr = cr; subtract_vectors(&dc_dx_mr, &cm); scalar_div(dx_mr, &dc_dx_mr); for (p.x = pl.x; p.x <= pr.x; p.x++) { dy = p1.y - p0.y; dc_dy = c1; subtract_vectors(&dc_dy, &c0); scalar_div(dy, &dc_dy); dz_dy = (p1.z - p0.z) / dy; p.y = p0.y; p.z = p0.z; c = c0; while (1) { plot(s, vtoc(&c), &p); if (p0.y < p1.y) { p.z += dz_dy; add_vectors(&c, &dc_dy); p.y++; if (p.y > p1.y) break; } else { p.z -= dz_dy; subtract_vectors(&c, &dc_dy); p.y--; if (p.y < p1.y) break; } } add_vectors(&p0, &dp_dx_lr); add_vectors(&c0, &dc_dx_lr); if (p.x < pm.x) { add_vectors(&p1, &dp_dx_lm); add_vectors(&c1, &dc_dx_lm); } else { add_vectors(&p1, &dp_dx_mr); add_vectors(&c1, &dc_dx_mr); } } break; case PHONG: n0 = norm[il]; n1 = norm[pl.x != pm.x? il : im]; dn_dx_lr = norm[ir]; subtract_vectors(&dn_dx_lr, norm + il); scalar_div(dx_lr, &dn_dx_lr); dn_dx_lm = norm[im]; subtract_vectors(&dn_dx_lm, norm + il); scalar_div(dx_lm, &dn_dx_lm); dn_dx_mr = norm[ir]; subtract_vectors(&dn_dx_mr, norm + im); scalar_div(dx_mr, &dn_dx_mr); for (p.x = pl.x; p.x <= pr.x; p.x++) { dy = p1.y - p0.y; dn_dy = n1; subtract_vectors(&dn_dy, &n0); scalar_div(dy, &dn_dy); dz_dy = (p1.z - p0.z) / dy; p = p0; n = n0; while (1) { calculate_intensity(&c, k, ambient, l, &p, &n, v); plot(s, vtoc(&c), &p); if (p0.y < p1.y) { p.z += dz_dy; add_vectors(&n, &dn_dy); p.y++; if (p.y > p1.y) break; } else { p.z -= dz_dy; subtract_vectors(&n, &dn_dy); p.y--; if (p.y < p1.y) break; } } add_vectors(&p0, &dp_dx_lr); add_vectors(&n0, &dn_dx_lr); if (p.x < pm.x) { add_vectors(&p1, &dp_dx_lm); add_vectors(&n1, &dn_dx_lm); } else { add_vectors(&p1, &dp_dx_mr); add_vectors(&n1, &dn_dx_mr); } } break; } }