t_point cylinder_inter(t_line line, t_list *list) { t_point n_line; double a; double b; double c; double delta; t_point p1; t_point p2; double t1; double t2; n_line = vector_minus(line.pos, list->pos); a = line.ori.x * line.ori.x + line.ori.y * line.ori.y; b = 2 * n_line.x * line.ori.x + 2 * n_line.y * line.ori.y; c = n_line.x * n_line.x + n_line.y * n_line.y \ - list->radius * list->radius; delta = b * b - 4 * a * c; if (delta < 0) return (line.pos); t1 = (-b + sqrt(delta)) / (2 * a); t2 = (-b - sqrt(delta)) / (2 * a); p1 = vector_add_mult(line.pos, t1, line.ori); p2 = vector_add_mult(line.pos, t2, line.ori); return (closer_point(line.pos, p1, p2)); }
/* * Calculate light color */ color lightColor(const intersection *inter, const ray *srcRay) { vec3 v = vector_normalized(vector_float_mul(-1.0f, srcRay->dir)); color cD = BLACK, refCoef = reflectCoef(inter->mat.reflect_coef, inter->normal, srcRay->dir); // For each light calculate and sum color for (int k = 0; k < num_lights; ++k) { vec3 l = vector_minus(lights[k].position, inter->position); float normL = vector_norm(l); l = vector_normalized(l); // Look for object between light source and current intersection ray objectRay; // Ray from object to light ray_init(&objectRay, inter->position, l, EPSILON, normL, 0); float interFound = 0.0f; for (int i = 0; i < object_count; ++i) { interFound += interDist(&objectRay, &(scene[i])); } if (!interFound) { vec3 h = vector_normalized(vector_add(l, v)); float sc_nl = clamp(vector_dot(inter->normal, l), 0.0f, 1.0f); float sc_hn = clamp(vector_dot(h, inter->normal), 0.0f, 1.0f); cD = vector_add(cD, vector_vec_mul(lights[k].col, vector_float_mul(sc_nl, (vector_add(vector_float_mul(1 / M_PI, inter->mat.kd), (vector_float_mul(pow(sc_hn, inter->mat.shininess), vector_float_mul(((inter->mat.shininess + 8) / (8 * M_PI)), refCoef)))))))); } } return cD; }
camera init_camera(point3 position, point3 at, vec3 up, float fov, float aspect) { camera cam; cam.fov = fov; cam.aspect = aspect; cam.position = position; cam.zdir = vector_normalized(vector_minus(at, position)); cam.xdir = vector_normalized(vector_cross(up, cam.zdir)); cam.ydir = vector_normalized(vector_cross(cam.zdir, cam.xdir)); cam.center = vector_float_mul(1.f / tanf((cam.fov * M_PI / 180.f) * 0.5f), cam.zdir); return cam; }
float interDistSphere(const ray *r, const object *obj) { vec3 ominusc = vector_minus(r->orig, obj->center); float a = vector_dot(r->dir, r->dir); float b = 2.0f * vector_dot(r->dir, ominusc); float c = (vector_dot(ominusc, ominusc) - obj->radius * obj->radius); float delta = b * b - 4.0f * a * c; if (delta > 0.0f) { float sqrtDelta = sqrt(delta); float t0 = (-b - sqrtDelta) / (2.0f * a), t1 = (-b + sqrtDelta) / (2.0f * a); return t0 > t1 ? t1 : t0; } return -1.0f; }
/* * Calculate the intersection between a ray and an object */ int intersect(ray *r, const object *obj, intersection *inter) { float dist = interDist(r, obj); if (dist != 0.0f) { switch (obj->type) { case CYLINDER: // break; case PLANE: inter->normal = obj->normal; break; case SPHERE: inter->normal = vector_normalized(vector_minus(ray_at(*r, dist), obj->center)); break; } inter->position = ray_at(*r, dist); inter->mat = obj->mat; return 1; // Intersection found } return 0; }
vec3 vector_reflect(vec3 v, vec3 n) { return vector_minus(v, vector_float_mul(2.f * vector_dot(n, v), n)); }