From 14c2402d3a14e1947f8852fe692b45344a781e35 Mon Sep 17 00:00:00 2001
From: Benjamin Koltes <benjamin.koltes@student.ecp.fr>
Date: Sun, 20 Mar 2016 20:51:55 +0100
Subject: [PATCH] fix de light.py et ajout des tests

---
 __pycache__/camera.cpython-33.pyc           | Bin 0 -> 1100 bytes
 __pycache__/intersection.cpython-33.pyc     | Bin 0 -> 1765 bytes
 __pycache__/light.cpython-33.pyc            | Bin 0 -> 1651 bytes
 __pycache__/operation_vector.cpython-33.pyc | Bin 0 -> 7404 bytes
 __pycache__/raytracer.cpython-33.pyc        | Bin 0 -> 2603 bytes
 __pycache__/scene.cpython-33.pyc            | Bin 0 -> 2054 bytes
 camera.py                                   |   3 +-
 light.py                                    |   8 ++++-
 one_sphere.png                              | Bin 6168 -> 0 bytes
 operation_vector.py                         |  10 +++---
 raytracer.py                                |   5 ++-
 scene.py                                    |   3 +-
 script_one_sphere.py                        |  23 +++++++++-----
 tests/01_camera_ok.py                       |  14 +++++++++
 tests/02_rayon_ok.py                        |  31 ++++++++++++++++++
 tests/03_sphere_intersection_ok.py          |  33 ++++++++++++++++++++
 tests/04_material_ok.py                     |  14 +++++++++
 tests/05_phong_ok.py                        |  32 +++++++++++++++++++
 18 files changed, 158 insertions(+), 18 deletions(-)
 create mode 100644 __pycache__/camera.cpython-33.pyc
 create mode 100644 __pycache__/intersection.cpython-33.pyc
 create mode 100644 __pycache__/light.cpython-33.pyc
 create mode 100644 __pycache__/operation_vector.cpython-33.pyc
 create mode 100644 __pycache__/raytracer.cpython-33.pyc
 create mode 100644 __pycache__/scene.cpython-33.pyc
 delete mode 100644 one_sphere.png
 create mode 100644 tests/01_camera_ok.py
 create mode 100644 tests/02_rayon_ok.py
 create mode 100644 tests/03_sphere_intersection_ok.py
 create mode 100644 tests/04_material_ok.py
 create mode 100644 tests/05_phong_ok.py

diff --git a/__pycache__/camera.cpython-33.pyc b/__pycache__/camera.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ac9cd14ce80218af0287c5e0f604d59b9c1e5cf
GIT binary patch
literal 1100
zcmbQo!^>rJ>s{DaMh1pt1|-1Dz`)?Zz`#&!&cMKs!oZNi$dJRpkjuyr#mK-2;xjSi
zFfrsZGej{nFuJEOGo-LEv@n3kW+sLx7KRj7hF}dg1_p*qkf9ok3=9mVAZ}P{a!Gy>
zgb%VKD6ujbBneUlqL~;N7@R=%>M$@c)G#o(rZRx6OkrS%VgflLg$ZO$6f*<dN@UBx
zRyZf-rWPe8vw)0bU|;~zAXA+|rpkj%Wds=<&%jW_1ZFTY)G&h?OdyX2gWcw*0dia^
zH^>9IiRr2Fc}4l<#mM~R{G8%a9tH-6wEX16ocNs7y!4U`4UlD}Afh-mCk<ISR_*+t
zu+1zkNz6-5jR%{PssVB}m;f8Drx%k9_KsdbWhn;(14Dd#W?p7Vd^{`2H=qDzVB}=v
zWGn?41@X8ZOi41x3n1e_%0L(#0x6&nU|`4sN2ydTGuZQt3=%cW4AQkMpm4}y1O+rq
ziU}&k%22|@P{PcR!URR>%nZ$pAdwmth8k9|Miz!NuwXM2Lohf1{W3uz4@m+b7ZVH-
zkduQFE5Y#yNh;uA0EZ1Mj6q&OgfU1*QGR(Th)&MWDFr2>JTO@SCM&^#2`0csp@b;N
zsG`Km_{0(}P<Vm}21Z^+J}@rjWnf@{hABjmp9a_yka);T%uS7tF9qp|kI&6dDa`?K
zdBAa0Selpvm4_&XL>kyz5Tn4U45~Q?l!A)m<H3#u6WCn}aSJ$gfd~Oc9#*i45OJvE
z1Q-|?@(WUn5=%1k^Ww|E*$u1;8l0RA3=Bnyl_f=q$*D!)P=kdx#2B#s2m;e3AP?C<
O{A&ja>|%&p1egFwcGMRD

literal 0
HcmV?d00001

diff --git a/__pycache__/intersection.cpython-33.pyc b/__pycache__/intersection.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fae1ae74b367b9008f501976711328e4472c8010
GIT binary patch
literal 1765
zcmbQo!^?H+`K_?sEDQ|E3`l^Pfq}t+fq|jeoPmKMg@GZ3ks*hHAq2`|WC(FjVPZ&O
zW@upmk<CmDQA`XeEDR~EAdx6$h7>l2U=4N#28K+Kp&E<~3=E|pLMs_Wg2X^H69WT-
z6UY_?1_p*21_swu28Jj`kbNNI7#UKSV8$^s1Z%K>4B=s5VDQW<Ni8Z)O)kmI&r1f0
zg3JTaAoH9-=E;N1V+0u)&%jW_1ZFTY)G&h?Odtz_!EW-?0C}{OgMopeAip>hWMC;9
z0|P@|eo<~>4w#vrl$DxX0<j!qM{#OS8ZjC`Zqfh|rJ!(hwu%WYPAw{qaZ1h0O3cm7
zi*d<MF3nBND?t)+&n$^aNiB=d$xn~TMDn9vK_%G6`1s7c%#!$cR*)A#&SYTZWaMNl
z6-5gZJ(xm2h_gZ7i;vGs%uS7tFXdujV2F>;%}*)K0dYa$86RI*nwSHXhbV?v1P&vp
zj-34D#GK;zc(9+q1a&+HasYCKg2NaTkphgR=yJ&*aZs4@GB7ZJLIE7v(-|2UY8V-^
z7#M1qzzjx)T4sh4CQxKIGcuGgGh}lx6isHVVPME&VW?#RiD$7g)UtvT1T%w3EgLwE
zurNr}vV&4OD4nn~h=|m3Fx0SvkVp+HNL*N=mXo1|1I$ceVyIzb5UJs05Rs_mVyNK)
z<%4V%hN8V772F^`3xlvk3L{vVbPWdsOiUammd?ab%gvCd4%5uUP;?Kh8Log4tbmOn
zodLusVPmM_W@u&v+r-3B%)wZ~jwHgsP{hNS!oUz*!ig$s$_UB<%nWeVBI30?40$48
zPct*Xm4k(A*cr087@8RvYFHVvSs98-8B4esYIwkig+U^V2Q0_H(9Fybj75gK1|pRQ
zE;WKRK#}B^35vE%P{e{ugLF^~GB7-_*8oLhDIX{`mn0UIWag#E7vyK=m6URV3Z2X%
zNDeOrX)LKMNCjud;DU_QA_y}%HLnE9EJ{qtEG;etW#*jJJTRS`SOM1Qm!Fpk5y;E~
z3xM)AM#=&wa*#}7PG(hV3dCg~$Ahwe30QwoVkNi;%LkK?!U5_8P+3+47ET0Pk&>B~
z2IeM#$>dUyNhzs0C5d2*k@Ge<W5dcGaJB*y)X7_*aD-dN1qx?9P}qY@4Iwbe#mL3T
z$0)=o#>m5H$jHMe%EZQ~!pOoX#3;@r!YITj#RQHFxFOIIMSy{UA-^ECC=pa*#+Rig
wm*f|LJz1QbnwJXpByyfcH3RHH1VJ6If{HC0NU3HAijHDX`N+k{#U#uI0HFSUp8x;=

literal 0
HcmV?d00001

diff --git a/__pycache__/light.cpython-33.pyc b/__pycache__/light.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..25de9666d344f0b6096dd800e61ad58c1f75cdfd
GIT binary patch
literal 1651
zcmbQo!^>6h?OoVkCI*IN1|-1Dz`)?Zz`#(f&%nUop2EP8!pP79CYzZUq8J!bm>5!+
zK_XF%3@I!ODXd^N6GI9cL$C%r0|P@cBh)ky&BVaK-~=*Ffq{XchJnE~m4N}Ik%1wK
z31o5#6IeSl$jo3376t}}Qcea2hTwwylAO%+jFM!Kb3o>SXpmvfAj8B!hB1Q7i)Ub{
zVFEK48B!P+f;B*v`e}evmU1vKFcjn$XO?8<=asU8T$Z1cU!(ytsT5>WacWK)E=3?K
zH9$nEB?AM4vsFxJacWU<j8ke}R$^{uUW`kAa%paAUI~(rduB;YN@`hrPJVg}*zI}+
zm0;uJ<1_OzOXA}}jw%LO%)rRWSSp0<O+A<zKS&sWoE{&amzbLxA79GFz`zh6pPQdj
znginUfVqXGi8)Yth+>ExVE;pP<m4wO<`l=rgZ%*}DD(^`vXempT@3P)03%wIfr1(o
zbi51<3?T1<qwF3i%9t6l7#Ok`8ERP>Y9MSThFUflo0*}O9Tb&WEDSY_3=&za49yG-
zwH%-bhO#+9Nv4K_p@x$|L<B_Ca4<;Jaxv7P=->v)*Kjb1q%bjLGcpu4g3@daBZEkA
z4I2YoH!DL87efs<gGdcKgRqErEe}Ht4@hA)14Gdk5TlldAx{)6$jp$<!ccS)ltw{<
z3?RW828JxS%h?!&MIfoyFB23bnIP|Hf<g$KBfzO3H?btOC^In!%qcENO)kwzEGh+M
zn3T-4w9?{Ka3~gMWaee&r4|>1mBCXlC<)}{7v(1AWLBl7ASGr{7=yXs6o;ybje&sy
zqNx<b%umWnO)dd5%Q92TQ;SMLPR%ZcP!K~Ca|$vNOF<6z0h4}UG6+nDfyqp8LIM*M
zrX~SU_RPr7OOMaY$tlgv%u6gu1-Y|W4itKfJRry<%*ewi#wfrfz{tTU$H>FT3BpXJ
z*z_iYyaUn-qCps(?nFT8juD#fY9I_I1`$|60WJ(c83-OdpcqNaP0CEnD**>=GPuwH
znTHv=kRSyI2AH5QL_kFX)M}(Kkph)?Ap030g$AYyKS-H|l0C5o5xCI7)DLz$f}qeB
UpwP5|lvZ}2lmssFgjsn+0L43W^#A|>

literal 0
HcmV?d00001

diff --git a/__pycache__/operation_vector.cpython-33.pyc b/__pycache__/operation_vector.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..200dee8539d5beca61dbe0c0a5cc3b84ef2dcba1
GIT binary patch
literal 7404
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

literal 0
HcmV?d00001

diff --git a/__pycache__/raytracer.cpython-33.pyc b/__pycache__/raytracer.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d438c668c55e9e716dd620b8256fd685dab4b5db
GIT binary patch
literal 2603
zcmbQo!^`#R>$@;nHU@@d1|-1Dz`)?Zz`#&k&A`Br!oZNi$dJRpkjuyr#mJD$#1O^A
zzz7m$V#r};$Yo)OVuA3P8FE+|a@iQ7*dTlsh8%W=Tn>gP4u)J#hA2)3M)wp}h7>l2
z76uU6%)}7I#gM|zkir2HiQ;BR;bchR0<(D-Qn(p{HFy{p7&1W)(_ms?U?>$}U|=Z7
z$j?iU&&<gw&CSe9EJ-aDVqjoM%uUKn%qu|>)?fr_-~{Q<D@iRXPE9U>2(d9RFodNh
zm*f{g%wz>=FDgo`ECsQuQj7A7lR<hxwt{Go#ZI8GP+(wSs9|7mO=SQDLka^Z7*ZG+
zQkcLFW@boXW(d|`0oe))zM#a)WDpH921J95aRwP91~P^bWKui>Lk$y{!3YZEV6glA
zAg<yADJ@AXD#^@Ck1xp2%quD71jR*WQEGBYW`3Rq$jnlZZN;fMX{7{}gPfrOB1&x;
z7#N(bVnT~ki;82MQuDGBb2IZ|T=J7kb5rw5kc8YbOJY(|%i?qL(_@MfD@%$JlT(ZI
z3MxxE7#JAh<1_OzOXB0%LGA=OgMpEgu@n?tL5Y=mFj+rHctAAdCFZ8a$Cq+}b?4@%
zl;(iAAT9Cng{6r(P<e=Ai0R-Ef$GS~PfpA!j*kcX0!&cBE1*yeN~{E>iDFO;2{4vI
zh2W9L&%nUI4GJ@mPjeX=7}6OSYMB{I7(ltAnUSHEg`pyop@xwmi;=-4Hjbf|m7#=*
zp@tO{vCT{jwQLMEY@q1PW@ado0kN}KKvG$(3=&yv49yG-wd@Qf><l$53^nWwAPp=~
zb~Y13Q58r-EeAtk6+@v62!+?MAgl(dSj<qu0ZM}@Odv9ynW34HA-IH-p@xG2WDy5L
z78lr5PKF9suq(M4Tw<*lYPlF{I2lTK7;3nXl=6bvTv&{3W@Rw1<zy&4#1IZLnTsKd
zk0Fbnp_UtDOqKx1A2G}fwLA>9ybQH`AOlJS!QSEl<%?#p<C>WmN(4c!1bLSiDvlz^
zhY*DN1e}2Uz>$)fmj*5hGC{dg1C;B*IW{dPKe40~6hrw*S*gh-@j02rkj#<^%lP1Y
z;+LP73QoEO`Nf%_EQBr7fKqZ^eo-#i!raWfQc%i(lomM38L$e7&ESNZlbN0YbpzJY
z3S=P2hQu7OV{#KqQj0PZbHH9n&d<p&g0k|9QXq~<tk3`@K`;kaN);!k=B0vdPEO2C
zElLD?1@2u)2!QfYN@j6MVqS7;DJaPD!4?*!7MJFfB$j}MQc6KaC+8#<7stc3LmdEf
z3fM#7oDFtfJk+nCY?2&b0d`h$d?l2w0%uGxL51AO$-uw>E_ULJ5-UM5T&x5t!Wh{Y
zc^Cy4`5Ac_#lWNhqY$GoqbQ>QqXi>BqbMV|sDx`w24!rJK9F&sPyrXib3nx~149-A
zLoE|HKQe-IH50f<W(MW$G;m%5W$!$O5@wKiGbo2AfO2?6I9Ld*!X?%doXZ)&8IBc{
zV?o)NouPykl%;DJLB=;TGt_c`a~C+zgK|4qC8!!@U}$AxNMmNODRgHDFEn8Q<?&!}
zHQ<*C3T6#ZAq!67nYoGSsquM5`Q^pP{N((cVsNa1YcDXXC^0V`l0u3SE8`O(83G<8
zU?s`<`9&!joS+H|lqjJo2~-I}k{2kb^5Szc)ALe`!AUzW9+U#|KwOZE64TN$lQSS`
zD-)cYvcRbTmPkR0i@-?%Oi&>`fHD-kCW<dg%}Yrwk^>dXpuzxD0dX>lG72*aGYT;Z
zF{(3yn+xdb{WN$%J_dOclCnXD64|Bz=K^>>$;{6KCp5SK*uMON)S^UC@e*GKZe)OS
zDYOIuS(;axTL5WlB%(Gtz+o4ZSP3>05mO-Nq5A<Go(O^pAq$FY8%UjO2P!Lyc^DWN
Q#25t_1sKJcgjson0gmfdSO5S3

literal 0
HcmV?d00001

diff --git a/__pycache__/scene.cpython-33.pyc b/__pycache__/scene.cpython-33.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ac3f713769654225108a1111d89b0afaa5f39b8a
GIT binary patch
literal 2054
zcmbQo!^_2S_gxqVGXq010}^0nU|?`yU|=YAXJBARVPHsMWXNG)2ystgVn|_TXkh@6
z%}fkYj12B6EDR~EU?ElpkPs7tdkPyv3OiVc9W2Dmkix+btij2^z>o>DM1zrmfuR&c
zXeEP4kQj(&Vqjo!0@<p-z`#($z~Gw70J0*5fgy?s<b)I^kfBk`AlrjASU`rbF)%O$
z7i6Rsr6z;;Ad^5e$RuZwN%A0*7(s@`GceRJff<YpHOycJ6Ub}9VAuF*fV^A^GA=na
zucRmy%q&Vw$t*1{<zQf7$W1IsEy_&HfmjQ&qc}Aut(294fgw3RzbFOFDoU)(&qGxX
za*+mzDCK5gV9?WxDNat!OVul=1S^Y=&&<m#iH`@H2eO=jk&}^=v6LU~Ej^eLKZwmB
zx5UTiCFZ8a$Cq+3Ffhc&=jNxB=76|7U~XY)Vh&Uuq8MTY*qcxtIr+(nImPkuV26PT
z4A+4i0|{7Az!ZZ5RDcm2C=gLfBM#&=Uuc*nvx5SNfq?-;gKPpvofZD5t6>4hAu~e_
zE11E;P{Rghup-AQ$Q$6ONzTv7FDeCDkeHj4nV44sW~XGPrIi+^g5#pNAT_x(C$XrM
z6O?c=GV?O?Qj3ehAy$-{mXn%Xl9`{U0WzT!99@X$r;f>>Fu)!cps<1^15lI~^MKTX
zQwk`xa59z(GB7Z}LUW)}49Jx*H-Li>6q5ps;IM^>V^1{}pqR#=-BVb=Ssz^1q_Bb6
zte`?BSOa7&IEI5k84JS#a8eRuU|>iG7b)>@1|xDZ0XY?%1@e=!Qj<&Kb25udz%ieb
znVtdRLh=tR=D`sKCcxTo<!fP3QUd7#<?B*DP_72K5*|g#Ad5kf38Fz5>|7B@cw{j!
zWHB<-FfueVGBBnvFu+PGkUFrf$c_ai^u&UK)Vvf8usq08a0vw}So6Uy1ruP6$j${N
zsKk_%c!*)*AP0jCU|=j2fIAl<Pride_8>wNT$12)Zw}b0U;@Lvpri$I57;azB<F(5
zOmOJJrTsKO!2(W!WR;oVBmgoE5;)+J0mKE{4M`9nZ^g$GQJ{iq3UCq?0=XIFE&)a!
z79M6q+J%<zpkU80NG(bPl{fKasmUezMd09q6ue;H!15D9GdQpi1V*rdvWX3(rmzDg
OiDHloxR`|5ggF87^NNB1

literal 0
HcmV?d00001

diff --git a/camera.py b/camera.py
index a4e5e23..083f32b 100644
--- a/camera.py
+++ b/camera.py
@@ -1,4 +1,5 @@
 from operation_vector import Vector
+from raytracer import Ray
 
 class Camera:
     def __init__(self, image_nrows, image_ncols, distance_focale):
@@ -11,6 +12,6 @@ class Camera:
         x = (n-row)/n
         n = self.image_ncols//2
         y = (n-col)/n
-        return Vector((x, y, self.focal_length))
+        return Ray(Vector([0,0,0]), Vector((x, y, self.focal_length)))
 
     
diff --git a/light.py b/light.py
index c324f9d..674fb4e 100644
--- a/light.py
+++ b/light.py
@@ -13,7 +13,13 @@ def phong_illuminate(light, position, normal, object, viewer):
     R = 2*(L*N)*N - L
     V = (viewer - position).normalized()
 
-    i = ((kd*(L*N) + ks*(R*V)**alpha))*(N*L > 0)
+    if (N*L) <= 0:
+        return 0*position
+    i = ((kd*(L*N) + ks*(R*V)**alpha))
+    if i < 0:
+        i = 0
+    elif i > 1:
+        i = 1
     
     return i*(light.color ** object.material.color)
     
diff --git a/one_sphere.png b/one_sphere.png
deleted file mode 100644
index 090a8d4f232416bfe3d6ea894b2eb203cac83bfb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6168
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

diff --git a/operation_vector.py b/operation_vector.py
index 0c9825c..fe5ffd2 100644
--- a/operation_vector.py
+++ b/operation_vector.py
@@ -3,12 +3,12 @@ from random import random
 class Vector:
     def __init__(self, coord):
         x, y, z = coord
-        self.x = x
-        self.y = y
-        self.z = z
+        self.x = float(x)
+        self.y = float(y)
+        self.z = float(z)
 
     def coord(self):
-        return (self.x, self.y, self.z)
+        return (float(self.x), float(self.y), float(self.z))
     
     def __add__(first, second):
         if type(second) == Vector:
@@ -19,7 +19,7 @@ class Vector:
     
     def __rmul__(vector, item):
         d, e, f = vector.coord()
-        return Vector((item*d, item*e, item*f))
+        return Vector((float(item*d), float(item*e), float(item*f)))
 
     def __radd__(vector, item):
         return vector + item
diff --git a/raytracer.py b/raytracer.py
index 4b746b3..fe34768 100644
--- a/raytracer.py
+++ b/raytracer.py
@@ -25,7 +25,7 @@ def trace_ray(ray, scene, camera):
         color += phong_illuminate(light, class_intersect.position, class_intersect.normal, class_intersect.object, Vector([0,0,0]))
     color_object = class_intersect.object.material.color
     c_x, c_y, c_z = color.coord()
-    return Vector([min(c_x,1), min(c_y,1), min(c_z,1)])
+    return Vector([max(min(c_x, 1), 0), max(0, min(c_y, 1)), max(0, min(c_z,1))])
 
 def raytracer_render(camera, scene):
     n_lignes = camera.image_nrows
@@ -33,8 +33,7 @@ def raytracer_render(camera, scene):
     affiche = zeros((n_lignes, n_colonnes,3))
     for i in range(n_lignes):
         for j in range(n_colonnes):
-            ray_direction = camera.ray_at(i, j)
-            ray = Ray(Vector((0,0,0)), ray_direction)
+            ray = camera.ray_at(i, j)
             color = trace_ray(ray, scene, camera)
             affiche[i,j,:] = color.coord()
     return affiche
diff --git a/scene.py b/scene.py
index ff44e7b..c18a96b 100644
--- a/scene.py
+++ b/scene.py
@@ -7,12 +7,13 @@ class Sphere:
         self.material = material
 
 class Material:
-    def __init__(self, color, ambiant, diffuse, specular, shininess):
+    def __init__(self, color, ambiant, diffuse, specular, shininess, reflection):
         self.color = color
         self.ambiant = ambiant
         self.diffuse = diffuse
         self.specular = specular
         self.shininess = shininess
+        self.reflection = reflection
 
 class Scene:
     def __init__(self):
diff --git a/script_one_sphere.py b/script_one_sphere.py
index ff511e4..eeec468 100644
--- a/script_one_sphere.py
+++ b/script_one_sphere.py
@@ -3,13 +3,22 @@ from light import Spotlight
 from camera import Camera
 from raytracer import raytracer_render
 from matplotlib.image import imsave
+from math import cos, sin, pi
 
 camera = Camera(200,200,2)
-materiau_sphere = Material(Vector((0,0,1)), .1, .3, .8, 20)
+materiau_sphere = Material(Vector((0,0,1)), .5, .3, .7, 20, 1)
 sphere = Sphere(Vector([0,0,3]), 1, materiau_sphere)
-lumiere = Spotlight(Vector((1, 1, 0)), Vector((1,1,1)))
-scene = Scene()
-scene.add_object(sphere)
-scene.add_light(lumiere)
-affiche = raytracer_render(camera, scene)
-imsave('one_sphere.png',affiche)
+for theta in range(36):
+    a = 3*cos(theta*pi/18)
+    b = 3*sin(theta*pi/18)
+    lumiere = Spotlight(Vector((0, a, 3+b)), Vector((1,1,1)))
+    lumiere_2 = Spotlight(Vector((0, -a, 3-b)), Vector((1,1,1)))
+    scene = Scene()
+    scene.add_object(sphere)
+    scene.add_light(lumiere)
+    scene.add_light(lumiere_2)
+    affiche = raytracer_render(camera, scene)
+    imsave('one_sphere_' + str(theta) + '.png',affiche)
+    print(theta)
+    
+    
diff --git a/tests/01_camera_ok.py b/tests/01_camera_ok.py
new file mode 100644
index 0000000..362b228
--- /dev/null
+++ b/tests/01_camera_ok.py
@@ -0,0 +1,14 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+
+# Import the Camera module
+from camera import *
+
+# Instantiate a Camera object
+c = Camera(100, 200, 3)
+
+# Test its members
+assert(c.image_nrows == 100)
+assert(c.image_ncols == 200)
+assert(c.focal_length == 3)
diff --git a/tests/02_rayon_ok.py b/tests/02_rayon_ok.py
new file mode 100644
index 0000000..1ce0c2f
--- /dev/null
+++ b/tests/02_rayon_ok.py
@@ -0,0 +1,31 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+
+import numpy as np
+from camera import *
+from operation_vector import Vector
+
+c = Camera(100, 200, 3)
+
+r_center = c.ray_at(c.image_nrows / 2, c.image_ncols / 2);
+
+assert (abs(r_center.direction*Vector([0,0,1]) - r_center.direction.norm()) < 0.01, "c.ray_at(c.image_nrows / 2, c.image_ncols / 2) should have the direction [0,0,1].")
+
+r_zero = c.ray_at(0,0);
+
+r_zero_ref_dir = Vector([1,1,c.focal_length])
+r_zero_ref_dir = r_zero_ref_dir / r_zero_ref_dir.norm()
+
+assert abs(r_zero.direction* (r_zero_ref_dir) -
+        r_zero.direction.norm()) < 0.01, "c.ray_at(0,0) should have the direction [1,1,camera.focal_length].";
+
+
+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.";
+
+
diff --git a/tests/03_sphere_intersection_ok.py b/tests/03_sphere_intersection_ok.py
new file mode 100644
index 0000000..d7893c8
--- /dev/null
+++ b/tests/03_sphere_intersection_ok.py
@@ -0,0 +1,33 @@
+# Show to python where to find the modules
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+from scene import *
+from camera import *
+from intersection import *
+
+def is_parallel(v1, v2):
+    return ((v1*v2) / (v1.norm() * v2.norm()) - 1.) < 0.01
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0,0,1.]), 1, 1, 1, 1, 1))
+
+r = Ray(Vector([0,0,0]), Vector([0,0,1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,2.])), "Error with a ray starting outside the sphere."
+assert is_parallel(i.normal, Vector([0,0,-1.])), "Error with the normal of a ray starting outside the sphere."
+
+r = Ray(Vector([0,0,10]), Vector([0,0,-1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,4.])), "Error with a ray starting outside the sphere."
+assert is_parallel(i.normal, Vector([0,0,1.])), "Error with the normal of a ray starting outside the sphere."
+
+r = Ray(Vector([0,0,3]), Vector([0,0,-1]))
+i = intersect(s, r)
+assert (i.position == Vector([0,0,2.])), "Error with a ray starting inside the sphere."
+assert is_parallel(i.normal, Vector([0,0,1.])), "Error with the normal of a ray starting inside the sphere."
+
+r = Ray(Vector([0,0,5]), Vector([0,0,1]))
+i = intersect(s, r)
+assert i is None, "Error with a ray not intersecting the sphere: intersect should return None."
+
diff --git a/tests/04_material_ok.py b/tests/04_material_ok.py
new file mode 100644
index 0000000..1f12e23
--- /dev/null
+++ b/tests/04_material_ok.py
@@ -0,0 +1,14 @@
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+from scene import *
+
+m = Material(Vector([0,0,1]), 0.1, 0.2, 0.3, 0.4, 0.5);
+
+assert((m.color == Vector([0,0,1])))
+assert(m.ambiant == 0.1)
+assert(m.diffuse == 0.2)
+assert(m.specular == 0.3)
+assert(m.shininess == 0.4)
+assert(m.reflection == 0.5)
diff --git a/tests/05_phong_ok.py b/tests/05_phong_ok.py
new file mode 100644
index 0000000..9d7dedf
--- /dev/null
+++ b/tests/05_phong_ok.py
@@ -0,0 +1,32 @@
+# Show to python where to find the Camera module
+import sys
+sys.path.append('..')
+from operation_vector import Vector
+
+# Import the Camera module
+from scene import *
+from light import *
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([0,0,0]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+
+assert((phong_illuminate(l, p, n, s, v) == Vector([0,0,0.15])))
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([1,1,0]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+assert((phong_illuminate(l, p, n, s, v) - Vector([0, 0, 0.13])).norm() < 0.01)
+
+
+s = Sphere(Vector([0,0,3]), 1, Material(Vector([0.1,0.2,0.3]), 0.1, 0.2, 0.3, 0.4, 0.5));
+n = Vector([0,0,-1])
+l = Spotlight(Vector([0,0,10]), Vector([0,0,1]));
+p = Vector([0,0,2])
+v = Vector([0,0,0])
+assert((phong_illuminate(l, p, n, s, v) == Vector([0,0,0])))
+
-- 
GitLab