From d109170ec17536a1ade885eee71a64b8ae234f10 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Mon, 26 Feb 2024 16:55:38 +0100 Subject: [PATCH] [FEAT] Chapter 07 is done. --- README.md | 3 ++ apps/CMakeLists.txt | 3 ++ apps/chapter_07.cpp | 108 ++++++++++++++++++++++++++++++++++++++ data/chapter_07.png | Bin 0 -> 19142 bytes raytracing/src/camera.cpp | 58 ++++++++++++++++++++ raytracing/src/camera.h | 8 +++ raytracing/src/canvas.cpp | 26 +++++++++ raytracing/src/canvas.h | 4 ++ raytracing/src/world.cpp | 6 +-- raytracing/src/world.h | 6 +-- tests/07_making_scene.cpp | 38 ++++++++++++++ 11 files changed, 254 insertions(+), 6 deletions(-) create mode 100644 apps/chapter_07.cpp create mode 100644 data/chapter_07.png diff --git a/README.md b/README.md index a681424..ccbcc8b 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,6 @@ Ray Tracing: The Next Week book: http://raytracerchallenge.com/ ### Chapter 06 ![chapter_06](data/chapter_06.png) + +### Chapter 07 +![chapter_07](data/chapter_07.png) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index d9394c5..7636efd 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -10,3 +10,6 @@ target_link_libraries(chapter_05 PRIVATE raytracing gcov) add_executable(chapter_06 chapter_06.cpp) target_link_libraries(chapter_06 PRIVATE raytracing gcov) + +add_executable(chapter_07 chapter_07.cpp) +target_link_libraries(chapter_07 PRIVATE raytracing gcov) diff --git a/apps/chapter_07.cpp b/apps/chapter_07.cpp new file mode 100644 index 0000000..17e97d0 --- /dev/null +++ b/apps/chapter_07.cpp @@ -0,0 +1,108 @@ +/*! + * chapter_07.cpp + * + * Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * @Author: NADAL Jean-Baptiste + * @Date: 26/02/2024 + * + */ + +// This is an independent project of an individual developer. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com + +#include + +#include + +/* ------------------------------------------------------------------------- */ + +using namespace Raytracer; + +/* ------------------------------------------------------------------------- */ + +int main(void) +{ + World the_world; + Camera the_camera; + Canvas the_canvas; + Sphere *the_floor, *the_left_wall, *the_right_wall; + Sphere *the_middle, *the_right, *the_left; + printf("Chapter 07 example.\n"); + + // Floor is an extremely flattened sphere with a matte texture. + the_floor = new Sphere(); + the_floor->set_transform(Matrix::scaling(10, 0.01, 10)); + the_floor->material().set_color(Color(1, 0.9, 0.9)); + the_floor->material().set_specular(0); + the_world.add_object(the_floor); + + // The Wall on the left has the same scale and color as the floor, + // But is also rotated and translated into place. + the_left_wall = new Sphere(); + the_left_wall->set_transform(Matrix::translation(0, 0, 5) * Matrix::rotation_y(-std::numbers::pi / 4) * + Matrix::rotation_x(std::numbers::pi / 2) * Matrix::scaling(10, 0.01, 10)); + the_left_wall->set_material(the_floor->material()); + the_world.add_object(the_left_wall); + + // The Wall on the right is identical to the left wall, but is rotated the opposite direction in y. + the_right_wall = new Sphere(); + the_right_wall->set_transform(Matrix::translation(0, 0, 5) * Matrix::rotation_y(std::numbers::pi / 4) * + Matrix::rotation_x(std::numbers::pi / 2) * Matrix::scaling(10, 0.01, 10)); + the_right_wall->set_material(the_floor->material()); + the_world.add_object(the_right_wall); + + // The large sphere in the middle is a unit sphere, translated upward slightly and colored green. + the_middle = new Sphere(); + the_middle->set_transform(Matrix::translation(-0.5, 1, 0.5)); + the_middle->material().set_color(Color(0.1, 1, 0.5)); + the_middle->material().set_diffuse(0.7); + the_middle->material().set_specular(0.3); + the_world.add_object(the_middle); + + // The smaller green sphere on the right is scaled in half + the_right = new Sphere(); + the_right->set_transform(Matrix::translation(1.5, 0.5, -0.5) * Matrix::scaling(0.5, 0.5, 0.5)); + the_right->material().set_color(Color(0.5, 1, 0.1)); + the_right->material().set_diffuse(0.7); + the_right->material().set_specular(0.3); + the_world.add_object(the_right); + + // The smallest sphere is scaled by a third, before being translated + the_left = new Sphere(); + the_left->set_transform(Matrix::translation(-1.5, 0.33, -0.75) * Matrix::scaling(0.33, 0.33, 0.33)); + the_left->material().set_color(Color(1, 0.8, 0.1)); + the_left->material().set_diffuse(0.7); + the_left->material().set_specular(0.3); + the_world.add_object(the_left); + + // The Light source is white, shining from above and to the left + the_world.set_light(PointLight(Tuple::Point(-10, 10, -10), Color(1, 1, 1))); + + // Configure the camera. + // the_camera = Camera(100, 50, std::numbers::pi / 2); + the_camera = Camera(320, 200, std::numbers::pi / 2); + the_camera.set_transform( + Matrix::view_transform(Tuple::Point(0, 1.5, -5), Tuple::Point(0, 1, 0), Tuple::Vector(0, 1, 0))); + + the_canvas = the_camera.render(the_world); + + the_canvas.save_to_file("chapter07.ppm"); + + return 0; +} diff --git a/data/chapter_07.png b/data/chapter_07.png new file mode 100644 index 0000000000000000000000000000000000000000..c56a3c034c1e4dc3c52dbf6f3b145db48939ffbd GIT binary patch literal 19142 zcmV);K!(4GP)PyA07*naRCr$Poq6zXM_K3l{oO4$ge-_4l0+h?DBvzQTh){nj-qTL1Zzeuwg4s} z2?>O3H!Eur*$i6{OCgF5$PxlmmLp0C5TY~A2!FsJm_%xjfvk7=t?xV4>)WSKcR$~! zPoMLi_jiA9)veszv-Roj=kt7@rPwSYC$#@IX&=p= zpSxG3V`yJP9@phwNMFv{cdCGqeo6Lsc`uHwh0jK9FUBj7Q~sqVKK}7y5(6M*cw~ig z;TNem`wUL!K+i?aLpm1KA#!k2ubg>r>No^Hq(gdbwMYPx5L73`u{Q(^k^X?d&OZm~ zhev8+TaWN8f6=e$9Djq1TO1Y=E3rslVSjD+zg~D_nMpvX*q=`ZQHMmb|$1F zlNE|oI&e-GKvn@D<*id4GuL5L@16K}s{ozYLn)GgAq3LQGsw1go*6!~^)$4vl0pNt z4d+a$x?LvK2iRBEdCX?wq#ym!wgTj;KMu^24UqsXr=y_fBInhBBn3C^Fw;+>+MzZ8 zbM4rtGW_WK-lzMi2Q;>#%fOJbdH6Ue25Kud$6KnPNMG7feT@*k1whK^NRL!8^yR=3 zfg0%rbD^OB;-Flo0N7Xf+jvh<;YI7Fa%h~Y4+p>if}NCH7a(>79TdSZR3xc0M*u$3 zwpx{<-->*<$aU;%%spcE)&OAN@S}_j>Np*hA_7XXf)VKroYMu6Rn(uBpsw2cRCzhI z+W=q$f}KD}sivNeBM}7kXrvz&sm-9>8@` z*HI2LTRDY_&pZ<@Ur+{0WGDbW-=79k+DKyyeG36dRy3gOkWr~F;jel%NB?$-p<`5M zuB{9+`Oc5L?|n-*1*XvkfZ;>JiaM!Fs9ODX?srjtLjy43IAn|ZA#if=gUIQz2Tds0 z#EcQW2C#=lJ5%>P3c-hnh$K50^*;w7WZ&`2+YLd^pK>7fwyM~v*c zawDC31OUvnU5(H<1fZ-R5@z542YH_^kV`mFie)hPN+PPRHj{ZL(l$y2MU-G=bNUdw ziakyP@R`qq-;bl@l8{1-ALw9co-q4zC@9T&WJLjxq+~rM-%CPVO0}ojl?6HDOk&rh z-dX;;Qh=rTJ`jc|n4t3jr=L_O)B}0~A1N3r0*v)6@41v+WCc?}o5+6pFb)8@@QYRi z7k-{XYqU|aHkzfZ0>6x5x1BDD$n4xd%9G{b*Qjqsc${n3T3{prsH9(otR3kV^|2> zc)`+!Lkv41#dp-7u7NRxze&eZI5nm<4=|wy9UpsySLv-`0F>HJtYB1*n0gt`Kw$>D z@Vk5WSVXw%9`C(31i*#BFQJsskalU+Uq&JJ5&q`XVNSuba)X%>VCjkFG#JIan8A)< z^f$^L3NC;nZ!rbE=MsZ&sL|c1V2acm3BbPdemOP4>UbP)hK9ZdMu>+)JQ{TlmD8xA z{sO?V!rxqdWCnk7`9FC}3&11<2}S7llai6&9Cwhmk6sTbJ<>@75M`B*VG$$F-} z4=^~GY6r@0lGl09PMwnlU={df6iv1RP&uxa`)rmLRf@=YWP^i^OEqK;fRqZ)9cMu< z=Nxh);gtYro0YpaAS#}EJ+C(OGPXnZ$qYPM*Lr1OU&jy-NwEXgX;kqM?2(6)06gm9 z$7nnXY!38D4wMRS3XYe+v0C_>nHOp6?IVBi2j%MiR zAOb%msoMo^IePc;(qjXNYIEd;82vqZJ1_^H6i$Wka`$6i@3&h6fMbJSwli=W zex&Npy(1F-Q18qi1qjH zdBPL)MCc*lmjv3#LSNJiQ_4<@9I)e4bwC~W6qU2NunPbRk7}b798+&eO@RpkXp7tx zgoyq3eh%99oPr#s;A`~D4vJ4zwRgP&;OXIJ2*3llgC2dUIS5wURQ*w%BA3f8$qgn^ z&dmRXj=@)eAqz^k$Ko)h+PS56LluBh_SE%(3T3NJ@A}efsWeaS6-x7b2&38n1R9Z2 z39*;S84v4xMCtf9WWo;uDxmDDs=vrPx5`Nw38frzc_88#Tm1#^^B3=ZZ*~M&o<6#H zfnDqb0T$Js$UTC3E`=8|(3dLCBET25;Y52i0obKcksMZ7OGsEpTthZ$&UhpDChuoD z6>=UF{v!2;)Ds9e%6Sc)|C8nU@O$4o2VBj858z%TM?jls_+0X)nG<%vmtF5pRV_D_ zHwPft(1@&TaV6;<+IP!>g);ICEJIHkSlo zOXY#^>TA%0GBkUf>{rN*YC+Fae4Wa*fKlB>p9NWzbvocZSODxBeo1xWdRwyuC@i7Q zfHpdK9tBA%uK^zq!knmKQjQ~+CZHTc$NZmFfPQCgKn(<8@_Gb7z&TJK0`8+uK@>fD zui$=N%1QOvT#>4Tx|zC3YN(9pp{h`p`Qd61ussv$L$o9k$W|XbP}X9Q0H_3 zV2Q#@I-kP)Un*}DdvB`%!w%aOgp>gcdb~FDxP3fHkn%0)U7rEfR*O{)2}dHRaXB~C zO{vA+0GNE8l8!(rn2Z-7tCayiG#N}mvJ2c=prXPjs_t^?&oi==15DL#a{5ce%clTn zo3&(u^q_EyJ*=dkBZa2g3%Q4B1JX7!_o5s)sTS=COn7zyU(Crv0OYDaG&FT}kgcuu z-N=SxLM^F&f^tz{Lp>tZdAb0S>L4ZRFz3wJ0E~3_58rqrISM>_7$Uh`6i!_nI`s@N zg_9JF5eG&+GHT}w2A?ex2|zCVvM?#}ij;!s(pi|GB*6sQRH40}KqD?jW!u+_?t7h6aZUL8_D1YY}hD_7|~8wXpIJZfYWH{n2fMN zsv1qfB>^}#_(5SR$73?o9}@a%p60tO1-CxcU$p+H`pSX7Wco`Ye3A+<{5cI*0K(+G z5X%Y9=?o$2nUsR3u8)ACYndr0O%)00=c#*8DIECOAV8x490GnM(6}9gGUn2bvIzB; z00m3^1^39cDf<|qo{{yxesjbCSVIv~#`O+MQ{fvFl% z#TS;L1;DEC%T#FAOAP=&62PXWC{<@GlsXUbiqttQ08({G8DU|Lj~o8V`pW^(@31vh zA!^iB&ZF9*^dS|X=j?z99M|tVKr3p4%yN{1&lbA@z|xy>uj9ZE0u^P;|3vLm|LWK^w<7@?35dP{Sx1S{cMsCf3E;AhrvQK{2Venc>yisX#m$(4 zV!*UWfFUFFMK_LI1Uh2mag-yb?m;P>SP=MGDdxMai9`F=TQK3PeL3=B8+Sp0_8}kdK)nR zmjYl-5F(IR_&Ln}NtKuCbJX=Mdj;*mzi%$`U_ZZcW6(B%hr|I`3O`iA0E&@(MaqaH z&miwtYbp~$+12SNG{YXO6)dP+r=XUkO;dp3LWNs zO4D(TI-nZLl<9k)^rS!mZd3S?3e?peHftW~Xq2+64nIUmQ;wqt0Os<4a@6?0%0Un& z+)8qVluh({oT}Fj4@deUb$iOmQr9m9_#$j;0&r;fAqGpRMN-uOzo0&;5F~dz zbu8zdQ^%-{5hMWZj|)P1-RNM*>~jcQT4s=mwmA1goOJGfR3D?tlC@t@Iid`Rm1Pb< z;9*>8$}JdqK4RbrV50X%&OW?h22TSPO zfd@Vs^|K6vAB6zSISUKM7yvyQM z5$XIC+*XE9q9>ZT*ygz&Q zyJ@wzKvlu-pq5ua4pq-$axebsW68!63WBpjwkDGfNk;r>|O8D)#`<( zXlPn=4P}Hq9;e!<>!Wk+$h~(d6QT}}dicQLv&B&Wd~R+cG(phpdzGj^DxZ~6izomQ zMd!R8r(w{#T0r7;yk}GH{MR7=)2)6;mn0>*+XE-!&gw6RJl8^!&Qd z0}wUn43zvsB%lU>A3Ex*g(6wvdB|Ne_ZLyl(J+Kk%HZ)5_)+!K34k>~=yyC~qXiBm z=^mj!L)quAHeAWlGTw*0SE6qhsYZKI2Tr8{*x{zJ4#2G#=zLR|@VOw=*y^t%{915B zlr!Qi`UGHZU?d0d$h&>eguq!4m4wHAQfR+}$7xhjiv~9%d~VLrTknI`?K0&4Dyu(Pk1_;K0;&{-wh@>+ zO)DXqFetnirEbvq4y_xLcVzVa5<8^WLza(Vf`6EOuMC{+y}r*WKvbc`-WV}l;yU={ zcGO>^CUg0_s5On*@_&87 z5b5s&odX+w0ql~F5fnGk)4275=FThJH&>V40EigvqLkklLSGLyS#OT2?-~H46m;Rn zr#WSqN*CCUsQ~CCU|ZLr(__LquA&gR23T-D47*H!q8{7FGg$Wo%Fe!DMr5G(N&=9) zK?V51o`^Eq1Z2r~FxMgZyhd43?=`mEUsv_lL;g<|=}+JBj&|OyMCF0u?9gCD`(dja z7pgnQ1&WIPaqwB}cR_81Q&v=10QZankbKD@;fEM)OI~50wscSf8sF6kr$G^Ahny2> z@V;_?S*O%P_-g^^1Yk?X#c>5g41^+JEB&1U^grt1q|HWbgt})DNC#GWu!u^$Yzu&7 zMQ$Vb>9!)@SXCXO5*v3a1Y5L0YlOatBN;IK_3QLc!)Y+7k=O*xU>N#FFeDhkK86CR z$mkhmz$_vtEk_uzUNl~sqB2ID!1w*+PtFHH$eWhJFYpTFbDZnZXTs+*fQCY?@qDzA zJA}Ty0T4+e6z=?zb0k#$PtF;XA+Y+PVQkg%A;ESQJpr|cV;v3Ct(f{1)=TOfSM~(i31Xkw7*$c*Xan`cKz($V5;IfWMKL29qN_++YE5p?5*lN<_}WWnw5rcJ6PC>d)(7$vRq4 z_$!Mh0q9ufw`)nr3&61P2&hALKZ(;fvrj94T_0ewW$g4`Xqu>``jNDeRe)Ilb}3{D z{19V}R0x{OLls@4)1aX*$CDw78fiqNjwy!%91lDC7oNRex59KL#MV^IHm5>tOvP+t zONiAi@o#S5mCT!lPQ?cx2ZZumNZB!=SYmIzTr)K6GX2+ozh#G>|1Nn2SP6bC4@4Q` zK=4CBiG;qb_ebk>Kmg`C_3giXf)IOFG;U;>kSqRJeCm3y(`l1!MchAa0h<6`YMFJi294d32Ed?;cxi-JI;TU0iVQ&2fnEUpALDI z>az+^sy_um{YSx1{dY@;#p?!w3WS?tc0_}4cK@pQ_eZ{8NC4WO0~U8@7Z8Y1RS6o) z5T{}887v71<|@zZ!VKhf5PLxG6P(iqV3!vuE#wf&4*;62o7B{euznGhh=j;vQGa(_ z_-HZNwK7kvsc6@PyApgZ?3I7ls!xZ&=I;i8Ivh6elQ6X5um$1TmQZSNbwkV!ZiqYI z@S#@MML?K@83TqXo2jiFt3ZaKin6B`fTDFt2CmiKwUj65`^{$JQ9t!l-YD=Q;OBvf zQ*mf0>l7H*8&*(%6xfm>0n+dl)t>_2-d#=ACkt=GUZwn|4uFl^pB(_P|FtU64T=~5 z`XR9dpj3js8hl_)-1W{+6oZgdb`_wA+EuUTf&IAQ%xe^A2;c=Gg~J2*6@zro_d5V~ zfnS$`5260RPJ<}A7PQcgfz~e*eiTHh+}|CSohrm`srn{b`6=*O_{|4AW-{b83Q&#u zst{PKznRScnGjfw2KxgdP6@`tVL4)KbAz*kYvQhV-4gA~4MhgRj8t*pePH9Nbt2eb zlMzXca-jXX>$8ylUf~%jJJ109)nARLq0k2-Y9w~AA>bFlnG6kp&WC_<8Pwk$S3E{c z6#T4ylEAZJuLnT`KNarUX)hLlHVl^F^HiXn7UOb)G7OG}!!i_>5Zn;rupTX*{_8>U z&6_`yY^o9%k_s``F=~Jk=vT10p(k?A8wz+4dmKXPrK%zcK)6ub34Q=9k(?f?5-CXb zIXH61l@@*;PGnme^`{0q{6GH4ubcj&2SXI>oC4IN!HqniKSxmI15H>gL*eyJAzV(- z430<$e&?|G<}J5oO}M4-3PD9GMGi9aWLoziFc*A1cajO}vkE($>SCPTuH zF@?ne2=uy$qC=q;4M`*Apx_t1PXOp-I}ytI@2)ych~1M&&Tp>z+~9{7`nstvNdOuc z`eCr05+g^0WjMTUM~BTkK{+sDbAnO{9@)@;9$Xi*`&Pv_KY43%j-YR2QHT`+k+OLX zFkxGw9$I>QXxI&<@Vw`AspA#^;hT*Ze!6b3H$mao01_u$K;VaV8pM+l?V{i(CpFvo zeb%t7`ZKCe)t`l*9sRX)|NIkJ9RQZ`k+4(RWgMHG|@>6Zn!jb6h19uW1|1_0p-Dt+OSoL_;oRqp|G2#!)5 zGW6|B{i(3mj`jw5zsA6ao$u#QeR1$JOW#t1Ai-dWng?h@V1Gcw2cTUsvOdoTs=0!P z*2V0BHSsS&D6EUl(P5b-bIkit2G#3vPM_|xAf@(SQl?U7fX{LO914C(<4zTrNqjc^ z09Y2mFLB=*dA$-q-f{U4h{?WPLa2FuX2jQ)(T)0gA+QHOIpnUUD84cK%HeWTzi2$8wDzdJ5ESxg?XS5J45 zp|3BV{LokaT`qTX3ec?hkpCaTFER?OSA+OV;=I8S8w%SE6YPJb`ZIs@k~ysc<@#Zj z3zVVo;SJRlV-U1`v~*-RXFNQOSz?CiYX*Z`i>l2h4^j@MotM^hOdR0=969{7 zRf;L}WfttrW2;a6_duasaHY4oi(}X|Ch+(b_MyK;VV1f&p-7_%UHt1iwUx>Q_(^ z{4)2YMt&(}7gdn9zzKzY$EBx=$^P9s^i>h-Q+_h*jnn(3wON<&m)EXhg-M4&3ObSBMJ``eYF7$RkG|K3! z07C)~uxtM{X#g$*{1`7?d(^iDCDgN`ost;URgIZBM-66;K2};{KGXOR6@sZW#a!%W}uX zCyUAcJx2Wnxj*|}c8eG5PnFWNZ!(a&s|CF91=0XS4K!A- zrCxwpnP?u5TX{o=z6c~s!s9y*oNA`MgzC?zMwbJ$dB1r$yi2TzT`MbU3d`o&hM39; z&2AekvjW8X|M_Z=`N|NxF1VHd^S8>1%?Y%tL%cAU0$>Y>JpyZp!I6c7t)^XfU@zCk zxsQqia0%e21q|LzQ1yqxuLUhM^o=OW61cgBPB@z{p8qH@Ic~2Bf2H~h%+`+nn%tin z_%I4^&&qCb;_)YlhaPvFc<}xQ#C_krSFEqDH2~OBe|AeOe_z1HiV(A9ez;ARzdl&P z&?!JWBCK`T;p2W^GgLxg%|D{cnvWmggCi14Q5&3w@pIdzSQ3r zU-M`&IcB%s-_K2bG26W;<)>Ak4twYG|0ZH0j(^B;;)fsiL*m2}P88qx+SkS1cit&h z53P#X)>d;PRGSBMYk^IU(B}MF10hWa(s{u72C6m(Xgly-pZHq^^%6DKb^c%lJ0Hg_ z76>|SRMxe^QZq14{+XZg<^k@&56ZnDdA}&w3I;xsfb<+dta0VsKe2b00iZnD+wMwj z`4ZXnWjYfplNIr>6HXM5d+g(cRD%EXf4(NZ{jG0_jn#Fx1$VE(5&!@o07*naRMvbe ztYAY_U;U+4gt+;D-gFpG1**A#c4dg&Gf*l(d5-r}0Q7%_Fl^jHRZ|I4yP9W@*CRRP z9v|=D8jZqg6$i1?IRF;{KV}%~V89K1f%BI&^i2U$0Z`8U+cnYCMjD&G#7BVT0EpC7 z#~!m^oN(OnVrz3#+<(t~V)gJ5l>-bnLY@D=w>xyWJ$|qn1fCCQCPl0L0_D6wGYuvS zL3^+Q3|n9vBOFHrw-8!G!wwZ3VL3GbpZ2t-{c{l9p%FMaykhuyN-6hRC;$RWB1Hgexx=&2*O{P2b|30bis*O5i2U>-CExiQy2PrOX6~y zqBhi@91Y&`)&qyRKyRZ|vvt1vh?1KQv#Cd?gI`Mp#u~UX3{lf4)sc8s8!buy=Zyk( zpq-NdWHrEm@YC;ymyXjYy~8ikI5h@7k^nsSkwVD)pIiEt9{^Fgz;ORRyDN;H==nshNuA$sQ@DtcIPMlmY)M$5D@#vQ2$Th z*i`M(AY!59nGFSq<0U`&mMjQ!y32NhUkY5|4mK1dQ^%zO6#FCq&7OaLUP}+NX`r~d zf8OrTKKRt%?Ua{bBLue_jJF}Gw;ZnVmAK$*aT^$N^?wxI@^> zUFG4xvlIHxn*^A;aQj&jfO-JLPJyu#MrKz1*?EB8{J;1%_~ABK^X~$?WpIsc@#j-v z(qVA$$;@yrUi2Y$(oR?&t< z&g-K7q?5V*%HvPq~R|P=(3ltU`Y&%elVmNDw3_GpCc!&y&GSL9sM(}H?r%Xi+0>1#1 zh&QD=qdb253r^Aiq(*@w^8lN>!8CV*R`APx7|B%kS|XBvcqcsaZ_2TnVAUDMKEBBZprDXh0(^O8wOUTMOPTd8vjs z)bIA+Izfnib{U)*0k&3aPx2Jtd>bsI2-UuT_9N&<8K&Up20%_urMLD4 zlq*k~%iqFR{)Pv@ER<@&kbtazc+rrA;86h}9N6T}g~|)qIJZ1$0Cs^NGlaE;R+Yeb z$)hRsfBTdFQ5j$I~xKWlLIBCv*kE7Ita1@zj>YZk@pK4mBozBOV!Z1*jemTzkpT8*f9X}Df_D-DY)ATdSPr^?^P%d5eRG?IXo2x=Y z@X$=GJvbFd?wN|eyr^eIh*VBx>Z> zc4P@aC;oDV%v5->Tb=i{rz+LAYp+mg1$RqZg;Nc`nN)w9GclDRu%`lTIJ|j8i1kBL zvHsvptll>h2mkMuxa}>UFT_wkm$BhCAmHp97nLzm&QpKx=gd67C4irU6qxH+)Sw5V z>PT-@sQzpR`TVc$am(TKYLIY4gmxI*{w9bW1)ficb{|MjeH6(pe@lEH*e;2SeIHm3 zgb?%o9Q;1|-}PU)aO0jYggF0B1HU~o>@|w9v71cXTP0{dif#u)bWSk%IJyL1V`ms| zFTh|LOe+NTm7mH3no!tV2OQnsE7B*wZUN{Y=6_#3M0{;HV10ec|OLBxb0OAGTc&ga@ z(23Z6j2ZCQ<*7eYhj!#wDr1-bGZ3^Pums?iHz48$MGotMk+lc)DDlB>O~v2+!N3p% z>$}Ejc~sHNrso5?eF0U> zX!?cS6*~TH5T^pYwZK~Wg_|KHmcyC(fNmLFD*tBz7}@bT)q(%%BY%a5zJSV$J?Gr7 zK2_{LX+^=$4th+~hvm&5llzkjT8d;@FG>X}^*0k+-ayDyD!_F;Eyj)t%Us}w1mNMB zSeGjBfteZ@dEo9X@sA(69kJa}o6SGz}UU|RDR0< zzri3mn~BfB5pDob%%{d2nvV?2Q26lwn~FQ$J3bXy1#EsJ z_XxQZ>|%Ya41hd@xoyD zg}7i8*e!oE5LEO0Y&g8>tp&EBu=iaMmk0C*KkR0xa=xDgAk!G$_~P?gubpzN7LcbK zFuDsfFnr}#e@Ps3k`8^9`ct_-{l^)Xys-~Js{j!I%0Ur3AR<-Zp_y2hq3{D!apYb- zGW?GpuB!s81B~)m%r>QNmpk6&-S_}3g8s|UV!M77u#R1J>z`+InQ`_ksL$G z0rK>xKfMuBzv|9k(z(BV6R{#ker4{@sy~19*Bb$jwAkl%J21xxY>I;ipIl zEJI-rfI1Io6rdduwkl9gi+NxwR_~dK!{42XFMsR{^Xe$sOVF>(1;PtuQ+3Dz{J;S? z5d0b{32d}R#q~Mpk*LtIgucK2w5K)unrXB1{^0}d5#dIbEdH5HcujD)5~Q&qLhuzh zGyR1#;%i^(`j@?G{(dP4c7)?+ANw|O%!w;v&wf4WSuJ<7;jjI)vT5)=yZ4G8{-GZc z_ug}_xcjbeimi=lV;YQG4Pqxmt2u%5=`e0I*v<~#oGEz9A2A=Lx*SLfkRVq&jT~@)ckxs zXCM1kvG4d5v3tJ|yX?egyYi!vI~8L8{$s_DKj|mLzuf&zao0cJtpRA(0;~CeW;KZ1 z7{P|YdOo110{w~6YD&yhtq_q4P%6u@L$G(SRe)U1C(r=gfnOu+YP3hHW;@LJd-1RQ zgIHM+LVk*OePbrp)`d8-HWPpgewR13jH{Ug~`xlg$BcSNLUe1L&YfsjBlE?Rhf!?)^^L zca2JmZEnrP#)c598#A%GHd6pR;sH=XP%6RuB?KRsif?^)DlRioC@y<#*eLBCr&tJm)Lup z83Eoi5tH3QIV3d&#uP}8EYG*Ua?9Ynd4O&{pj3Z$8jLp~dP|N1%N(E@4HkMNSgsK^ zJI1U^0B*$r$T9p;oC~J1x|X#B>S+LO6Zl0z#ToQSz!J&($xBav<}(}Z8cW2Va?I6Y z-|mT+&Som)-PoLowGAEmD)?Cd9+`}EP-6^UE=^;7Wie9oPBA|2r;Vu!t;LfS-|M2P? z#ql`>=r;e;Wl|7St3c-4VcE?PVyi(E_{>0vUJ+tIXjg=I^8sZZQ2q|Q_>%mW2qhfD zIgXv^wz!LH!wq?p767>`H5#B{dWKYIOck61Gmi3$o*RM3Z$A6k&7$Sjr!s$o*3_S5W@0c!{YGzdbX39|5Dh zRZcaI23k>MCH}F{**X9oP4N3K&v}lvF}khdDfaEr1+eN*=Kd@I z<=}@@fDV9iBv|GEtpYqEM}zf%Qy?#F+L_FiYuQ%TiiA|3&_Xxik z(%KZkj1F@;ZE)^84E$25h+N(^bquWoTa*uNzCj#w;>64Ylq*4mSn;R9cq&=JPi=)S z(*hcNdNQ=x5=-X&?4}52C5YV>M(+}B20-j;5VKpfRDkk+@^|GKm(6R5NKIwomxE@| zPwaZ?4ozA2(n7f93Ss-pX;J|`>z9AI2>Q9sm3nyNLEwvVuaW2fmVsPY4$>efXe6MC zK+lzBHWQCM?n<>wmD^Kbb0#*nCgMkacf9WgY{s&j*Bfw@Fj8%YA1xocNRiGRU zkqS@_hDa6S1CaafXT0N@`I5O{&RcXq#4d#c+cDQ6-+At3$>nVgXXW1{2ZRCzDQ|t# zJ+IR%L5`J6;k=a~{!TEaKrRPp^MH{pv62c<=KmxF?L0tlIh<63_IK4w4;1H@)je|c zK=t)VyHIh*egpO3VTA;o^We?${L- zbxLTdX)jVeh~47kQ%)2A_~oyPBdb$S0SXoVY5-1M7%UZ_90*Y(!X{^A-{JL_{ht0S zQ#HK!+5LQQ+xvyi(UwMJNK`(D3`6=RS8{U%&`870#1Dq&#Edcn;S7u}6plV&7i;g<^To?P)>tU6QX4v&?rDV0MY_r*wYw5R50x6_pVo7-n?@zcM2RU36E3G z;g7#{jo241hvN){SP0rVfObWQT@!4>U#S9vl^}AveEYlRWtS(NLlG1yhsfv~t!|aE z83c|sp~mU5YykEJzu$S@^V;Rkc{tAtQkB;kh`Bsk;Eny4NCEL-)62x3-8#l}3UJe` z{D@3}u`5BEgCO2im_u51gugc&c(eYe(ooS{TMLBmIsb}e-j$m|aMd2`?H!fTJHK?5 zIPQ@vV(&v%)P8_+MaU%F5yqxh&9{IXlcB>cv4RZ|)N(j81x9@z#M=_f?`qe){EGS8 z0ZyP7C{oHf1HN4JWXp=ckpndDxhw#7h2IMd-d z<7 zgh27e3$E1sMVv%XXNv~nd%kj&*e3@=%$|Ua6(J@y&=?6ec|bP+A|WWJzqpCeWx z3?az>$q`_=cG&)2`@2`R2C&cw!#cfUCqX$);FA_)lm*yOwR~gH|NZ|x?dN|U8w5e& z_kz<;Z`fk4BO|b*yc%_ng{#9zL+^R;60zGTz^&;_Y;NihcwMSM2|u+2PKYCBBD7R~ zO#seAU|{>a1&D=?G0kE&Bbr z1xIj9A+!?+fU(Z}!skD~Wpp_YmGnlG=MRh_m+PTmm_6R3S8F_1E_eIR#bS?H{h>l& zng5gUlS|+f0JZXKOoM671JpUdBdcxr$$xPG^bdD|VIlC`y8|9Sd=pslP<<#DK4uL6 zx=$Z)Bf@S@pjtkt$A`3C%mFxG5;y-coErsJ`9HH2mdOFi@OSgD-WkUKz5dLrFxA}E zQ6RR}vCoi$aFKUtblJ@DSpP_c)G2QKU`_$XAlCvJr2^aq?IIMZL#i`_o@|jYyzj2p zh<$stA=w&%>k4lund3AJiyct_?xbHE4gtf^NBy!ns*C@riq0Na6~t^qC#zW(J`i{l^CoCY&r2B(+6 z*^LlnC@gb;{xley|C7*6{S*KjR-l_Wr=Yv2>poyPNVp6*%-7z0sW|2Y`GvUVfJoy5 zdv-7+2SBwY{``9&{&W}HRBt%zYS(ImL9eTV2I`Pff|MOW#{=hvIDrda`&u#i#2^2$ zt^y*CrW&MSU}IB;pmNOS3@Z+xeB;X(ie0;OmD@a^41w3z^;8(W4!F4#&MLrzN9N1k zVgS6>gI~_W_X0esj;MZ7S^c%3Uuf)?-*n0RLrHd2IQT@S{YG$WQ&j((AZizwcB{Sd z>}%!@YSDERu%JjKE&&u}5np}HH5z~|S`Gk1DrdN`5ZN?dsj5M|)g8B8AolN@s9aKG zAjHfCOam~T_mj`P_R6=-o3hZ@=MscgjagM$ppNacDQ7#hI<)V3`JY^(R*9$y(rW#* z-X~C2wHgeuJHy!T1DoBT)g}n5agAZ&7jtHmFv%T<>o6jIda*q!bO!7Wu`Q_1%(J2Z zY`_p0U4b81AW>Te;r^l7L`7bzhAQlk&$#u|=c@%5vh3kx==n}C-j2{m^6-;YbDaSo zy8}~oL3Lj0cn26d$c{uEp8uAM)Q&Ogn;~+YuvsCZAZR|4u2zG16QN^plmGUnSLhwR zeW#OkycrvU>nU-M>VkyoQ(if`L|$E>_^PX~7L!|S2%Ksqn>#w1RbfX1Pc_mlH=n1J zg#55}mamvc@d_O9o@`8BQy+&6>G zMyVN7QirZR=XLs&1Z+^60?uYa zD#O(8x^rI-&B<)FVQ@ooRTE-&RE}{-yQI=IsNEJq@qz{by~?I4dIyAcz4!HRKU+*D z6O|8Ca{|rxK;%b}a=+`Z{(V~YRZu(r09lc0L^>$bafJ0!MHv>Tp`!W#!^3Q7h^QPS zY8w*}QQ%RI7jfP~i1V+!(o=w~9<`$g$(0lp4BK}muRL(3+Y2rSzTcDJGrvKV4$?uv z&e>^@se{sCMHfux5mj&?>?rluHC%>8%ZP!Pt)qf|mj|G;upJOq0U^_4pLgk*4FMI+?#T6Izbh71Q%+t_0cwM*SK%0~@QApOSG zo)sYl!dCeygRWeEot#JoWz!{x8f|-K{d6(lTB(_?4h89B>~neqqAg1sfDFJPl?Hp7 znrg7H;uabfn=+G5Wk`=qfv^W+s~HmrD>(|JPf`&KOF1qGh9vBO=mQZtR9&&v zUk46QLdGvk9)Mn>byX&aQL@hI0KsUdV1_M}Qt1rJ0YW>ZQ!YABIEH#e`sEm4*txEd z+$+#8k@{ktld*L~A?ED;9H{_5^??uM11qp%#^fnlfa*cT)aY=OV}a@v35(HAv>-*e zQ7YB;C#bZM{)wpVMFH`g%P!LZM5Ho#4q9n|7oj{VqFxa1Pz1^VCY{tE zSZCF8G95yT8ui(!t`J9zoCEYf#As`TeU!p3j#hf;qlo=O{giOVsBNR?JL+7`8uG8LOi1t;` zX(Kj1wDJq<@D-O{Dkh)0>82SpoW6hxVkyB65bV8kA%=~1EWogOFN?y4jdg%@ z1ERE%{@TgO^kC}?3zsuoINJem#4p?n1QV6gtHGjmTuBWgM$M|*v4U_B^@@gZHGzpb zc(iXv&g+z-K-&Rz^x(=ewuClF5f*z*WB{e0GgV0?45S7d zb%zX;phmdlb&EKeT74XG&c%Jap#Kid32^g;n*aa`Xh}ptR90Ps4(jYnE-@jng&QMO zgDL<`ID-XN#asjg(GJ4Q3zBsR01oaL6`T>30Zj_B^-nD}z%hex8~5R4|3mvRQ}vPk zog=OQW>Aj%tQG)A{z9yfEmJ{=H!U6<37(r(dPum7oWtojV-CxD0wHO51J`jaRaoqB zP=$^<{y;z>(GA%q=AOvNGFqSEd07BL1q2mJ^#thHm0)cMRsS<`qp>XpR)v(3 zas07=;W+=EVYmp6=vN{!EY7_6;vfVLNKO_W^_*aV(1I_c63o_R?bHM4n2=6#RD!Uw z!(sJnRH66bc$Nu<9Hu1Rt2+R_8`HeSsEimKOT|Q>-f)!u|8(d8Nx-4`ltn?1Fr;49 zN6i71$a{27KQKTDM>&=1yVc)1)Fs+?(esdcC&d+$EolAw&L|DQppi(pfrhmN8W-t!n01aC;zIj6VHd?PLHtIw0eeQEk;iI`HI*P)uc*<25X^Z^YtyLnLC-5zBpl=FF+8j3{ClhazEt5r zFeL4OsUlzgn%87PV9$F&4`z5eG#5CEj?jlkToOZMDUv?aV8&n(VAfQGkPU$OKeS(? z&K-3!sM?FZYae#Nab5wB(DulkrvUihZn`PobeV2w`{WIjC>j{Lt*#iL1+BQ+!F32_s-VselybMx+Ol8+wLsl}X(S-p$hQmt{NW1{U z>oiKw4add+LZFU0s*rPTrzj~=?kXt@1`J#IF_2#@=)k3K@=ERQ&Xfq>!S0oX$$Bcauz09dVIIY!4&c=}W*fDqeW4UR<- zGTMaQeq04foR6wPPKaF1W+E``2Y_P0)|=J zF;y|L!gg7B+W__503moj+D6g$=Zxwn%2NY|FMai^!5m;jK6?CW|CKQ@SKk^7yEy08 z4uv~6WaJ&I*7j{Rhv2FH#fZR^`ye*iQO zhOyRzp)FDcE>dwob**iIdJ3HMWY`BBBhVE;@A?Ywu5&# zqc;V}RV7EU3gmb@)X2#5maKg^N&`(*a15(PxaGp60uYjh?ZsfMXbNyZ_SStUcTO9$ z%Hh3p>N6QsyEOnvR`N18+=9GU=X@X`;r%`k8rZ@i$ThApwNaw%ltDFYGTJx|Qq7x; zI=8@KadNnWC`h0`baq~uXT;j>j90yCo&#Jo067hY=9~JG@SPi~Vjg2?2rhLyF%3l3 z?Lcis+Mkm^y7xg2&XgZMmm7%%Wy*1!6COw3kCOw=l*=y%4}d{ufGU-dKjIh`$72m9 z-8<%x$WF~kzW1!ww`*G^+o12ZEwnAN&om_I42LG;o4j0+(JC{c{Lv`NF)v2p#4}#P zQh)4gl1+p%uq~s(_Fi7MFmHo67K>aWsIC z+m7M+;{)Il8q-pQR$N2khE>dV>r+i|K-k%NWt7K4M~sI8Aw%JD9a;-+J>&|P9)LxL z#8n?aBX>5W5vvJ~lISai!8INZ1i31rkMx8~o3&!+;2*e-tPq6kb_8t1e-qBYBo~Cq zNGD=rFYY}AHWjnojfkTHISoXHtsQbpaGNmG5`7v^pN2D*HYD4;Bo#Ff2#W*>1D+hA zk#s7a%?t)Ws8L;sx5;pQrFl!)y5o)vcQ76pm<3Kx-5XTq%c=%R8{jsA)6B~+qZ zCs>ja@$8=x!nIW4i_bs5=RuGX&%>R5~h0@VnW;Ghr$`b`z5mU&Kfb-&F( z$W3`fVVc$gRviM-w?7C>wfI2!)~0ro>PR<_U7!$dw&{Q!8u&ujxEp zhJbX{usHH8$O)CS@6aGDb#{#FVh*eUKyGD1=a*I_b0DPHxWEeJc>g4Hh8Pu2ybsw{ zB}TFxAqeybZb&=|Cszv3Qu{4PW0g3(5>@E8--}-PO2(G>K_!w#<=nD96F$FCQujF; zOi5|`s{VhgKr>^IoZJyq_l5buF}7`2!$79wa6!mbgJivyq)19_xC02e>8znZD4+Af z9RT9<&#C}zC>2=h@dt!pkzs(Lt@FKs6OK8m>Q1X9M_lUYN)`VO2vxIhD*);?g|v?A z^JB^dW-AeezgR*8dsgX`#$?N;LKDuNKUgc7GWup%t6Z6pd9H2{l@ z1MK8g6aw(9YGG2TVGJ22Z6gS_pw>fMmpHs3!ea6np_du3-D`)(+Yf--Ssj$9z|s(@ zWKd*aRlv>pB8s48+X-XOh0+UmdZle1xeiv51GjxG5Dp5!63@bF0OmH{V^x7A%7Cn= z5}=h_Gq52H0l}qJgF7Hh`YCHKFFfzO;YNYCB>+LiSxpsG%qx-5?4k$;42#AJ!DN45 zmO+v(?LV+1ELDUrumFUNA*c}en$pTBmCr_JJh>AtHu$0BCx2r|B@D#~FnIEU@#F3MGX001BW5 zG!SM>uLcu+7HXpkLI?tNrT&l;MLPg21YoNHLBrufaI7kj-GK+p36?|wRg_>CM+jV- z>jZHQv*9Suv9hh{{g=b VG5q(#kTw7S002ovPDHLkV1gXOvxooy literal 0 HcmV?d00001 diff --git a/raytracing/src/camera.cpp b/raytracing/src/camera.cpp index 118f1e9..0a1e763 100644 --- a/raytracing/src/camera.cpp +++ b/raytracing/src/camera.cpp @@ -36,6 +36,12 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ +Camera::Camera(void) : m_h_size(0), m_v_size(0), m_field_of_view(0), m_half_width(0), m_half_height(0), m_pixel_size(0) +{ +} + +/* ------------------------------------------------------------------------- */ + Camera::Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view) : m_h_size(a_h_size), m_v_size(a_v_size), @@ -65,6 +71,39 @@ Camera::Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view) : /* ------------------------------------------------------------------------- */ +Camera::Camera(const Camera &an_other) +{ + m_h_size = an_other.m_h_size; + m_v_size = an_other.m_v_size; + m_field_of_view = an_other.m_field_of_view; + m_transform = an_other.m_transform; + m_half_width = an_other.m_half_width; + m_half_height = an_other.m_half_height; + m_pixel_size = an_other.m_pixel_size; +} + +/* ------------------------------------------------------------------------- */ + +const Camera &Camera::operator=(const Camera &an_other) +{ + if (this == &an_other) + { + return *this; + } + + m_h_size = an_other.m_h_size; + m_v_size = an_other.m_v_size; + m_field_of_view = an_other.m_field_of_view; + m_transform = an_other.m_transform; + m_half_width = an_other.m_half_width; + m_half_height = an_other.m_half_height; + m_pixel_size = an_other.m_pixel_size; + + return *this; +} + +/* ------------------------------------------------------------------------- */ + uint16_t Camera::hsize(void) const { return m_h_size; @@ -132,3 +171,22 @@ Ray Camera::ray_for_pixel(double an_x, double an_y) const return Ray(the_origin, the_direction); } + +/* ------------------------------------------------------------------------- */ + +Canvas Camera::render(const World &a_world) +{ + Canvas the_image(m_h_size, m_v_size); + + for (int y = 0; y < m_v_size - 1; y++) + { + for (int x = 0; x < m_h_size - 1; x++) + { + Ray the_ray = ray_for_pixel(x, y); + Color the_color = a_world.color_at(the_ray); + the_image.write_pixel(x, y, the_color); + } + } + + return the_image; +} diff --git a/raytracing/src/camera.h b/raytracing/src/camera.h index e696c6e..775ccd5 100644 --- a/raytracing/src/camera.h +++ b/raytracing/src/camera.h @@ -30,8 +30,10 @@ #include +#include "canvas.h" #include "matrix.h" #include "ray.h" +#include "world.h" /* ------------------------------------------------------------------------- */ @@ -40,7 +42,11 @@ namespace Raytracer class Camera { public: + Camera(void); Camera(uint16_t a_h_size, uint16_t a_v_size, double a_field_of_view); + Camera(const Camera &a_nother); + + const Camera &operator=(const Camera &an_other); uint16_t hsize(void) const; uint16_t vsize(void) const; @@ -53,6 +59,8 @@ namespace Raytracer Ray ray_for_pixel(double an_x, double an_y) const; + Canvas render(const World &a_world); + private: uint16_t m_h_size; diff --git a/raytracing/src/canvas.cpp b/raytracing/src/canvas.cpp index 77a0d65..995a42d 100644 --- a/raytracing/src/canvas.cpp +++ b/raytracing/src/canvas.cpp @@ -38,6 +38,12 @@ using namespace Raytracer; /* ------------------------------------------------------------------------- */ +Canvas::Canvas(void) : m_width(0), m_height(0) +{ +} + +/* ------------------------------------------------------------------------- */ + Canvas::Canvas(uint16_t a_width, uint16_t a_height) : m_width(a_width), m_height(a_height) { m_pixels = std::vector>(m_width, std::vector(m_height)); @@ -53,6 +59,26 @@ Canvas::Canvas(uint16_t a_width, uint16_t a_height) : m_width(a_width), m_height /* ------------------------------------------------------------------------- */ +Canvas::Canvas(const Canvas &a_canvas) : + m_width(a_canvas.m_width), + m_height(a_canvas.m_height), + m_pixels(a_canvas.m_pixels) +{ +} + +/* ------------------------------------------------------------------------- */ + +Canvas &Canvas::operator=(const Canvas &a_canvas) +{ + m_width = a_canvas.m_width; + m_height = a_canvas.m_height; + m_pixels = a_canvas.m_pixels; + + return *this; +} + +/* ------------------------------------------------------------------------- */ + uint16_t Canvas::width(void) const { return m_width; diff --git a/raytracing/src/canvas.h b/raytracing/src/canvas.h index 743824c..1b74cca 100644 --- a/raytracing/src/canvas.h +++ b/raytracing/src/canvas.h @@ -42,7 +42,11 @@ namespace Raytracer class Canvas { public: + Canvas(void); Canvas(uint16_t a_width, uint16_t a_height); + Canvas(const Canvas &a_canvas); + + Canvas &operator=(const Canvas &a_canvas); uint16_t width(void) const; uint16_t height(void) const; diff --git a/raytracing/src/world.cpp b/raytracing/src/world.cpp index 0411e33..c80ac22 100644 --- a/raytracing/src/world.cpp +++ b/raytracing/src/world.cpp @@ -140,7 +140,7 @@ bool World::contains(const Shape &a_shape) /* ------------------------------------------------------------------------- */ -Intersections World::intersect_world(const Ray &a_ray) +Intersections World::intersect_world(const Ray &a_ray) const { Intersections the_all_intersec; @@ -155,7 +155,7 @@ Intersections World::intersect_world(const Ray &a_ray) /* ------------------------------------------------------------------------- */ -Color World::shade_hit(const IntersectionData &an_intersection_data) +Color World::shade_hit(const IntersectionData &an_intersection_data) const { return an_intersection_data.object().material().lighting( m_light, an_intersection_data.point(), an_intersection_data.eyev(), an_intersection_data.normalv()); @@ -163,7 +163,7 @@ Color World::shade_hit(const IntersectionData &an_intersection_data) /* ------------------------------------------------------------------------- */ -Color World::color_at(const Ray &a_ray) +Color World::color_at(const Ray &a_ray) const { Color the_color = Color::Black(); diff --git a/raytracing/src/world.h b/raytracing/src/world.h index b273ffe..2928e85 100644 --- a/raytracing/src/world.h +++ b/raytracing/src/world.h @@ -60,9 +60,9 @@ namespace Raytracer bool contains(const Shape &a_shape); - Intersections intersect_world(const Ray &a_ray); - Color shade_hit(const IntersectionData &an_intersection_data); - Color color_at(const Ray &a_ray); + Intersections intersect_world(const Ray &a_ray) const; + Color shade_hit(const IntersectionData &an_intersection_data) const; + Color color_at(const Ray &a_ray) const; static World default_world(void); diff --git a/tests/07_making_scene.cpp b/tests/07_making_scene.cpp index c31ca86..d693c57 100644 --- a/tests/07_making_scene.cpp +++ b/tests/07_making_scene.cpp @@ -635,3 +635,41 @@ SCENARIO("Constructing a ray when the camera is transformed", "[features/camera. } } } + +/* ------------------------------------------------------------------------- */ + +SCENARIO("Rendering a world with the camera", "[features/camera.feature]") +{ + GIVEN("w <- default_world()") + { + World w = World::default_world(); + AND_GIVEN("c <- camera(11, 11, pi/2)") + { + Camera c(11, 11, std::numbers::pi / 2); + AND_GIVEN("from <- point(0, 0, -5)") + { + Tuple from = Tuple::Point(0, 0, -5); + AND_GIVEN("to <- point(0, 0, 0)") + { + Tuple to = Tuple::Point(0, 0, 0); + AND_GIVEN("up <- vector(0, 1, 0)") + { + Tuple up = Tuple::Vector(0, 1, 0); + AND_GIVEN("c.transform <- view_transform(from, to, up)") + { + c.set_transform(Matrix::view_transform(from, to, up)); + WHEN("image <- c.render(w)") + { + Canvas image = c.render(w); + THEN("pixel_at(image, 5, 5) = color(0.38066, 0.47583, 0.2855)") + { + REQUIRE(image.pixel_at(5, 5) == Color(0.38066, 0.47583, 0.2855)); + } + } + } + } + } + } + } + } +}