void test_sphere_normal_at_point(void){ struct sphere s = create_sphere(create_point(4.2,3.5,6.5),5.715767665); struct point p = create_point(5.3,2.4,5.4); struct vector v = sphere_normal_at_point(s,p); checkit_double(v.x,.57735); checkit_double(v.y,-.57735); checkit_double(v.z,-.57735); struct sphere s2 = create_sphere(create_point(1.2,0,0),4.45); struct point p2 = create_point(6.65,0,0); struct vector v2 = sphere_normal_at_point(s2,p2); checkit_double(v2.x,1); checkit_double(v2.y,0); checkit_double(v2.z,0); }
color_t shootRay(ray_t ray, intersect_t *intersect, int recursionCount) { rayIntersectionTest(ray, intersect); if (intersect->t > 0) { // We hit something color_t color; GeomType geomType = intersect->geomType; void *geomObject = intersect->object; bool reflective = false; // Check the material if (geomType == GeomTypeTriangle) { triangle_t *temp = (triangle_t *)geomObject; color = temp->material.color; reflective = temp->material.reflective; } else if (geomType == GeomTypeSphere) { sphere_t *temp = (sphere_t *)geomObject; color = temp->material.color; reflective = temp->material.reflective; } else if (geomType == GeomTypeLight) { return rgb(255, 255, 255); } // Get a normal where we intersected vec_t normal; if (geomType == GeomTypeTriangle) { triangle_t *temp = (triangle_t *)geomObject; normal = temp->normal; } else if (geomType == GeomTypeSphere) { sphere_t *temp = (sphere_t *)geomObject; normal = sphere_normal_at_point(*temp, intersect->point); } if (reflective && recursionCount < 10) { // First find the reflected ray vec_t r = vec_sub(ray.direction, vec_mult(normal, 2 * vec_dot(normal, ray.direction))); point_t start = point_offset(intersect->point, vec_mult(r, 0.0001)); ray_t reflectedRay = ray_new(start, r); // Shoot out a new ray and take its color color = shootRay(reflectedRay, intersect, recursionCount + 1); } else if (!reflective) { point_t sPos = intersect->point; ray_t sRay; float totalDiffuse = 0; for (int m = 0; m < numLights; m++) { if (lights[m].size == 0) { sRay = ray_to_light(lights[m], sPos); sRay.point = point_offset(sRay.point, vec_mult(sRay.direction, 0.0001)); rayIntersectionNonLightTest(sRay, intersect); if (intersect->t <= 0) { // We did't hit anything, diffuse like normal totalDiffuse += fabsf(vec_dot(sRay.direction, normal)); } // Otherwise, we're in shadow } else { float lightRays = 100 * lights[m].size; float lightDiffuse = 0; for (int l = 0; l < lightRays; l++) { sRay = ray_to_light(lights[m], sPos); sRay.point = point_offset(sRay.point, vec_mult(sRay.direction, 0.0001)); rayIntersectionNonLightTest(sRay, intersect); if (intersect->t <= 0) { // We didn't hit anything, diffuse like normal lightDiffuse += fabsf(vec_dot(sRay.direction, normal)); } // Otherwise, we're in shadow } totalDiffuse += lightDiffuse / lightRays; } } totalDiffuse /= numLights; // We want the total intensity of lights to be the // same no matter how many we have if (totalDiffuse < 0.2) totalDiffuse = 0.2; if (totalDiffuse > 1) totalDiffuse = 1; color.r *= totalDiffuse; color.g *= totalDiffuse; color.b *= totalDiffuse; } return color; } // No intersection, color black return rgb(0, 0, 0); }