0027974: Visualization, ray tracing - Improve ray tracing engine
authordbp <dbp@opencascade.org>
Thu, 20 Oct 2016 09:10:47 +0000 (12:10 +0300)
committerapn <apn@opencascade.com>
Tue, 8 Nov 2016 13:43:23 +0000 (16:43 +0300)
* Multiple importance sampling for path tracing
* Improved light sources sampling (better handling several light sources)
* Fixed issues in light source intersection (light distance is taken into account)
* Add new TCL sample - OCCT Ball model for demonstrating physically-based materials
* Fix potential issue on NVIDIA GPUs ("Error: Failed to upload light source buffer")
* Path tracing materials reviewed; directional light source was smoother by default

19 files changed:
data/occ/Ball.brep [new file with mode: 0644]
samples/tcl/pathtrace_ball.tcl [new file with mode: 0644]
samples/tcl/pathtrace_cube.tcl [moved from samples/tcl/pathtrace.tcl with 56% similarity]
src/Graphic3d/Graphic3d_BSDF.hxx
src/Graphic3d/Graphic3d_MaterialAspect.cxx
src/Graphic3d/Graphic3d_NameOfMaterial.hxx
src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Shaders/PathtraceBase.fs
src/Shaders/RaytraceBase.fs
src/Shaders/RaytraceRender.fs
src/Shaders/Shaders_PathtraceBase_fs.pxx
src/Shaders/Shaders_RaytraceBase_fs.pxx
src/Shaders/Shaders_RaytraceRender_fs.pxx
src/V3d/V3d_DirectionalLight.cxx
tests/v3d/raytrace/sample_ball [new file with mode: 0644]
tests/v3d/raytrace/sample_cube [new file with mode: 0644]

diff --git a/data/occ/Ball.brep b/data/occ/Ball.brep
new file mode 100644 (file)
index 0000000..f4be26a
--- /dev/null
@@ -0,0 +1,1131 @@
+DBRep_DrawableShape
+
+CASCADE Topology V1, (c) Matra-Datavision
+Locations 42
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+2  3 1 4 1 5 1 0
+2  3 1 4 1 0
+2  1 -1 2 -1 5 -1 0
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+2  3 1 4 1 5 1 9 -1 0
+2  1 -1 2 -1 9 -1 0
+2  1 -1 2 -1 0
+2  9 1 5 -1 0
+2  9 1 2 1 0
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+2  15 1 4 1 5 1 0
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1              13 
+2  1 -1 0
+2  5 1 2 1 0
+2  9 1 2 1 17 -1 0
+2  1 -1 17 -1 0
+2  15 1 4 1 5 1 2 1 0
+2  9 1 5 -1 4 -1 15 -1 0
+2  1 -1 2 -1 5 -1 4 -1 15 -1 0
+2  3 1 15 -1 0
+2  3 1 4 1 5 1 2 1 0
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1              13 
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1               0 
+2  29 1 30 1 0
+2  28 -1 0
+2  29 1 30 1 28 1 0
+2  27 -1 28 -1 30 -1 29 -1 0
+2  27 -1 0
+1
+0.853553390593274 -0.146446609406726             0.5               0 
+-0.146446609406726 0.853553390593274             0.5               0 
+           -0.5            -0.5 0.707106781186548              13 
+2  36 1 28 1 0
+2  27 -1 28 -1 36 -1 0
+1
+              1               0               0               0 
+              0               1               0               0 
+              0               0               1              13 
+2  39 1 30 1 28 1 0
+2  39 1 30 1 0
+2  27 -1 28 -1 30 -1 39 -1 0
+Curve2ds 83
+1 0 0.5 1 0 
+1 0 0 1 0 
+1 1.5707963267948966 0 0 1 
+1 0 -10 1 0 
+1 0 4.5 1 0 
+1 0 0 1 0 
+8 0.5 4.5
+1 6.2831853071795862 0 0 1 
+1 0 10 1 0 
+1 1.5707963267948966 4.7123889803846897 -0 -1 
+2 0.5 -9.5 1 0 -0 1 0.5
+1 0 1.5707963267948966 1 0 
+2 0 0 1 0 -0 1 9.5
+8 0 1.5707963267948966
+1 6.2831853071795862 0 0 1 
+2 0.5 9.5 0 1 -1 0 0.5
+8 -3.9999999999999998e-007 5.0000004000000002
+1 0 -7.5 1 0 
+8 -3.9999999999999998e-007 5.0000004000000002
+1 1.5707963267948966 0 0 1 
+2 13 0 1 0 -0 1 12
+1 1.5707963267948966 -4.7123889803846897 -0 1 
+8 -1 11
+1 5 0 0 -1 
+8 -1 11
+1 0 0 0 1 
+2 4.5 -9.5 1 0 -0 1 0.5
+1 1.5707963267948966 -4.7123889803846897 0 1 
+1 0 0 0 -1 
+1 0 0 0 1 
+1 0 1.5707963267948966 1 0 
+2 0 0 1 0 -0 1 9.5
+8 0 1.5707963267948966
+1 6.2831853071795862 0 0 1 
+2 4.5 9.5 0 1 1 -0 0.5
+1 0 0 0 1 
+1 0 0 1 0 
+8 -11 1
+1 5 0 0 -1 
+8 -11 1
+1 0 0 -1 0 
+2 13 0 0 1 1 -0 12
+1 6.2831853071795862 -6.2831853071795862 0 1 
+1 0 7.5 1 0 
+1 6.2831853071795862 -0 0 1 
+2 0 0 1 0 -0 1 7.5
+1 0 0 1 0 
+1 -1.5707963267948966 3.6325030024024034 1 0 
+1 -1.5707963267948966 -0.89566479385786479 1 0 
+1 0 -0.72972765622696634 1 0 
+2 0 0 1 0 -0 1 8.9442719099991592
+1 6.2831853071795862 -6.2831853071795862 0 1 
+1 0 -6.2831853071795862 0 1 
+7 0 0  9 26 4  6.2831853071795871 1.1512457199744355  6.2657569811881775 1.1301911635072104  6.2522653288172787 1.1087312403046508  6.2420545906795395 1.086978272289276  6.2346140334263671 1.0650246051788614  6.2295423170972208 1.0429438691678288  6.2265195619980966 1.0207930435392802  6.2252871152746234 0.99861532523059571  6.2256350169984129 0.97644380132824338  6.2282782403923749 0.94323698760487007  6.2295113175774635 0.93218010107054083  6.2310854632309027 0.92111336175646208  6.2329457535343824 0.91013427078949416  6.2351486723147582 0.89905124383253865  6.2375864147883471 0.88812905419672306  6.2403050231171999 0.87719123833127532  6.2432712970734734 0.86630575658250486  6.2496852215071383 0.84461177029792622  6.2531324936810044 0.83380476152813043  6.2568090093981139 0.8230384335765577  6.2607046769088326 0.81231390967768047  6.2648103791426006 0.80163273985568972  6.2691179736864591 0.79099690092312702  6.2736202928085687 0.78040879648235584  6.2783111434384118 0.76987125692433955  6.2831853071795862 0.75938753942942516 
+ 27.003426592720988 10 29.276919684818349 8 30.41366623086703 8 31.55041277691571 10
+1 0 0 0 1 
+1 0 1.5707963267948966 1 0 
+1 6.2831853071795862 -6.2831853071795862 0 1 
+1 0 -6.2831853071795862 0 1 
+1 0 -1.5707963267948966 1 0 
+7 0 0  8 30 5  0.3779509768224647 0.34354415539986732  0.51120379024957674 0.2649153037445921  0.65921090384312597 0.21374323169496912  0.81668762665124994 0.19597808343096601  0.97677176420217449 0.21686921324765604  1.1263448115898793 0.27409872128209306  1.2603208405533932 0.36070966168945717  1.3780764536900438 0.4703403120310527  1.5198934910738324 0.65975054663200527  1.5614116994031515 0.72706113911981674  1.596064092988112 0.79764428880859206  1.6232310951574311 0.87089377562663617  1.6398341079484258 0.94567306390412609  1.6425218632649019 1.0210236364519476  1.6247100152538945 1.0958961627400088  1.5249296054705577 1.2001423415110832  1.4794159463927925 1.233522905850106  1.418778833262673 1.2650165416763526  1.3355048897682453 1.2932743391137209  1.2310097386371057 1.3178333091115033  1.0813950282080182 1.3351149772680326  0.91534691973605897 1.3427206663703126  0.58930917102788438 1.3394279180880329  0.42936190083720127 1.328528287252184  0.29301645303448959 1.3084972681558367  0.19884459136626947 1.2823439000276915  0.1234322888796944 1.2527611765167879  0.069490842882694581 1.2204155121033911  0.029110083321880253 1.1864126025174104  -1.27675647831893e-015 1.1512457199744355 
+ 6.9915739190569493e-015 9 13.501713296360498 7 20.252569944540742 7 23.627998268630865 7 27.003426592720988 9
+1 0 0 0 1 
+7 0 0  6 7 2  -5.5511151231257827e-017 0.75938753942942483  0.039546765478415173 0.6743273857017027  0.09189047604055324 0.59297629109659056  0.1530249128017743 0.51741648607178559  0.22161219712017902 0.44980315287431782  0.29703962071048623 0.39128774034440467  0.37795097682246465 0.34354415539986749 
+ 31.55041277691571 7 37.699111843077532 7
+1 0 0 0 1 
+8 0 27.003426592720981
+7 0 0  1 2 2  0 27.003426592720988  4.5469861841947221 27.003426592720988 
+ 0 2 27.003426592720981 2
+8 0 27.003426592720981
+1 0 27.003426592720988 1 0 
+1 4.5469861841947221 0 0 1 
+7 0 0  7 20 4  4.5044325607409892 9.9811071530166409  4.5585728487996313 9.9811071530166302  4.6126920720359603 9.9811071530214939  4.6667889747012383 9.9811071530183639  4.720847385047735 9.9811071530109192  4.7748564021853994 9.9811071530106918  4.8288305829366003 9.981107153020611  4.9098299015712232 9.9811071530292583  4.9368403485141696 9.9811071514101286  4.9638170534361716 9.9811071585903228  4.9909135330859886 9.9811071457521106  5.017814804941767 9.981107153845457  5.0447519718498661 9.9811071595263208  5.0985854371097865 9.981107173612509  5.1254912587507651 9.981107181499814  5.1523980062844545 9.9811071887542067  5.1793140944688627 9.9811071941331022  5.2062445159379838 9.9811071966269171  5.2331908412021138 9.9811071954608508  5.2601512186476489 9.9811071900934003 
+ 27.003426592720988 8 29.276919684818349 6 30.41366623086703 6 31.55041277691571 8
+8 0 4.5469861841947221
+1 0 31.55041277691571 1 0 
+8 0 4.5469861841947221
+7 0 0  1 2 2  0 31.55041277691571  6.1486990661618215 31.55041277691571 
+ 0 2 4.5469861841947221 2
+8 0 27.003426592720981
+1 0 6.9915739190569493e-015 1 0 
+8 0 27.003426592720981
+7 0 0  1 2 2  0 37.699111843077532  6.1486990661618215 37.699111843077532 
+ 0 2 27.003426592720981 2
+1 27.003426592720981 0 0 1 
+7 0 0  8 30 5  8.8817841970012523e-016 9.9811071530166444  0.28061394563911779 9.9811071530166622  0.56242898442335065 9.9811071530165165  0.84433250728446585 9.9811071530168949  1.1259782560117784 9.9811071530163886  1.4074785126943941 9.9811071530167883  1.688990968223079 9.9811071530165947  1.9704865752963596 9.9811071530166551  2.3927337494168062 9.9811071530166284  2.533482733558821 9.9811071530166977  2.6742319564529571 9.9811071530165787  2.814980703870094 9.9811071530165716  2.955729309207638 9.9811071530168523  3.0964815285374105 9.9811071530164686  3.2372444041008652 9.9811071530166942  3.4484120041861899 9.9811071530166178  3.5188050868662057 9.981107153016918  3.5892026655828597 9.9811071530161808  3.6596052272786523 9.9811071530170032  3.7300129761187826 9.9811071530164792  3.8004256130789078 9.9811071530167297  3.8708420522728133 9.9811071530166142  4.0116781650622233 9.9811071530166871  4.0820978386559776 9.981107153016497  4.1525169444306806 9.9811071530168878  4.2229321981586958 9.9811071530164206  4.2933389043870056 9.9811071530167546  4.3637306149748394 9.9811071530166302  4.4340987956550491 9.981107153016632  4.5044325607409874 9.9811071530166444 
+ 6.9915739190569493e-015 9 13.501713296360498 7 20.252569944540742 7 23.627998268630865 7 27.003426592720988 9
+1 6.1486990661618215 0 0 1 
+7 0 0  6 7 2  5.2601512186476489 9.9811071900934003  5.4302857042684973 9.9811071562221869  5.6011284920110018 9.9811070817552903  5.7722546908193646 9.981107321458639  5.942344480081065 9.9811070811414719  6.112795997553417 9.9811071530167474  6.283185307179588 9.9811071530166391 
+ 31.55041277691571 7 37.699111843077532 7
+1 6.2831853071795862 -0 0 1 
+1 0 -0 0 1 
+7 0 0  6 7 2  5.8486126989606406 6.1032778078668555  5.9210414602807093 6.1032778078668395  5.9934092509519425 6.1032778096457578  6.0661365998582584 6.1032778035090809  6.1376401199521196 6.1032778130605676  6.2109669492619117 6.103277807866859  6.2831853071795862 6.1032778078668537 
+ 37.779814481202841 7 40.388933793672713 7
+1 0 0 0 1 
+7 0 0  12 178 17  1.4797720844872568e-015 6.1032778078668573  0.1630838917770901 6.1032778078659504  0.32072595266758785 6.1032762474697355  0.47703629007524523 6.103291103992297  0.63474936416620154 6.1033008437572445  0.79514501957021333 6.1032961265271952  0.95833092881077753 6.1032844241539612  1.1236945157915703 6.1032768953467844  1.2903713271428761 6.1032768091460925  1.4576157173768058 6.1032787525259282  1.6249986134181098 6.1032778090991222  1.7923960223176569 6.1032778392212723  2.0434582567583925 6.103277992947155  2.1271399216390878 6.1032780324088067  2.210808557958563 6.1032781451270228  2.2944652188517645 6.1032782314313758  2.3781092890558502 6.1032781664866675  2.4617312620744349 6.103277908564829  2.5453082969559579 6.1032775530298888  2.6288025561985879 6.1032773364152382  2.7121623229653751 6.1032775853135135  2.7953258994326409 6.1032786154067322  2.8782282847392282 6.1032805761281361  3.002101808048157 6.1032845781519898  3.0433128328700687 6.1032860816841916  3.0844365848579431 6.1032877468853268  3.1254660413090916 6.103289532437878  3.1663946799168707 6.1032913711591226  3.2072168785177912 6.1032931772000687  3.2479283150508707 6.1032948538701701  3.2885263672356118 6.1032963006480347  3.3290105125598544 6.1032974210755135  3.369382727982805 6.1032981298487332  3.4096478898567977 6.1032983605200313  3.4698973156354453 6.1032979289612772  3.4899557734031732 6.1032976576479774  3.5099906101621863 6.1032972548716184  3.5300031094127697 6.1032967195133931  3.5499947958972098 6.1032960533868925  3.5699674566690058 6.1032952614117963  3.5899231618765874 6.1032943515863343  3.6098642859264576 6.10329333523066  3.6297935282235105 6.1032922269230561  3.64971393430862 6.1032910447296311  3.669628916681714 6.1032898101985218  3.6994989554091906 6.1032879176680694  3.7094552296693117 6.1032872799362066  3.7194115741496194 6.10328663837159  3.7293684887930789 6.1032859961841988  3.7393264987847954 6.1032853567848599  3.7492861550483534 6.1032847236708259  3.7592480352646276 6.1032841005329361  3.7692127441982568 6.1032834910977245  3.7791809147642197 6.1032828992188071  3.7891532084133659 6.1032823287610016  3.7991303160233882 6.1032817836182325  3.8141042796885953 6.1032810096706953  3.8190969846180658 6.103280758980727  3.8240911633668877 6.1032805160758095  3.8290869079137728 6.1032802814118847  3.8340843121516244 6.1032800555149889  3.8390834718687961 6.1032798387931804  3.8440844848106015 6.1032796317911941  3.8490874506717176 6.1032794349034898  3.8540924711228337 6.1032792486377918  3.8590996498396599 6.1032790734079239  3.8641090925074555 6.1032789096662814  3.8716268140235424 6.1032786819126255  3.8741333141145597 6.1032786089720421  3.8766404205898719 6.1032785390598372  3.8791481470429869 6.1032784722329927  3.8816565071926088 6.1032784085338019  3.8841655148904861 6.1032783480267927  3.8866751841116747 6.1032782907451733  3.8891855289654274 6.1032782367531997  3.8916965636889316 6.1032781860870475  3.8942083026502736 6.1032781388009605  3.8967207603488645 6.1032780949362921  3.9017471424843366 6.103278014144089  3.9042610669186861 6.1032779772123726  3.9067757393608051 6.1032779438044438  3.9092911745490833 6.1032779139268678  3.9118073874226771 6.103277887687625  3.9143243929510652 6.1032778650386383  3.9168422063574906 6.1032778461149979  3.9193608428871283 6.1032778308742639  3.921880318001981 6.1032778194082962  3.9244006472521087 6.1032778117238733  3.9269218463426108 6.1032778078668404  3.9318927590885817 6.1032778078670225  3.9343424220382297 6.1032778115024042  3.9367929106779638 6.1032778184841394  3.9392442156796164 6.1032778285168634  3.9416963277646184 6.1032778413607129  3.9441492375503788 6.1032778567366233  3.9466029357642904 6.1032778744284846  3.9490574130201455 6.1032778942036714  3.9515126600235564 6.1032779158476975  3.953968667426015 6.1032779391671479  3.9564254259196812 6.103277963967944  3.9613404264685417 6.1032780161806652  3.9637986685252318 6.1032780435935718  3.9662576430548859 6.103278072128373  3.9687173407674265 6.1032781016358095  3.9711777523744249 6.103278131925034  3.9736388686204038 6.1032781628991595  3.9761006802557088 6.1032781943616801  3.9785631780620174 6.1032782262396523  3.9810263528440921 6.103278258370227  3.9834901954319784 6.103278290667709  3.9859546966885224 6.1032783230144991  3.9933501491435015 6.1032784199277286  3.9982830490263344 6.1032784843570909  4.0032184743081416 6.1032785478497207  4.0081563526338071 6.1032786097003555  4.0130966122691474 6.1032786694374774  4.0180391820646033 6.1032787264878179  4.0229839916326098 6.1032787806040805  4.0279309712801075 6.1032788313710054  4.0328800521494381 6.1032788786438674  4.0378311661964856 6.1032789221957824  4.0427842462622774 6.103278961934282  4.0576491857286037 6.1032790694567183  4.0675667444424013 6.1032791255612775  4.0774913720378549 6.103279165480175  4.0874225530420709 6.103279189455237  4.0973597873189611 6.1032791979995569  4.1073025912931866 6.1032791924597349  4.1172504978353741 6.10327917386034  4.127203057548682 6.1032791440023049  4.1371598382278174 6.1032791042063961  4.1471204256829122 6.1032790561932861  4.1570844232814137 6.1032790014240508  4.1869855095456137 6.1032788213931868  4.2069316980466525 6.1032786797365635  4.2268869732590666 6.1032785296112229  4.246848588257385 6.1032783814550653  4.2668140816879463 6.103278243297404  4.2867812660530955 6.1032781208142239  4.3067482158649826 6.1032780177798447  4.3267132559940933 6.1032779360258784  4.3466749497806836 6.1032778759073691  4.3666320873857876 6.1032778363388367  4.3865836739412982 6.1032778151284557  4.4464194056327742 6.1032777971805698  4.486284418420551 6.1032778542172581  4.5261177012254361 6.1032779455218753  4.5659160202668785 6.1032780448202208  4.6056787000616524 6.1032781335428741  4.6454071602437397 6.1032781997592656  4.6851044528039294 6.1032782376084773  4.7247747988231792 6.1032782460863766  4.7644231257023844 6.1032782285163432  4.8040546039971588 6.1032781914230911  4.843674184504879 6.1032781438331414  4.9625100366690162 6.1032780013228836  5.0417003379740581 6.1032779109743505  5.1209029142061206 6.1032778419988603  5.2001440339852039 6.1032778006257207  5.2794341832859129 6.1032777854115396  5.3587718884685094 6.1032777893067562  5.4381475405340076 6.1032778029343193  5.517547217778648 6.10327781625646  5.5969565101872059 6.1032778220180512  5.6763643422469947 6.1032778175567461  5.7557667969642416 6.103277807868194  5.8362910857873427 6.1032778078665952  5.8374112324719727 6.1032778078691212  5.8385313791452997 6.103277807860656  5.8396515258562065 6.1032778078775332  5.8407716725023002 6.1032778078536376  5.8418918192239593 6.103277807879202  5.8430119658515878 6.1032778078579435  5.8441321125386505 6.1032778078718524  5.8452522591605423 6.1032778078646714  5.8463724057906052 6.1032778078675607  5.8474925523867505 6.1032778078667071  5.8486126989606362 6.103277807866851 
+ 2.6898219505952046 13 14.473677021732097 11 20.365604557300543 11 23.311568325084767 11 24.784550208976881 11 25.521041150922937 11 25.889286621895963 11 26.073409357382477 11 26.257532092868992 11 26.436306776466001 11 26.61508146006301 11 26.972630827257024 11 27.687729561645057 11 29.117927030421122 11 31.978321967973255 11 37.699111843077517 11 37.779814481202834 13
+1 0 0 0 1 
+8 0 35.089992530607631
+7 0 0  1 2 2  0 37.779814481202841  2.6091193124698719 37.779814481202841 
+ 0 2 35.089992530607631 2
+8 0 35.089992530607631
+1 0 37.779814481202834 1 0 
+1 2.6091193124698719 0 0 1 
+7 0 0  6 7 2  -7.2791520144974188e-017 0.32876221527190325  0.038860605398199299 0.29254783502261628  0.078860538115405998 0.25803537950446875  0.1203288779877546 0.22528843487789374  0.16229112456328881 0.19494232320838417  0.20661056779336082 0.166184091014069  0.25148252724183728 0.14019083844221625 
+ 37.779814481202841 7 40.388933793672713 7
+8 0 35.089992530607631
+7 0 0  1 2 2  0 40.388933793672713  2.6091193124698719 40.388933793672713 
+ 0 2 35.089992530607631 2
+8 0 35.089992530607631
+1 0 2.6898219505952046 1 0 
+1 35.089992530607631 0 0 1 
+7 0 0  11 152 16  0.25148252724183923 0.14019083844221555  0.33377553669904381 0.092520466878005053  0.4175834501273526 0.053447250995149423  0.50360598882167806 0.022277126812306054  0.59254587450122831 -0.00095636689549173908  0.68451027317536917 -0.015685405308244742  0.7788582052432218 -0.021123326846720355  0.87435735503904455 -0.016611069409324747  0.96951371331915392 -0.0019034479334027528  1.0629374858490224 0.022695872340652148  1.1536087015849701 0.056441852530410785  1.328203205742843 0.14073645210701854  1.412120302569017 0.19126575240307903  1.4920315454584008 0.24937885529478615  1.5677198339240079 0.31407517021251297  1.6393072177661707 0.38441125812695648  1.7071342125025215 0.45958390727571941  1.7716263640744319 0.53889994115182127  1.833186549133651 0.62169595960983071  1.8921514967984117 0.70727121380274272  1.9488510181598089 0.79489681580096139  2.0175477823472856 0.90623140059145291  2.0311794175198741 0.92858844021773912  2.0447089547398729 0.95102536843077656  2.0581438064731015 0.97353250704445149  2.0714931779564143 0.99610073377873054  2.084768067168699 1.0187214822422546  2.0979812648684502 1.0413867419541449  2.1111473545547277 1.0640890583223859  2.124282712499844 1.0868215326608583  2.1374055077274696 1.1095778221787407  2.1636658963208175 1.1551264577925235  2.1768009937806392 1.1779192287469014  2.190001316547868 1.2007252001736173  2.2032594768681073 1.2235401184283223  2.2166046171772806 1.2463606677267955  2.2301150856184271 1.2691846270394294  2.2438875384589312 1.2920111120524198  2.25801046084083 1.3148407691329009  2.2725900973766597 1.3376757883215147  2.2878767839873002 1.3605196022801895  2.3128711167688447 1.3948044061768345  2.3215213357528763 1.4062359528092765  2.3306950362838696 1.417670767772804  2.3401383573429353 1.4291108309030454  2.3504497336803896 1.4405548085896343  2.3617160953194198 1.4520035764524299  2.3738755929075848 1.4634587639329946  2.3877280577833075 1.474918678247412  2.4043923967572338 1.4863805157142025  2.4242460826358037 1.4978447064274421  2.4614082729210893 1.5121470295870159  2.4694586460736017 1.5150060942188428  2.478222062214984 1.5178634152121804  2.4878273105230688 1.5207185117560136  2.4984559910210771 1.5235706836903775  2.5103397663678848 1.5264190290128985  2.5237637335322658 1.5292624381686544  2.5391039125424615 1.5320994420176  2.5569268500412439 1.5349277906170908  2.578179334849823 1.5377436397142097  2.6110754452623346 1.5412393676325797  2.6179750878848642 1.5419372912655183  2.6252160659495196 1.5426339092121937  2.6328254630852075 1.5433291100605047  2.6408365316867344 1.5440227547477754  2.6492886928516279 1.5447146765172242  2.6582275364608079 1.5454046809758273  2.6677048210948784 1.5460925460317239  2.6777784741056294 1.5467780219497955  2.6885125915656731 1.5474608313112865  2.7114422850291779 1.5488205067635936  2.7236427679286721 1.5494973457603429  2.7366450742360815 1.5501709002928727  2.7505525327162594 1.5508407271350804  2.765473276362274 1.5515063405737024  2.7815178528560418 1.5521672236371238  2.7988141009255689 1.5528227753548394  2.8175266101285414 1.5534722336101685  2.8378680823132947 1.5541146134289177  2.8600899122965338 1.5547487002786002  2.9331380930539637 1.5566220139402076  2.9903755250317259 1.5578318331961658  3.0584606571763318 1.5589942630084259  3.1402320354819855 1.5600786532243116  3.2398123356742494 1.5611009105977995  3.3639683282709094 1.5619468698619392  3.5086997850556947 1.562689247981411  3.7101221981577521 1.5631034566735587  3.9083089542155545 1.5631788373097031  4.0953665692021008 1.5629536884570394  4.427540303192564 1.5620017817838077  4.5729190784165183 1.5612754372697792  4.689240122857262 1.5603509129601389  4.7807405634922908 1.559300401666931  4.8549843128815668 1.5581652369387866  4.9167718400434186 1.5569672636846916  4.9682385732268042 1.5557226534379769  5.0115350778396852 1.554443686450627  5.0492281620402011 1.553137143283944  5.0816798197402591 1.5518089021642711  5.1386210296360915 1.5491173450278943  5.1630697330555115 1.5477540770168681  5.1843914446495196 1.5463773631273263  5.2032276240483304 1.5449900259400489  5.2200389870277997 1.5435940386565357  5.235163821999433 1.5421908198034071  5.2488619164602728 1.5407814509682132  5.2613440938206013 1.5393668176589281  5.2727873601534085 1.5379476731854853  5.2833356612718978 1.5365246256550649  5.312587426976572 1.5322448927310368  5.3289298524874411 1.5293777950205685  5.3429918402474517 1.5265003891391591  5.3553407118241276 1.5236150157005981  5.3663397749917836 1.5207231719040226  5.3762312647391761 1.5178258598082393  5.3851952466918478 1.514923832642054  5.3933844830682496 1.5120177391657226  5.4009352610205994 1.509108166064975  5.4079541835138949 1.5061955783957588  5.4405878790200806 1.4916184767458718  5.4590098440474515 1.4799122985694957  5.4746090117696875 1.4681832823309169  5.4878325450714414 1.4564353832618633  5.499627594819958 1.4446745544254702  5.5106001588016893 1.4329053118544626  5.5207057190078483 1.4211294698451915  5.5300686905617225 1.4093494345626443  5.5391908909032379 1.3975690393286679  5.5478264862246327 1.385789011460981  5.5645179157292777 1.3622345494795052  5.5725531311188448 1.3504600302935454  5.5803469518790862 1.3386901306217194  5.5879514155894272 1.3269265939790722  5.5954044105906515 1.315171014871414  5.6027325941620649 1.3034248540476021  5.6099543103110765 1.2916894536527928  5.617082508025911 1.2799660524993632  5.6241276590761657 1.2682558012235752  5.6311006761745404 1.2565597775330937  5.6933370687459899 1.1514327922981551  5.7451061355165027 1.0589720862192382  5.7974718182192477 0.9679519900889586  5.8502967749105625 0.87872216236983502  5.9043686163030493 0.79123600999508081  5.9605089889268932 0.70570542787886281  6.0189675652459451 0.62271932914949324  6.0800250348551721 0.54290566120699313  6.1443057715405827 0.46679884787898995  6.2119168311148538 0.39517764202438399  6.2831853071795862 0.3287622152719033 
+ 2.6898219505952046 12 11.462320083247111 10 20.234818215899018 10 22.427942749061994 10 24.621067282224971 10 25.71762954880646 10 25.991770115451835 10 26.060305257113178 10 26.128840398774521 10 26.265910682097207 10 26.402980965419893 10 26.540051248742579 10 26.81419181538795 10 27.910754081969436 10 29.007316348550926 10 37.779814481202834 12
+1 6.2831853071795862 -6.2831853071795862 0 1 
+1 0 -6.2831853071795862 0 1 
+1 0 -1.5707963267948966 1 0 
+Curves 40
+2 0 0 0.5 0 0 1 1 0 -0 -0 1 0 10
+1 0 10 0 0 0 1 
+2 0 0 4.5 0 0 1 1 0 -0 -0 1 0 10
+1 10 0 0 0 0 1 
+2 0 9.5 0.5 1 0 0 -0 0 1 0 -1 0 0.5
+2 0 0 0 0 0 1 1 0 -0 -0 1 0 9.5
+2 9.5 0 0.5 -0 1 0 1 0 -0 -0 0 -1 0.5
+1 0 7.5 0 0 0 1 
+2 0 0 13 1 0 0 -0 0 1 0 -1 0 12
+1 0 0 5 0 1 0 
+2 0 9.5 4.5 1 0 0 -0 0 1 0 -1 0 0.5
+1 0 0 0 -0 1 0 
+2 0 0 5 0 0 1 1 0 -0 -0 1 0 9.5
+2 9.5 0 4.5 0 -1 0 1 0 0 -0 0 1 0.5
+1 0 0 0 1 0 -0 
+1 0 0 5 -1 0 0 
+2 0 0 0 -2.4492935982947064e-016 -1 0 1 -2.4492935982947064e-016 0 0 0 1 12
+1 7.5 -1.83697019872103e-015 0 0 0 1 
+2 0 0 0 0 0 1 1 0 -0 -0 1 0 7.5
+2 0 0 3.6325030024024034 0 0 1 0 -1 0 1 0 -0 7.5
+2 0 0 5 0 0 1 1 0 -0 -0 1 0 8.9442719099991592
+2 0 0 0 -2.4492935982947064e-016 -1 0 1 -2.4492935982947064e-016 0 0 0 1 11.949999999999999
+7 1 0  7 14 3  4.8678334076839933 -5.5094817597023393e-015 23.913601509814971  1.0584045643979316 5.2453015164677348 -0.139366199637567 23.745238035244242  1.0584045643979256 5.6237339251218996 -0.25030180427678811 23.556089231112377  1.058404564403195 6.000155335997583 -0.33193339347582629 23.347641349460922  1.0584045643812252 6.3716391314814462 -0.38299224786023656 23.121066700248512  1.05840456442027 6.7341701420999582 -0.40413612837708934 22.879669545995512  1.0584045643849909 7.0878353428550005 -0.39455494210023057 22.622815562318031  1.0584045643979363 7.6199296077227503 -0.33247050230520758 22.202667771014344  1.0584045643979345 7.8074916713889291 -0.30048331055091615 22.047423020747203  1.0584045630682277 7.9902398896533704 -0.25899596379060397 21.888864556070441  1.0584045612010267 8.1679077234144675 -0.2080919936909334 21.727239906056148  1.058404559447049 8.3401664552877257 -0.1478738879140305 21.56285397218738  1.0584045583157158 8.5066251897509328 -0.078463090128382623 21.396069028263479  1.0584045581749411 8.6668308532806098 -2.0261570199409107e-015 21.22730472029712  1.058404559251283
+ 27.003426592720988 8 29.908219967738049 6 31.55041277691571 8
+2 0 0 0 -2.4492935982947064e-016 -1 0 1 -2.4492935982947064e-016 0 0 0 1 11.949999999999999
+7 1 0  8 30 5  10.457607314751494 4.1520753998578845 17.025073803590558  1.058404564397933 10.198481727311403 5.6623700024094594 16.14036370859473  1.0584045643979338 9.4539501708476585 7.2622577929764258 15.535535515130185  1.0584045643979241 8.248455319341824 8.7656620017466604 15.324881788429542  1.0584045643979452 6.7008332749465058 9.9684032620937923 15.568749329531027  1.0584045643979114 5.0021636982240958 10.709494567624294 16.245859418607623  1.0584045643979547 3.3673075559849113 10.910959145646991 17.259420313760781  1.0584045643979203 1.9821989652580452 10.590075049423096 18.465739311358281  1.0584045643979354 0.46233693526959474 9.4618878826869235 20.33819285527785  1.0584045643979281 0.048690766228185467 8.978002120913434 20.972843769888573  1.0584045643979543 -0.25669344451313325 8.3976451054714634 21.599157397299123  1.0584045643978861 -0.44243494262249605 7.736724418849791 22.197837969496838  1.0584045643979778 -0.50209407157768826 7.0149965747848277 22.750361996850078  1.0584045643979134 -0.43464996282412471 6.2548109899931248 23.240204192165898  1.0584045643979332 -0.24444052319786905 5.4796190804290523 23.653849263534159  1.058404564397933 0.21134466937368046 4.3290351139813454 24.145146188102085  1.0584045643979352 0.39168474135954856 3.9475410756227007 24.287383521786708  1.0584045643979199 0.5992962469447507 3.5709736489202397 24.4068533993306  1.0584045643979663 0.83273930778730065 3.2022059119093376 24.502542395511178  1.0584045643978861 1.0902913086077537 2.8440467470611557 24.57368240343067  1.0584045643979589 1.369970683137562 2.4991968232922894 24.619764940731635  1.0584045643979301 1.6695665212729058 2.1702061516836157 24.640550226812369  1.058404564397931 2.3037820523698858 1.5486619865855618 24.631590217987657  1.0584045643979321 2.6384017449409858 1.2561084934038753 24.601844923140632  1.0584045643979478 2.9881288309581384 0.98413292758025961 24.546866295964236  1.0584045643978879 3.3503651350884658 0.73490396564717209 24.466958037972709  1.058404564398006 3.7223546064721535 0.51035962621342801 24.362698585317943  1.0584045643978726 4.1012249687261386 0.3121698954630876 24.234938085552656  1.0584045643979565 4.4840360652674551 0.14170303609468959 24.084788035501798  1.0584045643979303 4.8678334076839933 -5.3290705182007514e-015 23.913601509814971  1.0584045643979316
+ 6.9915739190569493e-015 9 13.501713296360498 7 20.252569944540742 7 23.627998268630865 7 27.003426592720988 9
+7 1 0  6 7 2  8.6668308532806098 4.4408920985006262e-016 21.22730472029712  1.0584045592512832 9.366646654445173 0.34274512567321036 20.490102758859706  1.0584045639530038 9.9446323300351516 0.86282287914093869 19.713654529496349  1.0584045742896391 10.359805174140732 1.5460699019423574 18.936954819538212  1.0584045410165293 10.584474557202489 2.3499904929220348 18.209631446218562  1.0584045743748955 10.614948853319143 3.235021708620883 17.562271418492891  1.0584045643979356 10.457607314751494 4.1520753998578837 17.025073803590562  1.0584045643979318
+ 31.55041277691571 7 37.699111843077532 7
+7 1 0  6 7 2  4.8678334076839933 -5.3290705182007514e-015 23.913601509814971  1.0584045643979316 4.8893404642098988 0.069839868069845323 23.904008639105555  1.0179465873219375 4.896724512084587 0.13618834146639447 23.865642289046118  0.99621518633173289 4.8877306608750013 0.18531983119089634 23.804808660859752  0.98906881166944505 4.8637563483541895 0.20706401329963153 23.733059473797994  0.99621518633173278 4.8298018476888132 0.19783727430884301 23.664571664122754  1.0179465873219375 4.7929501726221675 0.16098559924219735 23.612455525447338  1.0584045643979316
+ 0 7 27.003426592720981 7
+7 1 0  7 14 3  4.7929501726221675 0.16098559924219849 23.612455525447338  1.0584045643979316 5.1521282218765023 0.028372330589910788 23.452250032705589  1.0584045643979256 5.5122576821856644 -0.077184147099903427 23.272239750335164  1.058404564403195 5.8702899236121713 -0.15487689765374871 23.074009795527981  1.0584045643812252 6.2240672847329659 -0.20342960064170129 22.858183369579738  1.05840456442027 6.5687118658790302 -0.22358373722484781 22.628733976158063  1.0584045643849909 6.905433172854063 -0.21444547531385644 22.384174329528804  1.0584045643979363 7.4116662466030805 -0.15537850379287529 21.984446834113328  1.0584045643979345 7.5900951956392344 -0.12495128441996044 21.83676323468568  1.0584045630682277 7.7639466555503773 -0.085487787826995787 21.685926801436445  1.0584045612010267 7.9329790729820315 -0.037064500764224462 21.532162416050209  1.058404559447049 8.0968842775637437 0.02022387536292386 21.375754946702266  1.0584045583157158 8.2552874820463309 0.086264424483480789 21.217049247968745  1.0584045581749411 8.4077472824322346 0.16092601586926938 21.056450160728609  1.058404559251283
+ 27.003426592720988 8 29.908219967738049 6 31.55041277691571 8
+7 1 0  6 7 2  8.6668308532806098 -2.0261570199409107e-015 21.22730472029712  1.058404559251283 8.6505926888112246 0.069827658909503293 21.244410373923479  1.0179465858748133 8.6119288239185661 0.13616123597998753 21.238615340066893  0.99621518664683628 8.5575423406736881 0.1852780411830999 21.209889529217804  0.98906881257972901 8.49786444931717 0.2070106738548623 21.163394752280627  0.99621518664683639 8.4445989558002843 0.19777768923732034 21.10856629700185  1.0179465858748133 8.4077472824322346 0.16092601586926938 21.056450160728609  1.058404559251283
+ 0 7 4.5469861841947221 7
+7 1 0  6 7 2  10.457607314751494 4.1520753998578845 17.025073803590558  1.058404564397933 10.423613398627618 4.1806892314120248 17.083877256985957  1.017946587321938 10.36328810240129 4.1967433088891051 17.128952151700382  0.99621518633173267 10.287548434956518 4.1962961097004188 17.150372369922597  0.98906881166944483 10.21107519181346 4.179044167461468 17.143319956675114  0.99621518633173278 10.148725595134607 4.1487255951346134 17.109824690323038  1.017946587321938 10.111873920067961 4.1118739200679686 17.057708551647622  1.058404564397933
+ 0 7 27.003426592720981 7
+7 1 0  8 30 5  10.111873920067961 4.1118739200679686 17.057708551647622  1.058404564397933 9.8653041547214002 5.5489878285561156 16.215866714730296  1.0584045643979338 9.1568485638090795 7.071353724560546 15.640345218721979  1.0584045643979241 8.009765461755368 8.5019111104197265 15.439898630351284  1.0584045643979452 6.5371327970249702 9.6463740454239986 15.671949671620606  1.0584045643979114 4.9207715450486917 10.351556081325018 16.316250674183813  1.0584045643979547 3.3651316742446826 10.543258777378405 17.280699899562304  1.0584045643979203 2.0471379416729407 10.237922985992494 18.428567214053135  1.0584045643979354 0.60092019144771136 9.164401657137029 20.210291803691817  1.0584045643979281 0.20731707473264649 8.7039623778142019 20.814190973351067  1.0584045643979543 -0.083269871646901805 8.1517263191198346 21.41015683557875  1.0584045643978861 -0.26001134305620699 7.522830268278728 21.97982859074045  1.0584045643979778 -0.31677971383952475 6.8360734454066741 22.505580297157156  1.0584045643979134 -0.25260358120186144 6.1127223355698828 22.971687393523155  1.0584045643979332 -0.071610660515527336 5.3750920261587583 23.365289465752422  1.058404564397933 0.36208965094750045 4.2802591251658821 23.832780803072399  1.0584045643979352 0.53369142007958992 3.9172502210723819 23.96812608617094  1.0584045643979199 0.73124319688855532 3.558929211725431 24.081807100705007  1.0584045643979663 0.95337487173496605 3.2080299613639633 24.172859526548677  1.0584045643978861 1.1984472979445782 2.8672252492329964 24.24055247510173  1.0584045643979589 1.4645749252132183 2.5390848844642702 24.284402102308327  1.0584045643979301 1.7496539721635305 2.2260353184174777 24.304180246034672  1.058404564397931 2.3531388546353225 1.634607816198351 24.295654390694665  1.0584045643979321 2.6715446897853385 1.3562298803189661 24.26735039168382  1.0584045643979478 3.0043258959428143 1.0974327769234078 24.215035730920661  1.0584045643978879 3.3490101912753545 0.86028010022933099 24.138999394189767  1.058404564398006 3.7029750682162588 0.64661596296250234 24.039791789760415  1.0584045643978726 4.0634874253346904 0.45802943282505026 23.918221871641258  1.0584045643979565 4.4277495701067666 0.29582247391725236 23.77534727954265  1.0584045643979303 4.7929501726221675 0.16098559924219735 23.612455525447338  1.0584045643979316
+ 6.9915739190569493e-015 9 13.501713296360498 7 20.252569944540742 7 23.627998268630865 7 27.003426592720988 9
+7 1 0  6 7 2  8.4077472824322346 0.16092601586927091 21.056450160728609  1.0584045592512832 9.0737273420740348 0.48706530608348814 20.354915792797655  1.0584045639530038 9.6240175289394081 0.98211077507932587 19.615751756611353  1.0584045742896391 10.018763193514083 1.632418192160936 18.876787974861582  1.0584045410165293 10.232590199172119 2.3970380340767714 18.184921234053807  1.0584045743748955 10.261591540111413 3.2392556823542611 17.568876480526207  1.0584045643979356 10.111873920067961 4.1118739200679677 17.057708551647625  1.0584045643979318
+ 31.55041277691571 7 37.699111843077532 7
+1 6 -1.4695761589768238e-015 0 0 0 1 
+7 1 0  6 7 2  8.0668770102020808 0.098439964817656933 15.857587247241948  1.0000000000000004 8.165321172711133 0.40809825600438854 15.56901523481479  0.99999999999999722 8.2323723673686455 0.73599211674116671 15.289746910465151  1.0000000000000051 8.2659991962099699 1.0816031679969018 15.02158522508712  0.99999999999999312 8.2685628965545241 1.4330975095396172 14.77122839624287  1.0000000000000053 8.2364160494168619 1.8031059019107807 14.53232419916106  0.999999999999998 8.1729592474930683 2.1729592474930675 14.31566912540802  1
+ 37.779814481202841 7 40.388933793672713 7
+7 1 0  12 178 17  8.1729592474930666 2.1729592474930772 14.315669125408014  1.0000000000000009 8.0296607494956636 3.0081641001581292 13.8264174500764  0.99999999999979217 7.7423771484404122 3.8411955366909436 13.440513248052714  1.0000000000008566 7.3296432767451023 4.6602697146782006 13.153208272316585  0.99999999999790079 6.7953325452781037 5.4583660218612327 12.966697477024411  1.0000000000036997 6.1418634707595192 6.2163089699220304 12.89281662146181  0.99999999999500966 5.380183498938214 6.9030696664546003 12.945775999351344  1.0000000000052705 4.5341428039443672 7.4837961370160428 13.133370839300776  0.99999999999561862 3.6387590998922645 7.9287306578188748 13.451886389414492  1.000000000002826 2.7337628561564631 8.218821148724416 13.886693165405223  0.99999999999865352 1.8557006645402028 8.3464825638909161 14.417305308825926  1.0000000000004041 1.0337628608158764 8.3126131072993203 15.022452468584349  0.99999999999998779 -0.072296639696200593 8.0291219281374389 16.005013394386602  0.99999999999991396 -0.41988628639463332 7.8958608367201295 16.345026267846265  1.0000000000007365 -0.74302567276071674 7.7247741204011531 16.694497055929229  0.99999999999776246 -1.0385706997131141 7.517154735104012 17.050288145873868  1.0000000000044871 -1.303639675069439 7.2747110461164386 17.409153700625836  0.99999999999337319 -1.5356673173777056 6.9996010959542243 17.767753766369072  1.0000000000074829 -1.7324596647914277 6.6944402802428247 18.122687749182404  0.99999999999344158 -1.8922498883769858 6.3622824311804145 18.470547260898783  1.0000000000044684 -2.0137550107257152 6.0065743089446508 18.807988334277734  0.99999999999767808 -2.096233528871311 5.631083500846719 19.131823007180458  1.0000000000008662 -2.1395439424458305 5.2397997282553721 19.439130276171706  0.99999999999981126 -2.1465343083170483 4.6353144779335897 19.871514490625973  1.0000000000000866 -2.1391985528188995 4.4308887968520834 20.010880239827976  0.99999999999963507 -2.1222477401056947 4.2240408267152736 20.145160162512788  1.0000000000009877 -2.095772792756299 4.0152816994113962 20.274057067429407  0.99999999999808376 -2.0599003391659307 3.8051211018143012 20.39729999625791  1.0000000000027898 -2.0147883174015204 3.5940630075102113 20.514644143618415  0.99999999999687883 -1.9606215784429963 3.3826014084648413 20.625870776973141  1.0000000000027249 -1.8976074902458944 3.1712160467506627 20.730787156685242  0.99999999999814426 -1.8259715408908139 2.9603681462309126 20.82922645588593  1.0000000000009628 -1.7459529425793781 2.7504961442615792 20.921047680535963  0.99999999999964562 -1.657800234977989 2.5420114233962003 21.006135589324959  1.0000000000000697 -1.5137502159732756 2.2319353529199755 21.123533125858419  0.99999999999997857 -1.4637627295876738 2.1290187460445011 21.160959282183381  1.0000000000000533 -1.4118354639862618 2.0265922076715999 21.19666709079527  0.99999999999987532 -1.3579994854490547 1.9247018206376643 21.230645931794385  1.0000000000002431 -1.302285654983125 1.8233917741662686 21.262886383289324  0.99999999999960754 -1.2447243909390817 1.722704372650915 21.293380047512112  1.0000000000005083 -1.1853454316196066 1.6226800444187608 21.322119376814193  0.99999999999947697 -1.1241775979039206 1.5233573505184606 21.349097499835917  1.0000000000004272 -1.0612485558485858 1.4247729934822135 21.374308047464499  0.99999999999972411 -0.99658457931725009 1.3269618261109308 21.397744979008717  1.000000000000139 -0.93021031258097242 1.2299568602423698 21.419402408187874  0.99999999999994582 -0.82811764312418301 1.0857054831724424 21.44921043978448  1.000000000000052 -0.79366487409969899 1.0378310565273661 21.458700083015316  0.99999999999967859 -0.75879307227523851 0.99016991290449186 21.467742606013655  1.0000000000008915 -0.72350496754211724 0.94272586540858816 21.476337247391999  0.9999999999983149 -0.68780316590857682 0.89550262619614696 21.484483229773435  1.0000000000024019 -0.65169014224737909 0.84850381042491163 21.492179751847214  0.99999999999731071 -0.61516823345611948 0.80173294072194246 21.499425980348057  1.0000000000023774 -0.57823963161479641 0.7551934524048165 21.506221041482576  0.99999999999836198 -0.54090637762563354 0.70888869919331388 21.512564012374554  1.000000000000844 -0.50317035486007722 0.66282195965674795 21.518453911946715  0.99999999999971179 -0.46503328320451587 0.61699644420580846 21.523889691743229  1.0000000000000329 -0.40722842824824301 0.5486247320270019 21.531360493613434  1.0000000000000233 -0.38786026869730605 0.52589525480847588 21.533736949603469  0.99999999999974387 -0.36839242841631981 0.50322726485047831 21.535999453612746  1.000000000000755 -0.3488250906827064 0.48062115212332257 21.538147860169559  0.99999999999859379 -0.32915842801245443 0.45807730309327876 21.540182018664311  1.000000000001924 -0.3093926020406661 0.43559610090583734 21.542101773135528  0.99999999999794398 -0.28952776328306973 0.41317792576229806 21.543906961840939  1.0000000000017613 -0.26956405107551129 0.39082315505563781 21.545597417094232  0.99999999999878975 -0.24950159332594968 0.36853216380908327 21.547172964813935  1.0000000000006459 -0.22934050645889359 0.34630532484821241 21.548633424319007  0.99999999999975508 -0.20908089521877615 0.32414300920507211 21.549978607938176  1.0000000000000482 -0.1785438312574148 0.29099687498481508 21.551823177118756  0.99999999999998812 -0.16834020208661471 0.27996438678565916 21.552409165804711  1.0000000000000151 -0.15811197668681443 0.26894816798479226 21.552966262411335  0.99999999999996547 -0.14785916594314497 0.25794826467445642 21.553494442124308  1.0000000000000902 -0.13758177999967591 0.24696472287397464 21.553993679633937  0.99999999999983247 -0.12727982825741035 0.23599758851097263 21.554463949208706  1.0000000000002096 -0.11695331936911835 0.22504690747395761 21.554905224554766  0.99999999999980416 -0.10660226123517802 0.21411272557588168 21.555317478971489  1.0000000000001581 -0.096226661003993019 0.203195088606694 21.55570068516808  0.99999999999987554 -0.085826525062315362 0.19229404231613012 21.556054815401591  1.0000000000000921 -0.075401859039385233 0.18140963243962549 21.556379841363899  0.99999999999994282 -0.054503476555995078 0.15967417696982089 21.556971627090764  1.0000000000001137 -0.04402976009692372 0.14882313137599423 21.557238386855353  0.99999999999937117 -0.033531523279666686 0.13798881365348592 21.557475984684338  1.0000000000016469 -0.023008770214577368 0.12717126951477242 21.557684391221979  0.9999999999970749 -0.012461504214037245 0.11637054470292174 21.557863576524824  1.00000000000386 -0.0018897278710352516 0.10558668493121548 21.558013510161068  0.99999999999606604 0.0087065570614823784 0.094819736005211208 21.558134161035564  1.0000000000031313 0.019327349530583238 0.084069743701353339 21.558225497581489  0.99999999999807454 0.029972649328898537 0.073336753910041352 21.558287487544444  1.0000000000008766 0.040642456977814323 0.062620812544792237 21.558320098144584  0.99999999999974343 0.051336773810465974 0.051921965620796318 21.558323295947361  1.0000000000000118 0.072463089632382349 0.030868815023047613 21.558271560321337  1.0000000000000562 0.082893685386003835 0.020513530077337361 21.55821831268084  0.99999999999957911 0.093347289869261996 0.010174547175858972 21.558137272852992  1.0000000000011737 0.10382380294456839 -0.00014799118323605143 21.558028410481484  0.99999999999787692 0.11432312370465425 -0.01045394275300815 21.55789169597475  1.0000000000027878 0.12484515043933175 -0.020743165661250895 21.557727100554413  0.99999999999720457 0.13538978073819452 -0.031015518285949284 21.557534596192557  1.0000000000022051 0.14595691140453226 -0.041270859458713005 21.55731415568232  0.99999999999862743 0.15654643858352957 -0.051509048301833449 21.5570657525817  1.0000000000006599 0.16715825768804926 -0.06172994440414703 21.556789361248871  0.99999999999976641 0.17779226348106514 -0.071933407732770682 21.556484956828363  1.0000000000000537 0.19910443663475519 -0.092305189691709089 21.555820073677058  0.99999999999994149 0.20978260399726656 -0.10247350831993929 21.555459594947816  1.0000000000002514 0.22048274623936415 -0.11262411501956215 21.555071054992503  0.9999999999993997 0.23120475681520247 -0.12275687063847762 21.554654430548823  1.0000000000010218 0.24194852850753179 -0.132871636507502 21.554209699096653  0.9999999999986664 0.25271395353118331 -0.14296827438844772 21.553736838983909  1.0000000000013385 0.26350092343081366 -0.15304664659266765 21.553235829234357  0.99999999999896383 0.2743093292343981 -0.16310661587563313 21.552706649785993  1.0000000000006235 0.28513906134129341 -0.17314804557363361 21.552149281240553  0.99999999999970202 0.29599000963900535 -0.18317079951853188 21.551563705075964  1.0000000000001186 0.30686206345492995 -0.19317474212015062 21.550949903494097  0.99999999999995959 0.33954120790698505 -0.22312973078430653 21.54902377151889  1.000000000000117 0.36141128154531987 -0.24302393771431108 21.54762671389129  0.99999999999943978 0.38336444303177641 -0.26284127884902153 21.54611655061818  1.0000000000014098 0.40539979453622133 -0.28258068299508521 21.544493158163149  0.99999999999754408 0.42751643041202891 -0.30224108838852048 21.542756425384308  1.000000000003231 0.44971343764792149 -0.32182144321693373 21.540906253435963  0.99999999999664857 0.47198989639165845 -0.3413207057634442 21.538942555677451  1.000000000002788 0.49434488033990442 -0.36073784497326367 21.536865257554354  0.99999999999814349 0.51677745724314184 -0.38007184047898246 21.534674296479835  1.0000000000009674 0.53928668926965262 -0.39932168306502991 21.532369621700383  0.99999999999962552 0.56187163345099078 -0.41848637473001027 21.529951194149561  1.0000000000000944 0.62985075924014033 -0.47572203739334151 21.522354570581545  0.99999999999978462 0.67546923415901139 -0.51353459627582954 21.516835033753797  1.0000000000009763 0.7213791847448765 -0.55099471283406798 21.510860155293543  0.99999999999746503 0.76757295301926831 -0.58809467860882814 21.504429899730134  1.0000000000046916 0.81404281733014772 -0.6248269746995545 21.497544411378172  0.99999999999341482 0.86078100381870071 -0.66118427577979588 21.490204008973539  1.0000000000071674 0.90777969711181239 -0.69715945333108564 21.482409180035248  0.99999999999391209 0.95503105020190437 -0.73274557744500468 21.474160575221557  1.0000000000040117 1.0025271935985349 -0.76793591797182126 21.465459002328888  0.99999999999800937 1.0502602436277022 -0.80272394423215543 21.456305420318735  1.0000000000006757 1.0982223100160902 -0.83710332395305365 21.446700933019876  0.99999999999990175 1.2427718878943963 -0.93899711498650706 21.416538482281396  1.0000000000000697 1.3400228745802347 -1.0052672243409888 21.394631493503216  0.99999999999990563 1.4380951546927261 -1.0698290692515737 21.370935825216218  1.0000000000001323 1.5369256183873261 -1.1326367269976325 21.345463645339038  0.99999999999979061 1.6364514588841361 -1.193647404154266 21.318229116762577  1.000000000000304 1.7366102773365697 -1.2528213087899216 21.289248233076343  0.99999999999967792 1.8373401877576196 -1.3101215227195908 21.258538654455524  1.000000000000236 1.9385799218672821 -1.365513873708049 21.226119543341781  0.99999999999988587 2.0402689340282714 -1.4189668076978768 21.192011400345329  1.0000000000000289 2.142347506099985 -1.4704512610446336 21.156235899949074  1.0000000000000053 2.2447568523550032 -1.5199405327231696 21.118815726359244  0.99999999999998868 2.5528039683598243 -1.6623494042527849 21.001691775084385  1.000000000000046 2.7592612641963434 -1.7492072819923488 20.917122296186324  0.99999999999976075 2.9663458730961034 -1.8277926137634655 20.826259715068382  1.000000000000665 3.1736091296659574 -1.897944658933409 20.72930758815486  0.99999999999871414 3.3806173103216444 -1.959530831180917 20.626478825324476  1.0000000000018212 3.5869500016948717 -2.0124444173937865 20.517995229375295  0.99999999999806077 3.7921984690708572 -2.0566022966078954 20.404087035600178  1.0000000000015814 3.99596402479848 -2.0919426588859187 20.284992451198768  0.99999999999901135 4.1978563967168832 -2.1184227242718467 20.160957194887388  1.0000000000004539 4.3974920965789401 -2.1360164616649566 20.032234036311465  0.99999999999987332 4.5944927884680533 -2.1447123077646291 19.899082335620371  0.99999999999999378 5.1764653947399921 -2.1441080423644561 19.487138077557784  1.000000000000095 5.5524187306982125 -2.1081992103116312 19.195907417876246  0.99999999999941613 5.9133519704878577 -2.0366990630627928 18.890130739925844  1.000000000001672 6.2563016709492629 -1.929913960101227 18.572120152219256  0.99999999999670497 6.5783856113283257 -1.7885259943291691 18.244396002908257  1.0000000000048734 6.8768557641713421 -1.6135770394322888 17.909638147075437  0.99999999999441846 7.1491512662521499 -1.4064527969838805 17.570637213870771  1.0000000000050213 7.3929513895400669 -1.1688668438721646 17.230245873788942  0.99999999999643796 7.6062285120292668 -0.90284467939470181 16.891330105861112  1.0000000000019702 7.7873010887819119 -0.61070777263869935 16.556720464863165  0.99999999999918077 7.9348866227425709 -0.29505760965705763 16.229163348557559  1.0000000000002349 8.0497524968121272 0.045984381254867035 15.906787805632833  0.99999999999995892 8.0513435185900057 0.050732623985981551 15.902305268711048  1.0000000000003633 8.0529276985017972 0.055484979584436989 15.89782466148157  0.99999999999899669 8.0545050339831938 0.060241440208500308 15.893345991306919  1.0000000000017668 8.0560755224622955 0.065001998009727391 15.888869265546468  0.99999999999773581 8.057639161377578 0.069766645153170881 15.884394491565711  1.0000000000022295 8.0591959481572921 0.074535373782679493 15.87992167672062  0.99999999999826428 8.060745880236535 0.079308176068563885 15.87545082837922  1.0000000000010814 8.0622889550481762 0.084085044154668775 15.870981953897065  0.99999999999946565 8.0638251700239891 0.08886597020609166 15.8665150606402  1.0000000000001983 8.0653545225978469 0.093650946374327582 15.8620501559676  0.99999999999995515 8.0668770102020808 0.098439964817657266 15.85758724724195  1
+ 2.6898219505952046 13 14.473677021732097 11 20.365604557300543 11 23.311568325084767 11 24.784550208976881 11 25.521041150922937 11 25.889286621895963 11 26.073409357382477 11 26.257532092868992 11 26.436306776466001 11 26.61508146006301 11 26.972630827257024 11 27.687729561645057 11 29.117927030421122 11 31.978321967973255 11 37.699111843077517 11 37.779814481202834 13
+7 1 0  2 3 2  8.0668770102020808 0.098439964817657266 15.85758724724195  1 8.0259154141761293 0.057478368791705758 15.799658802605602  0.92537659311247955 8.0447630708436169 -2.2204460492503131e-015 15.744410161399125  1
+ 0 3 35.089992530607631 3
+7 1 0  6 7 2  8.0447630708436186 -6.6613381477509392e-016 15.74441016139912  1.0000000000000004 8.1441501839885291 0.31262436321805953 15.453074052536182  0.99999999999999722 8.2118369462851035 0.64367289075905043 15.171125624680144  1.0000000000000051 8.2458129353939515 0.99252649486225297 14.900424225052499  0.99999999999999312 8.2483567054713767 1.3475572968363632 14.647580817617726  1.0000000000000053 8.2159391517581124 1.7209177765135244 14.406497764170359  0.999999999999998 8.1518614215746723 2.0943901572068553 14.187722708731973  1
+ 37.779814481202841 7 40.388933793672713 7
+7 1 0  2 3 2  8.1729592474930666 2.1729592474930772 14.315669125408014  1.0000000000000009 8.1319976514671151 2.1319976514671248 14.257740680771665  0.92537659311248055 8.1518614215746688 2.0943901572068659 14.187722708731966  1.0000000000000009
+ 0 3 35.089992530607631 3
+7 1 0  12 178 17  8.1518614215746688 2.0943901572068659 14.187722708731966  1.0000000000000009 8.0071607399772109 2.9377675348005825 13.693683679136079  0.99999999999979217 7.7169833828557985 3.7792876656562426 13.303825913989821  1.0000000000008566 7.2998907514762177 4.6066938509592044 13.013686132087054  0.99999999999790079 6.7600464359266965 5.4125518581303975 12.825583237394785  1.0000000000036997 6.1001504202139749 6.1774774502389018 12.751317472144848  0.99999999999500966 5.3313334099608856 6.8703631150103686 12.805012417037421  1.0000000000052705 4.4775573085605229 7.4562777000475933 12.994421283987815  0.99999999999561862 3.573962159416844 7.9053025565970945 13.315851046127294  1.000000000002826 2.6604941638854682 8.1981576903653508 13.754690048918881  0.99999999999865352 1.7740436773264774 8.3270613127787492 14.290356845459524  1.0000000000004041 0.94421637657095125 8.2928560828529942 14.901320098410286  0.99999999999998779 -0.17247555992473496 8.0066097955121265 15.893347185694921  0.99999999999991396 -0.52340827426053105 7.8720556347964248 16.236638235837475  1.0000000000007365 -0.84964867764116336 7.6993084264857723 16.589475727245976  0.99999999999776246 -1.1480158992536245 7.4896793734521516 16.948683312950266  1.0000000000044871 -1.4155979532367198 7.2449030902548879 17.310975386301084  0.99999999999337319 -1.6498071058939603 6.9671691721749838 17.67297387768145  1.0000000000074829 -1.8484352339350369 6.6591274411971408 18.031243673444862  0.99999999999344158 -2.0097091739243726 6.323866867997765 18.382346657356834  1.0000000000044684 -2.1323460628505559 5.9648681709122124 18.722914374404617  0.99999999999767808 -2.2156086697992476 5.5859300910692991 19.049739316920391  1.0000000000008662 -2.2593607188105915 5.1910693442332407 19.35988483321761  0.99999999999981126 -2.26650294484444 4.5810567014954877 19.796278071137657  1.0000000000000866 -2.2591327777070402 4.3747616961364155 19.936938739350353  0.99999999999963507 -2.2420630779504309 4.1660205075755563 20.072470468421542  1.0000000000009877 -2.2153851651266825 3.9553469896372393 20.202574493453859  0.99999999999808376 -2.1792259144665733 3.7432533631222911 20.326978353351073  1.0000000000027898 -2.1337433693660177 3.5302460035550629 20.445435764879324  0.99999999999687883 -2.0791223541469082 3.3168212289136614 20.557726496598843  1.0000000000027249 -2.0155700864545851 3.1034610873658273 20.663656242977531  0.99999999999814426 -1.9433117900546888 2.8906291450183881 20.763056498291675  1.0000000000009628 -1.8625863072637738 2.6787662736356057 20.85578443073404  0.99999999999964562 -1.7736417116597156 2.4682864383954679 20.94172275635454  1.0000000000000697 -1.6282755250936614 2.1552155092223817 21.06030804149044  0.99999999999997857 -1.5778279418079224 2.0513002562530049 21.098115471508073  1.0000000000000533 -1.5254191521838285 1.9478750641071534 21.134189631789205  0.99999999999987532 -1.4710801702860516 1.8449863825365871 21.168519607982333  1.0000000000002431 -1.4148418087407819 1.7426787844614964 21.201095669567398  0.99999999999960754 -1.3567344446521092 1.6409949767803025 21.231909096661123  1.0000000000005083 -1.2967877855341543 1.5399758111972246 21.260952006819128  0.99999999999947697 -1.2350306352167992 1.4396602950222561 21.288217181851383  1.0000000000004272 -1.1714906597841095 1.3400856020052352 21.313697894611416  0.99999999999972411 -1.1061941534814181 1.2412870831359921 21.337387735822372  1.000000000000139 -1.039165804645815 1.1432982774716414 21.359280440863287  0.99999999999994582 -0.93605979011226514 0.9975772456840899 21.389414354451922  1.000000000000052 -0.90126386923949697 0.94921395158315613 21.399008120028846  0.99999999999967859 -0.86604355444714365 0.9010650276989316 21.408150212270332  1.0000000000008915 -0.83040158642135786 0.85313435878307642 21.416839821267097  0.9999999999983149 -0.79434058384820894 0.8054257306349859 21.425076120774207  1.0000000000024019 -0.75786303628243123 0.75794283403699669 21.432858260367961  0.99999999999731071 -0.72097129744500776 0.71068926937465449 21.440185357479734  1.0000000000023774 -0.68366757848733206 0.66366855177829898 21.447056488959856  0.99999999999836198 -0.64595394178596033 0.61688411700564716 21.453470682586428  1.000000000000844 -0.6078322946907293 0.57033932781987007 21.459426908098294  0.99999999999971179 -0.56930438372206149 0.52403748109163839 21.464924068114094  1.0000000000000329 -0.51090549143092368 0.45495398262792941 21.472479448955792  1.0000000000000233 -0.49133802304110663 0.43198769508704427 21.474882849375799  0.99999999999974387 -0.47166958120186075 0.40908335766547577 21.477171043193799  1.000000000000755 -0.45190035304360565 0.38624137157415372 21.479343878887303  0.99999999999859379 -0.43203051510174184 0.36346213463460808 21.481401199857231  1.000000000001924 -0.41206023323173069 0.34074604153784893 21.483342844135016  0.99999999999794398 -0.39198966232751831 0.31809348411121174 21.485168644074751  1.0000000000017613 -0.37181894632526546 0.29550485158781736 21.486878426061779  0.99999999999878975 -0.35154821789530288 0.27298053091402785 21.488472010190797  1.0000000000006459 -0.33117759844684658 0.25052090702846908 21.489949209969957  0.99999999999975508 -0.31070719789485368 0.22812636319634194 21.491309831996627  1.0000000000000482 -0.27985207294540171 0.1946327403806154 21.493175597471328  0.99999999999998812 -0.26954211060810218 0.18348456493156329 21.493768324702319  1.0000000000000151 -0.25920723987866401 0.17235280270727316 21.494331832259871  0.99999999999996547 -0.24884747232437876 0.16123750136837378 21.494866094618768  1.0000000000000902 -0.23846281879402742 0.15013870847886235 21.495371085779418  0.99999999999983247 -0.22805328939132119 0.13905647157568479 21.495846779293991  1.0000000000002096 -0.21761889350356745 0.12799083809097178 21.496293148200902  0.99999999999980416 -0.2071596397608122 0.11694185547197566 21.496710165084711  1.0000000000001581 -0.19667553606867072 0.10590957107940069 21.497097801993974  0.99999999999987554 -0.18616658957602983 0.094894032295475661 21.49745603049157  1.0000000000000921 -0.17563280669215775 0.083895286466409313 21.497784821604267  0.99999999999994282 -0.15451557945130823 0.061931475440771599 21.498383470061789  1.0000000000001137 -0.14393213509596059 0.050966410242733851 21.498653327407688  0.99999999999937117 -0.1333238656569673 0.040018232719604363 21.498893688364483  1.0000000000016469 -0.12269077605174949 0.029086990225871467 21.499104522916792  0.9999999999970749 -0.11203287041373722 0.018172730142349547 21.499285800457677  1.00000000000386 -0.10135015216573207 0.0072754998621875622 21.499437489912822  0.99999999999606604 -0.090642623918791188 -0.0036046531774598378 21.499559559529676  1.0000000000031313 -0.079910287576644645 -0.014467681487709605 21.49965197711311  0.99999999999807454 -0.069153144233966568 -0.025313537523485419 21.499714709765566  1.0000000000008766 -0.058371194255480319 -0.036142173661918076 21.499747724085914  0.99999999999974343 -0.047564437216404354 -0.046953542192639031 21.499750986015901  1.0000000000000118 -0.026215921647240847 -0.068228123009612673 21.499698706251262  1.0000000000000562 -0.015675848282300731 -0.078692062567233823 21.499644870470462  0.99999999999957911 -0.0051127499780534436 -0.089139274496072396 21.499562924412782  1.0000000000011737 0.0054732742980236893 -0.099569619539858323 21.499452839676991  0.99999999999787692 0.016082124781134244 -0.10998295865570817 21.499314588552323  1.0000000000027878 0.026713700905933724 -0.1203791531128755 21.499148144147156  0.99999999999720457 0.037367901359652844 -0.13075806440550819 21.498953480198217  1.0000000000022051 0.048044624066581054 -0.14111955440871293 21.498730571316038  0.99999999999862743 0.058743766236176498 -0.15146348526953712 21.498479392736826  1.0000000000006599 0.069465224362502909 -0.16178971953270116 21.498199920534475  0.99999999999976641 0.080208894254031993 -0.17209812009131742 21.497892131477304  1.0000000000000537 0.10174044783827974 -0.19267898039518938 21.497219874740075  0.99999999999994149 0.11252833153136432 -0.20295144013893074 21.49685540705633  1.0000000000002514 0.12333821726022798 -0.21320579277218332 21.496462577602379  0.9999999999993997 0.1341699994921437 -0.22344190197462099 21.496041364641311  1.0000000000010218 0.14502357203381067 -0.23365963185974836 21.495591747251613  0.9999999999986664 0.15589882806828959 -0.24385884693767457 21.495113705155049  1.0000000000013385 0.16679566014679592 -0.25403941220726001 21.494607218966557  0.99999999999896383 0.17771396023415331 -0.26420119309100754 21.494072269896034  1.0000000000006235 0.18865361970047001 -0.27434405552407082 21.493508840041848  0.99999999999970202 0.19961452935628499 -0.28446786591618256 21.492916912149965  1.0000000000001186 0.21059657945771271 -0.29457249119758488 21.492296469773301  0.99999999999995959 0.24360582026835287 -0.32482841405822516 21.490349552005021  1.000000000000117 0.26569610148418965 -0.34492175865805175 21.488937485983303  0.99999999999943978 0.28786962115611381 -0.36493677221286935 21.487411173346196  1.0000000000014098 0.31012548851219846 -0.38487240271381928 21.485770500271606  0.99999999999754408 0.33246280474623324 -0.40472760696280785 21.48401536482227  1.000000000003231 0.35488066349255387 -0.42450135099691311 21.482145676898149  0.99999999999664857 0.37737815132906993 -0.4441926103984879 21.480161358134531  1.000000000002788 0.39995434819804165 -0.46380037069361402 21.478062341838964  0.99999999999814349 0.42260832788862457 -0.48332362756407532 21.475848572864663  1.0000000000009674 0.44533915842253347 -0.50276138718125729 21.473520007513716  0.99999999999962552 0.46814590248982979 -0.5221126663762754 21.471076613401141  1.0000000000000944 0.53679104848341463 -0.57990414583692029 21.463401881158031  0.99999999999978462 0.58285436427300574 -0.61808198819879134 21.457825993232973  1.0000000000009763 0.62921002687556005 -0.655902241113127 21.451790535631272  0.99999999999746503 0.67585041906116716 -0.69335730080832469 21.44529551783711  1.0000000000046916 0.72276785691947643 -0.73043974414298329 21.438341124023665  0.99999999999341482 0.76995460142731398 -0.76714233311025337 21.43092770817697  1.0000000000071674 0.81740286903931691 -0.80345801827234542 21.423055788972619  0.99999999999391209 0.8651048417114473 -0.83937994113042569 21.414726044507585  1.0000000000040117 0.91305267590632377 -0.87490143543347809 21.405939306778041  0.99999999999800937 0.96123851099490576 -0.91001602741208032 21.396696556001139  1.0000000000006757 1.0096544767363718 -0.9447174349571239 21.386998914706929  0.99999999999990175 1.1555691466440614 -1.0475638272605856 21.356545095524915  1.0000000000000697 1.2537347185973606 -1.1144510294444077 21.334427989046254  0.99999999999990563 1.3527262467616132 -1.1796123400448826 21.310506456130419  1.0000000000001323 1.4524807098372023 -1.2430020850323888 21.284792760144978  0.99999999999979061 1.5529353397461734 -1.3045776303484997 21.257301135657613  1.000000000000304 1.6540277270274755 -1.3642992635380953 21.228047630260996  0.99999999999967792 1.7556959262133718 -1.422130075599715 21.197049946290967  1.000000000000236 1.8578785612320514 -1.4780358425483247 21.164327282672964  0.99999999999988587 1.9605149307795928 -1.5319849072948726 21.129900176640952  1.0000000000000289 2.0635451137220349 -1.5839480612346 21.093790345562276  1.0000000000000053 2.1669100744728911 -1.6338984260565477 21.05602052868889  0.99999999999998868 2.4778351562152285 -1.7776371541378015 20.937801929474205  1.000000000000046 2.6862259269826541 -1.8653104952655646 20.852441799904913  0.99999999999976075 2.8952565177261267 -1.9446383042722397 20.760728057038811  1.000000000000665 3.1044752044275326 -2.0154577929061706 20.662865016919529  0.99999999999871414 3.313444590694048 -2.0776342523433131 20.55906671730154  1.0000000000018212 3.521740096449852 -2.1310588661890684 20.44955644032915  0.99999999999806077 3.7289484465947611 -2.17564652371812 20.334566234873019  1.0000000000015814 3.9346661597255701 -2.2113336328055153 20.214336439314486  0.99999999999901135 4.138498036768457 -2.2380759331887479 20.089115203841963  1.0000000000004539 4.3400556497103588 -2.2558463094347712 19.95915801319158  0.99999999999987332 4.5389558302421795 -2.2646326041259046 19.824727209051549  0.99999999999999378 5.1265458149110099 -2.2640410844814651 19.408820119921895  1.000000000000095 5.5061359657878484 -2.2277940891569559 19.114778880051777  0.99999999999941613 5.8705598064731133 -2.1556097381951984 18.806050286935633  1.000000000001672 6.2168203367549637 -2.0477989092397948 18.484973361603487  0.99999999999670497 6.5420059498793393 -1.905051827280035 18.154094984188141  1.0000000000048734 6.8433430216333617 -1.7284218280252697 17.816121225937597  0.99999999999441846 7.1182484993076418 -1.519309120628515 17.473868681154183  1.0000000000050213 7.3643824909007147 -1.2794445512543851 17.130215799176273  0.99999999999643796 7.5797008539684114 -1.0108733657318227 16.788054216375709  1.0000000000019702 7.7625077848787312 -0.71593897303842091 16.450240088082317  0.99999999999918077 7.9115084076981104 -0.39726670815315135 16.11954542060905  1.0000000000002349 8.0274745296037082 -0.052958031504910075 15.794081989342084  0.99999999999995892 8.0290807910540636 -0.048164307519442673 15.789556516241049  1.0000000000003633 8.0306801451048493 -0.043366431271414374 15.785032991315584  0.99999999999899669 8.0322725891612592 -0.038564410677035088 15.780511421999474  1.0000000000017668 8.0338581206382127 -0.033758253664756932 15.775991815725158  0.99999999999773581 8.035436736929686 -0.028947968141638469 15.771474179927564  1.0000000000022295 8.0370084354640809 -0.024133562044775569 15.766958522038109  0.99999999999826428 8.0385732136255221 -0.019315043276749044 15.762444849492073  1.0000000000010814 8.040131068843456 -0.014492419772778042 15.757933169721355  0.99999999999946565 8.0416819985100805 -0.0096656994427744003 15.753423490160237  1.0000000000001983 8.0432260000421198 -0.004834890212541687 15.748915818241649  0.99999999999995515 8.0447630708436169 -2.2204460492503131e-015 15.744410161399125  1
+ 2.6898219505952046 13 14.473677021732097 11 20.365604557300543 11 23.311568325084767 11 24.784550208976881 11 25.521041150922937 11 25.889286621895963 11 26.073409357382477 11 26.257532092868992 11 26.436306776466001 11 26.61508146006301 11 26.972630827257024 11 27.687729561645057 11 29.117927030421122 11 31.978321967973255 11 37.699111843077517 11 37.779814481202834 13
+2 0 0 0 -2.4492935982947064e-016 -1 0 1 -2.4492935982947064e-016 0 0 0 1 8.5
+Polygon3D 0
+PolygonOnTriangulations 0
+Surfaces 17
+2 0 0 0 0 0 1 1 0 -0 -0 1 0 10
+5 0 0 0.5 -0 -0 -1 1 0 -0 -0 1 -0 9.5 0.5
+1 0 0 0 1 0 -0 0 0 1 0 -1 0 
+5 0 0 4.5 0 0 1 1 0 -0 -0 1 0 9.5 0.5
+1 0 0 0 -0 1 0 0 0 1 1 0 -0 
+1 0 0 0 0 0 1 1 0 -0 -0 1 0 
+2 0 0 0 0 0 1 1 0 -0 -0 1 0 7.5
+4 0 0 0 0 0 1 1 0 -0 -0 1 0 12
+1 0 0 5 0 0 1 1 0 -0 -0 1 0 
+4 0 0 0 0 0 1 1 0 -0 -0 1 0 11.949999999999999
+9 1 1 0 0 6 7 7 14 2 3 4.8678334076839933 -5.5094817597023393e-015 23.913601509814971  1.0584045643979316 5.2453015164677348 -0.139366199637567 23.745238035244242  1.0584045643979256 5.6237339251218996 -0.25030180427678811 23.556089231112377  1.058404564403195 6.000155335997583 -0.33193339347582629 23.347641349460922  1.0584045643812252 6.3716391314814462 -0.38299224786023656 23.121066700248512  1.05840456442027 6.7341701420999582 -0.40413612837708934 22.879669545995512  1.0584045643849909 7.0878353428550005 -0.39455494210023057 22.622815562318031  1.0584045643979363 7.6199296077227503 -0.33247050230520758 22.202667771014344  1.0584045643979345 7.80749167138893 -0.30048331055091615 22.047423020747203  1.0584045630682277 7.9902398896533704 -0.25899596379060397 21.888864556070441  1.0584045612010267 8.1679077234144675 -0.2080919936909334 21.727239906056148  1.058404559447049 8.3401664552877257 -0.1478738879140305 21.56285397218738  1.0584045583157158 8.5066251897509328 -0.078463090128382623 21.396069028263479  1.0584045581749411 8.6668308532806098 -2.0261570199409107e-015 21.22730472029712  1.058404559251283 
+4.8893404642098979 0.069839868069846461 23.904008639105555  1.0179465873219373 5.2630606848804442 -0.0681425618906248 23.737316848712524  1.0179465873219353 5.6377425643221422 -0.17797590844705186 23.550040655065622  1.0179465873234215 6.0103957780818904 -0.25880037470922235 23.343686569000813  1.0179465873172318 6.3782512783894774 -0.30934568374694649 23.119314380594631  1.0179465873282243 6.737117110306249 -0.33028675193336643 22.880365489009378  1.0179465873182973 7.0873102710789571 -0.32079632703385041 22.626030786359898  1.0179465873219382 7.6141052174490671 -0.25933020854379807 22.210067398289254  1.0179465873219393 7.7997957773540678 -0.22766267680854826 22.056372032059578  1.0179465869480502 7.9807209240210906 -0.18659004502828713 21.899395917612686  1.0179465864230444 8.1566192389674903 -0.13619440130791294 21.739381943780224  1.0179465859298535 8.3271662157041657 -0.076576637853799312 21.576630907380775  1.0179465856117553 8.491974259778063 -0.0078564509769611796 21.411501513192537  1.017946585572169 8.6505926888112246 0.069827658909503293 21.244410373923479  1.0179465858748133 
+4.8967245120845879 0.13618834146639386 23.865642289046118  0.99621518633173289 5.2658724336801264 -0.00010593542667340639 23.700989897852999  0.99621518633173056 5.6359787919944377 -0.10859456371355554 23.515998226824173  0.99621518633142236 6.0040349303688245 -0.18843436679471975 23.312198501889458  0.99621518633273232 6.367464031010396 -0.23835316754497968 23.090513242508941  0.99621518633038575 6.7218584665970278 -0.25904681143377695 22.854551150133467  0.99621518633251605 7.0678158538519966 -0.24966711239683528 22.603289886691488  0.99621518633173345 7.5881458075827632 -0.18895532537170318 22.192431331650557  0.99621518633173389 7.7715531959649047 -0.15767776865612448 22.040626163280493  0.99621518641314044 7.9502542571520154 -0.11711107597672975 21.885580464655444  0.99621518652746699 8.1239938191471239 -0.06733557413283997 21.72753146331414  0.99621518663484832 8.2924525122174337 -0.008450208751478519 21.566774948238656  0.99621518670411668 8.455246768885111 0.059427455713329302 21.403665269860447  0.9962151867127359 8.6119288239185661 0.13616123597998753 21.238615340066893  0.99621518664683628 
+4.8877306608750013 0.18531983119089654 23.804808660859752  0.98906881166944516 5.2523713488252488 0.050689684351219122 23.642166647496083  0.9890688116694436 5.6179672972923633 -0.056473361481576743 23.459426989517993  0.98906881166852567 5.9814917782901036 -0.13534251348732471 23.258145276269278  0.98906881167237692 6.3405574684866748 -0.18464372138205479 23.03910870993845  0.98906881166551452 6.690544137301317 -0.20509346191046859 22.806090913589138  0.989068811671725 7.0323260275864161 -0.19582291306716981 22.557859353221787  0.9890688116694446 7.5462829878050295 -0.13585472310395549 22.152032987634712  0.98906881166944738 7.7274396956604674 -0.10496159197966014 22.002091119606554  0.98906881190461959 7.9039483218371078 -0.064893638790774144 21.848948367227415  0.98906881223489274 8.0755598515946332 -0.015729454064456541 21.692836376988655  0.98906881254509171 8.2419599785846991 0.042433935479266799 21.534046001054016  0.98906881274520841 8.4027691048249782 0.10948106692955983 21.372927297276558  0.98906881277009895 8.5575423406736881 0.1852780411830999 21.209889529217804  0.98906881257972901 
+4.8637563483541895 0.20706401329963217 23.733059473797994  0.99621518633173289 5.224851871082258 0.073742788174410545 23.571998723383018  0.99621518633173001 5.5869001560851252 -0.032377620603876264 23.391030386565593  0.99621518633142248 5.9468602613731489 -0.11048330687445482 23.191729215756414  0.99621518633273176 6.3024939104994386 -0.1592987470314802 22.974775979272827  0.99621518633038808 6.6490136497814216 -0.17955664533525023 22.744074019372938  0.99621518633251327 6.9875113023671984 -0.17037194859274246 22.498225472354637  0.99621518633173478 7.4964555836926268 -0.11098863499731421 22.09635717605066  0.99621518633173245 7.6758420189910286 -0.080397873689897717 21.947880887689198  0.99621518641314688 7.8506261858340496 -0.040722203869607163 21.796234898694397  0.99621518652745633 8.0205639122018297 0.007961149514083915 21.641646465535352  0.99621518663486008 8.1853448741488979 0.065556668998452972 21.484402557113192  0.99621518670410891 8.3445925957950955 0.13195054460818786 21.324849854767116  0.99621518671273845 8.49786444931717 0.2070106738548623 21.163394752280627  0.99621518664683639 
+4.8298018476888132 0.19783727430884376 23.664571664122754  1.0179465873219373 5.1889798969431533 0.065224005656555256 23.504366171381001  1.0179465873219353 5.5491093572488355 -0.040332472031113301 23.324355889016417  1.0179465873234215 5.9071415986856737 -0.11802522259306596 23.126125934187204  1.0179465873172318 6.2609189597960446 -0.16657792556778753 22.910299508273361  1.0179465873282243 6.6055635409445133 -0.18673206216224969 22.680850114825098  1.0179465873182973 6.9422848479207104 -0.17759380024721122 22.43629046820422  1.0179465873219382 7.4485179216697217 -0.11852682872622994 22.036562972788744  1.0179465873219393 7.6269468700987026 -0.088099609863929146 21.888879372910246  1.0179465869480502 7.8007983292215943 -0.048636113926789439 21.738042938939063  1.0179465864230444 7.9698307460600279 -0.00021282741698135099 21.58427855272604  1.0179465859298535 8.1337359504672726 0.05707554841154619 21.427871082656495  1.0179465856117553 8.292139155168865 0.12311609755002634 21.269165383624035  1.017946585572169 8.4445989558002843 0.19777768923732034 21.10856629700185  1.0179465858748133 
+4.7929501726221675 0.16098559924219849 23.612455525447338  1.0584045643979316 5.1521282218765023 0.028372330589910788 23.452250032705589  1.0584045643979256 5.5122576821856644 -0.077184147099903427 23.272239750335164  1.058404564403195 5.8702899236121713 -0.15487689765374871 23.074009795527981  1.0584045643812252 6.2240672847329659 -0.20342960064170129 22.858183369579738  1.05840456442027 6.5687118658790302 -0.22358373722484781 22.628733976158063  1.0584045643849909 6.905433172854063 -0.21444547531385644 22.384174329528804  1.0584045643979363 7.4116662466030805 -0.15537850379287529 21.984446834113328  1.0584045643979345 7.5900951956392344 -0.12495128441996042 21.83676323468568  1.0584045630682277 7.7639466555503773 -0.085487787826995787 21.685926801436445  1.0584045612010267 7.9329790729820306 -0.037064500764224462 21.532162416050209  1.058404559447049 8.0968842775637437 0.02022387536292386 21.375754946702266  1.0584045583157158 8.2552874820463309 0.086264424483480789 21.217049247968745  1.0584045581749411 8.4077472824322346 0.16092601586926938 21.056450160728609  1.058404559251283 
+
+0 7
+4.5469861841947221 7
+
+27.003426592720988 8
+29.908219967738049 6
+31.55041277691571 8
+
+9 1 1 0 0 6 8 7 30 2 5 10.457607314751494 4.1520753998578845 17.025073803590558  1.058404564397933 10.198481727311403 5.6623700024094594 16.14036370859473  1.0584045643979338 9.4539501708476585 7.2622577929764258 15.535535515130185  1.0584045643979241 8.248455319341824 8.7656620017466604 15.324881788429543  1.0584045643979452 6.7008332749465058 9.9684032620937923 15.568749329531027  1.0584045643979114 5.0021636982240958 10.709494567624294 16.245859418607623  1.0584045643979547 3.3673075559849113 10.910959145646991 17.259420313760781  1.0584045643979203 1.982198965258045 10.590075049423096 18.465739311358281  1.0584045643979354 0.46233693526959474 9.4618878826869235 20.33819285527785  1.0584045643979281 0.048690766228185467 8.978002120913434 20.972843769888573  1.0584045643979543 -0.25669344451313325 8.3976451054714634 21.599157397299123  1.0584045643978861 -0.44243494262249605 7.736724418849791 22.197837969496838  1.0584045643979778 -0.50209407157768826 7.0149965747848277 22.750361996850078  1.0584045643979134 -0.43464996282412471 6.2548109899931248 23.240204192165898  1.0584045643979332 -0.24444052319786902 5.4796190804290523 23.653849263534159  1.058404564397933 0.21134466937368046 4.3290351139813454 24.145146188102085  1.0584045643979352 0.39168474135954856 3.9475410756227007 24.287383521786708  1.0584045643979199 0.5992962469447507 3.5709736489202397 24.4068533993306  1.0584045643979663 0.83273930778730065 3.2022059119093376 24.502542395511178  1.0584045643978861 1.0902913086077537 2.8440467470611557 24.57368240343067  1.0584045643979589 1.369970683137562 2.4991968232922894 24.619764940731635  1.0584045643979301 1.6695665212729058 2.1702061516836157 24.640550226812369  1.058404564397931 2.3037820523698858 1.5486619865855618 24.631590217987657  1.0584045643979321 2.6384017449409858 1.2561084934038753 24.601844923140632  1.0584045643979478 2.9881288309581384 0.9841329275802595 24.546866295964236  1.0584045643978879 3.3503651350884658 0.73490396564717209 24.466958037972709  1.058404564398006 3.7223546064721535 0.51035962621342801 24.362698585317943  1.0584045643978726 4.1012249687261386 0.3121698954630876 24.234938085552656  1.0584045643979565 4.4840360652674551 0.14170303609468959 24.084788035501798  1.0584045643979303 4.8678334076839933 -5.3290705182007514e-015 23.913601509814971  1.0584045643979316 
+10.423613398627618 4.1806892314120248 17.083877256985957  1.017946587321938 10.16706067412985 5.6759880898024289 16.207951465541857  1.0179465873219342 9.4299215858122025 7.2599905637207858 15.609128622844983  1.0179465873219471 8.2363961158763175 8.7484674431826761 15.400566481048681  1.0179465873219202 6.7041404405302094 9.9392666624187811 15.642012656643896  1.0179465873219573 5.0223369867111991 10.672999658121668 16.312399706620493  1.0179465873219233 3.4037133625569185 10.872463890473137 17.315896936148846  1.0179465873219433 2.0323575416716859 10.554765858613536 18.510238369213972  1.0179465873219373 0.52758625101551182 9.437780483957944 20.364100285876933  1.017946587321936 0.1180471827435019 8.9586992332213491 20.992449739348139  1.0179465873219489 -0.18430486229482934 8.3841045937494574 21.612544686704208  1.0179465873219136 -0.36820212949658782 7.7297462013391147 22.205280947984154  1.0179465873219635 -0.4272689018127096 7.0151844069210725 22.752318953641314  1.0179465873219231 -0.36049444691231969 6.2625467194240132 23.237297496377082  1.0179465873219407 -0.172173600471071 5.4950517052417762 23.646835477874731  1.017946587321938 0.27908609215585045 4.3558919091299098 24.133254305827904  1.0179465873219378 0.45763556409779849 3.9781857324166365 24.27407936229018  1.0179465873219433 0.66318569105062686 3.6053572509377041 24.392363021121977  1.0179465873219256 0.89431089125107377 3.2402510158812623 24.4871019194185  1.0179465873219489 1.149305653301496 2.8856480202705401 24.557535576831139  1.0179465873219296 1.4262080859412833 2.5442221180284026 24.603160559732629  1.0179465873219447 1.7228292312367861 2.2184980011266786 24.623739468308109  1.0179465873219335 2.3507476241255465 1.6031251600001255 24.614868423583339  1.0179465873219447 2.6820448713322143 1.3134764360797169 24.585418470341118  1.0179465873219171 3.0282995103849699 1.0442013208813767 24.530985727011391  1.0179465873219684 3.3869391632833761 0.79744695810495525 24.451870879650755  1.0179465873219136 3.7552351440500691 0.57513212373743894 24.348646621106884  1.0179465873219513 4.1303436951891612 0.37891022263575813 24.222154657801404  1.01794658732193 4.5093538529890491 0.210135931993368 24.073495450485847  1.017946587321942 4.8893404642098988 0.069839868069845323 23.904008639105555  1.0179465873219375 
+10.36328810240129 4.1967433088891051 17.128952151700382  0.99621518633173267 10.109874185278754 5.6737478572343543 16.263742918966479  0.99621518633173189 9.3817536626828293 7.2383707722054611 15.6722464048392  0.99621518633173245 8.2028304409004758 8.7086368054705634 15.466235927189825  0.99621518633173523 6.6893212256587535 9.8848671310068141 15.704728117251619  0.99621518633172967 5.0280938818573482 10.609623233000988 16.366913282719675  0.99621518633173312 3.4292733908762578 10.806647110042467 17.358133174280749  0.99621518633173389 2.0746954926308945 10.492835970935324 18.53786237624999  0.996215186331733 0.58833440297487627 9.389516410738949 20.369043124868192  0.99621518633173123 0.18380586129323007 8.9162965039662279 20.989705004946291  0.99621518633174222 -0.11484704224985531 8.3487317718775298 21.602213369084797  0.99621518633171424 -0.29649440896949031 7.7023791605485723 22.187697768385409  0.99621518633175121 -0.35483852585100983 6.996559708800036 22.728043009699309  0.99621518633172446 -0.28888102642036539 6.2531302054258573 23.207088057751903  0.99621518633173156 -0.10286420096681681 5.4950251480865182 23.611615525955322  0.99621518633173634 0.34287453196595585 4.3698024605226031 24.092083237982475  0.99621518633172812 0.51923953129927281 3.9967173492666008 24.231185363118577  0.99621518633175909 0.72227484475397929 3.6284502568340162 24.348021874501789  0.99621518633167672 0.95057233192081547 3.2678109326070244 24.441601684921473  0.99621518633179995 1.2024473475665101 2.9175463454073838 24.511173618165188  0.99621518633168171 1.4759620032905487 2.5802976357566947 24.556240399889354  0.9962151863317571 1.7689541220756371 2.2585586071537227 24.576567534759739  0.99621518633172712 2.3891902154039411 1.65071457639556 24.567805023283494  0.99621518633173589 2.7164341895653101 1.364609574541177 24.538715376994215  0.99621518633173023 3.0584525586001465 1.0986289194547503 24.484948593835281  0.99621518633173012 3.4127044163982401 0.85489348549852906 24.406801681104326  0.99621518633174377 3.7764944612291877 0.63529857329501915 24.304840325009287  0.99621518633172035 4.147013727693496 0.44147735903720253 24.179895934071659  0.99621518633173956 4.5213868664131063 0.27476794604989419 24.033055505399872  0.99621518633173123 4.896724512084587 0.13618834146639447 23.865642289046118  0.99621518633173289 
+10.287548434956518 4.1962961097004188 17.150372369922597  0.98906881166944483 10.037228658872355 5.6552666824898221 16.295727195485807  0.98906881166944338 9.3179983646247386 7.2007858164776426 15.711452753686721  0.98906881166944505 8.1534695958503711 8.6531001503157672 15.507957629102602  0.98906881166944871 6.6584400719691121 9.8149689026510138 15.743537869888014  0.98906881166943861 5.0174960328767613 10.530875855303325 16.397637866558934  0.98906881166945004 3.438196869494087 10.725494104151796 17.376755131005581  0.98906881166944238 2.1001581381273073 10.415514545941416 18.542080039085082  0.98906881166944638 0.63194526581297428 9.3256663308408871 20.350902380685543  0.98906881166944283 0.23235594915982372 8.8582243590385392 20.963986084253381  0.98906881166945682 -0.062650452977359272 8.2975894962697119 21.569015824931363  0.98906881166942073 -0.24207993609258516 7.6591287409314406 22.147351558808229  0.98906881166947291 -0.29971168118175928 6.9619272252305677 22.68109927617791  0.98906881166942395 -0.23455951165586253 6.2275748702689313 23.154295265270893  0.98906881166945337 -0.050813920158281789 5.4787261473722753 23.553883521552912  0.98906881166944449 0.38948241828561159 4.3672422383823166 24.028484804134148  0.9890688116694436 0.56369403082630853 3.998712433190982 24.165888515865163  0.98906881166945526 0.76425031746724237 3.6349418196287688 24.281298473218371  0.98906881166942573 0.98976033095414184 3.278705840513088 24.373735689991463  0.9890688116694617 1.2385599952884632 2.9327179246419628 24.442458161704632  0.98906881166944016 1.5087350833575162 2.5995869646573841 24.486974685651784  0.98906881166944294 1.7981498179605557 2.2817763151402031 24.507053629645544  0.98906881166944538 2.4108129335627431 1.6813539571214502 24.498398106951427  0.9890688116694466 2.7340613141848524 1.3987422489171224 24.469663640320015  0.9890688116694405 3.0719036968195654 1.1360091726128223 24.416553340483425  0.9890688116694516 3.421830199390179 0.89524970705334628 24.339360588330983  0.98906881166943816 3.7811784293443411 0.67833601156224432 24.238644163136868  0.98906881166945027 4.1471737182746029 0.48688132152648489 24.115225322066273  0.98906881166944194 4.5169758243321825 0.32220740225672895 23.970177790176081  0.98906881166944571 4.8877306608750013 0.18531983119089634 23.804808660859752  0.98906881166944505 
+10.21107519181346 4.179044167461468 17.143319956675114  0.99621518633173278 9.9631891127738506 5.6238301143828417 16.296983943694613  0.99621518633173212 9.2509514288140782 7.1543231669018521 15.718390023844197  0.99621518633173067 8.0977446189643665 8.5925175891716741 15.51687335054751  0.99621518633173933 6.6172502987764714 9.7430902441993084 15.750163197243083  0.9962151863317239 4.9922600956961416 10.452036897261276 16.397903803322855  0.99621518633173922 3.4283154351281269 10.644762998935441 17.367501744805839  0.9962151863317299 2.1032855876656797 10.337797171188036 18.521496953613703  0.99621518633173434 0.64934719811120445 9.2585448443613974 20.312733287205642  0.99621518633173045 0.253642829559932 8.7956475080771348 20.919856375033106  0.99621518633174511 -0.038495416411959305 8.2404633349420813 21.51900380343519  0.99621518633170958 -0.21618042288416994 7.6082099199810802 22.091716753573859  0.99621518633175521 -0.27325185184485878 6.9177868430228333 22.620275187609145  0.9962151863317219 -0.20873311466296496 6.1905741203502975 23.088870598600874  0.99621518633173289 -0.026773962534804241 5.4490059685386116 23.484573917090223  0.99621518633173534 0.40924165980115657 4.348328297660208 23.954560958811907  0.99621518633172956 0.58175952567432265 3.9833814690589282 24.090628783253436  0.99621518633175166 0.78036593344539451 3.6231475615491164 24.204916684345417  0.99621518633169315 1.0036834591397286 3.2703750341156876 24.296455193933319  0.99621518633177852 1.2500642054912259 2.9277509346454642 24.364509521567665  0.99621518633170003 1.5176125561781761 2.5978587912078765 24.408593240186615  0.99621518633174744 1.8042134987776763 2.2831380087820388 24.428476969613698  0.99621518633172856 2.4109200877439028 1.6885531684419983 24.419905598960295  0.99621518633173778 2.7310257337371007 1.408689110821804 24.391450498935956  0.99621518633171813 3.0655834937144513 1.1485104180400745 24.338856556143789  0.99621518633175576 3.4121078875563979 0.91009170081791702 24.262414299120888  0.99621518633171036 3.7679624074296045 0.69528691668813458 24.162677074492443  0.99621518633174755 4.1303993612296637 0.50569361659342782 24.04045815487212  0.99621518633172546 4.4966061209400339 0.34262071517746495 23.896820826183649  0.99621518633173489 4.8637563483541895 0.20706401329963153 23.733059473797994  0.99621518633173278 
+10.148725595134607 4.1487255951346134 17.109824690323038  1.017946587321938 9.9021558297880485 5.5858395036227719 16.267982853405684  1.0179465873219342 9.1937002388757314 7.10820539962711 15.692461357397509  1.0179465873219471 8.0466171368219612 8.5387627854865773 15.492014769026493  1.0179465873219202 6.5739844720917251 9.6832257204903378 15.724065810296263  1.0179465873219573 4.9576232201151971 10.388407756391945 16.368366812859044  1.0179465873219233 3.4019833493114318 10.580110452444892 17.332816038237805  1.0179465873219433 2.0839896167395495 10.274774661059178 18.480683352728533  1.0179465873219373 0.63777186651437301 9.2012533322036614 20.262407942367236  1.017946587321936 0.24416874979924064 8.7408140528808929 20.86630711202648  1.0179465873219489 -0.046418196580171767 8.1885779941864101 21.462272974254173  1.0179465873219136 -0.22315966798964926 7.5596819433454279 22.031944729415869  1.0179465873219635 -0.27992803877282402 6.8729251204733002 22.557696435832568  1.0179465873219231 -0.21575190613523887 6.1495740106365302 23.023803532198571  1.0179465873219407 -0.03475898544887901 5.4119437012254075 23.417405604427838  1.017946587321938 0.39894132601414345 4.3171108002325189 23.884896941747819  1.0179465873219378 0.5705430951462418 3.9541018961390781 24.020242224846339  1.0179465873219433 0.76809487195520543 3.5957808867919594 24.133923239380483  1.0179465873219256 0.99022654680156563 3.2448816364307729 24.224975665224001  1.0179465873219489 1.2352989730112842 2.9040769242994893 24.292668613777238  1.0179465873219296 1.5014266002798293 2.5759365595310073 24.336518240983679  1.0179465873219447 1.7865056472301761 2.2628869934840887 24.356296384710109  1.0179465873219335 2.3899905297019792 1.6714594912650496 24.347770529370063  1.0179465873219447 2.7083963648519354 1.3930815553853972 24.3194665303593  1.0179465873219171 3.0411775710095306 1.1342844519904736 24.267151869595967  1.0179465873219684 3.3858618663419477 0.89713177529545796 24.191115532865297  1.0179465873219136 3.7398267432829204 0.68346763802957611 24.091907928435766  1.0179465873219513 4.100339100401337 0.49488110789146766 23.970338010316702  1.01794658732193 4.4646012451734123 0.33267414898396375 23.827463418218056  1.017946587321942 4.8298018476888132 0.19783727430884301 23.664571664122754  1.0179465873219375 
+10.111873920067961 4.1118739200679686 17.057708551647622  1.058404564397933 9.8653041547214002 5.5489878285561156 16.215866714730296  1.0584045643979338 9.1568485638090795 7.071353724560546 15.640345218721979  1.0584045643979241 8.009765461755368 8.5019111104197265 15.439898630351282  1.0584045643979452 6.5371327970249702 9.6463740454239986 15.671949671620606  1.0584045643979114 4.9207715450486917 10.351556081325018 16.316250674183813  1.0584045643979547 3.3651316742446826 10.543258777378405 17.280699899562304  1.0584045643979203 2.0471379416729407 10.237922985992494 18.428567214053135  1.0584045643979354 0.60092019144771136 9.164401657137029 20.210291803691817  1.0584045643979281 0.20731707473264649 8.7039623778142019 20.814190973351067  1.0584045643979543 -0.083269871646901805 8.1517263191198346 21.41015683557875  1.0584045643978861 -0.26001134305620699 7.522830268278728 21.97982859074045  1.0584045643979778 -0.31677971383952475 6.8360734454066741 22.505580297157156  1.0584045643979134 -0.25260358120186144 6.1127223355698828 22.971687393523155  1.0584045643979332 -0.071610660515527336 5.3750920261587583 23.365289465752422  1.058404564397933 0.36208965094750045 4.2802591251658821 23.832780803072399  1.0584045643979352 0.53369142007958992 3.9172502210723819 23.96812608617094  1.0584045643979199 0.73124319688855532 3.558929211725431 24.081807100705007  1.0584045643979663 0.95337487173496616 3.2080299613639633 24.172859526548677  1.0584045643978861 1.1984472979445782 2.8672252492329964 24.24055247510173  1.0584045643979589 1.4645749252132183 2.5390848844642702 24.284402102308327  1.0584045643979301 1.7496539721635305 2.2260353184174777 24.304180246034672  1.058404564397931 2.3531388546353225 1.634607816198351 24.295654390694665  1.0584045643979321 2.6715446897853385 1.3562298803189661 24.26735039168382  1.0584045643979478 3.0043258959428143 1.0974327769234078 24.215035730920661  1.0584045643978879 3.3490101912753545 0.86028010022933099 24.138999394189767  1.058404564398006 3.7029750682162588 0.64661596296250234 24.039791789760415  1.0584045643978726 4.0634874253346904 0.45802943282505026 23.918221871641258  1.0584045643979565 4.4277495701067666 0.29582247391725236 23.77534727954265  1.0584045643979303 4.7929501726221675 0.16098559924219735 23.612455525447338  1.0584045643979316 
+
+0 7
+27.003426592720981 7
+
+6.9915739190569493e-015 9
+13.501713296360498 7
+20.252569944540742 7
+23.627998268630865 7
+27.003426592720988 9
+
+9 1 1 0 0 6 6 7 7 2 2 8.6668308532806098 4.4408920985006262e-016 21.22730472029712  1.0584045592512832 9.366646654445173 0.34274512567321036 20.490102758859706  1.0584045639530038 9.9446323300351516 0.86282287914093869 19.713654529496349  1.0584045742896391 10.359805174140732 1.5460699019423574 18.936954819538212  1.0584045410165293 10.584474557202489 2.3499904929220348 18.209631446218562  1.0584045743748955 10.614948853319143 3.235021708620883 17.562271418492891  1.0584045643979356 10.457607314751494 4.1520753998578837 17.025073803590562  1.0584045643979318 
+8.6505926888112246 0.069827658909506152 21.244410373923479  1.0179465858748136 9.3434750812091298 0.40917001803841346 20.514517201793847  1.0179465871968398 9.9157855753598376 0.92411830649964211 19.745709032424578  1.0179465901032525 10.32677256118183 1.6006155371933666 18.976741926696096  1.017946580747622 10.549220238896362 2.3964828743436319 18.256684115180384  1.0179465901272275 10.579392690032162 3.2727409839160226 17.615741026436233  1.0179465873219427 10.423613398627618 4.180689231412023 17.083877256985961  1.0179465873219378 
+8.6119288239185661 0.13616123597998997 21.238615340066893  0.99621518664683639 9.2963526831822314 0.47135233374024965 20.517638646875188  0.99621518635898187 9.8617396360620866 0.98004284823846 19.758151091899283  0.99621518572609213 10.267620048783654 1.6483055549614278 18.998617511635203  0.9962151877632841 10.487357281459341 2.4343481844393633 18.287423446488098  0.99621518572087708 10.517161504130618 3.2999034004728989 17.654308806773159  0.99621518633173756 10.363288102401286 4.1967433088891051 17.128952151700386  0.99621518633173278 
+8.5575423406736881 0.18527804118310143 21.209889529217804  0.98906881257972901 9.2336280317856687 0.51637695141389361 20.497702428580443  0.98906881174814876 9.7921899619550352 1.0188987424805853 19.747402847880132  0.98906880991988277 10.193036492412574 1.6790441084054326 18.997168560017844  0.98906881580492456 10.410101826686331 2.4554018331328216 18.294712100848152  0.98906880990480883 10.439543068493428 3.3104064647780036 17.669314509152269  0.98906881166945049 10.287548434956516 4.1962961097004206 17.1503723699226  0.98906881166944505 
+8.49786444931717 0.20701067385486471 21.163394752280627  0.9962151866468365 9.1673917508430023 0.53489087254685508 20.45812110548033  0.99621518635898265 9.7205854546618351 1.0325606522430861 19.715048322707645  0.99621518572609047 10.117472600322529 1.6863213297504906 18.972128403892825  0.99621518776328655 10.332436335233563 2.4550613813490623 18.276544503465431  0.99621518572087553 10.361592079979165 3.3017674537440587 17.657216757616681  0.99621518633173811 10.211075191813459 4.179044167461468 17.143319956675118  0.99621518633173289 
+8.4445989558002843 0.19777768923732308 21.108566297001847  1.0179465858748136 9.1105790190873766 0.52391698202852499 20.407031929060082  1.0179465871968398 9.6608692079705101 1.0189624527537529 19.667867899873354  1.0179465901032525 10.055614853888271 1.6692698535526087 18.928904111769427  1.017946580747622 10.269441882386763 2.4338897209561399 18.237037367928288  1.0179465901272275 10.298443215178056 3.2761073574209032 17.620992619201623  1.0179465873219427 10.148725595134605 4.1487255951346125 17.109824690323041  1.0179465873219378 
+8.4077472824322346 0.16092601586927091 21.056450160728609  1.0584045592512832 9.0737273420740348 0.48706530608348819 20.354915792797655  1.0584045639530038 9.6240175289394081 0.98211077507932587 19.615751756611353  1.0584045742896391 10.018763193514083 1.632418192160936 18.876787974861582  1.0584045410165293 10.232590199172119 2.3970380340767714 18.184921234053807  1.0584045743748955 10.261591540111413 3.2392556823542611 17.568876480526207  1.0584045643979356 10.111873920067961 4.1118739200679677 17.057708551647625  1.0584045643979318 
+
+0 7
+6.1486990661618215 7
+
+31.55041277691571 7
+37.699111843077532 7
+
+2 0 0 0 0 0 1 1 0 -0 -0 1 0 6
+9 1 1 0 0 2 6 3 7 2 2 8.0668770102020808 0.098439964817656933 15.857587247241948  1.0000000000000004 8.165321172711133 0.40809825600438854 15.56901523481479  0.99999999999999722 8.2323723673686455 0.73599211674116671 15.289746910465151  1.0000000000000051 8.2659991962099699 1.0816031679969018 15.02158522508712  0.99999999999999312 8.2685628965545241 1.4330975095396172 14.77122839624287  1.0000000000000053 8.2364160494168619 1.8031059019107807 14.53232419916106  0.999999999999998 8.1729592474930683 2.1729592474930675 14.31566912540802  1 
+8.0259154141761293 0.05747836879170598 15.799658802605599  0.92537659311248011 8.1243595766851815 0.36713665997843925 15.511086790178439  0.925376593112479 8.1914107706389832 0.6950305140844959 15.23181846853304  0.92537659026418417 8.2250376017183449 1.0406415850606483 14.963656776190133  0.92537660008995304 8.2276012985046361 1.392135905562518 14.713299951413523  0.92537658479651985 8.1954544533909104 1.7621443058848265 14.474395754524712  0.92537659311248022 8.1319976514671168 2.1319976514671151 14.25774068077167  0.92537659311247977 
+8.0447630708436186 -6.6613381477509392e-016 15.74441016139912  1.0000000000000004 8.1441501839885291 0.31262436321805953 15.453074052536182  0.99999999999999722 8.2118369462851035 0.64367289075905043 15.171125624680144  1.0000000000000051 8.2458129353939515 0.99252649486225297 14.900424225052499  0.99999999999999312 8.2483567054713767 1.3475572968363632 14.647580817617726  1.0000000000000053 8.2159391517581124 1.7209177765135244 14.406497764170359  0.999999999999998 8.1518614215746723 2.0943901572068553 14.187722708731973  1 
+
+0 3
+2.6091193124698719 3
+
+37.779814481202841 7
+40.388933793672713 7
+
+9 1 1 0 0 2 12 3 178 2 17 8.1729592474930666 2.1729592474930772 14.315669125408014  1.0000000000000009 8.0296607494956636 3.0081641001581292 13.8264174500764  0.99999999999979217 7.7423771484404122 3.8411955366909436 13.440513248052714  1.0000000000008566 7.3296432767451023 4.6602697146782006 13.153208272316585  0.99999999999790079 6.7953325452781037 5.4583660218612327 12.966697477024411  1.0000000000036997 6.1418634707595192 6.2163089699220304 12.89281662146181  0.99999999999500966 5.380183498938214 6.9030696664546003 12.945775999351344  1.0000000000052705 4.5341428039443672 7.4837961370160428 13.133370839300776  0.99999999999561862 3.6387590998922645 7.9287306578188748 13.451886389414492  1.000000000002826 2.7337628561564631 8.218821148724416 13.886693165405223  0.99999999999865352 1.8557006645402028 8.3464825638909161 14.417305308825926  1.0000000000004041 1.0337628608158764 8.3126131072993203 15.022452468584349  0.99999999999998779 -0.072296639696200593 8.0291219281374389 16.005013394386602  0.99999999999991396 -0.41988628639463332 7.8958608367201295 16.345026267846265  1.0000000000007365 -0.74302567276071674 7.7247741204011531 16.694497055929229  0.99999999999776246 -1.0385706997131141 7.517154735104012 17.050288145873868  1.0000000000044871 -1.303639675069439 7.2747110461164386 17.409153700625836  0.99999999999337319 -1.5356673173777056 6.9996010959542243 17.767753766369072  1.0000000000074829 -1.7324596647914277 6.6944402802428247 18.122687749182404  0.99999999999344158 -1.8922498883769858 6.3622824311804145 18.470547260898783  1.0000000000044684 -2.0137550107257152 6.0065743089446508 18.807988334277734  0.99999999999767808 -2.096233528871311 5.631083500846719 19.131823007180458  1.0000000000008662 -2.1395439424458305 5.2397997282553721 19.439130276171706  0.99999999999981126 -2.1465343083170483 4.6353144779335897 19.871514490625973  1.0000000000000866 -2.1391985528188995 4.4308887968520834 20.010880239827976  0.99999999999963507 -2.1222477401056947 4.2240408267152736 20.145160162512788  1.0000000000009877 -2.095772792756299 4.0152816994113962 20.274057067429407  0.99999999999808376 -2.0599003391659307 3.8051211018143012 20.39729999625791  1.0000000000027898 -2.0147883174015204 3.5940630075102113 20.514644143618415  0.99999999999687883 -1.9606215784429963 3.3826014084648413 20.625870776973141  1.0000000000027249 -1.8976074902458944 3.1712160467506627 20.730787156685242  0.99999999999814426 -1.8259715408908139 2.9603681462309126 20.82922645588593  1.0000000000009628 -1.7459529425793781 2.7504961442615792 20.921047680535963  0.99999999999964562 -1.657800234977989 2.5420114233962003 21.006135589324959  1.0000000000000697 -1.5137502159732756 2.2319353529199755 21.123533125858419  0.99999999999997857 -1.4637627295876738 2.1290187460445011 21.160959282183381  1.0000000000000533 -1.4118354639862618 2.0265922076715999 21.19666709079527  0.99999999999987532 -1.3579994854490547 1.9247018206376643 21.230645931794385  1.0000000000002431 -1.302285654983125 1.8233917741662686 21.262886383289324  0.99999999999960754 -1.2447243909390817 1.722704372650915 21.293380047512112  1.0000000000005083 -1.1853454316196066 1.6226800444187608 21.322119376814193  0.99999999999947697 -1.1241775979039206 1.5233573505184606 21.349097499835917  1.0000000000004272 -1.0612485558485858 1.4247729934822135 21.374308047464499  0.99999999999972411 -0.99658457931725009 1.3269618261109308 21.397744979008717  1.000000000000139 -0.93021031258097242 1.2299568602423698 21.419402408187874  0.99999999999994582 -0.82811764312418301 1.0857054831724424 21.44921043978448  1.000000000000052 -0.79366487409969899 1.0378310565273661 21.458700083015316  0.99999999999967859 -0.75879307227523851 0.99016991290449186 21.467742606013655  1.0000000000008915 -0.72350496754211724 0.94272586540858816 21.476337247391999  0.9999999999983149 -0.68780316590857682 0.89550262619614696 21.484483229773435  1.0000000000024019 -0.65169014224737909 0.84850381042491163 21.492179751847214  0.99999999999731071 -0.61516823345611948 0.80173294072194246 21.499425980348057  1.0000000000023774 -0.57823963161479641 0.7551934524048165 21.506221041482576  0.99999999999836198 -0.54090637762563354 0.70888869919331388 21.512564012374554  1.000000000000844 -0.50317035486007722 0.66282195965674795 21.518453911946715  0.99999999999971179 -0.46503328320451587 0.61699644420580846 21.523889691743229  1.0000000000000329 -0.40722842824824301 0.5486247320270019 21.531360493613434  1.0000000000000233 -0.38786026869730605 0.52589525480847588 21.533736949603469  0.99999999999974387 -0.36839242841631981 0.50322726485047831 21.535999453612746  1.000000000000755 -0.3488250906827064 0.48062115212332257 21.538147860169559  0.99999999999859379 -0.32915842801245443 0.45807730309327876 21.540182018664311  1.000000000001924 -0.3093926020406661 0.43559610090583734 21.542101773135528  0.99999999999794398 -0.28952776328306973 0.41317792576229806 21.543906961840939  1.0000000000017613 -0.26956405107551129 0.39082315505563781 21.545597417094232  0.99999999999878975 -0.24950159332594968 0.36853216380908327 21.547172964813935  1.0000000000006459 -0.22934050645889359 0.34630532484821241 21.548633424319007  0.99999999999975508 -0.20908089521877615 0.32414300920507211 21.549978607938176  1.0000000000000482 -0.1785438312574148 0.29099687498481508 21.551823177118756  0.99999999999998812 -0.16834020208661471 0.27996438678565916 21.552409165804711  1.0000000000000151 -0.15811197668681443 0.26894816798479226 21.552966262411335  0.99999999999996547 -0.14785916594314497 0.25794826467445642 21.553494442124308  1.0000000000000902 -0.13758177999967591 0.24696472287397464 21.553993679633937  0.99999999999983247 -0.12727982825741035 0.23599758851097263 21.554463949208706  1.0000000000002096 -0.11695331936911835 0.22504690747395761 21.554905224554766  0.99999999999980416 -0.10660226123517802 0.21411272557588168 21.555317478971489  1.0000000000001581 -0.096226661003993019 0.203195088606694 21.55570068516808  0.99999999999987554 -0.085826525062315362 0.19229404231613012 21.556054815401591  1.0000000000000921 -0.075401859039385233 0.18140963243962549 21.556379841363899  0.99999999999994282 -0.054503476555995078 0.15967417696982089 21.556971627090764  1.0000000000001137 -0.04402976009692372 0.14882313137599423 21.557238386855353  0.99999999999937117 -0.033531523279666686 0.13798881365348592 21.557475984684338  1.0000000000016469 -0.023008770214577368 0.12717126951477242 21.557684391221979  0.9999999999970749 -0.012461504214037245 0.11637054470292174 21.557863576524824  1.00000000000386 -0.0018897278710352516 0.10558668493121548 21.558013510161068  0.99999999999606604 0.0087065570614823784 0.094819736005211208 21.558134161035564  1.0000000000031313 0.019327349530583238 0.084069743701353339 21.558225497581489  0.99999999999807454 0.029972649328898537 0.073336753910041352 21.558287487544444  1.0000000000008766 0.040642456977814323 0.062620812544792237 21.558320098144584  0.99999999999974343 0.051336773810465974 0.051921965620796318 21.558323295947361  1.0000000000000118 0.072463089632382349 0.030868815023047613 21.558271560321337  1.0000000000000562 0.082893685386003835 0.020513530077337361 21.55821831268084  0.99999999999957911 0.093347289869261996 0.010174547175858972 21.558137272852992  1.0000000000011737 0.10382380294456839 -0.00014799118323605143 21.558028410481484  0.99999999999787692 0.11432312370465425 -0.01045394275300815 21.55789169597475  1.0000000000027878 0.12484515043933175 -0.020743165661250895 21.557727100554413  0.99999999999720457 0.13538978073819452 -0.031015518285949284 21.557534596192557  1.0000000000022051 0.14595691140453226 -0.041270859458713005 21.55731415568232  0.99999999999862743 0.15654643858352957 -0.051509048301833449 21.5570657525817  1.0000000000006599 0.16715825768804926 -0.06172994440414703 21.556789361248871  0.99999999999976641 0.17779226348106514 -0.071933407732770682 21.556484956828363  1.0000000000000537 0.19910443663475519 -0.092305189691709089 21.555820073677058  0.99999999999994149 0.20978260399726656 -0.10247350831993929 21.555459594947816  1.0000000000002514 0.22048274623936415 -0.11262411501956215 21.555071054992503  0.9999999999993997 0.23120475681520247 -0.12275687063847762 21.554654430548823  1.0000000000010218 0.24194852850753179 -0.132871636507502 21.554209699096653  0.9999999999986664 0.25271395353118331 -0.14296827438844772 21.553736838983909  1.0000000000013385 0.26350092343081366 -0.15304664659266765 21.553235829234357  0.99999999999896383 0.2743093292343981 -0.16310661587563313 21.552706649785993  1.0000000000006235 0.28513906134129341 -0.17314804557363361 21.552149281240553  0.99999999999970202 0.29599000963900535 -0.18317079951853188 21.551563705075964  1.0000000000001186 0.30686206345492995 -0.19317474212015062 21.550949903494097  0.99999999999995959 0.33954120790698505 -0.22312973078430653 21.54902377151889  1.000000000000117 0.36141128154531987 -0.24302393771431108 21.54762671389129  0.99999999999943978 0.38336444303177641 -0.26284127884902153 21.54611655061818  1.0000000000014098 0.40539979453622133 -0.28258068299508521 21.544493158163149  0.99999999999754408 0.42751643041202891 -0.30224108838852048 21.542756425384308  1.000000000003231 0.44971343764792149 -0.32182144321693373 21.540906253435963  0.99999999999664857 0.47198989639165845 -0.3413207057634442 21.538942555677451  1.000000000002788 0.49434488033990442 -0.36073784497326367 21.536865257554354  0.99999999999814349 0.51677745724314184 -0.38007184047898246 21.534674296479835  1.0000000000009674 0.53928668926965262 -0.39932168306502991 21.532369621700383  0.99999999999962552 0.56187163345099078 -0.41848637473001027 21.529951194149561  1.0000000000000944 0.62985075924014033 -0.47572203739334151 21.522354570581545  0.99999999999978462 0.67546923415901139 -0.51353459627582954 21.516835033753797  1.0000000000009763 0.7213791847448765 -0.55099471283406798 21.510860155293543  0.99999999999746503 0.76757295301926831 -0.58809467860882814 21.504429899730134  1.0000000000046916 0.81404281733014772 -0.6248269746995545 21.497544411378172  0.99999999999341482 0.86078100381870071 -0.66118427577979588 21.490204008973539  1.0000000000071674 0.90777969711181239 -0.69715945333108564 21.482409180035248  0.99999999999391209 0.95503105020190437 -0.73274557744500468 21.474160575221557  1.0000000000040117 1.0025271935985349 -0.76793591797182126 21.465459002328888  0.99999999999800937 1.0502602436277022 -0.80272394423215543 21.456305420318735  1.0000000000006757 1.0982223100160902 -0.83710332395305365 21.446700933019876  0.99999999999990175 1.2427718878943963 -0.93899711498650706 21.416538482281396  1.0000000000000697 1.3400228745802347 -1.0052672243409888 21.394631493503216  0.99999999999990563 1.4380951546927261 -1.0698290692515737 21.370935825216218  1.0000000000001323 1.5369256183873261 -1.1326367269976325 21.345463645339038  0.99999999999979061 1.6364514588841361 -1.193647404154266 21.318229116762577  1.000000000000304 1.7366102773365697 -1.2528213087899216 21.289248233076343  0.99999999999967792 1.8373401877576196 -1.3101215227195908 21.258538654455524  1.000000000000236 1.9385799218672821 -1.365513873708049 21.226119543341781  0.99999999999988587 2.0402689340282714 -1.4189668076978768 21.192011400345329  1.0000000000000289 2.142347506099985 -1.4704512610446336 21.156235899949074  1.0000000000000053 2.2447568523550032 -1.5199405327231696 21.118815726359244  0.99999999999998868 2.5528039683598243 -1.6623494042527849 21.001691775084385  1.000000000000046 2.7592612641963434 -1.7492072819923488 20.917122296186324  0.99999999999976075 2.9663458730961034 -1.8277926137634655 20.826259715068382  1.000000000000665 3.1736091296659574 -1.897944658933409 20.72930758815486  0.99999999999871414 3.3806173103216444 -1.959530831180917 20.626478825324476  1.0000000000018212 3.5869500016948717 -2.0124444173937865 20.517995229375295  0.99999999999806077 3.7921984690708572 -2.0566022966078954 20.404087035600178  1.0000000000015814 3.99596402479848 -2.0919426588859187 20.284992451198768  0.99999999999901135 4.1978563967168832 -2.1184227242718467 20.160957194887388  1.0000000000004539 4.3974920965789401 -2.1360164616649566 20.032234036311465  0.99999999999987332 4.5944927884680533 -2.1447123077646291 19.899082335620371  0.99999999999999378 5.1764653947399921 -2.1441080423644561 19.487138077557784  1.000000000000095 5.5524187306982125 -2.1081992103116312 19.195907417876246  0.99999999999941613 5.9133519704878577 -2.0366990630627928 18.890130739925844  1.000000000001672 6.2563016709492629 -1.929913960101227 18.572120152219256  0.99999999999670497 6.5783856113283257 -1.7885259943291691 18.244396002908257  1.0000000000048734 6.8768557641713421 -1.6135770394322888 17.909638147075437  0.99999999999441846 7.1491512662521499 -1.4064527969838805 17.570637213870771  1.0000000000050213 7.3929513895400669 -1.1688668438721646 17.230245873788942  0.99999999999643796 7.6062285120292668 -0.90284467939470181 16.891330105861112  1.0000000000019702 7.7873010887819119 -0.61070777263869935 16.556720464863165  0.99999999999918077 7.9348866227425709 -0.29505760965705763 16.229163348557559  1.0000000000002349 8.0497524968121272 0.045984381254867035 15.906787805632833  0.99999999999995892 8.0513435185900057 0.050732623985981551 15.902305268711048  1.0000000000003633 8.0529276985017972 0.055484979584436989 15.89782466148157  0.99999999999899669 8.0545050339831938 0.060241440208500308 15.893345991306919  1.0000000000017668 8.0560755224622955 0.065001998009727391 15.888869265546468  0.99999999999773581 8.057639161377578 0.069766645153170881 15.884394491565711  1.0000000000022295 8.0591959481572921 0.074535373782679493 15.87992167672062  0.99999999999826428 8.060745880236535 0.079308176068563885 15.87545082837922  1.0000000000010814 8.0622889550481762 0.084085044154668775 15.870981953897065  0.99999999999946565 8.0638251700239891 0.08886597020609166 15.8665150606402  1.0000000000001983 8.0653545225978469 0.093650946374327582 15.8620501559676  0.99999999999995515 8.0668770102020808 0.098439964817657266 15.85758724724195  1 
+8.1319976514671151 2.1319976514671248 14.257740680771665  0.92537659311248055 7.9886991534693479 2.9672025041322763 13.768489005440291  0.92537659311233311 7.7014121464538796 3.8002533500746249 13.382575664376173  0.92537909236032589 7.288654587928419 4.6193274469445527 13.095266766852392  0.92535530307440661 6.7543414846793803 5.4174141773027609 12.908750831341688  0.92533970711482816 6.100906155529616 6.1753267616377174 12.83487416615651  0.92534726074455165 5.339264726245422 6.8620600744509428 12.887841981109077  0.92536599948524589 4.4932209340220108 7.4428022065813746 13.075438441090514  0.92537805475352031 3.5977928663262526 7.8877828860057075 13.39395284227844  0.92537819238689878 2.6927763290618678 8.1778833404055717 13.828764211226897  0.92537508031021443 1.8147517912357698 8.3055051681016892 14.359379038268884  0.92537659116082582 0.99280111856753339 8.271651462292855 14.964524118230905  0.92537654290953331 -0.11325835970938414 7.9881602324347085 15.947084849673903  0.92537629676888822 -0.46084836124252693 7.8548986622916814 16.287098257499913  0.92537623359051557 -0.78398760686025648 7.6838120595430146 16.636568708455648  0.92537605307929982 -1.0795322661143167 7.4761932122004708 16.992359037657057  0.92537591497505867 -1.3446009940070009 7.2337499895906046 17.351224178153032  0.92537601883365783 -1.5766286194665087 6.9586401170017105 17.709824537126515  0.92537643196713837 -1.7734211025061848 6.6534789797145972 18.06475933914686  0.9253770010605944 -1.9332115141674748 6.3213205545060402 18.412619693585949  0.92537734802785843 -2.0547168755816099 5.9656116613876895 18.750061133767357  0.92537694943234527 -2.1371957917574926 5.5901198033042174 19.073895393386039  0.92537530014738023 -2.1805069255442993 5.198834906231605 19.381201231103653  0.92537216069088035 -2.1874992494258079 4.5943490770907811 19.81358165562731  0.9253657525991944 -2.1801641834765872 4.3899220408649935 19.952946752870588  0.9253633451073644 -2.1632140904951784 4.1830727230893245 20.087225814078035  0.92536067872883065 -2.1367398968099032 3.974312377269178 20.216121622267917  0.9253578195532568 -2.1008682279128115 3.7641507475885869 20.339363270339547  0.92535487526449456 -2.0557570102180138 3.5530918383634753 20.456706042633648  0.92535198317068024 -2.0015910744068659 3.3416296666021097 20.567931309561246  0.92534929831350932 -1.9385777578044348 3.1302439969031544 20.672846434048413  0.92534698147215544 -1.8669425027919022 2.9193960584442924 20.771284687812273  0.92534518728337645 -1.7869244490712504 2.7095242440560958 20.863105176001795  0.92534405225505167 -1.6987720171910778 2.5010397919213676 20.94819276789714  0.92534368286095015 -1.5547217494430301 2.1909638571345811 21.065590634717289  0.92534437394615632 -1.5047341602854676 2.0880474504848028 21.103016955334301  0.92534480842057409 -1.4528067456815545 1.9856212056781779 21.138725012966351  0.92534545341024699 -1.3989705657341638 1.8837311910248449 21.172704195181151  0.9253463107232941 -1.3432564734055479 1.7824215783133013 21.204945084192588  0.92534737741803896 -1.2856948787711957 1.6817346529802177 21.23543928292743  0.9253486456668093 -1.2263155130956109 1.5817108241999052 21.264179241138134  0.92535010258874006 -1.1651471926866428 1.4823886349928361 21.291158081191867  0.92535173012465122 -1.1022175825897769 1.3838047722587303 21.316369423970514  0.92535350486365342 -1.0375529600503324 1.285994076843801 21.339807214424074  0.92535539791667631 -0.97117797781325166 1.1889895535668189 21.3614655471603  0.92535737475140489 -0.86908426334488009 1.0447389525904758 21.391274931553685  0.92536040520526697 -0.83463121186424072 0.99686488415777075 21.400765011543587  0.92536142637952767 -0.79975911963120971 0.94920409079850021 21.409807976652502  0.92536245369558734 -0.76447071725735372 0.90176038332994413 21.418403063120564  0.92536348198342189 -0.7287686117017298 0.85453747190073992 21.426549490940122  0.9253645058346589 -0.69265527921344949 0.80753896993519758 21.434246456071904  0.92536551957630975 -0.65613305830509683 0.76076839870296942 21.441493122253306  0.92536651737923126 -0.61920414320239292 0.71422919247651917 21.448288612705142  0.92536749320431244 -0.5818705772334547 0.66792470433922491 21.454632001368847  0.92536844093491144 -0.5441342467097221 0.62185821256994789 21.460522304043856  0.92536935435134371 -0.50599687482767308 0.57603292768182746 21.465958469115044  0.92537022723356377 -0.44819161228835558 0.50766156676166441 21.473429814238536  0.92537146647291624 -0.42882333571448061 0.48493222090000465 21.475806444364984  0.92537186787199588 -0.40935538034822327 0.46226435611677763 21.478069117401798  0.92537225681808766 -0.38978792978948551 0.43965836231533029 21.480217687479037  0.92537263253753965 -0.37012115690674996 0.41711462588975934 21.482252003620495  0.92537299426939479 -0.35035522370034844 0.39463352999222678 21.48417190945899  0.92537334124556603 -0.33049028109182776 0.37221545477986817 21.48597724290423  0.9253736727228894 -0.31052646882398527 0.34986077771511814 21.487667835880615  0.92537398795156423 -0.29046391525781612 0.32756987382933245 21.489243513963888  0.92537428620831652 -0.27030273727151188 0.30534311604712538 21.490704096119984  0.92537456677460284 -0.25004304009822631 0.28318087547939275 21.492049394346544  0.92537482895442713 -0.2195058597772781 0.25003484925343589 21.493894122654037  0.92537519362520004 -0.20930219562105901 0.23900239810467516 21.494480162170596  0.92537531041578902 -0.19907393641470694 0.22798621451036016 21.495037307525763  0.92537542235465076 -0.18882109309653972 0.21698634457240651 21.495565533836142  0.92537552935965317 -0.17854367586581654 0.2060028343167124 21.496064815808477  0.92537563134531708 -0.16824169417839263 0.19503572968711502 21.49653512758319  0.92537572823546654 -0.15791515674454804 0.18408507658031814 21.496976442940028  0.92537581994450957 -0.14756407152308215 0.17315092082608752 21.49738873502686  0.92537590640012013 -0.13718844571993172 0.16223330823037196 21.497771976611503  0.92537598752120021 -0.12678828578408119 0.15133228455807179 21.49812613985355  0.92537606323568267 -0.11636359740378355 0.14044789556524062 21.498451196442868  0.92537613346888536 -0.095465175066496322 0.11871247994925715 21.499043038531962  0.9253762628311345 -0.084991440864983225 0.1078614530626214 21.49930982404782  0.92537632195971631 -0.074493187821929929 0.097027152074126821 21.499547445192398  0.92537637546561857 -0.063970420084245472 0.086209622741266312 21.499755872553195  0.92537642327626857 -0.053423141061152979 0.075408910768384629 21.499935076203204  0.92537646532866435 -0.042851353341328835 0.064625061982558574 21.500085025603962  0.92537650155139384 -0.032255058815369608 0.053858122090552296 21.500205689726648  0.92537653188550051 -0.021634258515998983 0.043108137015084314 21.500297036879182  0.92537655626653348 -0.010988952775897065 0.032375152570823129 21.500359034861738  0.92537657463562362 -0.00031914109268749158 0.021659214760399781 21.500391650815626  0.92537658693619618 0.010375177784303968 0.010960369594612551 21.500394851311324  0.92537659311243192 0.031501493606542308 -0.010092781002897233 21.500343115684824  0.92537659311255493 0.041932087697031051 -0.020448067872353093 21.500289865507341  0.9253765872892844 0.052385688946650522 -0.030787054423730531 21.500208820808915  0.92537657611788449 0.062862197306278844 -0.041109597962092348 21.500099951431324  0.92537656004035307 0.073361511963829784 -0.051415556094959403 21.499963227963804  0.92537653949190934 0.08388353129473991 -0.061704786754837038 21.49979862180929  0.92537651485909234 0.094428152982092062 -0.071977148226100685 21.499606105099303  0.925376486538523 0.10499527391546337 -0.082232499158425565 21.499385650792643  0.92537645487444498 0.11558479032816038 -0.092470698595969125 21.499137232588613  0.92537642021725963 0.12619659771850289 -0.1026916059900671 21.498860824992732  0.92537638288070367 0.13683059093350591 -0.11289508122190695 21.49855640327835  0.92537634317027462 0.15814273833141002 -0.13326688893651406 21.497891483702787  0.9253762595691768 0.16882089261494881 -0.14343522150829102 21.497530985833627  0.92537621567901895 0.17952102116477064 -0.15358584264186703 21.497142425954792  0.92537616998321903 0.19024301748205019 -0.16371861309607461 21.496725780911959  0.92537612275165293 0.20098677444187718 -0.17383339408944609 21.496281028314883  0.92537607423155188 0.21175218427554254 -0.18393004733500273 21.495808146585954  0.92537602466356661 0.22253913864188801 -0.19400843502966891 21.495307114882973  0.9253759742622778 0.23334752857544316 -0.20406841990419711 21.49477791319735  0.92537592323880491 0.24417724457551548 -0.21410986520148212 21.494220522246877  0.9253758717820133 0.25502817655881671 -0.22413263472336142 21.493634923568102  0.92537582007344232 0.26590021392142926 -0.23413659282064447 21.493021099446842  0.92537576827922297 0.29857931239399926 -0.26409163096523081 21.49109489975633  0.92537561310710303 0.32044935624697723 -0.28398587147539534 21.489697797037245  0.92537550993870843 0.34240248788727179 -0.30380324521874291 21.488187589351277  0.92537540829556919 0.36443780978490059 -0.32354268064703406 21.486564153632642  0.92537530922614364 0.38655441655608724 -0.34320311576305329 21.48482737913594  0.92537521362954589 0.40875139548694239 -0.36278349854979641 21.482977167338085  0.92537512222369345 0.4310278269425023 -0.38228278721136899 21.481013431867684  0.92537503562753298 0.45338278488688522 -0.40169995059293706 21.478936098370429  0.92537495430263683 0.47581533725139646 -0.42103396833183515 21.476745104425014  0.92537487863370171 0.49832454640883705 -0.44028383119691794 21.47444039938491  0.92537480888911905 0.5209094695421923 -0.45944854122732348 21.472021944261414  0.92537474526496533 0.58888854650697064 -0.51668426048005367 21.464425245211611  0.92537457310045634 0.63450699594850946 -0.55449684874733673 21.458905668906873  0.92537448327981953 0.68041692619920147 -0.59195698435048527 21.452930762571192  0.92537441932611031 0.72661068000045681 -0.62905695969684849 21.446500490611143  0.92537438101390046 0.77308053628112638 -0.66578925696552815 21.439614996769052  0.92537436721503241 0.81981872153154223 -0.70214655219558297 21.432274598929329  0.92537437622919927 0.86681742055051281 -0.73812171804934046 21.424479783528653  0.92537440587109965 0.91406878620463461 -0.77370782590780784 21.416231200065472  0.92537445378480976 0.96156494866427145 -0.80889814655334824 21.407529655117692  0.92537451744118837 1.0092980236678375 -0.84368615019227899 21.398376106460191  0.92537459434680025 1.0572601202185881 -0.87806550522048576 21.388771656783266  0.92537468203321371 1.2018097718951752 -0.97995919686619315 21.358609334769703  0.92537497029505411 1.299060805489356 -1.0462292219015419 21.33670245084129  0.92537519710691818 1.3971331406373346 -1.1107909814837411 21.313006892765745  0.92537543749142148 1.4959636665385256 -1.1735985603666013 21.287534819841628  0.92537567469631732 1.5954895740898516 -1.2346091699099313 21.260300388813238  0.92537589593498171 1.6956484609498672 -1.2937830203942715 21.231319589345468  0.92537609201909266 1.7963784367703326 -1.3510831935704513 21.20061007942892  0.9253762570216153 1.8976182286199685 -1.4064755154552051 21.168191020968457  0.92537638790251475 1.999307286597398 -1.4599284293155872 21.134082915221697  0.92537648417210872 2.1013858896639634 -1.5114128689029869 21.098307438386747  0.92537654752352305 2.2037952516840056 -1.5609021318397822 21.060887277061184  0.92537658148551094 2.5118423733536757 -1.7033109930416863 20.943763339519553  0.92537661022330187 2.7182996752617541 -1.7901689073421272 20.859193802600473  0.92537651889569117 2.9253842808142876 -1.8687542979466381 20.768331138062486  0.92537637271285167 3.1326475155062239 -1.938906403275972 20.671378930608434  0.92537621369834222 3.3396556535731299 -2.000492621662409 20.568550106737852  0.92537607167544367 3.5459882871505668 -2.0534062323857958 20.460066476591845  0.92537596560796431 3.7512366937463844 -2.0975641147736823 20.346158275237244  0.92537590504769507 3.9550022019252395 -2.1329044653510776 20.227063704352865  0.92537589144177346 4.1568945549715615 -2.1593845135449028 20.103028473743528  0.92537591959183207 4.3565302726413186 -2.1769782359314727 19.974305343719248  0.92537597897699408 4.553531010768733 -2.1856740695355485 19.84115366789505  0.92537605517761568 5.1355036395046598 -2.1850697338858591 19.429209543110094  0.925376283360131 5.511457021558213 -2.1491608580416504 19.137978945920164  0.92537642801528341 5.8723902985529435 -2.0776606833305795 18.832202318498521  0.92537653847939449 6.2153400166387041 -1.9708755712002706 18.514191769531067  0.92537660467194993 6.5374239687460651 -1.8294876063233252 18.186467633852491  0.92537662911831686 6.8358941415086338 -1.6545386503541026 17.851709757659254  0.92537662277168786 7.1081896739284369 -1.4474143967923458 17.512708776211227  0.92537660106196906 7.3519898271815567 -1.2098284244632094 17.172317382700452  0.92537657964338782 7.5652669622527071 -0.94380624514703104 16.833401587384618  0.92537657047382438 7.7463395239500192 -0.65166934343861005 16.498791966806465  0.9253765775893168 7.8939250267161407 -0.33601920568303445 16.171234903921306  0.92537659311272658 8.0087909007863125 0.00502278522890931 15.848859360996473  0.92537659311243037 8.0103819225627042 0.0097710279601006533 15.844376824074811  0.92537659311292408 8.011966102479823 0.01452338355829097 15.839896216844842  0.92537659311123099 8.0135434379495649 0.019279844182844119 15.83541754667141  0.92537659311472431 8.0151139264472011 0.024040401983510762 15.83094082090876  0.92537659310953757 8.0166775653398936 0.028805049127304638 15.826466046931003  0.92537659311543508 8.0182343521411088 0.033573777756883416 15.8219932320828  0.92537659311015885 8.0197842842043467 0.038346580042300626 15.817522383743851  0.92537659311390741 8.021327359025225 0.043123448129011255 15.813053509260243  0.92537659311180009 8.0228635739970038 0.047904374179977172 15.808586616004014  0.92537659311271725 8.0243929265721121 0.052689350348420927 15.804121711331218  0.92537659311242892 8.0259154141761293 0.057478368791705758 15.799658802605602  0.92537659311247955 
+8.1518614215746688 2.0943901572068659 14.187722708731966  1.0000000000000009 8.0071607399772109 2.9377675348005825 13.693683679136079  0.99999999999979217 7.7169833828557985 3.7792876656562426 13.303825913989821  1.0000000000008566 7.2998907514762177 4.6066938509592044 13.013686132087054  0.99999999999790079 6.7600464359266965 5.4125518581303975 12.825583237394785  1.0000000000036997 6.1001504202139749 6.1774774502389018 12.751317472144848  0.99999999999500966 5.3313334099608856 6.8703631150103686 12.805012417037421  1.0000000000052705 4.4775573085605229 7.4562777000475933 12.994421283987815  0.99999999999561862 3.573962159416844 7.9053025565970945 13.315851046127294  1.000000000002826 2.6604941638854682 8.1981576903653508 13.754690048918881  0.99999999999865352 1.7740436773264774 8.3270613127787492 14.290356845459524  1.0000000000004041 0.94421637657095125 8.2928560828529942 14.901320098410286  0.99999999999998779 -0.17247555992473496 8.0066097955121265 15.893347185694921  0.99999999999991396 -0.52340827426053105 7.8720556347964248 16.236638235837475  1.0000000000007365 -0.84964867764116336 7.6993084264857723 16.589475727245976  0.99999999999776246 -1.1480158992536245 7.4896793734521516 16.948683312950266  1.0000000000044871 -1.4155979532367198 7.2449030902548879 17.310975386301084  0.99999999999337319 -1.6498071058939603 6.9671691721749838 17.67297387768145  1.0000000000074829 -1.8484352339350369 6.6591274411971408 18.031243673444862  0.99999999999344158 -2.0097091739243726 6.323866867997765 18.382346657356834  1.0000000000044684 -2.1323460628505559 5.9648681709122124 18.722914374404617  0.99999999999767808 -2.2156086697992476 5.5859300910692991 19.049739316920391  1.0000000000008662 -2.2593607188105915 5.1910693442332407 19.35988483321761  0.99999999999981126 -2.26650294484444 4.5810567014954877 19.796278071137657  1.0000000000000866 -2.2591327777070402 4.3747616961364155 19.936938739350353  0.99999999999963507 -2.2420630779504309 4.1660205075755563 20.072470468421542  1.0000000000009877 -2.2153851651266825 3.9553469896372393 20.202574493453859  0.99999999999808376 -2.1792259144665733 3.7432533631222911 20.326978353351073  1.0000000000027898 -2.1337433693660177 3.5302460035550629 20.445435764879324  0.99999999999687883 -2.0791223541469082 3.3168212289136614 20.557726496598843  1.0000000000027249 -2.0155700864545851 3.1034610873658273 20.663656242977531  0.99999999999814426 -1.9433117900546888 2.8906291450183881 20.763056498291675  1.0000000000009628 -1.8625863072637738 2.6787662736356057 20.85578443073404  0.99999999999964562 -1.7736417116597156 2.4682864383954679 20.94172275635454  1.0000000000000697 -1.6282755250936614 2.1552155092223817 21.06030804149044  0.99999999999997857 -1.5778279418079224 2.0513002562530049 21.098115471508073  1.0000000000000533 -1.5254191521838285 1.9478750641071534 21.134189631789205  0.99999999999987532 -1.4710801702860516 1.8449863825365871 21.168519607982333  1.0000000000002431 -1.4148418087407819 1.7426787844614964 21.201095669567398  0.99999999999960754 -1.3567344446521092 1.6409949767803025 21.231909096661123  1.0000000000005083 -1.2967877855341543 1.5399758111972246 21.260952006819128  0.99999999999947697 -1.2350306352167992 1.4396602950222561 21.288217181851383  1.0000000000004272 -1.1714906597841095 1.3400856020052352 21.313697894611416  0.99999999999972411 -1.1061941534814181 1.2412870831359921 21.337387735822372  1.000000000000139 -1.039165804645815 1.1432982774716414 21.359280440863287  0.99999999999994582 -0.93605979011226514 0.9975772456840899 21.389414354451922  1.000000000000052 -0.90126386923949697 0.94921395158315613 21.399008120028846  0.99999999999967859 -0.86604355444714365 0.9010650276989316 21.408150212270332  1.0000000000008915 -0.83040158642135786 0.85313435878307642 21.416839821267097  0.9999999999983149 -0.79434058384820894 0.8054257306349859 21.425076120774207  1.0000000000024019 -0.75786303628243123 0.75794283403699669 21.432858260367961  0.99999999999731071 -0.72097129744500776 0.71068926937465449 21.440185357479734  1.0000000000023774 -0.68366757848733206 0.66366855177829898 21.447056488959856  0.99999999999836198 -0.64595394178596033 0.61688411700564716 21.453470682586428  1.000000000000844 -0.6078322946907293 0.57033932781987007 21.459426908098294  0.99999999999971179 -0.56930438372206149 0.52403748109163839 21.464924068114094  1.0000000000000329 -0.51090549143092368 0.45495398262792941 21.472479448955792  1.0000000000000233 -0.49133802304110663 0.43198769508704427 21.474882849375799  0.99999999999974387 -0.47166958120186075 0.40908335766547577 21.477171043193799  1.000000000000755 -0.45190035304360565 0.38624137157415372 21.479343878887303  0.99999999999859379 -0.43203051510174184 0.36346213463460808 21.481401199857231  1.000000000001924 -0.41206023323173069 0.34074604153784893 21.483342844135016  0.99999999999794398 -0.39198966232751831 0.31809348411121174 21.485168644074751  1.0000000000017613 -0.37181894632526546 0.29550485158781736 21.486878426061779  0.99999999999878975 -0.35154821789530288 0.27298053091402785 21.488472010190797  1.0000000000006459 -0.33117759844684658 0.25052090702846908 21.489949209969957  0.99999999999975508 -0.31070719789485368 0.22812636319634194 21.491309831996627  1.0000000000000482 -0.27985207294540171 0.1946327403806154 21.493175597471328  0.99999999999998812 -0.26954211060810218 0.18348456493156329 21.493768324702319  1.0000000000000151 -0.25920723987866401 0.17235280270727316 21.494331832259871  0.99999999999996547 -0.24884747232437876 0.16123750136837378 21.494866094618768  1.0000000000000902 -0.23846281879402742 0.15013870847886235 21.495371085779418  0.99999999999983247 -0.22805328939132119 0.13905647157568479 21.495846779293991  1.0000000000002096 -0.21761889350356745 0.12799083809097178 21.496293148200902  0.99999999999980416 -0.2071596397608122 0.11694185547197566 21.496710165084711  1.0000000000001581 -0.19667553606867072 0.10590957107940069 21.497097801993974  0.99999999999987554 -0.18616658957602983 0.094894032295475661 21.49745603049157  1.0000000000000921 -0.17563280669215775 0.083895286466409313 21.497784821604267  0.99999999999994282 -0.15451557945130823 0.061931475440771599 21.498383470061789  1.0000000000001137 -0.14393213509596059 0.050966410242733851 21.498653327407688  0.99999999999937117 -0.1333238656569673 0.040018232719604363 21.498893688364483  1.0000000000016469 -0.12269077605174949 0.029086990225871467 21.499104522916792  0.9999999999970749 -0.11203287041373722 0.018172730142349547 21.499285800457677  1.00000000000386 -0.10135015216573207 0.0072754998621875622 21.499437489912822  0.99999999999606604 -0.090642623918791188 -0.0036046531774598378 21.499559559529676  1.0000000000031313 -0.079910287576644645 -0.014467681487709605 21.49965197711311  0.99999999999807454 -0.069153144233966568 -0.025313537523485419 21.499714709765566  1.0000000000008766 -0.058371194255480319 -0.036142173661918076 21.499747724085914  0.99999999999974343 -0.047564437216404354 -0.046953542192639031 21.499750986015901  1.0000000000000118 -0.026215921647240847 -0.068228123009612673 21.499698706251262  1.0000000000000562 -0.015675848282300731 -0.078692062567233823 21.499644870470462  0.99999999999957911 -0.0051127499780534436 -0.089139274496072396 21.499562924412782  1.0000000000011737 0.0054732742980236893 -0.099569619539858323 21.499452839676991  0.99999999999787692 0.016082124781134244 -0.10998295865570817 21.499314588552323  1.0000000000027878 0.026713700905933724 -0.1203791531128755 21.499148144147156  0.99999999999720457 0.037367901359652844 -0.13075806440550819 21.498953480198217  1.0000000000022051 0.048044624066581054 -0.14111955440871293 21.498730571316038  0.99999999999862743 0.058743766236176498 -0.15146348526953712 21.498479392736826  1.0000000000006599 0.069465224362502909 -0.16178971953270116 21.498199920534475  0.99999999999976641 0.080208894254031993 -0.17209812009131742 21.497892131477304  1.0000000000000537 0.10174044783827974 -0.19267898039518938 21.497219874740075  0.99999999999994149 0.11252833153136432 -0.20295144013893074 21.49685540705633  1.0000000000002514 0.12333821726022798 -0.21320579277218332 21.496462577602379  0.9999999999993997 0.1341699994921437 -0.22344190197462099 21.496041364641311  1.0000000000010218 0.14502357203381067 -0.23365963185974836 21.495591747251613  0.9999999999986664 0.15589882806828959 -0.24385884693767457 21.495113705155049  1.0000000000013385 0.16679566014679592 -0.25403941220726001 21.494607218966557  0.99999999999896383 0.17771396023415331 -0.26420119309100754 21.494072269896034  1.0000000000006235 0.18865361970047001 -0.27434405552407082 21.493508840041848  0.99999999999970202 0.19961452935628499 -0.28446786591618256 21.492916912149965  1.0000000000001186 0.21059657945771271 -0.29457249119758488 21.492296469773301  0.99999999999995959 0.24360582026835287 -0.32482841405822516 21.490349552005021  1.000000000000117 0.26569610148418965 -0.34492175865805175 21.488937485983303  0.99999999999943978 0.28786962115611381 -0.36493677221286935 21.487411173346196  1.0000000000014098 0.31012548851219846 -0.38487240271381928 21.485770500271606  0.99999999999754408 0.33246280474623324 -0.40472760696280785 21.48401536482227  1.000000000003231 0.35488066349255387 -0.42450135099691311 21.482145676898149  0.99999999999664857 0.37737815132906993 -0.4441926103984879 21.480161358134531  1.000000000002788 0.39995434819804165 -0.46380037069361402 21.478062341838964  0.99999999999814349 0.42260832788862457 -0.48332362756407532 21.475848572864663  1.0000000000009674 0.44533915842253347 -0.50276138718125729 21.473520007513716  0.99999999999962552 0.46814590248982979 -0.5221126663762754 21.471076613401141  1.0000000000000944 0.53679104848341463 -0.57990414583692029 21.463401881158031  0.99999999999978462 0.58285436427300574 -0.61808198819879134 21.457825993232973  1.0000000000009763 0.62921002687556005 -0.655902241113127 21.451790535631272  0.99999999999746503 0.67585041906116716 -0.69335730080832469 21.44529551783711  1.0000000000046916 0.72276785691947643 -0.73043974414298329 21.438341124023665  0.99999999999341482 0.76995460142731398 -0.76714233311025337 21.43092770817697  1.0000000000071674 0.81740286903931691 -0.80345801827234542 21.423055788972619  0.99999999999391209 0.8651048417114473 -0.83937994113042569 21.414726044507585  1.0000000000040117 0.91305267590632377 -0.87490143543347809 21.405939306778041  0.99999999999800937 0.96123851099490576 -0.91001602741208032 21.396696556001139  1.0000000000006757 1.0096544767363718 -0.9447174349571239 21.386998914706929  0.99999999999990175 1.1555691466440614 -1.0475638272605856 21.356545095524915  1.0000000000000697 1.2537347185973606 -1.1144510294444077 21.334427989046254  0.99999999999990563 1.3527262467616132 -1.1796123400448826 21.310506456130419  1.0000000000001323 1.4524807098372023 -1.2430020850323888 21.284792760144978  0.99999999999979061 1.5529353397461734 -1.3045776303484997 21.257301135657613  1.000000000000304 1.6540277270274755 -1.3642992635380953 21.228047630260996  0.99999999999967792 1.7556959262133718 -1.422130075599715 21.197049946290967  1.000000000000236 1.8578785612320514 -1.4780358425483247 21.164327282672964  0.99999999999988587 1.9605149307795928 -1.5319849072948726 21.129900176640952  1.0000000000000289 2.0635451137220349 -1.5839480612346 21.093790345562276  1.0000000000000053 2.1669100744728911 -1.6338984260565477 21.05602052868889  0.99999999999998868 2.4778351562152285 -1.7776371541378015 20.937801929474205  1.000000000000046 2.6862259269826541 -1.8653104952655646 20.852441799904913  0.99999999999976075 2.8952565177261267 -1.9446383042722397 20.760728057038811  1.000000000000665 3.1044752044275326 -2.0154577929061706 20.662865016919529  0.99999999999871414 3.313444590694048 -2.0776342523433131 20.55906671730154  1.0000000000018212 3.521740096449852 -2.1310588661890684 20.44955644032915  0.99999999999806077 3.7289484465947611 -2.17564652371812 20.334566234873019  1.0000000000015814 3.9346661597255701 -2.2113336328055153 20.214336439314486  0.99999999999901135 4.138498036768457 -2.2380759331887479 20.089115203841963  1.0000000000004539 4.3400556497103588 -2.2558463094347712 19.95915801319158  0.99999999999987332 4.5389558302421795 -2.2646326041259046 19.824727209051549  0.99999999999999378 5.1265458149110099 -2.2640410844814651 19.408820119921895  1.000000000000095 5.5061359657878484 -2.2277940891569559 19.114778880051777  0.99999999999941613 5.8705598064731133 -2.1556097381951984 18.806050286935633  1.000000000001672 6.2168203367549637 -2.0477989092397948 18.484973361603487  0.99999999999670497 6.5420059498793393 -1.905051827280035 18.154094984188141  1.0000000000048734 6.8433430216333617 -1.7284218280252697 17.816121225937597  0.99999999999441846 7.1182484993076418 -1.519309120628515 17.473868681154183  1.0000000000050213 7.3643824909007147 -1.2794445512543851 17.130215799176273  0.99999999999643796 7.5797008539684114 -1.0108733657318227 16.788054216375709  1.0000000000019702 7.7625077848787312 -0.71593897303842091 16.450240088082317  0.99999999999918077 7.9115084076981104 -0.39726670815315135 16.11954542060905  1.0000000000002349 8.0274745296037082 -0.052958031504910075 15.794081989342084  0.99999999999995892 8.0290807910540636 -0.048164307519442673 15.789556516241049  1.0000000000003633 8.0306801451048493 -0.043366431271414374 15.785032991315584  0.99999999999899669 8.0322725891612592 -0.038564410677035088 15.780511421999474  1.0000000000017668 8.0338581206382127 -0.033758253664756932 15.775991815725158  0.99999999999773581 8.035436736929686 -0.028947968141638469 15.771474179927564  1.0000000000022295 8.0370084354640809 -0.024133562044775569 15.766958522038109  0.99999999999826428 8.0385732136255221 -0.019315043276749044 15.762444849492073  1.0000000000010814 8.040131068843456 -0.014492419772778042 15.757933169721355  0.99999999999946565 8.0416819985100805 -0.0096656994427744003 15.753423490160237  1.0000000000001983 8.0432260000421198 -0.004834890212541687 15.748915818241649  0.99999999999995515 8.0447630708436169 -2.2204460492503131e-015 15.744410161399125  1 
+
+0 3
+35.089992530607631 3
+
+2.6898219505952046 13
+14.473677021732097 11
+20.365604557300543 11
+23.311568325084767 11
+24.784550208976881 11
+25.521041150922937 11
+25.889286621895963 11
+26.073409357382477 11
+26.257532092868992 11
+26.436306776466001 11
+26.61508146006301 11
+26.972630827257024 11
+27.687729561645057 11
+29.117927030421122 11
+31.978321967973255 11
+37.699111843077517 11
+37.779814481202834 13
+
+4 0 0 0 0 0 1 1 0 -0 -0 1 0 8.5
+Triangulations 0
+
+TShapes 111
+Ve
+1.00000036331198e-007
+-3.63311981128433e-014 10 0.5
+0 0
+
+0101101
+*
+Ve
+1.00001000002876e-007
+10 0 0.5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  1 0 1.5707963267949 6.28318530717959
+2  1 1 7 1.5707963267949 6.28318530717959
+2  2 2 0 1.5707963267949 6.28318530717959
+4 G1 1 7 2 0
+0
+
+0101000
++111 8 -110 8 *
+Ve
+1.00000036331198e-007
+-3.63311981128433e-014 10 4.5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  2 0 0.5 4.5
+2  3 1 10 0.5 4.5
+2  4 3 0 0.5 4.5
+0
+
+0101000
++111 11 -108 11 *
+Ve
+1.00001000280431e-007
+10 0 4.5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  3 0 1.5707963267949 6.28318530717959
+2  5 1 7 1.5707963267949 6.28318530717959
+2  6 4 0 1.5707963267949 6.28318530717959
+4 G1 1 7 4 0
+0
+
+0101000
++108 8 -106 8 *
+Ed
+ 1e-007 1 1 0
+1  4 0 0.5 4.5
+2  7 1 10 0.5 4.5
+2  8 5 0 0.5 4.5
+0
+
+0101000
++110 11 -106 11 *
+Wi
+
+0101000
++109 5 -107 9 -105 5 +104 9 *
+Fa
+0  1e-007 1 6
+
+0101000
++103 0 *
+Ve
+1.00000113618029e-007
+-1.13618028711744e-013 9.5 0
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  5 0 3.14159265358979 4.71238898038469
+2  9 2 5 3.14159265358979 4.71238898038469
+2  10 3 9 3.14159265358979 4.71238898038469
+0
+
+0101000
++101 12 -111 12 *
+Ve
+1e-007
+9.5 0 0
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  6 0 1.57079632679491 6.28318530717959
+2  11 2 0 1.57079632679491 6.28318530717959
+2  12 6 7 1.57079632679491 6.28318530717959
+4 G1 2 0 6 7
+0
+
+0101000
++101 8 -99 8 *
+Ed
+ 1e-007 1 1 0
+1  7 0 0 1.5707963267949
+2  13 2 0 0 1.5707963267949
+2  14 5 13 0 1.5707963267949
+0
+
+0101000
++110 8 -99 8 *
+Wi
+
+0101000
++109 5 +100 0 -98 5 +97 5 *
+Fa
+0  1e-007 2 5
+
+0101000
++96 0 *
+Ve
+1.00000113845795e-007
+-1.13845794505395e-013 7.5 0
+0 0
+
+0101101
+*
+Ve
+2.00001e-007
+0 7.5 3.6325030024024
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  8 0 0 3.6325030024024
+2  15 3 9 0 3.6325030024024
+2  16 7 16 0 3.6325030024024
+0
+
+0101000
++94 12 -93 12 *
+Ve
+2.00001e-007
+0 8.94427190999916 5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  9 0 3.81672418652682 3.98266132415772
+2  17 3 14 3.81672418652682 3.98266132415772
+2  18 8 17 3.81672418652682 3.98266132415772
+0
+
+0101000
++93 18 -91 18 *
+Ve
+2.00001e-007
+5.81707229594993e-016 9.5 5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  10 0 8.94427190999916 9.5
+2  19 3 9 8.94427190999916 9.5
+2  20 9 6 8.94427190999916 9.5
+0
+
+0101000
++91 12 -89 12 *
+Ed
+ 1e-007 1 1 0
+1  11 0 4.71238898038469 6.28318530717959
+2  21 3 9 4.71238898038469 6.28318530717959
+2  22 4 5 4.71238898038469 6.28318530717959
+0
+
+0101000
++108 12 -89 12 *
+Ed
+ 1e-007 1 1 0
+1  12 0 7.5 9.5
+2  23 3 0 7.5 9.5
+2  24 6 10 7.5 9.5
+0
+
+0101000
++94 11 -101 11 *
+Wi
+
+0101000
+-92 2 -90 0 -88 2 +87 2 +107 14 +100 2 +86 14 *
+Fa
+0  1e-007 3 14
+
+0101000
++85 0 *
+Ve
+1e-007
+9.5 0 5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  13 0 1.5707963267949 6.28318530717959
+2  25 4 0 1.5707963267949 6.28318530717959
+2  26 9 7 1.5707963267949 6.28318530717959
+4 G1 4 0 9 7
+0
+
+0101000
++89 8 -83 8 *
+Ed
+ 1e-007 1 1 0
+1  14 0 0 1.5707963267949
+2  27 4 0 0 1.5707963267949
+2  28 5 13 0 1.5707963267949
+0
+
+0101000
++106 8 -83 8 *
+Wi
+
+0101000
++105 5 -87 0 -82 5 +81 5 *
+Fa
+0  1e-007 4 5
+
+0101000
++80 0 *
+Ve
+1.0000100183697e-007
+7.5 -1.83697019872103e-015 0
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  15 0 7.5 9.5
+2  29 5 0 7.5 9.5
+2  30 6 10 7.5 9.5
+0
+
+0101000
++78 11 -99 11 *
+Ve
+1.00000021344407e-007
+8.94427190999912 -1.0953573965284e-015 4.99999999999998
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  16 0 -9.5 -8.94427190999912
+2  31 5 9 -9.5 -8.94427190999912
+2  32 9 6 -9.5 -8.94427190999912
+0
+
+0101000
++83 12 -76 12 *
+Ve
+1.00000095035091e-007
+7.5000000000001 -1.83697019872105e-015 3.63250300240256
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  17 0 5.38752051332174 5.55345765095262
+2  33 5 20 5.38752051332174 5.55345765095262
+2  34 8 0 5.38752051332174 5.55345765095262
+0
+
+0101000
++74 21 -76 21 *
+Ed
+ 1e-007 1 1 0
+1  18 0 0 3.63250300240256
+2  35 5 23 0 3.63250300240256
+2  36 7 0 0 3.63250300240256
+0
+
+0101000
++78 24 -74 24 *
+Wi
+
+0101000
+-77 14 +97 19 -104 14 -81 19 -75 2 +73 17 +72 22 *
+Fa
+0  1e-007 5 14
+
+0101000
++71 0 *
+Ed
+ 1e-007 1 1 0
+1  19 0 1.57079632679491 6.28318530717959
+2  37 6 25 1.57079632679491 6.28318530717959
+2  38 7 0 1.57079632679491 6.28318530717959
+0
+
+0101000
++94 24 -78 24 *
+Wi
+
+0101000
++98 5 +86 9 -69 16 -77 9 *
+Fa
+0  1e-007 6 6
+
+0101000
++68 0 *
+Ed
+ 1e-007 1 1 0
+1  20 0 3.14159265358979 7.85398163397448
+2  39 7 22 3.14159265358979 7.85398163397448
+2  40 8 17 3.14159265358979 7.85398163397448
+0
+
+0101000
++93 18 -74 18 *
+Wi
+
+0101000
++69 22 -92 2 -66 0 +72 22 *
+Fa
+0  1e-007 7 22
+
+0101000
++65 0 *
+Ed
+ 1e-007 1 1 0
+1  21 0 1.5707963267949 6.28318530717959
+2  41 8 17 1.5707963267949 6.28318530717959
+2  42 9 26 1.5707963267949 6.28318530717959
+0
+
+0101000
++91 18 -76 18 *
+Wi
+
+0101000
++73 17 +66 0 -90 0 -63 0 *
+Fa
+0  1e-007 8 17
+
+0101000
++62 0 *
+Wi
+
+0101000
++88 2 -63 0 +75 2 +82 19 *
+Fa
+0  1e-007 9 26
+
+0101000
++60 0 *
+Sh
+
+0101100
++102 2 -95 2 +84 0 +79 2 +70 0 -67 2 -64 0 -61 0 +59 0 *
+So
+
+0100000
++58 0 *
+Co
+
+0100000
++57 0 *
+Ve
+0.0001
+4.86783340768397 0 23.913601509815
+0 0
+
+0101101
+*
+Ve
+1e-007
+7.31726462490544e-016 -1.79221294028092e-031 24.95
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  22 0 7.43443102715402 7.85398163397448
+3  43 44CN 10 0 7.43443102715402 7.85398163397448
+0
+
+0101000
++55 34 -54 34 *
+Ve
+0.0001
+8.66683085328061 -2.12276133264432e-015 21.2273047202971
+0 0
+
+0101101
+*
+Ed
+ 4.25441950557495e-005 1 1 0
+1  23 0 27.003426592721 31.5504127769157
+2  45 10 33 27.003426592721 31.5504127769157
+2  46 11 0 27.003426592721 31.5504127769157
+4 G1 10 33 11 0
+0
+
+0101000
++55 35 -52 35 *
+Ed
+ 1e-007 1 1 1
+2  47 10 0 0 6.28318530717959
+0
+
+0101100
++54 34 -54 34 *
+Ve
+1e-007
+7.31726462490544e-016 -1.79221294028092e-031 1.05
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  24 0 4.71238898038469 7.04257284660901
+3  48 49CN 10 0 4.71238898038469 7.04257284660901
+0
+
+0101000
+-52 34 +49 34 *
+Ed
+ 1e-007 1 1 1
+2  50 10 0 0 6.28318530717959
+0
+
+0101100
++49 34 -49 34 *
+Ve
+9.06348433802539e-005
+10.4576073147515 4.15207539985788 17.0250738035906
+0 0
+
+0101101
+*
+Ed
+ 6.12769011917843e-005 1 1 0
+1  25 0 6.99157391905695e-015 27.003426592721
+2  51 10 33 6.99157391905695e-015 27.003426592721
+2  52 12 0 6.99157391905695e-015 27.003426592721
+4 G1 10 33 12 0
+0
+
+0101000
++46 35 -55 35 *
+Ed
+ 3.99209209172985e-005 1 1 0
+1  26 0 31.5504127769157 37.6991118430775
+2  53 10 33 31.5504127769157 37.6991118430775
+2  54 13 0 31.5504127769157 37.6991118430775
+4 G1 10 33 13 0
+0
+
+0101000
++52 35 -46 35 *
+Wi
+
+0101100
++53 33 -51 0 -50 33 +48 33 -53 33 +47 33 -45 0 -48 33 -44 0 *
+Fa
+0  1e-007 10 31
+
+0101000
++43 32 *
+Ve
+0.00010660168527067
+4.79295017262215 0.160985599242204 23.6124555254473
+0 0
+
+0101101
+*
+Ed
+ 4.25441950557495e-005 1 1 0
+1  27 0 0 27.003426592721
+2  55 11 0 0 27.003426592721
+2  56 12 0 0 27.003426592721
+4 G1 11 0 12 0
+0
+
+0101000
++55 35 -41 35 *
+Ve
+0.00010660168527067
+8.40774728243224 0.16092601586927 21.0564501607286
+0 0
+
+0101101
+*
+Ed
+ 4.25441950557495e-005 1 1 0
+1  28 0 27.003426592721 31.5504127769157
+2  57 11 0 27.003426592721 31.5504127769157
+2  58 14 37 27.003426592721 31.5504127769157
+4 G1 11 0 14 37
+0
+
+0101000
++41 35 -39 35 *
+Ed
+ 3.99209209172985e-005 1 1 0
+1  29 0 0 4.54698618419472
+2  59 11 0 0 4.54698618419472
+2  60 13 0 0 4.54698618419472
+4 G1 11 0 13 0
+0
+
+0101000
++52 35 -39 35 *
+Wi
+
+0101100
++40 0 -51 0 +38 0 -37 0 *
+Fa
+0  4.25441950557495e-005 11 0
+
+0101000
++36 0 *
+Ve
+7.92651752146647e-005
+10.111873920068 4.11187392006796 17.0577085516476
+0 0
+
+0101101
+*
+Ed
+ 3.99209209172985e-005 1 1 0
+1  30 0 0 27.003426592721
+2  61 12 0 0 27.003426592721
+2  62 13 0 0 27.003426592721
+4 G1 12 0 13 0
+0
+
+0101000
++46 35 -34 35 *
+Ed
+ 6.8656902571142e-006 1 1 0
+1  31 0 6.99157391905695e-015 27.003426592721
+2  63 12 0 6.99157391905695e-015 27.003426592721
+2  64 14 37 6.99157391905695e-015 27.003426592721
+4 G1 12 0 14 37
+0
+
+0101000
++34 35 -41 35 *
+Wi
+
+0101100
++33 0 -45 0 +32 0 -40 0 *
+Fa
+0  6.39631008936803e-006 12 0
+
+0101000
++31 0 *
+Ed
+ 3.99209209172985e-005 1 1 0
+1  32 0 31.5504127769157 37.6991118430775
+2  65 13 0 31.5504127769157 37.6991118430775
+2  66 14 37 31.5504127769157 37.6991118430775
+4 G1 13 0 14 37
+0
+
+0101000
++39 35 -34 35 *
+Wi
+
+0101100
++37 0 -44 0 +29 0 -33 0 *
+Fa
+0  3.99209209172985e-005 13 0
+
+0101000
++28 0 *
+Ve
+6.30856966041478e-005
+8.17295924749309 2.17295924749309 14.3156691254081
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  33 0 6.1032778078669 9.98110715301664
+3  67 68CN 14 0 6.1032778078669 9.98110715301664
+0
+
+0101000
++26 38 -34 38 *
+Ve
+6.30856966041478e-005
+8.06687701020208 0.0984399648176608 15.857587247242
+0 0
+
+0101101
+*
+Ed
+ 2.75179110362277e-005 1 1 0
+1  34 0 37.7798144812028 40.3889337936727
+2  69 14 37 37.7798144812028 40.3889337936727
+2  70 15 0 37.7798144812028 40.3889337936727
+4 G1 14 37 15 0
+0
+
+0101000
++24 35 -26 35 *
+Ed
+ 6.30856966041478e-005 1 1 0
+1  35 0 2.6898219505952 37.7798144812028
+2  71 14 37 2.6898219505952 37.7798144812028
+2  72 16 0 2.6898219505952 37.7798144812028
+4 G1 14 37 16 0
+0
+
+0101000
++26 35 -24 35 *
+Wi
+
+0101100
++25 37 +23 0 -29 0 +22 0 -38 0 -25 37 -32 0 *
+Fa
+0  1e-007 14 36
+
+0101000
++21 32 *
+Ve
+0.000117250570758433
+8.04476307084362 -1.97039866892149e-015 15.7444101613991
+0 0
+
+0101101
+*
+Ed
+ 2.71630571503642e-005 1 1 0
+1  36 0 0 35.0899925306076
+2  73 15 0 0 35.0899925306076
+2  74 16 0 0 35.0899925306076
+4 G1 15 0 16 0
+0
+
+0101000
++24 35 -19 35 *
+Ve
+0.000117250570758433
+8.15186142157466 2.09439015720687 14.187722708732
+0 0
+
+0101101
+*
+Ed
+ 2.71630571503642e-005 1 1 0
+1  37 0 37.7798144812028 40.3889337936727
+2  75 15 0 37.7798144812028 40.3889337936727
+2  76 17 40 37.7798144812028 40.3889337936727
+4 G1 15 0 17 40
+0
+
+0101000
++19 35 -17 35 *
+Ed
+ 2.71630571503642e-005 1 1 0
+1  38 0 0 35.0899925306076
+2  77 15 0 0 35.0899925306076
+2  78 16 0 0 35.0899925306076
+4 G1 15 0 16 0
+0
+
+0101000
++26 35 -17 35 *
+Wi
+
+0101100
++18 0 -23 0 +16 0 -15 0 *
+Fa
+0  2.71630571503642e-005 15 0
+
+0101000
++14 0 *
+Ed
+ 7.24378326576262e-005 1 1 0
+1  39 0 2.6898219505952 37.7798144812028
+2  79 16 0 2.6898219505952 37.7798144812028
+2  80 17 40 2.6898219505952 37.7798144812028
+4 G1 16 0 17 40
+0
+
+0101000
++17 35 -19 35 *
+Wi
+
+0101100
++15 0 -22 0 +12 0 -18 0 *
+Fa
+0  4.931627645739e-005 16 0
+
+0101000
++11 0 *
+Ve
+1e-007
+5.20474889637625e-016 -1.27479581526258e-031 4.5
+0 0
+
+0101101
+*
+Ed
+ 1e-007 1 1 0
+1  40 0 4.71238898038469 6.61194752245149
+3  81 82CN 17 0 4.71238898038469 6.61194752245149
+0
+
+0101000
+-19 42 +9 42 *
+Ed
+ 1e-007 1 1 1
+2  83 17 0 0 6.28318530717959
+0
+
+0101100
++9 42 -9 42 *
+Wi
+
+0101100
++8 40 -12 0 +7 40 -16 0 -8 40 *
+Fa
+0  1e-007 17 41
+
+0101000
++6 32 *
+Sh
+
+0101100
++42 28 -35 0 -30 0 -27 0 -20 28 -13 0 -10 0 -5 28 *
+So
+
+0100000
++4 0 *
+Co
+
+0100000
++3 0 *
+Co
+
+1100000
++56 1 +2 27 *
+
++1 0 
+0
+
diff --git a/samples/tcl/pathtrace_ball.tcl b/samples/tcl/pathtrace_ball.tcl
new file mode 100644 (file)
index 0000000..186bbcc
--- /dev/null
@@ -0,0 +1,78 @@
+# Script demonstrating Global illumination materials
+# using path tracing rendering engine in 3D view
+
+#Category: Visualization
+#Title: Path tracing - Ball
+
+set aBallPath [locate_data_file occ/Ball.brep]
+
+pload MODELING VISUALIZATION
+
+# Setup 3D viewer
+vclear
+vinit name=View1 w=512 h=512
+vglinfo
+vvbo 0
+vsetdispmode 1
+
+# Setup view parameters
+vcamera -persp
+vviewparams -scale 18 -eye 44.49 -0.15 33.93 -at -14.20 -0.15 1.87 -up -0.48 0.00 0.88
+
+# Load the model from disk
+puts "Importing shape..."
+restore $aBallPath ball
+
+# Tessellate the model
+incmesh ball 0.01
+
+# Display the model and assign material
+vdisplay -noupdate ball
+vsetmaterial -noupdate ball glass
+
+# Create a sphere inside the model
+psphere s 8
+incmesh s 0.01
+vdisplay -noupdate s
+vsetlocation -noupdate s 0 0 13
+vsetmaterial -noupdate s plaster
+
+# Create chessboard-style floor
+box tile 10 10 0.1
+eval compound [lrepeat 144 tile] tiles
+explode tiles
+for {set i 0} {$i < 12} {incr i} {
+  for {set j 1} {$j <= 12} {incr j} {
+    ttranslate tiles_[expr 12 * $i + $j] [expr $i * 10 - 90] [expr $j * 10 - 70] -0.15
+    vdisplay -noupdate tiles_[expr 12 * $i + $j]
+
+    vsetmaterial -noupdate tiles_[expr 12 * $i + $j] plaster
+
+    if {($i + $j) % 2 == 0} {
+      vbsdf tiles_[expr 12 * $i + $j] -kd 0.85
+    } else {
+      vbsdf tiles_[expr 12 * $i + $j] -kd 0.45
+    }
+  }
+}
+
+# Configure light sources
+vlight del 1
+vlight change 0 head 0
+vlight change 0 direction -0.25 -1 -1
+vlight change 0 sm 0.3
+vlight change 0 int 10
+
+# Load environment map
+vtextureenv on 1
+
+puts "Trying path tracing mode..."
+vrenderparams -ray -gi -rayDepth 10
+
+# Start progressive refinement mode
+#vprogressive
+
+puts "Make several path tracing iterations to refine the picture, please wait..."
+vfps 100
+puts "Done. To improve the image further, or after view manipulations, give command:"
+puts "vfps \[nb_iteratons\]" 
similarity index 56%
rename from samples/tcl/pathtrace.tcl
rename to samples/tcl/pathtrace_cube.tcl
index d1bf449..264ed77 100644 (file)
@@ -2,11 +2,12 @@
 # path tracing rendering engine in 3d view
 
 #Category: Visualization
-#Title: Path tracing
+#Title: Path tracing - Cube
 
 pload MODELING VISUALIZATION
 
 # setup 3D viewer content
+vclear
 vinit name=View1 w=512 h=512
 vglinfo
 
@@ -24,18 +25,18 @@ vcamera -persp
 # setup outer box
 box b 1 1 1 
 explode b FACE 
-vdisplay b_1 b_2 b_3 b_5 b_6
-vsetlocation b_1  1  0  0
-vsetlocation b_2 -1  0  0
-vsetlocation b_3  0  1  0
-vsetlocation b_5  0  0  1
-vsetlocation b_6  0  0 -1
+vdisplay -noupdate b_1 b_2 b_3 b_5 b_6
+vlocation -noupdate b_1 -setLocation  1  0  0
+vlocation -noupdate b_2 -setLocation -1  0  0
+vlocation -noupdate b_3 -setLocation  0  1  0
+vlocation -noupdate b_5 -setLocation  0  0  1
+vlocation -noupdate b_6 -setLocation  0  0 -1
 
-vsetmaterial b_1 plastic
-vsetmaterial b_2 plastic
-vsetmaterial b_3 plastic
-vsetmaterial b_5 plastic
-vsetmaterial b_6 plastic
+vsetmaterial -noupdate b_1 plastic
+vsetmaterial -noupdate b_2 plastic
+vsetmaterial -noupdate b_3 plastic
+vsetmaterial -noupdate b_5 plastic
+vsetmaterial -noupdate b_6 plastic
 vbsdf b_1 -kd 1 0.3 0.3 -ks 0
 vbsdf b_2 -kd 0.3 0.5 1 -ks 0
 vbsdf b_3 -kd 1 -ks 0
@@ -47,36 +48,36 @@ vfit
 
 # setup first inner sphere
 psphere s 0.2
-vdisplay s
-vsetlocation s 0.21 0.3 0.2
-vsetmaterial s glass
+vdisplay     -noupdate s
+vlocation    -noupdate s -setLocation 0.21 0.3 0.2
+vsetmaterial -noupdate s glass
 vbsdf s -absorpcolor 0.8 0.8 1.0
 vbsdf s -absorpcoeff 6
 
 # setup first inner box
 box c 0.3 0.3 0.2
-vdisplay c
-vsetlocation c 0.55 0.3 0.0
-vlocrotate c 0 0 0 0 0 1 -30
-vsetmaterial c plastic
+vdisplay     -noupdate c
+vlocation    -noupdate c -setLocation 0.55 0.3 0.0
+vlocation    -noupdate c -rotate 0 0 0 0 0 1 -30
+vsetmaterial -noupdate c plastic
 vbsdf c -kd 1.0 0.8 0.2 -ks 0.3 -n
 
 # setup second inner box
 box g 0.15 0.15 0.3
-vdisplay g
-vsetlocation g 0.7 0.25 0.2
-vlocrotate g 0 0 0 0 0 1 10
-vsetmaterial g glass
+vdisplay     -noupdate g
+vlocation    -noupdate g -setLocation 0.7 0.25 0.2
+vlocation    -noupdate g -rotate 0 0 0 0 0 1 10
+vsetmaterial -noupdate g glass
 vbsdf g -absorpcolor 0.8 1.0 0.8
 vbsdf g -absorpcoeff 6
 
 # setup second inner sphere
 psphere r 0.1
-vdisplay r
-vsetmaterial r plastic
+vdisplay -noupdate r
+vsetmaterial -noupdate r plastic
 vbsdf r -kd 0.5 0.9 0.3 -ks 0.0 -kr 0.3 -n
 vbsdf r -fresnel Constant 1.0
-vsetlocation r 0.5 0.65 0.1
+vlocation r -setLocation 0.5 0.65 0.1
 
 puts "Trying path tracing mode..."
 vrenderparams -ray -gi -rayDepth 8
index 8256a18..74e812f 100644 (file)
@@ -82,6 +82,12 @@ public:
         && myFresnelData == theOther.myFresnelData;
   }
 
+  //! Returns type of Fresnel.
+  Graphic3d_FresnelModel FresnelType() const
+  {
+    return myFresnelType;
+  }
+
 protected:
 
   //! Creates new Fresnel reflectance factor.
@@ -164,9 +170,9 @@ public:
 public:
 
   //! Creates uninitialized BSDF.
-  Graphic3d_BSDF()
+  Graphic3d_BSDF() : Roughness (1.f), AbsorptionCoeff (0.f)
   {
-    Roughness = AbsorptionCoeff = 0.f;
+    Fresnel = Graphic3d_Fresnel::CreateConstant (1.f);
   }
 
   //! Normalizes BSDF components.
index f908c93..8ea28c3 100644 (file)
@@ -66,7 +66,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
   mySpecularColor.SetValues (1.0, 1.0, 1.0, Quantity_TOC_RGB);
   myMaterialName     = theName;
 
-  myBSDF = Graphic3d_BSDF::CreateDiffuse (Graphic3d_Vec3 (0.2f, 0.2f, 0.2f));
+  myBSDF = Graphic3d_BSDF::CreateDiffuse (Graphic3d_Vec3 (0.0f));
 
   Standard_Integer index = Standard_Integer (theName);
   if (index < NumberOfMaterials())
@@ -87,7 +87,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
                                   static_cast<Standard_ShortReal> (myDiffuseColor.Blue()));
       myBSDF.Ks = Graphic3d_Vec3 (0.00784314f, 0.00784314f, 0.00784314f);
       myBSDF.Normalize();
-      myBSDF.Roughness = 32;
+      myBSDF.Roughness = 0.25f;
       break;
     case Graphic3d_NOM_SHINY_PLASTIC:
       myShininess    = Standard_ShortReal (1.0);
@@ -98,9 +98,9 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       myBSDF.Kd = Graphic3d_Vec3 (static_cast<Standard_ShortReal> (myDiffuseColor.Red()),
                                   static_cast<Standard_ShortReal> (myDiffuseColor.Green()),
                                   static_cast<Standard_ShortReal> (myDiffuseColor.Blue()));
-      myBSDF.Ks = Graphic3d_Vec3 (0.0156863f, 0.0156863f, 0.0156863f);
+      myBSDF.Ks = Graphic3d_Vec3 (0.145f, 0.145f, 0.145f);
       myBSDF.Normalize();
-      myBSDF.Roughness = 64.f;
+      myBSDF.Roughness = 0.17f;
       break;
     case Graphic3d_NOM_SATIN :
       myShininess    = Standard_ShortReal (0.09375);
@@ -108,12 +108,10 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       myDiffuseCoef  = Standard_ShortReal (0.4);
       mySpecularCoef = Standard_ShortReal (0.44);
 
-      myBSDF.Kd = Graphic3d_Vec3 (static_cast<Standard_ShortReal> (myDiffuseColor.Red()),
-                                  static_cast<Standard_ShortReal> (myDiffuseColor.Green()),
-                                  static_cast<Standard_ShortReal> (myDiffuseColor.Blue()));
-      myBSDF.Ks = Graphic3d_Vec3 (0.0313726f, 0.0313726f, 0.0313726f);
-      myBSDF.Roughness = 16.f;
-      myBSDF.Normalize();
+      myBSDF.Kd = Graphic3d_Vec3 (0.2f);
+      myBSDF.Ks = Graphic3d_Vec3 (0.6f);
+      myBSDF.Roughness = 0.6f;
+
       break;
     case Graphic3d_NOM_NEON_GNC:
       myShininess    = Standard_ShortReal (0.05);
@@ -124,11 +122,12 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       myEmissiveActivity = Standard_True;
       myAmbientActivity  = Standard_False;
 
-      myBSDF.Kr = Graphic3d_Vec3 (0.207843f, 0.207843f, 0.207843f);
+      myBSDF.Kd = Graphic3d_Vec3 (0.0f);
+      myBSDF.Kr = Graphic3d_Vec3 (0.5f);
       myBSDF.Le = Graphic3d_Vec3 (static_cast<Standard_ShortReal> (myDiffuseColor.Red()),
                                   static_cast<Standard_ShortReal> (myDiffuseColor.Green()),
                                   static_cast<Standard_ShortReal> (myDiffuseColor.Blue()));
-      myBSDF.Fresnel = Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.3f, 0.3f, 0.3f));
+      myBSDF.Fresnel = Graphic3d_Fresnel::CreateDielectric (1.5f);
       break;
     case Graphic3d_NOM_METALIZED:
       myShininess    = Standard_ShortReal (0.13);
@@ -143,7 +142,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
                                static_cast<Standard_ShortReal> (myDiffuseColor.Blue()));
 
         myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-          Graphic3d_Fresnel::CreateSchlick (aColor), 1024.f);
+          Graphic3d_Fresnel::CreateSchlick (aColor), 0.045f);
       }
       break;
     // Ascending Compatibility physical materials. The same definition is taken as in the next constructor.
@@ -156,7 +155,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.58f, 0.42f, 0.20f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.58f, 0.42f, 0.20f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.329f, 0.224f, 0.027f, Quantity_TOC_RGB);
@@ -174,7 +173,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.65f, 0.35f, 0.15f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.65f, 0.35f, 0.15f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.213f, 0.128f, 0.054f, Quantity_TOC_RGB);
@@ -192,7 +191,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.955008f, 0.637427f, 0.538163f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.955008f, 0.637427f, 0.538163f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.191f, 0.074f, 0.023f, Quantity_TOC_RGB);
@@ -210,7 +209,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (1.000000f, 0.765557f, 0.336057f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (1.000000f, 0.765557f, 0.336057f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.300f, 0.230f, 0.095f, Quantity_TOC_RGB);
@@ -228,7 +227,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateConductor (1.8800f, 3.4900f), 1024.f);
+        Graphic3d_Fresnel::CreateConductor (1.8800f, 3.4900f), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.106f, 0.059f, 0.114f, Quantity_TOC_RGB);
@@ -262,7 +261,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.971519f, 0.959915f, 0.915324f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.971519f, 0.959915f, 0.915324f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.275f, 0.275f, 0.250f, Quantity_TOC_RGB);
@@ -280,7 +279,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateConductor (Graphic3d_Vec3 (2.90f, 2.80f, 2.53f), Graphic3d_Vec3 (3.08f, 2.90f, 2.74f)), 1024.f);
+        Graphic3d_Fresnel::CreateConductor (Graphic3d_Vec3 (2.90f, 2.80f, 2.53f), Graphic3d_Vec3 (3.08f, 2.90f, 2.74f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.150f, 0.150f, 0.180f, Quantity_TOC_RGB);
@@ -318,7 +317,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.549585f, 0.556114f, 0.554256f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.549585f, 0.556114f, 0.554256f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.200f, 0.200f, 0.225f, Quantity_TOC_RGB);
@@ -336,7 +335,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       mySpecularCoef = 1.00f;
 
       myBSDF = Graphic3d_BSDF::CreateMetallic (Graphic3d_Vec3 (0.985f, 0.985f, 0.985f),
-        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.913183f, 0.921494f, 0.924524f)), 1024.f);
+        Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.913183f, 0.921494f, 0.924524f)), 0.045f);
 
       // Color resulting from ambient
       myAmbientColor .SetValues (0.300f, 0.300f, 0.300f, Quantity_TOC_RGB);
@@ -366,9 +365,10 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       // Color resulting from specular
       myEmissiveColor.SetValues (0.0, 1.0, 0.46, Quantity_TOC_RGB);
 
-      myBSDF.Kr = Graphic3d_Vec3 (0.207843f, 0.207843f, 0.207843f);
+      myBSDF.Kd = Graphic3d_Vec3 (0.0f);
+      myBSDF.Kr = Graphic3d_Vec3 (0.5f);
       myBSDF.Le = Graphic3d_Vec3 (0.0f, 1.0f, 0.46f);
-      myBSDF.Fresnel = Graphic3d_Fresnel::CreateSchlick (Graphic3d_Vec3 (0.3f, 0.3f, 0.3f));
+      myBSDF.Fresnel = Graphic3d_Fresnel::CreateDielectric (1.5f);
       break;
     case Graphic3d_NOM_OBSIDIAN:
       myMaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -385,9 +385,9 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       // Color resulting from specular
       mySpecularColor.SetValues (0.333f, 0.329f, 0.346f, Quantity_TOC_RGB);
 
-      myBSDF.Kd = Graphic3d_Vec3 (0.0156863f, 0.f, 0.0155017f);
+      myBSDF.Kd = Graphic3d_Vec3 (0.023f, 0.f, 0.023f);
       myBSDF.Ks = Graphic3d_Vec3 (0.0156863f, 0.0156863f, 0.0156863f);
-      myBSDF.Roughness = 1024.f;
+      myBSDF.Roughness = 0.1f;
       break;
     case Graphic3d_NOM_JADE:
       myMaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -407,7 +407,7 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       myBSDF.Fresnel = Graphic3d_Fresnel::CreateDielectric (1.5f);
       myBSDF.Kd = Graphic3d_Vec3 (0.208658f, 0.415686f, 0.218401f);
       myBSDF.Ks = Graphic3d_Vec3 (0.611765f, 0.611765f, 0.611765f);
-      myBSDF.Roughness = 512.f;
+      myBSDF.Roughness = 0.06f;
       break;
     case Graphic3d_NOM_CHARCOAL:
       myMaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -424,9 +424,9 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       // Color resulting from specular
       mySpecularColor.SetValues (0.000f, 0.000f, 0.000f, Quantity_TOC_RGB);
 
-      myBSDF.Kd = Graphic3d_Vec3 (0.0196078f, 0.0196078f, 0.0196078f);
-      myBSDF.Ks = Graphic3d_Vec3 (0.0196078f, 0.0196078f, 0.0196078f);
-      myBSDF.Roughness = 8;
+      myBSDF.Kd = Graphic3d_Vec3 (0.02f, 0.02f, 0.02f);
+      myBSDF.Ks = Graphic3d_Vec3 (0.1f, 0.1f, 0.1f);
+      myBSDF.Roughness = 0.3f;
       break;
     case Graphic3d_NOM_WATER:
       myMaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -491,6 +491,29 @@ void Graphic3d_MaterialAspect::Init (const Graphic3d_NameOfMaterial theName)
       // Color resulting from specular
       mySpecularColor.SetValues (0.970f, 0.970f, 0.970f, Quantity_TOC_RGB);
       break;
+
+    case Graphic3d_NOM_TRANSPARENT:
+      myMaterialType = Graphic3d_MATERIAL_PHYSIC;
+
+      myShininess    = 0.90f;
+      myAmbientCoef  = 1.00f;
+      myDiffuseCoef  = 1.00f;
+      mySpecularCoef = 1.00f;
+      myRefractionIndex  = 1.0f;
+
+      myBSDF.Kd = Graphic3d_Vec3 (0.1f);
+      myBSDF.Kt = Graphic3d_Vec3 (0.9f);
+      myBSDF.Fresnel = Graphic3d_Fresnel::CreateConstant (0.0f);
+      myTransparencyCoef = 0.80f;
+
+      // Color resulting from ambient
+      myAmbientColor.SetValues (0.550f, 0.550f, 0.550f, Quantity_TOC_RGB);
+      // Color resulting from dispersed
+      myDiffuseColor.SetValues (0.100f, 0.100f, 0.100f, Quantity_TOC_RGB);
+      // Color resulting from specular
+      mySpecularColor.SetValues (0.970f, 0.970f, 0.970f, Quantity_TOC_RGB);
+      break;
+
     case Graphic3d_NOM_UserDefined:
       myStringName = "UserDefined";
       break;
@@ -1035,7 +1058,8 @@ namespace
     {"Charcoal",         Graphic3d_MATERIAL_PHYSIC},
     {"Water",            Graphic3d_MATERIAL_PHYSIC},
     {"Glass",            Graphic3d_MATERIAL_PHYSIC},
-    {"Diamond",          Graphic3d_MATERIAL_PHYSIC}
+    {"Diamond",          Graphic3d_MATERIAL_PHYSIC},
+    {"Transparent",      Graphic3d_MATERIAL_PHYSIC}
 
   };
 }
index 9f28ca7..1fe5e74 100644 (file)
@@ -43,6 +43,7 @@ Graphic3d_NOM_CHARCOAL,
 Graphic3d_NOM_WATER,
 Graphic3d_NOM_GLASS,
 Graphic3d_NOM_DIAMOND,
+Graphic3d_NOM_TRANSPARENT,
 Graphic3d_NOM_DEFAULT,
 Graphic3d_NOM_UserDefined
 };
index 3864a62..59a59b2 100755 (executable)
@@ -109,9 +109,9 @@ OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
 // function : OpenGl_LightSource
 // purpose  : Creates new light source
 // =======================================================================
-OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
+OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theEmission,
                                             const BVH_Vec4f& thePosition)
-: Diffuse (theDiffuse),
+: Emission (theEmission),
   Position (thePosition)
 {
   //
@@ -207,7 +207,7 @@ OpenGl_TriangleSet::OpenGl_TriangleSet (const Standard_Size theArrayID)
   myArrayID (theArrayID)
 {
   myBuilder = new BVH_BinnedBuilder<Standard_ShortReal, 3 /* dim */, 48 /* bins */>
-    (5 /* leaf size */, 32 /* max height */, Standard_False, OSD_Parallel::NbLogicalProcessors() + 1 /* threads */);
+    (4 /* leaf size */, 32 /* max height */, Standard_False, OSD_Parallel::NbLogicalProcessors() + 1 /* threads */);
 }
 
 // =======================================================================
index 237e6f4..17ff432 100755 (executable)
@@ -136,7 +136,7 @@ class OpenGl_RaytraceLight
 public:
 
   //! Diffuse intensity (in terms of OpenGL).
-  BVH_Vec4f Diffuse;
+  BVH_Vec4f Emission;
 
   //! Position of light source (in terms of OpenGL).
   BVH_Vec4f Position;
@@ -144,7 +144,10 @@ public:
 public:
 
   //! Creates new light source.
-  OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
+  OpenGl_RaytraceLight() { }
+
+  //! Creates new light source.
+  OpenGl_RaytraceLight (const BVH_Vec4f& theEmission,
                         const BVH_Vec4f& thePosition);
 
   //! Returns packed (serialized) representation of light source.
index fbbe8cf..5d79813 100644 (file)
@@ -591,17 +591,17 @@ protected: //! @name data types related to ray-tracing
   //! Defines OpenGL texture samplers.
   enum ShaderSamplerNames
   {
-    OpenGl_RT_SceneNodeInfoTexture  = 0,
-    OpenGl_RT_SceneMinPointTexture  = 1,
-    OpenGl_RT_SceneMaxPointTexture  = 2,
-    OpenGl_RT_SceneTransformTexture = 3,
+    OpenGl_RT_EnvironmentMapTexture = 0,
 
-    OpenGl_RT_GeometryVertexTexture = 4,
-    OpenGl_RT_GeometryNormalTexture = 5,
-    OpenGl_RT_GeometryTexCrdTexture = 6,
-    OpenGl_RT_GeometryTriangTexture = 7,
+    OpenGl_RT_SceneNodeInfoTexture  = 1,
+    OpenGl_RT_SceneMinPointTexture  = 2,
+    OpenGl_RT_SceneMaxPointTexture  = 3,
+    OpenGl_RT_SceneTransformTexture = 4,
 
-    OpenGl_RT_EnvironmentMapTexture = 8,
+    OpenGl_RT_GeometryVertexTexture = 5,
+    OpenGl_RT_GeometryNormalTexture = 6,
+    OpenGl_RT_GeometryTexCrdTexture = 7,
+    OpenGl_RT_GeometryTriangTexture = 8,
 
     OpenGl_RT_RaytraceMaterialTexture = 9,
     OpenGl_RT_RaytraceLightSrcTexture = 10,
@@ -747,9 +747,6 @@ protected: //! @name methods related to ray-tracing
   //! Updates 3D scene light sources for ray-tracing.
   Standard_Boolean updateRaytraceLightSources (const OpenGl_Mat4& theInvModelView, const Handle(OpenGl_Context)& theGlContext);
 
-  //! Updates environment map for ray-tracing.
-  Standard_Boolean updateRaytraceEnvironmentMap (const Handle(OpenGl_Context)& theGlContext);
-
   //! Checks to see if the OpenGL structure is modified.
   Standard_Boolean toUpdateStructure (const OpenGl_Structure* theStructure);
 
index fa43fb3..1b36a4b 100644 (file)
@@ -42,6 +42,24 @@ namespace
 {
   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
+
+  //! Operator returning TRUE for positional light sources.
+  struct IsLightPositional
+  {
+    bool operator() (const OpenGl_Light& theLight)
+    {
+      return theLight.Type != Graphic3d_TOLS_DIRECTIONAL;
+    }
+  };
+
+  //! Operator returning TRUE for any non-ambient light sources.
+  struct IsNotAmbient
+  {
+    bool operator() (const OpenGl_Light& theLight)
+    {
+      return theLight.Type != Graphic3d_TOLS_AMBIENT;
+    }
+  };
 }
 
 // =======================================================================
@@ -1402,10 +1420,20 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
         return safeFailBack ("Failed to load source into ray-tracing fragment shaders", theGlContext);
       }
 
+      TCollection_AsciiString aLog;
+
       if (!myRaytraceShader->Compile (theGlContext)
        || !myPostFSAAShader->Compile (theGlContext)
        || !myOutImageShader->Compile (theGlContext))
       {
+#ifdef RAY_TRACE_PRINT_INFO
+        myRaytraceShader->FetchInfoLog (theGlContext, aLog);
+
+        if (!aLog.IsEmpty())
+        {
+          std::cout << "Failed to compile ray-tracing shader: " << aLog << "\n";
+        }
+#endif
         return safeFailBack ("Failed to compile ray-tracing fragment shaders", theGlContext);
       }
 
@@ -1417,6 +1445,14 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
        || !myPostFSAAProgram->Link (theGlContext)
        || !myOutImageProgram->Link (theGlContext))
       {
+#ifdef RAY_TRACE_PRINT_INFO
+        myRaytraceProgram->FetchInfoLog (theGlContext, aLog);
+
+        if (!aLog.IsEmpty())
+        {
+          std::cout << "Failed to compile ray-tracing shader: " << aLog << "\n";
+        }
+#endif
         return safeFailBack ("Failed to initialize vertex attributes for ray-tracing program", theGlContext);
       }
     }
@@ -1424,7 +1460,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
 
   if (myRaytraceInitStatus == OpenGl_RT_NONE)
   {
-    myAccumFrames = 0; // reject accumulated frames
+    myAccumFrames = 0; // accumulation should be restarted
 
     if (!theGlContext->IsGlGreaterEqual (3, 1))
     {
@@ -2266,14 +2302,31 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& theInvModelView, const Handle(OpenGl_Context)& theGlContext)
 {
-  myRaytraceGeometry.Sources.clear();
+  std::vector<OpenGl_Light> aLightSources;
 
-  myRaytraceGeometry.Ambient = BVH_Vec4f (0.0f, 0.0f, 0.0f, 0.0f);
+  if (myShadingModel != Graphic3d_TOSM_NONE)
+  {
+    aLightSources.assign (myLights.begin(), myLights.end());
 
-  OpenGl_ListOfLight::Iterator aLightIter (myShadingModel == Graphic3d_TOSM_NONE ? myNoShadingLight : myLights);
-  for (; aLightIter.More(); aLightIter.Next())
+    // move positional light sources at the front of the list
+    std::partition (aLightSources.begin(), aLightSources.end(), IsLightPositional());
+  }
+
+  // get number of 'real' (not ambient) light sources
+  const size_t aNbLights = std::count_if (aLightSources.begin(), aLightSources.end(), IsNotAmbient());
+
+  Standard_Boolean wasUpdated = myRaytraceGeometry.Sources.size () != aNbLights;
+
+  if (wasUpdated)
+  {
+    myRaytraceGeometry.Sources.resize (aNbLights);
+  }
+
+  myRaytraceGeometry.Ambient = BVH_Vec4f (0.f, 0.f, 0.f, 0.f);
+
+  for (size_t aLightIdx = 0, aRealIdx = 0; aLightIdx < aLightSources.size(); ++aLightIdx)
   {
-    const OpenGl_Light& aLight = aLightIter.Value();
+    const OpenGl_Light& aLight = aLightSources[aLightIdx];
 
     if (aLight.Type == Graphic3d_TOLS_AMBIENT)
     {
@@ -2284,10 +2337,10 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
       continue;
     }
 
-    BVH_Vec4f aDiffuse  (aLight.Color.r() * aLight.Intensity,
-                         aLight.Color.g() * aLight.Intensity,
-                         aLight.Color.b() * aLight.Intensity,
-                         1.0f);
+    BVH_Vec4f aEmission  (aLight.Color.r() * aLight.Intensity,
+                          aLight.Color.g() * aLight.Intensity,
+                          aLight.Color.b() * aLight.Intensity,
+                          1.0f);
 
     BVH_Vec4f aPosition (-aLight.Direction.x(),
                          -aLight.Direction.y(),
@@ -2301,13 +2354,13 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
                              static_cast<float>(aLight.Position.z()),
                              1.0f);
 
-      // store smoothing radius in w-component
-      aDiffuse.w() = Max (aLight.Smoothness, 0.f);
+      // store smoothing radius in W-component
+      aEmission.w() = Max (aLight.Smoothness, 0.f);
     }
     else
     {
-      // store cosine of smoothing angle in w-component
-      aDiffuse.w() = cosf (Min (Max (aLight.Smoothness, 0.f), static_cast<Standard_ShortReal> (M_PI / 2.0)));
+      // store cosine of smoothing angle in W-component
+      aEmission.w() = cosf (Min (Max (aLight.Smoothness, 0.f), static_cast<Standard_ShortReal> (M_PI / 2.0)));
     }
 
     if (aLight.IsHeadlight)
@@ -2315,23 +2368,26 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
       aPosition = theInvModelView * aPosition;
     }
 
-    myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
+    for (int aK = 0; aK < 4; ++aK)
+    {
+      wasUpdated |= (aEmission[aK] != myRaytraceGeometry.Sources[aRealIdx].Emission[aK])
+                 || (aPosition[aK] != myRaytraceGeometry.Sources[aRealIdx].Position[aK]);
+    }
+
+    if (wasUpdated)
+    {
+      myRaytraceGeometry.Sources[aRealIdx] = OpenGl_RaytraceLight (aEmission, aPosition);
+    }
+
+    ++aRealIdx;
   }
 
-  if (myRaytraceLightSrcTexture.IsNull())  // create light source buffer
+  if (myRaytraceLightSrcTexture.IsNull()) // create light source buffer
   {
     myRaytraceLightSrcTexture = new OpenGl_TextureBufferArb;
-
-    if (!myRaytraceLightSrcTexture->Create (theGlContext))
-    {
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to create light source buffer" << std::endl;
-#endif
-      return Standard_False;
-    }
   }
 
-  if (myRaytraceGeometry.Sources.size() != 0)
+  if (myRaytraceGeometry.Sources.size() != 0 && wasUpdated)
   {
     const GLfloat* aDataPtr = myRaytraceGeometry.Sources.front().Packed();
     if (!myRaytraceLightSrcTexture->Init (theGlContext, 4, GLsizei (myRaytraceGeometry.Sources.size() * 2), aDataPtr))
@@ -2341,54 +2397,11 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
 #endif
       return Standard_False;
     }
-  }
 
-  return Standard_True;
-}
-
-// =======================================================================
-// function : updateRaytraceEnvironmentMap
-// purpose  : Updates environment map for ray-tracing
-// =======================================================================
-Standard_Boolean OpenGl_View::updateRaytraceEnvironmentMap (const Handle(OpenGl_Context)& theGlContext)
-{
-  Standard_Boolean aResult = Standard_True;
-
-  if (!myToUpdateEnvironmentMap)
-  {
-    return aResult;
-  }
-
-  Handle(OpenGl_ShaderProgram) aPrograms[] = { myRaytraceProgram,
-                                               myPostFSAAProgram };
-
-  for (Standard_Integer anIdx = 0; anIdx < 2; ++anIdx)
-  {
-    if (!aPrograms[anIdx].IsNull())
-    {
-      aResult &= theGlContext->BindProgram (aPrograms[anIdx]);
-
-      if (!myTextureEnv.IsNull())
-      {
-        myTextureEnv->Bind (theGlContext,
-          GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
-
-        aResult &= aPrograms[anIdx]->SetUniform (theGlContext,
-          myUniformLocations[anIdx][OpenGl_RT_uSphereMapEnabled], 1);
-      }
-      else
-      {
-        aResult &= aPrograms[anIdx]->SetUniform (theGlContext,
-          myUniformLocations[anIdx][OpenGl_RT_uSphereMapEnabled], 0);
-      }
-    }
+    myAccumFrames = 0; // accumulation should be restarted
   }
 
-  myToUpdateEnvironmentMap = Standard_False;
-
-  theGlContext->BindProgram (NULL);
-
-  return aResult;
+  return Standard_True;
 }
 
 // =======================================================================
@@ -2461,7 +2474,7 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
 
-  // Enable/disable run time rendering effects
+  // Enable/disable run-time rendering effects
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uShadowsEnabled], myRenderParams.IsShadowEnabled ?  1 : 0);
   theProgram->SetUniform (theGlContext,
@@ -2506,6 +2519,11 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
       myUniformLocations[theProgramId][OpenGl_RT_uBackColorBot], aBackColor);
   }
 
+  const Standard_Boolean toDisableEnvironmentMap = myTextureEnv.IsNull() || !myTextureEnv->IsValid();
+  
+  theProgram->SetUniform (theGlContext,
+    myUniformLocations[theProgramId][OpenGl_RT_uSphereMapEnabled], toDisableEnvironmentMap ? 0 : 1);
+
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uSphereMapForBack], myRenderParams.UseEnvironmentMapBackground ?  1 : 0);
 
@@ -2533,6 +2551,11 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
   #endif
   }
 
+  if (!myTextureEnv.IsNull() && myTextureEnv->IsValid())
+  {
+    myTextureEnv->Bind (theGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
+  }
+
   mySceneMinPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
   mySceneMaxPointTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
   mySceneNodeInfoTexture->BindTexture    (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
@@ -2731,6 +2754,11 @@ Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection
 {
   Standard_Boolean aResult = Standard_True;
 
+  if (myToUpdateEnvironmentMap) // check whether the map was changed
+  {
+    myAccumFrames = myToUpdateEnvironmentMap = 0;
+  }
+
   if (myRaytraceParameters.AdaptiveScreenSampling)
   {
     if (myAccumFrames == 0)
@@ -2875,11 +2903,6 @@ Standard_Boolean OpenGl_View::raytrace (const Standard_Integer        theSizeX,
     return Standard_False;
   }
 
-  if (!updateRaytraceEnvironmentMap (theGlContext))
-  {
-    return Standard_False;
-  }
-
   OpenGl_Mat4 aLightSourceMatrix;
 
   // Get inversed model-view matrix for transforming lights
index 09db692..68bdad9 100644 (file)
@@ -1,3 +1,15 @@
+#ifdef _MSC_VER
+  #define PATH_TRACING // just for editing in MS VS
+
+  #define in
+  #define out
+  #define inout
+
+  typedef struct { float x; float y; } vec2;
+  typedef struct { float x; float y; float z; } vec3;
+  typedef struct { float x; float y; float z; float w; } vec4;
+#endif
+
 #ifdef PATH_TRACING
 
 ///////////////////////////////////////////////////////////////////////////////////////
@@ -42,13 +54,13 @@ struct SMaterial
 // Support subroutines
 
 //=======================================================================
-// function : LocalSpace
+// function : buildLocalSpace
 // purpose  : Generates local space for the given normal
 //=======================================================================
-SLocalSpace LocalSpace (in vec3 theNormal)
+SLocalSpace buildLocalSpace (in vec3 theNormal)
 {
-  vec3 anAxisX = cross (vec3 (0.f, 1.f, 0.f), theNormal);
-  vec3 anAxisY = cross (vec3 (1.f, 0.f, 0.f), theNormal);
+  vec3 anAxisX = vec3 (theNormal.z, 0.f, -theNormal.x);
+  vec3 anAxisY = vec3 (0.f, -theNormal.z, theNormal.y);
 
   float aSqrLenX = dot (anAxisX, anAxisX);
   float aSqrLenY = dot (anAxisY, anAxisY);
@@ -99,19 +111,6 @@ float convolve (in vec3 theVector, in vec3 theFactor)
 }
 
 //=======================================================================
-// function : sphericalDirection
-// purpose  : Constructs vector from spherical coordinates
-//=======================================================================
-vec3 sphericalDirection (in float theCosTheta, in float thePhi)
-{
-  float aSinTheta = sqrt (1.f - theCosTheta * theCosTheta);
-
-  return vec3 (aSinTheta * cos (thePhi),
-               aSinTheta * sin (thePhi),
-               theCosTheta);
-}
-
-//=======================================================================
 // function : fresnelSchlick
 // purpose  : Computes the Fresnel reflection formula using
 //            Schlick's approximation.
@@ -196,24 +195,24 @@ float fresnelConductor (in float theCosI, in float theEta, in float theK)
 // purpose  : Computes the Fresnel reflection formula for general medium
 //            in case of circularly polarized light.
 //=======================================================================
-vec3 fresnelMedia (in float theCosI, in vec3 theFresnelCoeffs)
+vec3 fresnelMedia (in float theCosI, in vec3 theFresnel)
 {
-  if (theFresnelCoeffs.x > FRESNEL_SCHLICK)
+  if (theFresnel.x > FRESNEL_SCHLICK)
   {
-    return fresnelSchlick (abs (theCosI), theFresnelCoeffs);
+    return fresnelSchlick (abs (theCosI), theFresnel);
   }
 
-  if (theFresnelCoeffs.x > FRESNEL_CONSTANT)
+  if (theFresnel.x > FRESNEL_CONSTANT)
   {
-    return vec3 (theFresnelCoeffs.z);
+    return vec3 (theFresnel.z);
   }
 
-  if (theFresnelCoeffs.x > FRESNEL_CONDUCTOR)
+  if (theFresnel.x > FRESNEL_CONDUCTOR)
   {
-    return vec3 (fresnelConductor (abs (theCosI), theFresnelCoeffs.y, theFresnelCoeffs.z));
+    return vec3 (fresnelConductor (abs (theCosI), theFresnel.y, theFresnel.z));
   }
 
-  return vec3 (fresnelDielectric (theCosI, theFresnelCoeffs.y));
+  return vec3 (fresnelDielectric (theCosI, theFresnel.y));
 }
 
 //=======================================================================
@@ -226,11 +225,11 @@ void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)
   // Compute relative index of refraction
   float anEta = (theIncident.z > 0.f) ? 1.f / theIndex : theIndex;
 
-  // Handle total internal reflection for transmission
+  // Handle total internal reflection (TIR)
   float aSinT2 = anEta * anEta * (1.f - theIncident.z * theIncident.z);
 
-  // Compute transmitted ray direction
-  float aCosT = sqrt (1.f - min (aSinT2, 1.f)) * (theIncident.z > 0.f ? -1.f : 1.f);
+  // Compute direction of transmitted ray
+  float aCosT = sqrt (1.f - min (aSinT2, 1.f)) * sign (-theIncident.z);
 
   theTransmit = normalize (vec3 (-anEta * theIncident.x,
                                  -anEta * theIncident.y,
@@ -242,281 +241,315 @@ void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 //=======================================================================
-// function : handleLambertianReflection
+// function : HandleLambertianReflection
 // purpose  : Handles Lambertian BRDF, with cos(N, PSI)
 //=======================================================================
-float handleLambertianReflection (in vec3 theInput, in vec3 theOutput)
+float HandleLambertianReflection (in vec3 theInput, in vec3 theOutput)
 {
-  return max (0.f, theInput.z) * (1.f / M_PI);
+  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? 0.f : theInput.z * (1.f / M_PI);
 }
 
 //=======================================================================
-// function : handleBlinnReflection
-// purpose  : Handles Blinn glossy BRDF, with cos(N, PSI)
+// function : SmithG1
+// purpose  :
 //=======================================================================
-vec3 handleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnelCoeffs, in float theExponent)
+float SmithG1 (in vec3 theDirection, in vec3 theM, in float theRoughness)
 {
-  vec3 aWeight = ZERO;
-
-  // Compute half-angle vector
-  vec3 aHalf = theInput + theOutput;
+  if (dot (theDirection, theM) * theDirection.z <= 0.f)
+  {
+    return 0.f;
+  }
 
-  if (aHalf.z < 0.f)
-    aHalf = -aHalf;
+  float aTanThetaM = sqrt (1.f - theDirection.z * theDirection.z) / theDirection.z;
 
-  float aLength = dot (aHalf, aHalf);
+  if (aTanThetaM == 0.0f)
+  {
+    return 1.f;
+  }
 
-  if (aLength <= 0.f)
-    return ZERO;
+  float aVal = 1.f / (theRoughness * aTanThetaM);
 
-  aHalf *= inversesqrt (aLength);
+  if (aVal >= 1.6f)
+  {
+    return 1.f;
+  }
 
-  // Compute Fresnel reflectance
-  float aCosDelta = dot (theOutput, aHalf);
+  // Use fast and accurate rational approximation to the
+  // shadowing-masking function (from Mitsuba renderer)
+  float aSqr = aVal * aVal;
 
-  vec3 aFresnel = fresnelMedia (aCosDelta, theFresnelCoeffs);
+  return (3.535f * aVal + 2.181f * aSqr) / (1.f + 2.276f * aVal + 2.577f * aSqr);
+}
 
-  // Compute fraction of microfacets that reflect light
-  float aCosThetaH = max (0.f, aHalf.z);
+//=======================================================================
+// function : HandleBlinnReflection
+// purpose  : Handles Blinn glossy BRDF, with cos(N, PSI)
+//=======================================================================
+vec3 HandleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnel, in float theRoughness)
+{
+  // calculate the reflection half-vec
+  vec3 aH = normalize (theInput + theOutput);
 
-  float aFraction = (theExponent + 2.f) * (M_PI / 2.f) * pow (aCosThetaH, theExponent);
+  // roughness value -> Blinn exponent
+  float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);
 
-  // Compute geometry attenuation term (already includes cos)
-  float aCosThetaI = max (0.f, theInput.z);
-  float aCosThetaO = max (0.f, theOutput.z);
+  // calculate microfacet distribution
+  float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);
 
-  float aGeom = min (1.f, 2.f * aCosThetaH / max (0.f, aCosDelta) * min (aCosThetaO, aCosThetaI));
+  // calculate shadow-masking function
+  float aG = SmithG1 (theOutput, aH, theRoughness) * SmithG1 (theInput, aH, theRoughness);
 
-  return aCosThetaO < 1.0e-3f ? ZERO :
-    aFraction * aGeom / (4.f * aCosThetaO) * aFresnel;
+  // return total amount of reflection
+  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :
+    aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);
 }
 
 //=======================================================================
-// function : handleMaterial
+// function : HandleMaterial
 // purpose  : Returns BSDF value for specified material, with cos(N, PSI)
 //=======================================================================
-vec3 handleMaterial (in SMaterial theMaterial, in vec3 theInput, in vec3 theOutput)
+vec3 HandleMaterial (in SMaterial theBSDF, in vec3 theInput, in vec3 theOutput)
 {
-  return theMaterial.Kd.rgb * handleLambertianReflection (theInput, theOutput) +
-    theMaterial.Ks.rgb * handleBlinnReflection (theInput, theOutput, theMaterial.Fresnel, theMaterial.Ks.w);
+  return theBSDF.Kd.rgb * HandleLambertianReflection (theInput, theOutput) +
+    theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);
 }
 
 //=======================================================================
-// function : sampleLambertianReflection
+// function : SampleLambertianReflection
 // purpose  : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
 //=======================================================================
-void sampleLambertianReflection (in vec3 theOutput, out vec3 theInput)
+vec3 SampleLambertianReflection (in vec3 theOutput, out vec3 theInput, inout float thePDF)
 {
   float aKsi1 = RandFloat();
   float aKsi2 = RandFloat();
 
   float aTemp = sqrt (aKsi2);
 
-  theInput = vec3 (aTemp * cos (2.f * M_PI * aKsi1),
-                   aTemp * sin (2.f * M_PI * aKsi1),
+  theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),
+                   aTemp * sin (M_2_PI * aKsi1),
                    sqrt (1.f - aKsi2));
 
-  theInput.z = mix (-theInput.z, theInput.z, step (0.f, theOutput.z));
-}
-
-// Types of bounces
-#define NON_SPECULAR_BOUNCE 0
-#define SPEC_REFLECT_BOUNCE 1
-#define SPEC_REFRACT_BOUNCE 2
+  thePDF *= abs (theInput.z) * (1.f / M_PI);
 
-#define IS_NON_SPEC_BOUNCE(theBounce) (theBounce == 0)
-#define IS_ANY_SPEC_BOUNCE(theBounce) (theBounce != 0)
-#define IS_REFL_SPEC_BOUNCE(theBounce) (theBounce == 1)
-#define IS_REFR_SPEC_BOUNCE(theBounce) (theBounce == 2)
+  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;
+}
 
 //=======================================================================
-// function : sampleSpecularTransmission
-// purpose  : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)
+// function : SampleBlinnReflection
+// purpose  : Samples Blinn BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
+//            The BRDF is a product of three main terms, D, G, and F,
+//            which is then divided by two cosine terms. Here we perform
+//            importance sample the D part of the Blinn model; trying to
+//            develop a sampling procedure that accounted for all of the
+//            terms would be complex, and it is the D term that accounts
+//            for most of the variation.
 //=======================================================================
-vec3 sampleSpecularTransmission (in vec3 theOutput, out vec3 theInput,
-  out int theBounce, in vec3 theWeight, in vec3 theFresnelCoeffs)
+vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel, in float theRoughness, inout float thePDF)
 {
-  vec3 aFresnel = fresnelMedia (theOutput.z, theFresnelCoeffs);
+  float aKsi1 = RandFloat();
+  float aKsi2 = RandFloat();
 
-  float aProbability = convolve (aFresnel, theWeight);
+  // roughness value --> Blinn exponent
+  float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);
 
-  // Check if transmission takes place
-  theBounce = RandFloat() <= aProbability ?
-    SPEC_REFLECT_BOUNCE : SPEC_REFRACT_BOUNCE;
+  // normal from microface distribution
+  float aCosThetaM = pow (aKsi1, 1.f / (aPower + 2.f));
 
-  // Sample input direction
-  if (theBounce == SPEC_REFLECT_BOUNCE)
-  {
-    theInput = vec3 (-theOutput.x,
-                     -theOutput.y,
-                      theOutput.z);
+  vec3 aM = vec3 (cos (M_2_PI * aKsi2),
+                  sin (M_2_PI * aKsi2),
+                  aCosThetaM);
 
-    theWeight = aFresnel * (1.f / aProbability);
-  }
-  else
-  {
-    transmitted (theFresnelCoeffs.y, theOutput, theInput);
+  aM.xy *= sqrt (1.f - aCosThetaM * aCosThetaM);
 
-    theWeight = (UNIT - aFresnel) * (1.f / (1.f - aProbability));
+  // calculate PDF of sampled direction
+  thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);
+
+  float aCosDelta = dot (theOutput, aM);
+
+  // pick input based on half direction
+  theInput = -theOutput + 2.f * aCosDelta * aM;
+
+  if (theInput.z <= 0.f || theOutput.z <= 0.f)
+  {
+    return ZERO;
   }
 
-  return theWeight;
+  // Jacobian of half-direction mapping
+  thePDF /= 4.f * dot (theInput, aM);
+
+  // compute shadow-masking coefficient
+  float aG = SmithG1 (theOutput, aM, theRoughness) * SmithG1 (theInput, aM, theRoughness);
+
+  return aG * aCosDelta / (theOutput.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);
 }
 
 //=======================================================================
-// function : sampleSpecularReflection
+// function : SampleSpecularReflection
 // purpose  : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
 //=======================================================================
-vec3 sampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnelCoeffs)
+vec3 SampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel)
 {
   // Sample input direction
   theInput = vec3 (-theOutput.x,
                    -theOutput.y,
                     theOutput.z);
 
-  return fresnelMedia (theOutput.z, theFresnelCoeffs);
+  return fresnelMedia (theOutput.z, theFresnel);
 }
 
-#define MIN_COS 1.0e-20f
-
 //=======================================================================
-// function : sampleBlinnReflection
-// purpose  : Samples Blinn BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
-//            The BRDF is a product of three main terms, D, G, and F,
-//            which is then divided by two cosine terms. Here we perform
-//            importance sample the D part of the Blinn model; trying to
-//            develop a sampling procedure that accounted for all of the
-//            terms would be complex, and it is the D term that accounts
-//            for most of the variation.
+// function : SampleSpecularTransmission
+// purpose  : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)
 //=======================================================================
-vec3 sampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnelCoeffs, in float theExponent)
+vec3 SampleSpecularTransmission (in vec3 theOutput,
+  out vec3 theInput, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)
 {
-  vec3 aWeight = ZERO;
-
-  // Generate two random variables
-  float aKsi1 = RandFloat();
-  float aKsi2 = RandFloat();
+  vec3 aFactor = fresnelMedia (theOutput.z, theFresnel);
 
-  // Compute sampled half-angle vector for Blinn distribution
-  float aCosThetaH = pow (aKsi1, 1.f / (theExponent + 1.f));
+  float aReflection = convolve (aFactor, theWeight);
 
-  vec3 aHalf = sphericalDirection (aCosThetaH, aKsi2 * 2.f * M_PI);
+  // sample specular BRDF/BTDF
+  if (RandFloat() <= aReflection)
+  {
+    theInput = vec3 (-theOutput.x,
+                     -theOutput.y,
+                      theOutput.z);
 
-  if (aHalf.z < 0)
+    theWeight = aFactor * (1.f / aReflection);
+  }
+  else
   {
-    aHalf = -aHalf;
+    theInside = !theInside;
+
+    transmitted (theFresnel.y, theOutput, theInput);
+
+    theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));
   }
 
-  // Compute incident direction by reflecting about half-vector
-  float aCosDelta = dot (theOutput, aHalf);
+  return theWeight;
+}
 
-  vec3 anInput = 2.f * aCosDelta * aHalf - theOutput;
+#define FLT_EPSILON 1.0e-5F
 
-  if (theOutput.z * anInput.z <= 0.f)
-  {
-    return ZERO;
-  }
+//=======================================================================
+// function : BsdfPdf
+// purpose  : Calculates BSDF of sampling input knowing output
+//=======================================================================
+float BsdfPdf (in SMaterial theBSDF,
+               in vec3      theOutput,
+               in vec3      theInput,
+               in vec3      theWeight)
+{
+  float aPd = convolve (theBSDF.Kd.rgb, theWeight);
+  float aPs = convolve (theBSDF.Ks.rgb, theWeight);
+  float aPr = convolve (theBSDF.Kr.rgb, theWeight);
+  float aPt = convolve (theBSDF.Kt.rgb, theWeight);
+
+  float aReflection = aPd + aPs + aPr + aPt;
 
-  theInput = anInput;
+  float aPDF = 0.f; // PDF of sampling input direction
 
-  // Compute Fresnel reflectance
-  vec3 aFresnel = fresnelMedia (aCosDelta, theFresnelCoeffs);
+  if (theInput.z * theOutput.z > 0.f)
+  {
+    vec3 aHalf = normalize (theInput + theOutput);
 
-  // Compute geometry attenuation term
-  float aCosThetaI = max (MIN_COS, theInput.z);
-  float aCosThetaO = max (MIN_COS, theOutput.z);
+    // roughness value --> Blinn exponent
+    float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);
 
-  float aGeom = min (max (MIN_COS, aCosDelta), 2.f * aCosThetaH * min (aCosThetaO, aCosThetaI));
+    aPDF = aPd * abs (theInput.z / M_PI) +
+      aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (aHalf.z, aPower + 1.f) / (4.f * dot (theInput, aHalf));
+  }
 
-  // Compute weight of the ray sample
-  return aFresnel * ((theExponent + 2.f) / (theExponent + 1.f) * aGeom / aCosThetaO);
+  return aPDF / aReflection;
 }
 
+//! Tool macro to handle sampling of particular BxDF
+#define PICK_BXDF(p, k) aPDF = p / aReflection; theWeight *= k / aPDF;
+
 //=======================================================================
-// function : sampleMaterial
+// function : SampleBsdf
 // purpose  : Samples specified composite material (BSDF)
 //=======================================================================
-void sampleMaterial (in SMaterial theMaterial,
-                     in vec3      theOutput,
-                     out vec3     theInput,
-                     inout vec3   theWeight,
-                     inout int    theBounce)
+float SampleBsdf (in SMaterial theBSDF,
+                  in vec3      theOutput,
+                  out vec3     theInput,
+                  inout vec3   theWeight,
+                  inout bool   theInside)
 {
-  // Compute the probability of ray reflection
-  float aPd = convolve (theMaterial.Kd.rgb, theWeight);
-  float aPs = convolve (theMaterial.Ks.rgb, theWeight);
-  float aPr = convolve (theMaterial.Kr.rgb, theWeight);
-  float aPt = convolve (theMaterial.Kt.rgb, theWeight);
+  // compute probability of each reflection type (BxDF)
+  float aPd = convolve (theBSDF.Kd.rgb, theWeight);
+  float aPs = convolve (theBSDF.Ks.rgb, theWeight);
+  float aPr = convolve (theBSDF.Kr.rgb, theWeight);
+  float aPt = convolve (theBSDF.Kt.rgb, theWeight);
 
   float aReflection = aPd + aPs + aPr + aPt;
 
-  // Choose BSDF component to sample
+  // choose BxDF component to sample
   float aKsi = aReflection * RandFloat();
 
-  theBounce = NON_SPECULAR_BOUNCE;
+  // BxDF's PDF of sampled direction
+  float aPDF = 0.f;
 
   if (aKsi < aPd) // diffuse reflection
   {
-    sampleLambertianReflection (theOutput, theInput);
+    PICK_BXDF (aPd, theBSDF.Kd.rgb);
 
-    theWeight *= theMaterial.Kd.rgb * (aReflection / aPd);
+    theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);
   }
-  else if (aKsi < aPd + aPs) //  glossy reflection
+  else if (aKsi < aPd + aPs) // glossy reflection
   {
-    theWeight *= theMaterial.Ks.rgb * (aReflection / aPs) *
-      sampleBlinnReflection (theOutput, theInput, theMaterial.Fresnel, theMaterial.Ks.w);
+    PICK_BXDF (aPs, theBSDF.Ks.rgb);
+
+    theWeight *= SampleBlinnReflection (theOutput, theInput, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);
   }
-  else if (aKsi < aPd + aPs + aPr) //  specular reflection
+  else if (aKsi < aPd + aPs + aPr) // specular reflection
   {
-    theWeight *= theMaterial.Kr.rgb * (aReflection / aPr) *
-      sampleSpecularReflection (theOutput, theInput, theMaterial.Fresnel);
+    PICK_BXDF (aPr, theBSDF.Kr.rgb);
+
+    aPDF = MAXFLOAT;
 
-    theBounce = SPEC_REFLECT_BOUNCE; // specular bounce
+    theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);
   }
-  else //  specular transmission
+  else if (aKsi < aReflection) // specular transmission
   {
-    theWeight *= theMaterial.Kt.rgb * (aReflection / aPt) *
-      sampleSpecularTransmission (theOutput, theInput, theBounce, theWeight, theMaterial.Fresnel);
+    PICK_BXDF (aPt, theBSDF.Kt.rgb);
+
+    aPDF = MAXFLOAT;
+
+    theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);
   }
 
   // path termination for extra small weights
-  theWeight = mix (theWeight, ZERO, float (aReflection < 1e-3f));
+  theWeight = mix (ZERO, theWeight, step (FLT_EPSILON, aReflection));
+
+  return aPDF;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 // Handlers and samplers for light sources
 //////////////////////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-// function : handlePointLight
-// purpose  :
-//=======================================================================
-float handlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance)
+// =======================================================================
+// function : Latlong
+// purpose  : Converts world direction to environment texture coordinates
+// =======================================================================
+vec2 Latlong (in vec3 thePoint)
 {
-  float aDistance = dot (theToLight, theToLight);
-
-  float aCosMax = inversesqrt (1.f + theRadius * theRadius / aDistance);
+  float aPsi = acos (-thePoint.z);
 
-  return float (aDistance < theDistance * theDistance) *
-    step (aCosMax, dot (theToLight, theInput) * inversesqrt (aDistance));
-}
+  float aPhi = atan (thePoint.y, thePoint.x) + M_PI;
 
-//=======================================================================
-// function : handleDirectLight
-// purpose  :
-//=======================================================================
-float handleDirectLight (in vec3 theInput, in vec3 theToLight, in float theCosMax)
-{
-  return step (theCosMax, dot (theInput, theToLight));
+  return vec2 (aPhi * 0.1591549f,
+               aPsi * 0.3183098f);
 }
 
 //=======================================================================
-// function : sampleLight
+// function : SampleLight
 // purpose  : General sampling function for directional and point lights
 //=======================================================================
-vec3 sampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinite, in float theSmoothness, inout float thePDF)
+vec3 SampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinite, in float theSmoothness, inout float thePDF)
 {
-  SLocalSpace aSpace = LocalSpace (theToLight * (1.f / theDistance));
+  SLocalSpace aSpace = buildLocalSpace (theToLight * (1.f / theDistance));
 
   // for point lights smoothness defines radius
   float aCosMax = isInfinite ? theSmoothness :
@@ -527,74 +560,111 @@ vec3 sampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinit
 
   float aTmp = 1.f - aKsi2 * (1.f - aCosMax);
 
-  vec3 anInput = vec3 (cos (2.f * M_PI * aKsi1),
-                       sin (2.f * M_PI * aKsi1),
+  vec3 anInput = vec3 (cos (M_2_PI * aKsi1),
+                       sin (M_2_PI * aKsi1),
                        aTmp);
 
   anInput.xy *= sqrt (1.f - aTmp * aTmp);
 
-  thePDF *= (aCosMax < 1.f) ? 1.f / (2.f * M_PI) / (1.f - aCosMax) : 1.f;
+  thePDF = (aCosMax < 1.f) ? (thePDF / M_2_PI) / (1.f - aCosMax) : MAXFLOAT;
 
   return normalize (fromLocalSpace (anInput, aSpace));
 }
 
-// =======================================================================
-// function : Latlong
-// purpose  : Converts world direction to environment texture coordinates
-// =======================================================================
-vec2 Latlong (in vec3 thePoint)
+//=======================================================================
+// function : HandlePointLight
+// purpose  :
+//=======================================================================
+float HandlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance, inout float thePDF)
 {
-  float aPsi = acos (-thePoint.z);
+  float aCosMax = inversesqrt (1.f + theRadius * theRadius / (theDistance * theDistance));
 
-  float aPhi = atan (thePoint.y, thePoint.x) + M_PI;
+  float aVisibility = step (aCosMax, dot (theInput, theToLight));
 
-  return vec2 (aPhi * 0.1591549f,
-               aPsi * 0.3183098f);
+  thePDF *= step (-1.f, -aCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - aCosMax);
+
+  return aVisibility;
+}
+
+//=======================================================================
+// function : HandleDistantLight
+// purpose  :
+//=======================================================================
+float HandleDistantLight (in vec3 theInput, in vec3 theToLight, in float theCosMax, inout float thePDF)
+{
+  float aVisibility = step (theCosMax, dot (theInput, theToLight));
+
+  thePDF *= step (-1.f, -theCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - theCosMax);
+
+  return aVisibility;
 }
 
 // =======================================================================
-// function: intersectLight
+// function: IntersectLight
 // purpose : Checks intersections with light sources
 // =======================================================================
-vec3 intersectLight (in SRay theRay, in bool isViewRay, in int theBounce, in float theDistance)
+vec3 IntersectLight (in SRay theRay, in int theDepth, in float theHitDistance, out float thePDF)
 {
-  vec3 aRadiance = ZERO;
+  vec3 aTotalRadiance = ZERO;
 
-  if ((isViewRay || IS_REFR_SPEC_BOUNCE(theBounce)) && uSphereMapForBack == 0)
-  {
-    aRadiance = BackgroundColor().xyz;
-  }
-  else
-  {
-    aRadiance = FetchEnvironment (Latlong (theRay.Direct)).xyz;
-  }
+  thePDF = 0.f; // PDF of sampling light sources
 
-  // Apply gamma correction (gamma is 2)
-  aRadiance = aRadiance * aRadiance * float (theDistance == MAXFLOAT);
-
-  for (int aLightIdx = 0; aLightIdx < uLightCount && (isViewRay || IS_ANY_SPEC_BOUNCE(theBounce)); ++aLightIdx)
+  for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)
   {
     vec4 aLight = texelFetch (
       uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
     vec4 aParam = texelFetch (
       uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx));
 
+    // W component: 0 for infinite light and 1 for point light
+    aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);
+
+    float aPDF = 1.f / uLightCount;
+
     if (aLight.w != 0.f) // point light source
     {
-      aRadiance += aParam.rgb * handlePointLight (
-        theRay.Direct, aLight.xyz - theRay.Origin, aParam.w /* radius */, theDistance);
+      float aCenterDst = length (aLight.xyz);
+
+      if (aCenterDst < theHitDistance)
+      {
+        float aVisibility = HandlePointLight (
+          theRay.Direct, normalize (aLight.xyz), aParam.w /* radius */, aCenterDst, aPDF);
+
+        if (aVisibility > 0.f)
+        {
+          theHitDistance = aCenterDst;
+          aTotalRadiance = aParam.rgb;
+
+          thePDF = aPDF;
+        }
+      }
     }
-    else if (theDistance == MAXFLOAT) // directional light source
+    else if (theHitDistance == MAXFLOAT) // directional light source
     {
-      aRadiance += aParam.rgb * handleDirectLight (theRay.Direct, aLight.xyz, aParam.w /* angle cosine */);
+      aTotalRadiance += aParam.rgb * HandleDistantLight (
+        theRay.Direct, aLight.xyz, aParam.w /* angle cosine */, aPDF);
+
+      thePDF += aPDF;
     }
   }
 
-  return aRadiance;
+  if (thePDF == 0.f && theHitDistance == MAXFLOAT) // light source not found
+  {
+    if (theDepth + uSphereMapForBack == 0) // view ray and map is hidden
+    {
+      aTotalRadiance = pow (BackgroundColor().rgb, vec3 (2.f));
+    }
+    else
+    {
+      aTotalRadiance = pow (FetchEnvironment (Latlong (theRay.Direct)).rgb, vec3 (2.f));
+    }
+  }
+  
+  return aTotalRadiance;
 }
 
-#define MIN_THROUGHPUT   vec3 (0.02f)
-#define MIN_CONTRIBUTION vec3 (0.01f)
+#define MIN_THROUGHPUT   vec3 (1.0e-3f)
+#define MIN_CONTRIBUTION vec3 (1.0e-2f)
 
 #define MATERIAL_KD(index)      (18 * index + 11)
 #define MATERIAL_KR(index)      (18 * index + 12)
@@ -618,29 +688,32 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
   vec3 aRadiance   = ZERO;
   vec3 aThroughput = UNIT;
 
-  int aBounce = 0; // type of previous hit point
-  int aTrsfId = 0; // offset of object transform
+  int  aTransfID = 0;     // ID of object transformation
+  bool aInMedium = false; // is the ray inside an object
 
-  bool isInMedium = false;
+  float aExpPDF = 1.f;
+  float aImpPDF = 1.f;
 
   for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)
   {
     SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
 
-    ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTrsfId);
+    ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTransfID);
 
     // check implicit path
-    vec3 aLe = intersectLight (theRay,
-      aDepth == 0 /* is view ray */, aBounce, aHit.Time);
+    vec3 aLe = IntersectLight (theRay, aDepth, aHit.Time, aExpPDF);
 
     if (any (greaterThan (aLe, ZERO)) || aTriIndex.x == -1)
     {
-      aRadiance += aThroughput * aLe; break; // terminate path
+      float aMIS = (aDepth == 0 || aImpPDF == MAXFLOAT) ? 1.f :
+        aImpPDF * aImpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);
+
+      aRadiance += aThroughput * aLe * aMIS; break; // terminate path
     }
 
-    vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0).xyz;
-    vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1).xyz;
-    vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2).xyz;
+    vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTransfID + 0).xyz;
+    vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTransfID + 1).xyz;
+    vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTransfID + 2).xyz;
 
     // compute geometrical normal
     aHit.Normal = normalize (vec3 (dot (aInvTransf0, aHit.Normal),
@@ -649,7 +722,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
 
     theRay.Origin += theRay.Direct * aHit.Time; // get new intersection point
 
-    // Evaluate depth on first hit
+    // evaluate depth on first hit
     if (aDepth == 0)
     {
       vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);
@@ -694,7 +767,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
                                dot (aInvTransf1, aNormal),
                                dot (aInvTransf2, aNormal)));
 
-    SLocalSpace aSpace = LocalSpace (aNormal);
+    SLocalSpace aSpace = buildLocalSpace (aNormal);
 
     // account for self-emission (not stored in the material)
     aRadiance += aThroughput * texelFetch (
@@ -702,6 +775,8 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
 
     if (uLightCount > 0 && convolve (aMaterial.Kd.rgb + aMaterial.Ks.rgb, aThroughput) > 0.f)
     {
+      aExpPDF = 1.f / uLightCount;
+
       int aLightIdx = min (int (floor (RandFloat() * uLightCount)), uLightCount - 1);
 
       vec4 aLight = texelFetch (
@@ -712,15 +787,21 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
       // 'w' component is 0 for infinite light and 1 for point light
       aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);
 
-      float aPDF = 1.f / uLightCount, aDistance = length (aLight.xyz);
+      float aDistance = length (aLight.xyz);
 
-      aLight.xyz = sampleLight (aLight.xyz, aDistance,
-        aLight.w == 0.f /* is infinite */, aParam.w /* max cos or radius */, aPDF);
+      aLight.xyz = SampleLight (aLight.xyz, aDistance,
+        aLight.w == 0.f /* is infinite */, aParam.w /* max cos or radius */, aExpPDF);
 
-      vec3 aContrib = (1.f / aPDF) * aParam.rgb /* Le */ * handleMaterial (
+      aImpPDF = BsdfPdf (aMaterial,
+        toLocalSpace (-theRay.Direct, aSpace), toLocalSpace (aLight.xyz, aSpace), aThroughput);
+
+      // MIS weight including division by explicit PDF
+      float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);
+
+      vec3 aContrib = aMIS * aParam.rgb /* Le */ * HandleMaterial (
           aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));
 
-      if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // first check if light source is important
+      if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important
       {
         SRay aShadow = SRay (theRay.Origin + aLight.xyz * uSceneEpsilon, aLight.xyz);
 
@@ -734,32 +815,29 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
       }
     }
 
-    vec3 anInput;
-
-    sampleMaterial (aMaterial,
-      toLocalSpace (-theRay.Direct, aSpace), anInput, aThroughput, aBounce);
-
-    if (isInMedium)
+    if (aInMedium) // handle attenuation
     {
       aThroughput *= exp (-aHit.Time *
         aMaterial.Absorption.w * (UNIT - aMaterial.Absorption.rgb));
     }
 
-    isInMedium = IS_REFR_SPEC_BOUNCE(aBounce) ? !isInMedium : isInMedium;
+    vec3 anInput = UNIT; // sampled input direction
 
-#ifndef RUSSIAN_ROULETTE
-    if (all (lessThan (aThroughput, MIN_THROUGHPUT)))
-    {
-      aDepth = INVALID_BOUNCES; // terminate path
-    }
-#else
-    float aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);
+    aImpPDF = SampleBsdf (aMaterial,
+      toLocalSpace (-theRay.Direct, aSpace), anInput, aThroughput, aInMedium);
+
+    float aSurvive = 1.f;
+
+#ifdef RUSSIAN_ROULETTE
+    aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);
+#endif
 
-    if (RandFloat() > aSurvive)
+    if (RandFloat() > aSurvive || all (lessThanEqual (aThroughput, MIN_THROUGHPUT)))
     {
       aDepth = INVALID_BOUNCES; // terminate path
     }
 
+#ifdef RUSSIAN_ROULETTE
     aThroughput /= aSurvive;
 #endif
 
index 8eb42b3..31520ad 100644 (file)
@@ -143,7 +143,9 @@ struct SIntersect
 #define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)
 #define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)
 
-#define M_PI 3.14159265f
+#define M_PI   3.141592653f
+#define M_2_PI 6.283185307f
+#define M_PI_2 1.570796327f
 
 #define LUMA vec3 (0.2126f, 0.7152f, 0.0722f)
 
@@ -835,8 +837,8 @@ vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle)
 // =======================================================================
 vec4 FetchEnvironment (in vec2 theTexCoord)
 {
-  return mix (vec4 (0.0f, 0.0f, 0.0f, 1.0f),
-    textureLod (uEnvironmentMapTexture, theTexCoord, 0.0f), float (uSphereMapEnabled));
+  return uSphereMapEnabled == 0 ?
+    vec4 (0.f, 0.f, 0.f, 1.f) : textureLod (uEnvironmentMapTexture, theTexCoord, 0.f);
 }
 
 // =======================================================================
@@ -1020,8 +1022,8 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
 
         if (aVisibility > 0.0f)
         {
-          vec3 aIntensity = vec3 (texelFetch (
-            uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
+          vec3 aIntensity = min (UNIT, vec3 (texelFetch (
+            uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx))));
 
           float aRdotV = dot (reflect (aLight.xyz, aSidedNormal), theRay.Direct);
 
index d852cf2..00263f3 100644 (file)
@@ -18,7 +18,7 @@ uniform int uBlockedRngEnabled;
 
 //! Maximum radiance that can be added to the pixel. Decreases noise
 //! level, but introduces some bias.
-#define MAX_RADIANCE vec3 (25.f)
+#define MAX_RADIANCE vec3 (50.f)
 
 // =======================================================================
 // function : main
index f75b065..1bb6832 100644 (file)
@@ -1,6 +1,18 @@
 // This file has been automatically generated from resource file src/Shaders/PathtraceBase.fs
 
 static const char Shaders_PathtraceBase_fs[] =
+  "#ifdef _MSC_VER\n"
+  "  #define PATH_TRACING // just for editing in MS VS\n"
+  "\n"
+  "  #define in\n"
+  "  #define out\n"
+  "  #define inout\n"
+  "\n"
+  "  typedef struct { float x; float y; } vec2;\n"
+  "  typedef struct { float x; float y; float z; } vec3;\n"
+  "  typedef struct { float x; float y; float z; float w; } vec4;\n"
+  "#endif\n"
+  "\n"
   "#ifdef PATH_TRACING\n"
   "\n"
   "///////////////////////////////////////////////////////////////////////////////////////\n"
@@ -45,13 +57,13 @@ static const char Shaders_PathtraceBase_fs[] =
   "// Support subroutines\n"
   "\n"
   "//=======================================================================\n"
-  "// function : LocalSpace\n"
+  "// function : buildLocalSpace\n"
   "// purpose  : Generates local space for the given normal\n"
   "//=======================================================================\n"
-  "SLocalSpace LocalSpace (in vec3 theNormal)\n"
+  "SLocalSpace buildLocalSpace (in vec3 theNormal)\n"
   "{\n"
-  "  vec3 anAxisX = cross (vec3 (0.f, 1.f, 0.f), theNormal);\n"
-  "  vec3 anAxisY = cross (vec3 (1.f, 0.f, 0.f), theNormal);\n"
+  "  vec3 anAxisX = vec3 (theNormal.z, 0.f, -theNormal.x);\n"
+  "  vec3 anAxisY = vec3 (0.f, -theNormal.z, theNormal.y);\n"
   "\n"
   "  float aSqrLenX = dot (anAxisX, anAxisX);\n"
   "  float aSqrLenY = dot (anAxisY, anAxisY);\n"
@@ -102,19 +114,6 @@ static const char Shaders_PathtraceBase_fs[] =
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : sphericalDirection\n"
-  "// purpose  : Constructs vector from spherical coordinates\n"
-  "//=======================================================================\n"
-  "vec3 sphericalDirection (in float theCosTheta, in float thePhi)\n"
-  "{\n"
-  "  float aSinTheta = sqrt (1.f - theCosTheta * theCosTheta);\n"
-  "\n"
-  "  return vec3 (aSinTheta * cos (thePhi),\n"
-  "               aSinTheta * sin (thePhi),\n"
-  "               theCosTheta);\n"
-  "}\n"
-  "\n"
-  "//=======================================================================\n"
   "// function : fresnelSchlick\n"
   "// purpose  : Computes the Fresnel reflection formula using\n"
   "//            Schlick's approximation.\n"
@@ -199,24 +198,24 @@ static const char Shaders_PathtraceBase_fs[] =
   "// purpose  : Computes the Fresnel reflection formula for general medium\n"
   "//            in case of circularly polarized light.\n"
   "//=======================================================================\n"
-  "vec3 fresnelMedia (in float theCosI, in vec3 theFresnelCoeffs)\n"
+  "vec3 fresnelMedia (in float theCosI, in vec3 theFresnel)\n"
   "{\n"
-  "  if (theFresnelCoeffs.x > FRESNEL_SCHLICK)\n"
+  "  if (theFresnel.x > FRESNEL_SCHLICK)\n"
   "  {\n"
-  "    return fresnelSchlick (abs (theCosI), theFresnelCoeffs);\n"
+  "    return fresnelSchlick (abs (theCosI), theFresnel);\n"
   "  }\n"
   "\n"
-  "  if (theFresnelCoeffs.x > FRESNEL_CONSTANT)\n"
+  "  if (theFresnel.x > FRESNEL_CONSTANT)\n"
   "  {\n"
-  "    return vec3 (theFresnelCoeffs.z);\n"
+  "    return vec3 (theFresnel.z);\n"
   "  }\n"
   "\n"
-  "  if (theFresnelCoeffs.x > FRESNEL_CONDUCTOR)\n"
+  "  if (theFresnel.x > FRESNEL_CONDUCTOR)\n"
   "  {\n"
-  "    return vec3 (fresnelConductor (abs (theCosI), theFresnelCoeffs.y, theFresnelCoeffs.z));\n"
+  "    return vec3 (fresnelConductor (abs (theCosI), theFresnel.y, theFresnel.z));\n"
   "  }\n"
   "\n"
-  "  return vec3 (fresnelDielectric (theCosI, theFresnelCoeffs.y));\n"
+  "  return vec3 (fresnelDielectric (theCosI, theFresnel.y));\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
@@ -229,11 +228,11 @@ static const char Shaders_PathtraceBase_fs[] =
   "  // Compute relative index of refraction\n"
   "  float anEta = (theIncident.z > 0.f) ? 1.f / theIndex : theIndex;\n"
   "\n"
-  "  // Handle total internal reflection for transmission\n"
+  "  // Handle total internal reflection (TIR)\n"
   "  float aSinT2 = anEta * anEta * (1.f - theIncident.z * theIncident.z);\n"
   "\n"
-  "  // Compute transmitted ray direction\n"
-  "  float aCosT = sqrt (1.f - min (aSinT2, 1.f)) * (theIncident.z > 0.f ? -1.f : 1.f);\n"
+  "  // Compute direction of transmitted ray\n"
+  "  float aCosT = sqrt (1.f - min (aSinT2, 1.f)) * sign (-theIncident.z);\n"
   "\n"
   "  theTransmit = normalize (vec3 (-anEta * theIncident.x,\n"
   "                                 -anEta * theIncident.y,\n"
@@ -245,281 +244,315 @@ static const char Shaders_PathtraceBase_fs[] =
   "//////////////////////////////////////////////////////////////////////////////////////////////\n"
   "\n"
   "//=======================================================================\n"
-  "// function : handleLambertianReflection\n"
+  "// function : HandleLambertianReflection\n"
   "// purpose  : Handles Lambertian BRDF, with cos(N, PSI)\n"
   "//=======================================================================\n"
-  "float handleLambertianReflection (in vec3 theInput, in vec3 theOutput)\n"
+  "float HandleLambertianReflection (in vec3 theInput, in vec3 theOutput)\n"
   "{\n"
-  "  return max (0.f, theInput.z) * (1.f / M_PI);\n"
+  "  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? 0.f : theInput.z * (1.f / M_PI);\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : handleBlinnReflection\n"
-  "// purpose  : Handles Blinn glossy BRDF, with cos(N, PSI)\n"
+  "// function : SmithG1\n"
+  "// purpose  :\n"
   "//=======================================================================\n"
-  "vec3 handleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnelCoeffs, in float theExponent)\n"
+  "float SmithG1 (in vec3 theDirection, in vec3 theM, in float theRoughness)\n"
   "{\n"
-  "  vec3 aWeight = ZERO;\n"
-  "\n"
-  "  // Compute half-angle vector\n"
-  "  vec3 aHalf = theInput + theOutput;\n"
+  "  if (dot (theDirection, theM) * theDirection.z <= 0.f)\n"
+  "  {\n"
+  "    return 0.f;\n"
+  "  }\n"
   "\n"
-  "  if (aHalf.z < 0.f)\n"
-  "    aHalf = -aHalf;\n"
+  "  float aTanThetaM = sqrt (1.f - theDirection.z * theDirection.z) / theDirection.z;\n"
   "\n"
-  "  float aLength = dot (aHalf, aHalf);\n"
+  "  if (aTanThetaM == 0.0f)\n"
+  "  {\n"
+  "    return 1.f;\n"
+  "  }\n"
   "\n"
-  "  if (aLength <= 0.f)\n"
-  "    return ZERO;\n"
+  "  float aVal = 1.f / (theRoughness * aTanThetaM);\n"
   "\n"
-  "  aHalf *= inversesqrt (aLength);\n"
+  "  if (aVal >= 1.6f)\n"
+  "  {\n"
+  "    return 1.f;\n"
+  "  }\n"
   "\n"
-  "  // Compute Fresnel reflectance\n"
-  "  float aCosDelta = dot (theOutput, aHalf);\n"
+  "  // Use fast and accurate rational approximation to the\n"
+  "  // shadowing-masking function (from Mitsuba renderer)\n"
+  "  float aSqr = aVal * aVal;\n"
   "\n"
-  "  vec3 aFresnel = fresnelMedia (aCosDelta, theFresnelCoeffs);\n"
+  "  return (3.535f * aVal + 2.181f * aSqr) / (1.f + 2.276f * aVal + 2.577f * aSqr);\n"
+  "}\n"
   "\n"
-  "  // Compute fraction of microfacets that reflect light\n"
-  "  float aCosThetaH = max (0.f, aHalf.z);\n"
+  "//=======================================================================\n"
+  "// function : HandleBlinnReflection\n"
+  "// purpose  : Handles Blinn glossy BRDF, with cos(N, PSI)\n"
+  "//=======================================================================\n"
+  "vec3 HandleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnel, in float theRoughness)\n"
+  "{\n"
+  "  // calculate the reflection half-vec\n"
+  "  vec3 aH = normalize (theInput + theOutput);\n"
   "\n"
-  "  float aFraction = (theExponent + 2.f) * (M_PI / 2.f) * pow (aCosThetaH, theExponent);\n"
+  "  // roughness value -> Blinn exponent\n"
+  "  float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\n"
   "\n"
-  "  // Compute geometry attenuation term (already includes cos)\n"
-  "  float aCosThetaI = max (0.f, theInput.z);\n"
-  "  float aCosThetaO = max (0.f, theOutput.z);\n"
+  "  // calculate microfacet distribution\n"
+  "  float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);\n"
   "\n"
-  "  float aGeom = min (1.f, 2.f * aCosThetaH / max (0.f, aCosDelta) * min (aCosThetaO, aCosThetaI));\n"
+  "  // calculate shadow-masking function\n"
+  "  float aG = SmithG1 (theOutput, aH, theRoughness) * SmithG1 (theInput, aH, theRoughness);\n"
   "\n"
-  "  return aCosThetaO < 1.0e-3f ? ZERO :\n"
-  "    aFraction * aGeom / (4.f * aCosThetaO) * aFresnel;\n"
+  "  // return total amount of reflection\n"
+  "  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :\n"
+  "    aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : handleMaterial\n"
+  "// function : HandleMaterial\n"
   "// purpose  : Returns BSDF value for specified material, with cos(N, PSI)\n"
   "//=======================================================================\n"
-  "vec3 handleMaterial (in SMaterial theMaterial, in vec3 theInput, in vec3 theOutput)\n"
+  "vec3 HandleMaterial (in SMaterial theBSDF, in vec3 theInput, in vec3 theOutput)\n"
   "{\n"
-  "  return theMaterial.Kd.rgb * handleLambertianReflection (theInput, theOutput) +\n"
-  "    theMaterial.Ks.rgb * handleBlinnReflection (theInput, theOutput, theMaterial.Fresnel, theMaterial.Ks.w);\n"
+  "  return theBSDF.Kd.rgb * HandleLambertianReflection (theInput, theOutput) +\n"
+  "    theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : sampleLambertianReflection\n"
+  "// function : SampleLambertianReflection\n"
   "// purpose  : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
   "//=======================================================================\n"
-  "void sampleLambertianReflection (in vec3 theOutput, out vec3 theInput)\n"
+  "vec3 SampleLambertianReflection (in vec3 theOutput, out vec3 theInput, inout float thePDF)\n"
   "{\n"
   "  float aKsi1 = RandFloat();\n"
   "  float aKsi2 = RandFloat();\n"
   "\n"
   "  float aTemp = sqrt (aKsi2);\n"
   "\n"
-  "  theInput = vec3 (aTemp * cos (2.f * M_PI * aKsi1),\n"
-  "                   aTemp * sin (2.f * M_PI * aKsi1),\n"
+  "  theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),\n"
+  "                   aTemp * sin (M_2_PI * aKsi1),\n"
   "                   sqrt (1.f - aKsi2));\n"
   "\n"
-  "  theInput.z = mix (-theInput.z, theInput.z, step (0.f, theOutput.z));\n"
-  "}\n"
-  "\n"
-  "// Types of bounces\n"
-  "#define NON_SPECULAR_BOUNCE 0\n"
-  "#define SPEC_REFLECT_BOUNCE 1\n"
-  "#define SPEC_REFRACT_BOUNCE 2\n"
+  "  thePDF *= abs (theInput.z) * (1.f / M_PI);\n"
   "\n"
-  "#define IS_NON_SPEC_BOUNCE(theBounce) (theBounce == 0)\n"
-  "#define IS_ANY_SPEC_BOUNCE(theBounce) (theBounce != 0)\n"
-  "#define IS_REFL_SPEC_BOUNCE(theBounce) (theBounce == 1)\n"
-  "#define IS_REFR_SPEC_BOUNCE(theBounce) (theBounce == 2)\n"
+  "  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;\n"
+  "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : sampleSpecularTransmission\n"
-  "// purpose  : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
+  "// function : SampleBlinnReflection\n"
+  "// purpose  : Samples Blinn BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
+  "//            The BRDF is a product of three main terms, D, G, and F,\n"
+  "//            which is then divided by two cosine terms. Here we perform\n"
+  "//            importance sample the D part of the Blinn model; trying to\n"
+  "//            develop a sampling procedure that accounted for all of the\n"
+  "//            terms would be complex, and it is the D term that accounts\n"
+  "//            for most of the variation.\n"
   "//=======================================================================\n"
-  "vec3 sampleSpecularTransmission (in vec3 theOutput, out vec3 theInput,\n"
-  "  out int theBounce, in vec3 theWeight, in vec3 theFresnelCoeffs)\n"
+  "vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel, in float theRoughness, inout float thePDF)\n"
   "{\n"
-  "  vec3 aFresnel = fresnelMedia (theOutput.z, theFresnelCoeffs);\n"
+  "  float aKsi1 = RandFloat();\n"
+  "  float aKsi2 = RandFloat();\n"
   "\n"
-  "  float aProbability = convolve (aFresnel, theWeight);\n"
+  "  // roughness value --> Blinn exponent\n"
+  "  float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\n"
   "\n"
-  "  // Check if transmission takes place\n"
-  "  theBounce = RandFloat() <= aProbability ?\n"
-  "    SPEC_REFLECT_BOUNCE : SPEC_REFRACT_BOUNCE;\n"
+  "  // normal from microface distribution\n"
+  "  float aCosThetaM = pow (aKsi1, 1.f / (aPower + 2.f));\n"
   "\n"
-  "  // Sample input direction\n"
-  "  if (theBounce == SPEC_REFLECT_BOUNCE)\n"
-  "  {\n"
-  "    theInput = vec3 (-theOutput.x,\n"
-  "                     -theOutput.y,\n"
-  "                      theOutput.z);\n"
+  "  vec3 aM = vec3 (cos (M_2_PI * aKsi2),\n"
+  "                  sin (M_2_PI * aKsi2),\n"
+  "                  aCosThetaM);\n"
   "\n"
-  "    theWeight = aFresnel * (1.f / aProbability);\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    transmitted (theFresnelCoeffs.y, theOutput, theInput);\n"
+  "  aM.xy *= sqrt (1.f - aCosThetaM * aCosThetaM);\n"
   "\n"
-  "    theWeight = (UNIT - aFresnel) * (1.f / (1.f - aProbability));\n"
+  "  // calculate PDF of sampled direction\n"
+  "  thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);\n"
+  "\n"
+  "  float aCosDelta = dot (theOutput, aM);\n"
+  "\n"
+  "  // pick input based on half direction\n"
+  "  theInput = -theOutput + 2.f * aCosDelta * aM;\n"
+  "\n"
+  "  if (theInput.z <= 0.f || theOutput.z <= 0.f)\n"
+  "  {\n"
+  "    return ZERO;\n"
   "  }\n"
   "\n"
-  "  return theWeight;\n"
+  "  // Jacobian of half-direction mapping\n"
+  "  thePDF /= 4.f * dot (theInput, aM);\n"
+  "\n"
+  "  // compute shadow-masking coefficient\n"
+  "  float aG = SmithG1 (theOutput, aM, theRoughness) * SmithG1 (theInput, aM, theRoughness);\n"
+  "\n"
+  "  return aG * aCosDelta / (theOutput.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : sampleSpecularReflection\n"
+  "// function : SampleSpecularReflection\n"
   "// purpose  : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
   "//=======================================================================\n"
-  "vec3 sampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnelCoeffs)\n"
+  "vec3 SampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel)\n"
   "{\n"
   "  // Sample input direction\n"
   "  theInput = vec3 (-theOutput.x,\n"
   "                   -theOutput.y,\n"
   "                    theOutput.z);\n"
   "\n"
-  "  return fresnelMedia (theOutput.z, theFresnelCoeffs);\n"
+  "  return fresnelMedia (theOutput.z, theFresnel);\n"
   "}\n"
   "\n"
-  "#define MIN_COS 1.0e-20f\n"
-  "\n"
   "//=======================================================================\n"
-  "// function : sampleBlinnReflection\n"
-  "// purpose  : Samples Blinn BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
-  "//            The BRDF is a product of three main terms, D, G, and F,\n"
-  "//            which is then divided by two cosine terms. Here we perform\n"
-  "//            importance sample the D part of the Blinn model; trying to\n"
-  "//            develop a sampling procedure that accounted for all of the\n"
-  "//            terms would be complex, and it is the D term that accounts\n"
-  "//            for most of the variation.\n"
+  "// function : SampleSpecularTransmission\n"
+  "// purpose  : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
   "//=======================================================================\n"
-  "vec3 sampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnelCoeffs, in float theExponent)\n"
+  "vec3 SampleSpecularTransmission (in vec3 theOutput,\n"
+  "  out vec3 theInput, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)\n"
   "{\n"
-  "  vec3 aWeight = ZERO;\n"
-  "\n"
-  "  // Generate two random variables\n"
-  "  float aKsi1 = RandFloat();\n"
-  "  float aKsi2 = RandFloat();\n"
+  "  vec3 aFactor = fresnelMedia (theOutput.z, theFresnel);\n"
   "\n"
-  "  // Compute sampled half-angle vector for Blinn distribution\n"
-  "  float aCosThetaH = pow (aKsi1, 1.f / (theExponent + 1.f));\n"
+  "  float aReflection = convolve (aFactor, theWeight);\n"
   "\n"
-  "  vec3 aHalf = sphericalDirection (aCosThetaH, aKsi2 * 2.f * M_PI);\n"
+  "  // sample specular BRDF/BTDF\n"
+  "  if (RandFloat() <= aReflection)\n"
+  "  {\n"
+  "    theInput = vec3 (-theOutput.x,\n"
+  "                     -theOutput.y,\n"
+  "                      theOutput.z);\n"
   "\n"
-  "  if (aHalf.z < 0)\n"
+  "    theWeight = aFactor * (1.f / aReflection);\n"
+  "  }\n"
+  "  else\n"
   "  {\n"
-  "    aHalf = -aHalf;\n"
+  "    theInside = !theInside;\n"
+  "\n"
+  "    transmitted (theFresnel.y, theOutput, theInput);\n"
+  "\n"
+  "    theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));\n"
   "  }\n"
   "\n"
-  "  // Compute incident direction by reflecting about half-vector\n"
-  "  float aCosDelta = dot (theOutput, aHalf);\n"
+  "  return theWeight;\n"
+  "}\n"
   "\n"
-  "  vec3 anInput = 2.f * aCosDelta * aHalf - theOutput;\n"
+  "#define FLT_EPSILON 1.0e-5F\n"
   "\n"
-  "  if (theOutput.z * anInput.z <= 0.f)\n"
-  "  {\n"
-  "    return ZERO;\n"
-  "  }\n"
+  "//=======================================================================\n"
+  "// function : BsdfPdf\n"
+  "// purpose  : Calculates BSDF of sampling input knowing output\n"
+  "//=======================================================================\n"
+  "float BsdfPdf (in SMaterial theBSDF,\n"
+  "               in vec3      theOutput,\n"
+  "               in vec3      theInput,\n"
+  "               in vec3      theWeight)\n"
+  "{\n"
+  "  float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
+  "  float aPs = convolve (theBSDF.Ks.rgb, theWeight);\n"
+  "  float aPr = convolve (theBSDF.Kr.rgb, theWeight);\n"
+  "  float aPt = convolve (theBSDF.Kt.rgb, theWeight);\n"
+  "\n"
+  "  float aReflection = aPd + aPs + aPr + aPt;\n"
   "\n"
-  "  theInput = anInput;\n"
+  "  float aPDF = 0.f; // PDF of sampling input direction\n"
   "\n"
-  "  // Compute Fresnel reflectance\n"
-  "  vec3 aFresnel = fresnelMedia (aCosDelta, theFresnelCoeffs);\n"
+  "  if (theInput.z * theOutput.z > 0.f)\n"
+  "  {\n"
+  "    vec3 aHalf = normalize (theInput + theOutput);\n"
   "\n"
-  "  // Compute geometry attenuation term\n"
-  "  float aCosThetaI = max (MIN_COS, theInput.z);\n"
-  "  float aCosThetaO = max (MIN_COS, theOutput.z);\n"
+  "    // roughness value --> Blinn exponent\n"
+  "    float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);\n"
   "\n"
-  "  float aGeom = min (max (MIN_COS, aCosDelta), 2.f * aCosThetaH * min (aCosThetaO, aCosThetaI));\n"
+  "    aPDF = aPd * abs (theInput.z / M_PI) +\n"
+  "      aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (aHalf.z, aPower + 1.f) / (4.f * dot (theInput, aHalf));\n"
+  "  }\n"
   "\n"
-  "  // Compute weight of the ray sample\n"
-  "  return aFresnel * ((theExponent + 2.f) / (theExponent + 1.f) * aGeom / aCosThetaO);\n"
+  "  return aPDF / aReflection;\n"
   "}\n"
   "\n"
+  "//! Tool macro to handle sampling of particular BxDF\n"
+  "#define PICK_BXDF(p, k) aPDF = p / aReflection; theWeight *= k / aPDF;\n"
+  "\n"
   "//=======================================================================\n"
-  "// function : sampleMaterial\n"
+  "// function : SampleBsdf\n"
   "// purpose  : Samples specified composite material (BSDF)\n"
   "//=======================================================================\n"
-  "void sampleMaterial (in SMaterial theMaterial,\n"
-  "                     in vec3      theOutput,\n"
-  "                     out vec3     theInput,\n"
-  "                     inout vec3   theWeight,\n"
-  "                     inout int    theBounce)\n"
+  "float SampleBsdf (in SMaterial theBSDF,\n"
+  "                  in vec3      theOutput,\n"
+  "                  out vec3     theInput,\n"
+  "                  inout vec3   theWeight,\n"
+  "                  inout bool   theInside)\n"
   "{\n"
-  "  // Compute the probability of ray reflection\n"
-  "  float aPd = convolve (theMaterial.Kd.rgb, theWeight);\n"
-  "  float aPs = convolve (theMaterial.Ks.rgb, theWeight);\n"
-  "  float aPr = convolve (theMaterial.Kr.rgb, theWeight);\n"
-  "  float aPt = convolve (theMaterial.Kt.rgb, theWeight);\n"
+  "  // compute probability of each reflection type (BxDF)\n"
+  "  float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
+  "  float aPs = convolve (theBSDF.Ks.rgb, theWeight);\n"
+  "  float aPr = convolve (theBSDF.Kr.rgb, theWeight);\n"
+  "  float aPt = convolve (theBSDF.Kt.rgb, theWeight);\n"
   "\n"
   "  float aReflection = aPd + aPs + aPr + aPt;\n"
   "\n"
-  "  // Choose BSDF component to sample\n"
+  "  // choose BxDF component to sample\n"
   "  float aKsi = aReflection * RandFloat();\n"
   "\n"
-  "  theBounce = NON_SPECULAR_BOUNCE;\n"
+  "  // BxDF's PDF of sampled direction\n"
+  "  float aPDF = 0.f;\n"
   "\n"
   "  if (aKsi < aPd) // diffuse reflection\n"
   "  {\n"
-  "    sampleLambertianReflection (theOutput, theInput);\n"
+  "    PICK_BXDF (aPd, theBSDF.Kd.rgb);\n"
   "\n"
-  "    theWeight *= theMaterial.Kd.rgb * (aReflection / aPd);\n"
+  "    theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);\n"
   "  }\n"
-  "  else if (aKsi < aPd + aPs) //  glossy reflection\n"
+  "  else if (aKsi < aPd + aPs) // glossy reflection\n"
   "  {\n"
-  "    theWeight *= theMaterial.Ks.rgb * (aReflection / aPs) *\n"
-  "      sampleBlinnReflection (theOutput, theInput, theMaterial.Fresnel, theMaterial.Ks.w);\n"
+  "    PICK_BXDF (aPs, theBSDF.Ks.rgb);\n"
+  "\n"
+  "    theWeight *= SampleBlinnReflection (theOutput, theInput, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);\n"
   "  }\n"
-  "  else if (aKsi < aPd + aPs + aPr) //  specular reflection\n"
+  "  else if (aKsi < aPd + aPs + aPr) // specular reflection\n"
   "  {\n"
-  "    theWeight *= theMaterial.Kr.rgb * (aReflection / aPr) *\n"
-  "      sampleSpecularReflection (theOutput, theInput, theMaterial.Fresnel);\n"
+  "    PICK_BXDF (aPr, theBSDF.Kr.rgb);\n"
+  "\n"
+  "    aPDF = MAXFLOAT;\n"
   "\n"
-  "    theBounce = SPEC_REFLECT_BOUNCE; // specular bounce\n"
+  "    theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);\n"
   "  }\n"
-  "  else //  specular transmission\n"
+  "  else if (aKsi < aReflection) // specular transmission\n"
   "  {\n"
-  "    theWeight *= theMaterial.Kt.rgb * (aReflection / aPt) *\n"
-  "      sampleSpecularTransmission (theOutput, theInput, theBounce, theWeight, theMaterial.Fresnel);\n"
+  "    PICK_BXDF (aPt, theBSDF.Kt.rgb);\n"
+  "\n"
+  "    aPDF = MAXFLOAT;\n"
+  "\n"
+  "    theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);\n"
   "  }\n"
   "\n"
   "  // path termination for extra small weights\n"
-  "  theWeight = mix (theWeight, ZERO, float (aReflection < 1e-3f));\n"
+  "  theWeight = mix (ZERO, theWeight, step (FLT_EPSILON, aReflection));\n"
+  "\n"
+  "  return aPDF;\n"
   "}\n"
   "\n"
   "//////////////////////////////////////////////////////////////////////////////////////////////\n"
   "// Handlers and samplers for light sources\n"
   "//////////////////////////////////////////////////////////////////////////////////////////////\n"
   "\n"
-  "//=======================================================================\n"
-  "// function : handlePointLight\n"
-  "// purpose  :\n"
-  "//=======================================================================\n"
-  "float handlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance)\n"
+  "// =======================================================================\n"
+  "// function : Latlong\n"
+  "// purpose  : Converts world direction to environment texture coordinates\n"
+  "// =======================================================================\n"
+  "vec2 Latlong (in vec3 thePoint)\n"
   "{\n"
-  "  float aDistance = dot (theToLight, theToLight);\n"
-  "\n"
-  "  float aCosMax = inversesqrt (1.f + theRadius * theRadius / aDistance);\n"
+  "  float aPsi = acos (-thePoint.z);\n"
   "\n"
-  "  return float (aDistance < theDistance * theDistance) *\n"
-  "    step (aCosMax, dot (theToLight, theInput) * inversesqrt (aDistance));\n"
-  "}\n"
+  "  float aPhi = atan (thePoint.y, thePoint.x) + M_PI;\n"
   "\n"
-  "//=======================================================================\n"
-  "// function : handleDirectLight\n"
-  "// purpose  :\n"
-  "//=======================================================================\n"
-  "float handleDirectLight (in vec3 theInput, in vec3 theToLight, in float theCosMax)\n"
-  "{\n"
-  "  return step (theCosMax, dot (theInput, theToLight));\n"
+  "  return vec2 (aPhi * 0.1591549f,\n"
+  "               aPsi * 0.3183098f);\n"
   "}\n"
   "\n"
   "//=======================================================================\n"
-  "// function : sampleLight\n"
+  "// function : SampleLight\n"
   "// purpose  : General sampling function for directional and point lights\n"
   "//=======================================================================\n"
-  "vec3 sampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinite, in float theSmoothness, inout float thePDF)\n"
+  "vec3 SampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinite, in float theSmoothness, inout float thePDF)\n"
   "{\n"
-  "  SLocalSpace aSpace = LocalSpace (theToLight * (1.f / theDistance));\n"
+  "  SLocalSpace aSpace = buildLocalSpace (theToLight * (1.f / theDistance));\n"
   "\n"
   "  // for point lights smoothness defines radius\n"
   "  float aCosMax = isInfinite ? theSmoothness :\n"
@@ -530,74 +563,111 @@ static const char Shaders_PathtraceBase_fs[] =
   "\n"
   "  float aTmp = 1.f - aKsi2 * (1.f - aCosMax);\n"
   "\n"
-  "  vec3 anInput = vec3 (cos (2.f * M_PI * aKsi1),\n"
-  "                       sin (2.f * M_PI * aKsi1),\n"
+  "  vec3 anInput = vec3 (cos (M_2_PI * aKsi1),\n"
+  "                       sin (M_2_PI * aKsi1),\n"
   "                       aTmp);\n"
   "\n"
   "  anInput.xy *= sqrt (1.f - aTmp * aTmp);\n"
   "\n"
-  "  thePDF *= (aCosMax < 1.f) ? 1.f / (2.f * M_PI) / (1.f - aCosMax) : 1.f;\n"
+  "  thePDF = (aCosMax < 1.f) ? (thePDF / M_2_PI) / (1.f - aCosMax) : MAXFLOAT;\n"
   "\n"
   "  return normalize (fromLocalSpace (anInput, aSpace));\n"
   "}\n"
   "\n"
-  "// =======================================================================\n"
-  "// function : Latlong\n"
-  "// purpose  : Converts world direction to environment texture coordinates\n"
-  "// =======================================================================\n"
-  "vec2 Latlong (in vec3 thePoint)\n"
+  "//=======================================================================\n"
+  "// function : HandlePointLight\n"
+  "// purpose  :\n"
+  "//=======================================================================\n"
+  "float HandlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance, inout float thePDF)\n"
   "{\n"
-  "  float aPsi = acos (-thePoint.z);\n"
+  "  float aCosMax = inversesqrt (1.f + theRadius * theRadius / (theDistance * theDistance));\n"
   "\n"
-  "  float aPhi = atan (thePoint.y, thePoint.x) + M_PI;\n"
+  "  float aVisibility = step (aCosMax, dot (theInput, theToLight));\n"
   "\n"
-  "  return vec2 (aPhi * 0.1591549f,\n"
-  "               aPsi * 0.3183098f);\n"
+  "  thePDF *= step (-1.f, -aCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - aCosMax);\n"
+  "\n"
+  "  return aVisibility;\n"
+  "}\n"
+  "\n"
+  "//=======================================================================\n"
+  "// function : HandleDistantLight\n"
+  "// purpose  :\n"
+  "//=======================================================================\n"
+  "float HandleDistantLight (in vec3 theInput, in vec3 theToLight, in float theCosMax, inout float thePDF)\n"
+  "{\n"
+  "  float aVisibility = step (theCosMax, dot (theInput, theToLight));\n"
+  "\n"
+  "  thePDF *= step (-1.f, -theCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - theCosMax);\n"
+  "\n"
+  "  return aVisibility;\n"
   "}\n"
   "\n"
   "// =======================================================================\n"
-  "// function: intersectLight\n"
+  "// function: IntersectLight\n"
   "// purpose : Checks intersections with light sources\n"
   "// =======================================================================\n"
-  "vec3 intersectLight (in SRay theRay, in bool isViewRay, in int theBounce, in float theDistance)\n"
+  "vec3 IntersectLight (in SRay theRay, in int theDepth, in float theHitDistance, out float thePDF)\n"
   "{\n"
-  "  vec3 aRadiance = ZERO;\n"
+  "  vec3 aTotalRadiance = ZERO;\n"
   "\n"
-  "  if ((isViewRay || IS_REFR_SPEC_BOUNCE(theBounce)) && uSphereMapForBack == 0)\n"
-  "  {\n"
-  "    aRadiance = BackgroundColor().xyz;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    aRadiance = FetchEnvironment (Latlong (theRay.Direct)).xyz;\n"
-  "  }\n"
+  "  thePDF = 0.f; // PDF of sampling light sources\n"
   "\n"
-  "  // Apply gamma correction (gamma is 2)\n"
-  "  aRadiance = aRadiance * aRadiance * float (theDistance == MAXFLOAT);\n"
-  "\n"
-  "  for (int aLightIdx = 0; aLightIdx < uLightCount && (isViewRay || IS_ANY_SPEC_BOUNCE(theBounce)); ++aLightIdx)\n"
+  "  for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)\n"
   "  {\n"
   "    vec4 aLight = texelFetch (\n"
   "      uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));\n"
   "    vec4 aParam = texelFetch (\n"
   "      uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx));\n"
   "\n"
+  "    // W component: 0 for infinite light and 1 for point light\n"
+  "    aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);\n"
+  "\n"
+  "    float aPDF = 1.f / uLightCount;\n"
+  "\n"
   "    if (aLight.w != 0.f) // point light source\n"
   "    {\n"
-  "      aRadiance += aParam.rgb * handlePointLight (\n"
-  "        theRay.Direct, aLight.xyz - theRay.Origin, aParam.w /* radius */, theDistance);\n"
+  "      float aCenterDst = length (aLight.xyz);\n"
+  "\n"
+  "      if (aCenterDst < theHitDistance)\n"
+  "      {\n"
+  "        float aVisibility = HandlePointLight (\n"
+  "          theRay.Direct, normalize (aLight.xyz), aParam.w /* radius */, aCenterDst, aPDF);\n"
+  "\n"
+  "        if (aVisibility > 0.f)\n"
+  "        {\n"
+  "          theHitDistance = aCenterDst;\n"
+  "          aTotalRadiance = aParam.rgb;\n"
+  "\n"
+  "          thePDF = aPDF;\n"
+  "        }\n"
+  "      }\n"
   "    }\n"
-  "    else if (theDistance == MAXFLOAT) // directional light source\n"
+  "    else if (theHitDistance == MAXFLOAT) // directional light source\n"
   "    {\n"
-  "      aRadiance += aParam.rgb * handleDirectLight (theRay.Direct, aLight.xyz, aParam.w /* angle cosine */);\n"
+  "      aTotalRadiance += aParam.rgb * HandleDistantLight (\n"
+  "        theRay.Direct, aLight.xyz, aParam.w /* angle cosine */, aPDF);\n"
+  "\n"
+  "      thePDF += aPDF;\n"
   "    }\n"
   "  }\n"
   "\n"
-  "  return aRadiance;\n"
+  "  if (thePDF == 0.f && theHitDistance == MAXFLOAT) // light source not found\n"
+  "  {\n"
+  "    if (theDepth + uSphereMapForBack == 0) // view ray and map is hidden\n"
+  "    {\n"
+  "      aTotalRadiance = pow (BackgroundColor().rgb, vec3 (2.f));\n"
+  "    }\n"
+  "    else\n"
+  "    {\n"
+  "      aTotalRadiance = pow (FetchEnvironment (Latlong (theRay.Direct)).rgb, vec3 (2.f));\n"
+  "    }\n"
+  "  }\n"
+  "  \n"
+  "  return aTotalRadiance;\n"
   "}\n"
   "\n"
-  "#define MIN_THROUGHPUT   vec3 (0.02f)\n"
-  "#define MIN_CONTRIBUTION vec3 (0.01f)\n"
+  "#define MIN_THROUGHPUT   vec3 (1.0e-3f)\n"
+  "#define MIN_CONTRIBUTION vec3 (1.0e-2f)\n"
   "\n"
   "#define MATERIAL_KD(index)      (18 * index + 11)\n"
   "#define MATERIAL_KR(index)      (18 * index + 12)\n"
@@ -621,29 +691,32 @@ static const char Shaders_PathtraceBase_fs[] =
   "  vec3 aRadiance   = ZERO;\n"
   "  vec3 aThroughput = UNIT;\n"
   "\n"
-  "  int aBounce = 0; // type of previous hit point\n"
-  "  int aTrsfId = 0; // offset of object transform\n"
+  "  int  aTransfID = 0;     // ID of object transformation\n"
+  "  bool aInMedium = false; // is the ray inside an object\n"
   "\n"
-  "  bool isInMedium = false;\n"
+  "  float aExpPDF = 1.f;\n"
+  "  float aImpPDF = 1.f;\n"
   "\n"
   "  for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)\n"
   "  {\n"
   "    SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);\n"
   "\n"
-  "    ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTrsfId);\n"
+  "    ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTransfID);\n"
   "\n"
   "    // check implicit path\n"
-  "    vec3 aLe = intersectLight (theRay,\n"
-  "      aDepth == 0 /* is view ray */, aBounce, aHit.Time);\n"
+  "    vec3 aLe = IntersectLight (theRay, aDepth, aHit.Time, aExpPDF);\n"
   "\n"
   "    if (any (greaterThan (aLe, ZERO)) || aTriIndex.x == -1)\n"
   "    {\n"
-  "      aRadiance += aThroughput * aLe; break; // terminate path\n"
+  "      float aMIS = (aDepth == 0 || aImpPDF == MAXFLOAT) ? 1.f :\n"
+  "        aImpPDF * aImpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
+  "\n"
+  "      aRadiance += aThroughput * aLe * aMIS; break; // terminate path\n"
   "    }\n"
   "\n"
-  "    vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0).xyz;\n"
-  "    vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1).xyz;\n"
-  "    vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2).xyz;\n"
+  "    vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTransfID + 0).xyz;\n"
+  "    vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTransfID + 1).xyz;\n"
+  "    vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTransfID + 2).xyz;\n"
   "\n"
   "    // compute geometrical normal\n"
   "    aHit.Normal = normalize (vec3 (dot (aInvTransf0, aHit.Normal),\n"
@@ -652,7 +725,7 @@ static const char Shaders_PathtraceBase_fs[] =
   "\n"
   "    theRay.Origin += theRay.Direct * aHit.Time; // get new intersection point\n"
   "\n"
-  "    // Evaluate depth on first hit\n"
+  "    // evaluate depth on first hit\n"
   "    if (aDepth == 0)\n"
   "    {\n"
   "      vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n"
@@ -697,7 +770,7 @@ static const char Shaders_PathtraceBase_fs[] =
   "                               dot (aInvTransf1, aNormal),\n"
   "                               dot (aInvTransf2, aNormal)));\n"
   "\n"
-  "    SLocalSpace aSpace = LocalSpace (aNormal);\n"
+  "    SLocalSpace aSpace = buildLocalSpace (aNormal);\n"
   "\n"
   "    // account for self-emission (not stored in the material)\n"
   "    aRadiance += aThroughput * texelFetch (\n"
@@ -705,6 +778,8 @@ static const char Shaders_PathtraceBase_fs[] =
   "\n"
   "    if (uLightCount > 0 && convolve (aMaterial.Kd.rgb + aMaterial.Ks.rgb, aThroughput) > 0.f)\n"
   "    {\n"
+  "      aExpPDF = 1.f / uLightCount;\n"
+  "\n"
   "      int aLightIdx = min (int (floor (RandFloat() * uLightCount)), uLightCount - 1);\n"
   "\n"
   "      vec4 aLight = texelFetch (\n"
@@ -715,15 +790,21 @@ static const char Shaders_PathtraceBase_fs[] =
   "      // 'w' component is 0 for infinite light and 1 for point light\n"
   "      aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);\n"
   "\n"
-  "      float aPDF = 1.f / uLightCount, aDistance = length (aLight.xyz);\n"
+  "      float aDistance = length (aLight.xyz);\n"
   "\n"
-  "      aLight.xyz = sampleLight (aLight.xyz, aDistance,\n"
-  "        aLight.w == 0.f /* is infinite */, aParam.w /* max cos or radius */, aPDF);\n"
+  "      aLight.xyz = SampleLight (aLight.xyz, aDistance,\n"
+  "        aLight.w == 0.f /* is infinite */, aParam.w /* max cos or radius */, aExpPDF);\n"
   "\n"
-  "      vec3 aContrib = (1.f / aPDF) * aParam.rgb /* Le */ * handleMaterial (\n"
+  "      aImpPDF = BsdfPdf (aMaterial,\n"
+  "        toLocalSpace (-theRay.Direct, aSpace), toLocalSpace (aLight.xyz, aSpace), aThroughput);\n"
+  "\n"
+  "      // MIS weight including division by explicit PDF\n"
+  "      float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
+  "\n"
+  "      vec3 aContrib = aMIS * aParam.rgb /* Le */ * HandleMaterial (\n"
   "          aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));\n"
   "\n"
-  "      if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // first check if light source is important\n"
+  "      if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important\n"
   "      {\n"
   "        SRay aShadow = SRay (theRay.Origin + aLight.xyz * uSceneEpsilon, aLight.xyz);\n"
   "\n"
@@ -737,32 +818,29 @@ static const char Shaders_PathtraceBase_fs[] =
   "      }\n"
   "    }\n"
   "\n"
-  "    vec3 anInput;\n"
-  "\n"
-  "    sampleMaterial (aMaterial,\n"
-  "      toLocalSpace (-theRay.Direct, aSpace), anInput, aThroughput, aBounce);\n"
-  "\n"
-  "    if (isInMedium)\n"
+  "    if (aInMedium) // handle attenuation\n"
   "    {\n"
   "      aThroughput *= exp (-aHit.Time *\n"
   "        aMaterial.Absorption.w * (UNIT - aMaterial.Absorption.rgb));\n"
   "    }\n"
   "\n"
-  "    isInMedium = IS_REFR_SPEC_BOUNCE(aBounce) ? !isInMedium : isInMedium;\n"
+  "    vec3 anInput = UNIT; // sampled input direction\n"
   "\n"
-  "#ifndef RUSSIAN_ROULETTE\n"
-  "    if (all (lessThan (aThroughput, MIN_THROUGHPUT)))\n"
-  "    {\n"
-  "      aDepth = INVALID_BOUNCES; // terminate path\n"
-  "    }\n"
-  "#else\n"
-  "    float aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);\n"
+  "    aImpPDF = SampleBsdf (aMaterial,\n"
+  "      toLocalSpace (-theRay.Direct, aSpace), anInput, aThroughput, aInMedium);\n"
+  "\n"
+  "    float aSurvive = 1.f;\n"
+  "\n"
+  "#ifdef RUSSIAN_ROULETTE\n"
+  "    aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);\n"
+  "#endif\n"
   "\n"
-  "    if (RandFloat() > aSurvive)\n"
+  "    if (RandFloat() > aSurvive || all (lessThanEqual (aThroughput, MIN_THROUGHPUT)))\n"
   "    {\n"
   "      aDepth = INVALID_BOUNCES; // terminate path\n"
   "    }\n"
   "\n"
+  "#ifdef RUSSIAN_ROULETTE\n"
   "    aThroughput /= aSurvive;\n"
   "#endif\n"
   "\n"
index a1578f7..63c7309 100644 (file)
@@ -146,7 +146,9 @@ static const char Shaders_RaytraceBase_fs[] =
   "#define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)\n"
   "#define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)\n"
   "\n"
-  "#define M_PI 3.14159265f\n"
+  "#define M_PI   3.141592653f\n"
+  "#define M_2_PI 6.283185307f\n"
+  "#define M_PI_2 1.570796327f\n"
   "\n"
   "#define LUMA vec3 (0.2126f, 0.7152f, 0.0722f)\n"
   "\n"
@@ -838,8 +840,8 @@ static const char Shaders_RaytraceBase_fs[] =
   "// =======================================================================\n"
   "vec4 FetchEnvironment (in vec2 theTexCoord)\n"
   "{\n"
-  "  return mix (vec4 (0.0f, 0.0f, 0.0f, 1.0f),\n"
-  "    textureLod (uEnvironmentMapTexture, theTexCoord, 0.0f), float (uSphereMapEnabled));\n"
+  "  return uSphereMapEnabled == 0 ?\n"
+  "    vec4 (0.f, 0.f, 0.f, 1.f) : textureLod (uEnvironmentMapTexture, theTexCoord, 0.f);\n"
   "}\n"
   "\n"
   "// =======================================================================\n"
@@ -1023,8 +1025,8 @@ static const char Shaders_RaytraceBase_fs[] =
   "\n"
   "        if (aVisibility > 0.0f)\n"
   "        {\n"
-  "          vec3 aIntensity = vec3 (texelFetch (\n"
-  "            uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));\n"
+  "          vec3 aIntensity = min (UNIT, vec3 (texelFetch (\n"
+  "            uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx))));\n"
   "\n"
   "          float aRdotV = dot (reflect (aLight.xyz, aSidedNormal), theRay.Direct);\n"
   "\n"
index db81a3f..a3a04e0 100644 (file)
@@ -21,7 +21,7 @@ static const char Shaders_RaytraceRender_fs[] =
   "\n"
   "//! Maximum radiance that can be added to the pixel. Decreases noise\n"
   "//! level, but introduces some bias.\n"
-  "#define MAX_RADIANCE vec3 (25.f)\n"
+  "#define MAX_RADIANCE vec3 (50.f)\n"
   "\n"
   "// =======================================================================\n"
   "// function : main\n"
index b7ff7f1..dc310e6 100644 (file)
@@ -70,6 +70,8 @@ V3d_DirectionalLight::V3d_DirectionalLight (const Handle(V3d_Viewer)& theViewer,
   SetHeadlight (theIsHeadlight);
   SetTarget (0., 0., 0.);
   SetPosition (-aV.X(), -aV.Y(), -aV.Z());
+  SetSmoothAngle (0.2);
+  SetIntensity (20.0);
 }
 
 // =======================================================================
diff --git a/tests/v3d/raytrace/sample_ball b/tests/v3d/raytrace/sample_ball
new file mode 100644 (file)
index 0000000..0f537b5
--- /dev/null
@@ -0,0 +1,7 @@
+puts "============"
+puts "Visualization - Path Tracing, Ball sample"
+puts "============"
+puts ""
+
+source $env(CSF_OCCTSamplesPath)/tcl/pathtrace_ball.tcl
+vdump $imagedir/${casename}_zoom.png
diff --git a/tests/v3d/raytrace/sample_cube b/tests/v3d/raytrace/sample_cube
new file mode 100644 (file)
index 0000000..33109d8
--- /dev/null
@@ -0,0 +1,6 @@
+puts "============"
+puts "Visualization - Path Tracing, Cube sample"
+puts "============"
+puts ""
+
+source $env(CSF_OCCTSamplesPath)/tcl/pathtrace_cube.tcl