From b401a2c9f8bb80c2bb0af123e32ef4d7c7d3f3d1 Mon Sep 17 00:00:00 2001 From: plouj Date: Fri, 4 Jan 2008 20:19:10 +0000 Subject: [PATCH] made nearest_object_intersecting_ray agnostic to the object types made nearest_object_intersecting_ray actually properly sort objects by distance from ray origin added a general ray_object_intersect function that will call appropriate intersection functions based on object type made sure ray_sphere_intersect only returns positive (in front of ray) values fixed return value of ray_sphere_intersect (from none to infinity) made the default scene mor complex updated the scene_test added a nice distance based test to nearest_object_intersecting_ray_test git-svn-id: http://svn.plouj.com/repos/eraytracer@15 b8c14938-b733-429d-887c-d66ed1f8cd15 --- raytracer.erl | 88 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/raytracer.erl b/raytracer.erl index 8a62350..3aa5e7e 100644 --- a/raytracer.erl +++ b/raytracer.erl @@ -46,30 +46,33 @@ nearest_object_intersecting_ray(_Ray, NearestObj, Distance, []) -> nearest_object_intersecting_ray(Ray, NearestObj, Distance, - [Object|Rest_of_scene]) -> - case Object of - #sphere{} -> - NewDistance = ray_sphere_intersect(Ray, Object), - if NewDistance /= none -> -% io:format("found new intersection at ~w~n", [Distance]), - nearest_object_intersecting_ray( - Ray, - Object, - NewDistance, - Rest_of_scene); - true -> - nearest_object_intersecting_ray(Ray, - NearestObj, - Distance, - Rest_of_scene) - end; - _Else -> + [CurrentObject|Rest_of_scene]) -> + NewDistance = ray_object_intersect(Ray, CurrentObject), + %io:format("Distace=~w NewDistace=~w~n", [Distance, NewDistance]), + if (NewDistance /= infinity) + and ((Distance == infinity) or (Distance > NewDistance)) -> + %io:format("another closer object found~n", []), + nearest_object_intersecting_ray( + Ray, + CurrentObject, + NewDistance, + Rest_of_scene); + true -> + %io:format("no closer obj found~n", []), nearest_object_intersecting_ray(Ray, NearestObj, Distance, Rest_of_scene) end. +ray_object_intersect(Ray, Object) -> + case Object of + #sphere{} -> + ray_sphere_intersect(Ray, Object); + _Else -> + infinity + end. + ray_sphere_intersect( #ray{origin=#vector{ x=X0, y=Y0, z=Z0}, @@ -86,10 +89,14 @@ ray_sphere_intersect( if Discriminant >= 0 -> T0 = (-B + math:sqrt(Discriminant))/2, T1 = (-B - math:sqrt(Discriminant))/2, - %io:format("T0=~w T1=~w~n", [T0, T1]), - lists:min([T0, T1]); + if (T0 >= 0) and (T1 >= 0) -> + %io:format("T0=~w T1=~w~n", [T0, T1]), + lists:min([T0, T1]); + true -> + infinity + end; true -> - none + infinity end. @@ -191,7 +198,13 @@ scene() -> screen=#screen{width=4, height=3}}, #sphere{radius=4, center=#vector{x=0, y=0, z=7}, - colour=#colour{r=0, g=128, b=255}} + colour=#colour{r=0, g=128, b=255}}, + #sphere{radius=4, + center=#vector{x=-5, y=3, z=9}, + colour=#colour{r=255, g=128, b=0}}, + #sphere{radius=4, + center=#vector{x=-5, y=-2, z=10}, + colour=#colour{r=128, g=255, b=0}} ]. @@ -237,7 +250,15 @@ scene_test() -> {sphere, 4, {vector, 0, 0, 7}, - {colour, 0, 128, 255}}] -> + {colour, 0, 128, 255}}, + {sphere, + 4, + {vector, -5, 3, 9}, + {colour, 255, 128, 0}}, + {sphere, + 4, + {vector, -5, -2, 10}, + {colour, 128, 255, 0}}] -> true; _Else -> false @@ -539,7 +560,26 @@ point_on_screen_test() -> nearest_object_intersecting_ray_test() -> io:format("nearest object intersecting ray test", []), - false. + % test to make sure that we really get the closest object + Sphere1=#sphere{radius=5, + center=#vector{x=0, y=0, z=10}, + colour=#colour{r=0, g=0, b=10}}, + Sphere2=#sphere{radius=5, + center=#vector{x=0, y=0, z=20}, + colour=#colour{r=0, g=0, b=20}}, + Sphere3=#sphere{radius=5, + center=#vector{x=0, y=0, z=30}, + colour=#colour{r=0, g=0, b=30}}, + Sphere4=#sphere{radius=5, + center=#vector{x=0, y=0, z=-10}, + colour=#colour{r=0, g=0, b=-10}}, + Scene1=[Sphere1, Sphere2, Sphere3, Sphere4], + Ray1=#ray{origin=#vector{x=0, y=0, z=0}, + direction=#vector{x=0, y=0, z=1}}, + + Subtest1 = {Sphere1, 5} == nearest_object_intersecting_ray(Ray1, Scene1), + + Subtest1. focal_length_test() -> Epsilon = 0.1, -- 2.11.4.GIT