From 66bc98e7a4c1ea6e80f442e146a8eb1e10e01b21 Mon Sep 17 00:00:00 2001 From: Benjamin Koltes <benjamin.koltes@student.ecp.fr> Date: Wed, 23 Mar 2016 14:50:09 +0100 Subject: [PATCH] yolo --- reflection.py | 26 ++++++++++++++++++++++++++ scenes/reflection.py | 5 +++-- scenes/two_spheres_reflection.png | Bin 2167 -> 2582 bytes tests/02_rayon.py | 3 +-- two_spheres_reflection.png | Bin 0 -> 9339 bytes 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 reflection.py create mode 100644 two_spheres_reflection.png diff --git a/reflection.py b/reflection.py new file mode 100644 index 0000000..bdb61f9 --- /dev/null +++ b/reflection.py @@ -0,0 +1,26 @@ +# Show to python where to find the modules +from scene import * +from light import Spotlight +from camera import Camera +from raytracer import raytracer_render +from matplotlib.image import imsave + +camera = Camera(600,600,1) +materiau_sphere_bleue = Material(Vector((0,0,1)), .5, .3, .3, 100, .5) +materiau_sphere_rouge = Material(Vector((1,0,0)), .5, .3, .3, 100, .3) +materiau_sphere_blanche = Material(Vector((1,1,1)), .5, .3, .3, 100, .7) +materiau_sphere_verte= Material(Vector((0,1,0)), .5, .3, .3, 100, .3) +sphere_bleue = Sphere(Vector([0,0,3]), .8, materiau_sphere_bleue) +sphere_rouge = Sphere(Vector([0.5,0.5,2]), .5, materiau_sphere_rouge) +sphere_blanche = Sphere(Vector([0,0,0]), 50, materiau_sphere_blanche) +sphere_verte = Sphere(Vector([2,-2,3]), .5, materiau_sphere_verte) +lumiere = Spotlight(Vector((1,1,0)), Vector((1,1,1))) +scene = Scene() +scene.add_object(sphere_bleue) +scene.add_object(sphere_rouge) +scene.add_object(sphere_blanche) +scene.add_object(sphere_verte) +scene.add_light(lumiere) +affiche = raytracer_render(camera, scene) +imsave('two_spheres_reflection.png',affiche) +print('Done') diff --git a/scenes/reflection.py b/scenes/reflection.py index cde3e1b..694f636 100644 --- a/scenes/reflection.py +++ b/scenes/reflection.py @@ -10,8 +10,8 @@ from matplotlib.image import imsave import sys camera = Camera(200,200,1) -materiau_sphere_bleue = Material(Vector((0,0,1)), .7, .7, .7, 100, .7) -materiau_sphere_rouge = Material(Vector((1,0,0)), .7, .7, .7, 100, .7) +materiau_sphere_bleue = Material(Vector((0,0,1)), .5, .3, .3, 100, .5) +materiau_sphere_rouge = Material(Vector((1,0,0)), .5, .3, .3, 100, .3) sphere_bleue = Sphere(Vector([0,0,3]), .8, materiau_sphere_bleue) sphere_rouge = Sphere(Vector([0.5,0.5,2]), .5, materiau_sphere_rouge) lumiere = Spotlight(Vector((1,1,0)), Vector((1,1,1))) @@ -21,3 +21,4 @@ scene.add_object(sphere_rouge) scene.add_light(lumiere) affiche = raytracer_render(camera, scene) imsave('two_spheres_reflection.png',affiche) +print('Done') diff --git a/scenes/two_spheres_reflection.png b/scenes/two_spheres_reflection.png index 3345277b857a806c034bb22e1094bef0573fbc05..196361e20de713ac5dc8d7c1f2cb55ff4706606a 100644 GIT binary patch literal 2582 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 literal 2167 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 FngH+czeE54 diff --git a/tests/02_rayon.py b/tests/02_rayon.py index 1ce0c2f..d3389e7 100644 --- a/tests/02_rayon.py +++ b/tests/02_rayon.py @@ -25,7 +25,6 @@ r_one = c.ray_at(c.image_nrows, c.image_ncols); r_one_ref_dir = Vector([-1,-1,c.focal_length]) r_one_ref_dir = r_one_ref_dir / r_one_ref_dir.norm() -assert abs(r_one.direction*(r_one_ref_dir) - - r_one.direction.norm() < 0.01), "c.ray_at(c.nrows,c.ncols) should have the direction [-1,-1,c.focal_length."; +assert abs(r_one.direction*(r_one_ref_dir) - r_one.direction.norm()) < 0.01, "c.ray_at(c.nrows,c.ncols) should have the direction [-1,-1,c.focal_length."; diff --git a/two_spheres_reflection.png b/two_spheres_reflection.png new file mode 100644 index 0000000000000000000000000000000000000000..89fa5b3d0f4ce9c9ebddff669a4909cf3cf51d8d GIT binary patch literal 9339 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 WVm~q`#4|83FnGH9xvX<aXaWEL->Rwr literal 0 HcmV?d00001 -- GitLab