diff --git a/examples/raytrace/config.json b/examples/raytrace/config.json index b64a131..78d1024 100644 --- a/examples/raytrace/config.json +++ b/examples/raytrace/config.json @@ -1,4 +1,4 @@ -{ "obj_filename" : "../common/cornellbox_suzanne.obj", +{ "obj_filename" : "cornellbox_suzanne.obj", "scene_scale" : 1.0, "width" : 512, "height" : 512, diff --git a/examples/raytrace/cornellbox_suzanne.obj b/examples/raytrace/cornellbox_suzanne.obj new file mode 100644 index 0000000..ad96197 --- /dev/null +++ b/examples/raytrace/cornellbox_suzanne.obj @@ -0,0 +1,1529 @@ +# Blender v2.67 (sub 0) OBJ File: 'cornellbox.blend' +# www.blender.org +mtllib cornellbox_suzanne.mtl +o ceil_Plane.005 +v -5.060082 9.574966 -4.955276 +v 4.658843 9.574966 -4.955276 +v -5.060082 9.574966 4.763649 +v 4.658843 9.574966 4.763649 +usemtl None +s off +f 2 1 3 4 +o left_Plane.004 +v -4.971709 -0.000988 -4.950935 +v -5.028017 9.717773 -4.950935 +v -4.971709 -0.000988 4.767989 +v -5.028017 9.717773 4.767989 +usemtl None +s off +f 6 5 7 8 +o right_Plane.003 +v 4.547822 -0.031673 -4.932439 +v 4.491515 9.687088 -4.932439 +v 4.547822 -0.031673 4.786486 +v 4.491515 9.687088 4.786486 +usemtl None +s off +f 10 9 11 12 +o back_Plane.002 +v -5.109836 9.772833 -4.479764 +v 4.609088 9.772833 -4.479764 +v -5.109836 0.056570 -4.707224 +v 4.609088 0.056570 -4.707224 +usemtl None +s off +f 14 13 15 16 +o lightobj_Plane.001 +v -1.964923 8.501755 -2.347890 +v 1.555262 8.501755 -2.347890 +v -1.964923 8.501755 1.207072 +v 1.555262 8.501755 1.207072 +usemtl None +s off +f 18 17 19 20 +o floor_Plane +v -5.144927 0.117050 -4.948757 +v 4.573997 0.117050 -4.948757 +v -5.144927 0.117050 4.770167 +v 4.573997 0.117050 4.770167 +usemtl None +s off +f 22 21 23 24 +o suzanne_tri +v 0.871029 1.442251 -0.053177 +v 0.873030 1.370656 -0.008330 +v 0.878278 1.279165 -0.089297 +v 0.876081 1.414948 -0.177287 +v 0.192109 1.279165 0.638144 +v 0.272632 1.370656 0.628181 +v 0.227745 1.442251 0.628799 +v 0.104140 1.414948 0.641084 +v 0.844029 1.207378 -0.186042 +v 0.843525 1.380200 -0.293914 +v 0.093531 1.207378 0.609597 +v -0.014187 1.380200 0.615388 +v 0.812424 1.229832 0.052639 +v 0.755010 1.145711 -0.001518 +v 0.272547 1.145711 0.509965 +v 0.329961 1.229832 0.564121 +v 0.832062 1.345989 0.071162 +v 0.349599 1.345989 0.582645 +v 0.782010 1.380584 0.131347 +v 0.712293 1.296540 0.162243 +v 0.433536 1.296540 0.457766 +v 0.406761 1.380584 0.529167 +v 0.624492 1.229716 0.143861 +v 0.410064 1.229717 0.371187 +v 0.635102 1.437287 0.175349 +v 0.532940 1.409984 0.164901 +v 0.425726 1.409984 0.278564 +v 0.442117 1.437287 0.379942 +v 0.742512 1.454661 0.137049 +v 0.410148 1.454661 0.489403 +v 0.744094 1.536146 0.095582 +v 0.643682 1.578034 0.097525 +v 0.364926 1.578034 0.393048 +v 0.368844 1.536146 0.493402 +v 0.536020 1.592696 0.060409 +v 0.321592 1.592696 0.287735 +v 0.714925 1.629850 -0.039329 +v 0.630427 1.656845 -0.119032 +v 0.147964 1.656845 0.392450 +v 0.232462 1.629850 0.472153 +v 0.779701 1.560813 0.021772 +v 0.297238 1.560813 0.533255 +v 0.835113 1.526218 -0.044096 +v 0.809668 1.560659 -0.154015 +v 0.123498 1.560659 0.573426 +v 0.234715 1.526218 0.592416 +v 0.755557 1.570357 -0.269494 +v 0.005059 1.570357 0.526145 +v 0.849446 1.538590 -0.041316 +v 0.887167 1.447215 -0.048694 +v 0.238326 1.538590 0.606561 +v 0.233161 1.447215 0.644648 +v 0.792256 1.583075 0.033615 +v 0.309793 1.583075 0.545097 +v 0.753093 1.551000 0.114811 +v 0.388566 1.551000 0.501264 +v 0.747956 1.462107 0.163664 +v 0.437036 1.462107 0.493286 +v 0.794621 1.380622 0.153982 +v 0.430093 1.380622 0.540436 +v 0.851839 1.338620 0.089817 +v 0.369376 1.338620 0.601300 +v 0.890974 1.368212 -0.002145 +v 0.279854 1.368212 0.645733 +v 0.839116 1.464589 0.077817 +v 0.356653 1.464589 0.589299 +v 0.812437 0.229518 0.288924 +v 0.846574 0.291378 0.342604 +v 0.742999 0.279044 0.470439 +v 0.708918 0.222149 0.438291 +v 0.621425 0.291378 0.581296 +v 0.565844 0.229518 0.550348 +v 0.887318 0.241813 0.155503 +v 0.891210 0.306193 0.288050 +v 0.569568 0.306193 0.629038 +v 0.437020 0.241813 0.632887 +v 0.906872 0.296149 0.120249 +v 0.912541 0.405014 0.265212 +v 0.548013 0.405014 0.651665 +v 0.402966 0.296150 0.654463 +v 0.877955 0.493753 0.114452 +v 0.890902 0.523576 0.266280 +v 0.547817 0.523576 0.630001 +v 0.395492 0.493753 0.625934 +v 0.791569 0.738209 0.086665 +v 0.820681 0.775478 0.253742 +v 0.531204 0.775478 0.560632 +v 0.362713 0.738209 0.541316 +v 0.653352 0.972774 0.106646 +v 0.781785 1.007292 -0.094398 +v 0.830312 1.140862 0.005074 +v 0.752323 1.133685 0.307398 +v 0.283520 1.140862 0.584754 +v 0.181387 1.007292 0.542113 +v 0.374596 0.972774 0.402170 +v 0.580780 1.133685 0.489259 +v 0.897719 1.106075 -0.253534 +v 0.924607 1.222270 -0.206692 +v 0.077617 1.222270 0.691243 +v 0.029286 1.106075 0.667134 +v 0.923739 1.254076 -0.497483 +v 0.949185 1.355571 -0.333864 +v -0.047905 1.355571 0.723199 +v -0.212729 1.254076 0.707342 +v 0.982568 1.567914 -0.484951 +v 0.957906 1.535916 -0.347118 +v -0.060627 1.535916 0.732678 +v -0.196786 1.567914 0.765339 +v 0.889630 1.629696 -0.368561 +v 0.959851 1.595293 -0.270105 +v 0.016368 1.595293 0.730127 +v -0.086017 1.629696 0.665770 +v 0.755557 1.760668 -0.194316 +v 0.806113 1.743563 -0.071451 +v 0.205714 1.743563 0.565060 +v 0.080109 1.760668 0.521759 +v 0.633843 1.923716 -0.072852 +v 0.725619 1.844866 0.024457 +v 0.296763 1.844866 0.479108 +v 0.194266 1.923716 0.393166 +v 0.546462 1.894123 0.070259 +v 0.666763 1.827607 0.119296 +v 0.388006 1.827607 0.414819 +v 0.332034 1.894123 0.297584 +v 0.529106 1.676817 0.182764 +v 0.635018 1.647339 0.228968 +v 0.495640 1.647339 0.376730 +v 0.443335 1.676817 0.273694 +v 0.495276 1.615073 0.236771 +v 0.567218 1.565816 0.304631 +v 0.633017 1.610185 0.141163 +v 0.668568 1.657075 0.056561 +v 0.325483 1.657075 0.420281 +v 0.407867 1.610185 0.379855 +v 0.709592 1.659519 -0.012140 +v 0.259293 1.659519 0.465244 +v 0.772143 1.615034 -0.092754 +v 0.182466 1.615034 0.532391 +v 0.866802 1.538398 -0.239739 +v 0.041254 1.538398 0.635464 +v 0.900883 1.459356 -0.261289 +v 0.021729 1.459356 0.670745 +v 0.915440 1.355648 -0.226080 +v 0.057728 1.355648 0.683222 +v 0.869363 1.244570 -0.086968 +v 0.193914 1.244570 0.629108 +v 0.821340 1.210052 0.028830 +v 0.306713 1.210052 0.574411 +v 0.712293 1.296540 0.162243 +v 0.433536 1.296540 0.457766 +v 0.680045 1.343468 0.185523 +v 0.572970 1.247129 0.310057 +v 0.454895 1.343468 0.424214 +v 0.626102 1.503995 0.188339 +v 0.454560 1.503995 0.370199 +v 0.561997 1.415102 0.299707 +v 0.647741 1.412620 0.198010 +v 0.465477 1.412620 0.391237 +v 0.809161 0.355680 0.446930 +v 0.762693 0.345791 0.489015 +v 0.723390 0.355680 0.537860 +v 0.846631 0.405091 0.407095 +v 0.685809 0.405091 0.577589 +v 0.830353 0.523653 0.402481 +v 0.680253 0.523653 0.561609 +v 0.756493 0.787888 0.375770 +v 0.828491 0.553284 0.389985 +v 0.667670 0.553284 0.560479 +v 0.649279 0.787888 0.489433 +v 0.720354 0.933561 0.330942 +v 0.670414 0.896522 0.401972 +v 0.702886 0.787888 0.432602 +v 0.602419 0.933561 0.455971 +v 0.746275 0.560692 0.473529 +v 0.766136 0.479207 0.492263 +v 0.738102 0.995305 0.293985 +v 0.775795 1.010197 0.318799 +v 0.749047 0.960786 0.347268 +v 0.620390 0.960786 0.483663 +v 0.593531 1.010197 0.512026 +v 0.566560 0.995305 0.475845 +v 0.698576 1.066900 0.288920 +v 0.727269 1.094126 0.305245 +v 0.577169 1.094126 0.464373 +v 0.559197 1.066900 0.436681 +v 0.627081 1.074308 0.361098 +v 0.677217 1.101533 0.354690 +v 0.623610 1.101533 0.411522 +v 0.645109 1.024936 0.378102 +v 0.675635 1.047236 0.406897 +v 0.695552 0.916340 0.425684 +v 0.749075 0.990456 0.368773 +v 0.704496 0.953417 0.434120 +v 0.641861 0.990456 0.482436 +v 0.700801 1.042348 0.430635 +v 0.709549 1.089238 0.374448 +v 0.645221 1.089238 0.442646 +v 0.743519 1.081831 0.342053 +v 0.614862 1.081831 0.478448 +v 0.781268 1.020125 0.356180 +v 0.631168 1.020125 0.515308 +v 0.741573 0.968079 0.243560 +v 0.516424 0.968079 0.482252 +v 0.768544 0.901409 0.247522 +v 0.521952 0.901409 0.508946 +v 0.714377 0.851768 0.089031 +v 0.360571 0.851768 0.464118 +v 0.683851 0.911030 0.092456 +v 0.362209 0.911030 0.433444 +v 0.757164 0.466835 0.483800 +v 0.819659 0.498948 0.413873 +v 0.691002 0.498948 0.550269 +v 0.826937 0.419906 0.420739 +v 0.698281 0.419906 0.557134 +v 0.789440 0.368014 0.449807 +v 0.725112 0.368014 0.518005 +v 0.759082 0.360606 0.485609 +v 0.748108 0.365455 0.410820 +v 0.717750 0.358047 0.446622 +v 0.683780 0.365455 0.479018 +v 0.776633 0.404976 0.373289 +v 0.647977 0.404976 0.509684 +v 0.778355 0.471684 0.374913 +v 0.649698 0.471684 0.511308 +v 0.715860 0.439571 0.444840 +v 0.708682 1.365730 0.180316 +v 0.688905 1.427474 0.183140 +v 0.451368 1.365730 0.453107 +v 0.453034 1.427474 0.433198 +v 0.676210 1.501551 0.160426 +v 0.429618 1.501551 0.421850 +v 0.679597 1.575629 0.120662 +v 0.390119 1.575629 0.427552 +v 0.751707 1.323766 0.167202 +v 0.440787 1.323766 0.496824 +v 0.837450 1.266909 0.044026 +v 0.322823 1.266909 0.589607 +v 0.881946 1.296501 -0.053619 +v 0.227940 1.296501 0.639724 +v 0.903025 1.372984 -0.173352 +v 0.109641 1.372984 0.667752 +v 0.892107 1.464359 -0.194390 +v 0.088002 1.464359 0.658081 +v 0.866970 1.526103 -0.185882 +v 0.095029 1.526103 0.632490 +v 0.813531 1.595370 -0.042975 +v 0.234575 1.595370 0.570804 +v 0.736563 1.620037 0.002562 +v 0.275543 1.620037 0.491311 +v 0.706261 1.617593 0.059896 +v 0.331012 1.617593 0.457715 +v 0.683124 1.553367 0.091770 +v 0.711649 1.592888 0.054239 +v 0.361482 1.553367 0.432759 +v 0.325679 1.592888 0.463425 +v 0.736591 1.595331 0.002588 +v 0.275571 1.595331 0.491338 +v 0.793810 1.580516 -0.050837 +v 0.225575 1.580516 0.551575 +v 0.838361 1.506323 -0.169909 +v 0.109305 1.506323 0.602997 +v 0.861693 1.451987 -0.180120 +v 0.100473 1.451987 0.626886 +v 0.872582 1.385317 -0.159109 +v 0.122084 1.385317 0.636531 +v 0.856836 1.306353 -0.055825 +v 0.224273 1.306353 0.614785 +v 0.821256 1.284168 0.028751 +v 0.306629 1.284168 0.574332 +v 0.742651 1.331135 0.137181 +v 0.410288 1.331135 0.489535 +v 0.699626 1.373099 0.150295 +v 0.420870 1.373099 0.445818 +v 0.670765 1.494105 0.133811 +v 0.402730 1.494105 0.417968 +v 0.681626 1.424953 0.144056 +v 0.413591 1.424953 0.428213 +v 0.471496 1.602509 0.063984 +v 0.403696 1.548172 0.150387 +v 0.321396 1.602509 0.223112 +v 0.488908 1.797592 -0.037729 +v 0.220873 1.797592 0.246428 +v 0.563818 1.812369 -0.160383 +v 0.102798 1.812369 0.328367 +v 0.669422 1.674027 -0.264825 +v 0.004695 1.674027 0.439884 +v 0.783802 1.557870 -0.425427 +v -0.148960 1.557870 0.563439 +v 0.853491 1.503495 -0.520787 +v -0.240092 1.503496 0.638573 +v 0.834105 1.246553 -0.506854 +v -0.227313 1.246553 0.618407 +v 0.781030 1.103401 -0.320644 +v -0.044518 1.103401 0.554559 +v 0.727843 1.031882 -0.145281 +v 0.127444 1.031882 0.491231 +v 0.435397 0.532851 0.180288 +v 0.388592 0.601926 0.136139 +v 0.479472 0.661150 -0.025150 +v 0.540889 0.574893 0.107961 +v 0.232880 0.661150 0.236275 +v 0.369347 0.574893 0.289821 +v 0.505729 0.318065 0.246631 +v 0.607554 0.369958 0.149364 +v 0.414569 0.369958 0.353957 +v 0.626282 0.192326 0.360344 +v 0.715468 0.214511 0.218936 +v 0.490319 0.214511 0.457628 +v 0.793877 0.231731 0.067363 +v 0.343578 0.231731 0.544747 +v 0.709352 0.419368 0.041332 +v 0.312660 0.419368 0.461884 +v 0.639187 0.621859 0.028847 +v 0.296102 0.621859 0.392568 +v 0.604938 0.767571 0.018020 +v 0.283296 0.767571 0.359008 +v 0.594133 0.841686 0.029307 +v 0.603077 0.905951 0.048483 +v 0.313599 0.905951 0.355373 +v 0.293933 0.841686 0.347563 +v 0.606632 0.967733 0.062577 +v 0.327875 0.967733 0.358100 +v -0.504797 0.775424 -0.706562 +v -0.157513 0.812732 -0.840789 +v -0.018989 0.659843 -0.720864 +v -0.335634 0.573202 -0.546997 +v -0.490730 0.659843 -0.220747 +v -0.618533 0.812732 -0.352039 +v 0.175368 0.591153 -0.473096 +v -0.071364 0.497181 -0.297721 +v -0.232045 0.591153 -0.041177 +v 0.430834 0.653588 -0.113987 +v 0.318511 0.594365 0.070035 +v 0.141356 0.653588 0.192902 +v 0.645892 0.949744 -0.630690 +v 0.650526 1.211458 -0.787415 +v -0.361919 0.949744 0.437740 +v -0.518107 1.211458 0.451509 +v -0.634712 1.234665 -0.829107 +v -0.187157 1.163301 -1.040586 +v -0.819720 1.163301 -0.369976 +v 0.074399 1.915578 -0.160228 +v 0.358432 1.853757 -0.515212 +v 0.130217 1.831034 -0.730479 +v -0.198731 1.880406 -0.417861 +v -0.491624 1.831034 -0.071235 +v -0.263409 1.853757 0.144032 +v -0.070886 1.672490 -0.920172 +v -0.502192 1.649998 -0.704105 +v -0.692728 1.672490 -0.260928 +v 0.719026 1.463783 -0.550966 +v 0.606143 1.490855 -0.528568 +v -0.278065 1.463783 0.506098 +v -0.262290 1.490855 0.392100 +v 0.585666 1.544922 -0.773416 +v 0.397454 1.655923 -0.736156 +v -0.507917 1.544922 0.385943 +v -0.481701 1.655923 0.195878 +v 0.405978 1.519832 -0.942910 +v 0.214182 1.620943 -0.909030 +v -0.687605 1.519833 0.216450 +v -0.664972 1.620943 0.023005 +v 0.256984 1.368811 -1.083451 +v 0.057994 1.474848 -1.056357 +v -0.836599 1.368812 0.075909 +v -0.821161 1.474848 -0.124322 +v 0.250209 1.084720 -1.057622 +v 0.026165 1.096823 -1.054161 +v -0.820826 1.096823 -0.156225 +v -0.811210 1.084720 0.067639 +v 0.574343 1.604683 -0.322290 +v -0.058220 1.604683 0.348320 +v 0.344225 1.693807 0.094289 +v 0.565972 1.260677 -0.877910 +v -0.613382 1.260677 0.372380 +v 0.429589 1.218444 -0.952857 +v -0.696158 1.218444 0.240602 +v 0.277137 0.719643 -0.559675 +v 0.503519 0.856041 -0.313918 +v -0.312540 0.719643 0.065470 +v -0.053994 0.856041 0.277128 +v 0.405794 0.801205 -0.663851 +v -0.409032 0.801205 0.199986 +v 0.227660 0.827931 -0.896317 +v 0.032393 0.820332 -0.865711 +v -0.632334 0.820332 -0.161002 +v -0.651495 0.827931 0.035717 +v 0.459220 1.324442 -1.204139 +v 0.438225 1.282593 -1.041368 +v 0.481279 1.243110 -1.043716 +v 0.484470 1.272626 -1.169582 +v -0.783846 1.243110 0.297504 +v -0.784014 1.282593 0.254387 +v -0.945283 1.324442 0.284843 +v -0.909312 1.272626 0.308033 +v 0.526936 1.262583 -1.365799 +v 0.521295 1.319324 -1.435558 +v -1.102717 1.262583 0.361874 +v -1.172686 1.319324 0.360313 +v 0.604071 1.116872 -1.400437 +v 0.645039 1.141538 -1.479930 +v -1.132796 1.116872 0.440899 +v -1.209763 1.141538 0.486435 +v 0.615296 0.916863 -1.314672 +v 0.652793 0.887193 -1.375959 +v -1.046521 0.916863 0.447101 +v -1.105517 0.887193 0.488110 +v 0.589136 0.838013 -1.092334 +v 0.592775 0.771305 -1.099641 +v -0.826089 0.838013 0.408014 +v -0.833171 0.771305 0.412073 +v 0.575531 0.862987 -0.825935 +v 0.559645 0.798800 -0.765742 +v -0.560937 0.862988 0.378890 +v -0.501774 0.798800 0.359519 +v 0.542359 0.855196 -1.147197 +v 0.548336 0.882613 -0.926765 +v -0.663182 0.882613 0.357624 +v -0.883587 0.855196 0.364518 +v 0.568659 0.919268 -1.326443 +v -1.060994 0.919268 0.401231 +v 0.564712 1.067423 -1.394604 +v -1.129269 1.067423 0.401267 +v 0.501938 1.173613 -1.367900 +v -1.106272 1.173613 0.337041 +v 0.457583 1.183618 -1.205684 +v -0.946921 1.183618 0.283298 +v 0.461502 1.168918 -1.094591 +v -0.835788 1.168918 0.280729 +v 0.462705 0.895024 -0.782005 +v 0.532702 0.949513 -0.726718 +v -0.523664 0.895024 0.263693 +v -0.464388 0.949514 0.330345 +v 0.449311 1.178923 -0.966474 +v -0.708601 1.178923 0.261084 +v 0.455175 0.870165 -0.917984 +v -0.659851 0.870165 0.264109 +v 0.469395 0.899796 -0.947529 +v 0.437483 0.949321 -0.805795 +v -0.548886 0.949321 0.239902 +v -0.688516 0.899796 0.280029 +v 0.392372 0.973873 -0.902045 +v 0.437063 0.966465 -0.945807 +v -0.647604 0.973873 0.200483 +v -0.688684 0.966465 0.247651 +v 0.427923 1.047950 -0.975908 +v 0.437007 1.097438 -0.913641 +v -0.656575 1.097438 0.245719 +v -0.719266 1.047950 0.240283 +v 0.454587 1.117102 -1.025935 +v -0.767652 1.117102 0.269820 +v 0.418672 1.092320 -1.059812 +v 0.432753 1.136728 -1.132448 +v -0.803568 1.092320 0.235943 +v -0.875258 1.136728 0.254237 +v 0.400952 1.033058 -1.012089 +v -0.756959 1.033058 0.215469 +v 0.365401 0.958981 -0.938226 +v -0.685297 0.958981 0.175669 +v 0.411897 0.944165 -0.980285 +v -0.724571 0.944165 0.224540 +v 0.442424 0.884903 -0.983710 +v -0.726209 0.884903 0.255214 +v 0.422842 0.855272 -0.948482 +v -0.692183 0.855272 0.233611 +v 0.508810 0.872647 -0.964049 +v -0.702709 0.872647 0.320340 +v 0.434194 1.151428 -1.249225 +v -0.991752 1.151428 0.262489 +v 0.483938 1.143905 -1.406357 +v -1.145715 1.143905 0.321316 +v 0.550268 1.045123 -1.440448 +v -1.175878 1.045123 0.389522 +v 0.559603 0.899450 -1.367204 +v -1.102214 0.899450 0.394568 +v 0.509999 0.837821 -1.188461 +v -0.926668 0.837821 0.334620 +v 0.479781 0.924386 -1.066609 +v 0.442172 0.971314 -1.037646 +v -0.806787 0.924386 0.297344 +v -0.780068 0.971314 0.258110 +v 0.486667 0.973719 -1.146031 +v 0.459808 1.023130 -1.117668 +v -0.885672 0.973719 0.308852 +v -0.858925 1.023130 0.280384 +v 0.498970 1.028017 -1.209603 +v 0.466722 1.074946 -1.186323 +v -0.948419 1.028017 0.324844 +v -0.927060 1.074946 0.291292 +v 0.525690 1.047758 -1.259578 +v 0.495163 1.107020 -1.256153 +v -0.996749 1.047758 0.354433 +v -0.995111 1.107020 0.323759 +v 0.426649 0.749082 -0.912672 +v 0.476001 0.733998 -1.209790 +v -0.656212 0.749082 0.235322 +v -0.949945 0.733998 0.301925 +v 0.604182 0.854927 -1.464770 +v -1.197013 0.854927 0.444764 +v 0.607290 1.094495 -1.537017 +v -1.268955 1.094495 0.452081 +v 0.454825 1.242572 -1.519736 +v -1.260599 1.242573 0.298868 +v 0.349697 1.232798 -1.307449 +v -1.054807 1.232798 0.181533 +v 0.319814 1.213211 -1.110103 +v -0.859540 1.213211 0.140187 +usemtl None +s off +f 25 26 27 +f 25 27 28 +f 29 30 31 +f 29 31 32 +f 28 27 33 +f 28 33 34 +f 35 29 32 +f 35 32 36 +f 27 37 38 +f 27 38 33 +f 39 40 29 +f 39 29 35 +f 26 41 37 +f 26 37 27 +f 40 42 30 +f 40 30 29 +f 41 43 44 +f 41 44 37 +f 45 46 42 +f 45 42 40 +f 37 44 47 +f 37 47 38 +f 48 45 40 +f 48 40 39 +f 44 49 50 +f 44 50 47 +f 51 52 45 +f 51 45 48 +f 43 53 49 +f 43 49 44 +f 52 54 46 +f 52 46 45 +f 53 55 56 +f 53 56 49 +f 57 58 54 +f 57 54 52 +f 49 56 59 +f 49 59 50 +f 60 57 52 +f 60 52 51 +f 56 61 62 +f 56 62 59 +f 63 64 57 +f 63 57 60 +f 55 65 61 +f 55 61 56 +f 64 66 58 +f 64 58 57 +f 65 67 68 +f 65 68 61 +f 69 70 66 +f 69 66 64 +f 61 68 71 +f 61 71 62 +f 72 69 64 +f 72 64 63 +f 68 28 34 +f 68 34 71 +f 36 32 69 +f 36 69 72 +f 67 25 28 +f 67 28 68 +f 32 31 70 +f 32 70 69 +f 25 67 73 +f 25 73 74 +f 75 70 31 +f 75 31 76 +f 67 65 77 +f 67 77 73 +f 78 66 70 +f 78 70 75 +f 65 55 79 +f 65 79 77 +f 80 58 66 +f 80 66 78 +f 55 53 81 +f 55 81 79 +f 82 54 58 +f 82 58 80 +f 53 43 83 +f 53 83 81 +f 84 46 54 +f 84 54 82 +f 43 41 85 +f 43 85 83 +f 86 42 46 +f 86 46 84 +f 41 26 87 +f 41 87 85 +f 88 30 42 +f 88 42 86 +f 26 25 74 +f 26 74 87 +f 76 31 30 +f 76 30 88 +f 89 87 74 +f 76 88 90 +f 85 87 89 +f 90 88 86 +f 89 83 85 +f 86 84 90 +f 89 81 83 +f 84 82 90 +f 89 79 81 +f 82 80 90 +f 89 77 79 +f 80 78 90 +f 89 73 77 +f 78 75 90 +f 89 74 73 +f 75 76 90 +f 91 92 93 +f 91 93 94 +f 93 95 96 +f 93 96 94 +f 97 98 92 +f 97 92 91 +f 95 99 100 +f 95 100 96 +f 101 102 98 +f 101 98 97 +f 99 103 104 +f 99 104 100 +f 105 106 102 +f 105 102 101 +f 103 107 108 +f 103 108 104 +f 109 110 106 +f 109 106 105 +f 107 111 112 +f 107 112 108 +f 113 114 115 +f 113 115 116 +f 117 118 119 +f 117 119 120 +f 114 121 122 +f 114 122 115 +f 123 124 118 +f 123 118 117 +f 121 125 126 +f 121 126 122 +f 127 128 124 +f 127 124 123 +f 125 129 130 +f 125 130 126 +f 131 132 128 +f 131 128 127 +f 129 133 134 +f 129 134 130 +f 135 136 132 +f 135 132 131 +f 133 137 138 +f 133 138 134 +f 139 140 136 +f 139 136 135 +f 137 141 142 +f 137 142 138 +f 143 144 140 +f 143 140 139 +f 141 145 146 +f 141 146 142 +f 147 148 144 +f 147 144 143 +f 145 149 150 +f 145 150 146 +f 151 152 148 +f 151 148 147 +f 149 153 154 +f 149 154 150 +f 154 153 152 +f 154 152 151 +f 155 156 146 +f 155 146 150 +f 147 157 158 +f 147 158 151 +f 156 159 142 +f 156 142 146 +f 143 160 157 +f 143 157 147 +f 161 138 142 +f 161 142 159 +f 143 139 162 +f 143 162 160 +f 163 134 138 +f 163 138 161 +f 139 135 164 +f 139 164 162 +f 165 130 134 +f 165 134 163 +f 135 131 166 +f 135 166 164 +f 167 126 130 +f 167 130 165 +f 131 127 168 +f 131 168 166 +f 169 122 126 +f 169 126 167 +f 127 123 170 +f 127 170 168 +f 171 115 122 +f 171 122 169 +f 123 117 172 +f 123 172 170 +f 173 116 115 +f 173 115 171 +f 117 120 174 +f 117 174 172 +f 173 175 176 +f 173 176 116 +f 176 177 174 +f 176 174 120 +f 155 150 154 +f 155 154 178 +f 154 151 158 +f 154 158 179 +f 178 154 180 +f 178 180 181 +f 180 154 179 +f 180 179 182 +f 176 175 181 +f 176 181 180 +f 182 177 176 +f 182 176 180 +f 183 184 93 +f 183 93 92 +f 93 184 185 +f 93 185 95 +f 186 183 92 +f 186 92 98 +f 95 185 187 +f 95 187 99 +f 188 186 98 +f 188 98 102 +f 99 187 189 +f 99 189 103 +f 110 190 191 +f 110 191 106 +f 192 193 111 +f 192 111 107 +f 188 102 106 +f 188 106 191 +f 107 103 189 +f 107 189 192 +f 194 195 196 +f 194 196 190 +f 196 195 197 +f 196 197 193 +f 191 190 196 +f 191 196 198 +f 196 193 192 +f 196 192 198 +f 199 188 191 +f 199 191 198 +f 192 189 199 +f 192 199 198 +f 200 201 202 +f 200 202 194 +f 203 204 205 +f 203 205 197 +f 206 207 201 +f 206 201 200 +f 204 208 209 +f 204 209 205 +f 210 211 207 +f 210 207 206 +f 208 212 210 +f 208 210 209 +f 213 214 211 +f 213 211 210 +f 212 214 213 +f 212 213 210 +f 195 194 202 +f 195 202 215 +f 203 197 195 +f 203 195 215 +f 215 202 216 +f 215 216 217 +f 218 203 215 +f 218 215 217 +f 214 219 220 +f 214 220 211 +f 221 219 214 +f 221 214 212 +f 211 220 222 +f 211 222 207 +f 223 221 212 +f 223 212 208 +f 207 222 224 +f 207 224 201 +f 225 223 208 +f 225 208 204 +f 201 224 216 +f 201 216 202 +f 218 225 204 +f 218 204 203 +f 219 224 222 +f 219 222 220 +f 223 225 219 +f 223 219 221 +f 219 217 216 +f 219 216 224 +f 218 217 219 +f 218 219 225 +f 210 206 116 +f 210 116 176 +f 120 209 210 +f 120 210 176 +f 206 200 226 +f 206 226 116 +f 227 205 209 +f 227 209 120 +f 200 194 228 +f 200 228 226 +f 229 197 205 +f 229 205 227 +f 194 190 110 +f 194 110 228 +f 111 193 197 +f 111 197 229 +f 109 230 228 +f 109 228 110 +f 229 231 112 +f 229 112 111 +f 230 232 226 +f 230 226 228 +f 227 233 231 +f 227 231 229 +f 113 116 226 +f 113 226 232 +f 227 120 119 +f 227 119 233 +f 188 199 234 +f 188 234 235 +f 234 199 189 +f 234 189 236 +f 186 188 235 +f 186 235 237 +f 236 189 187 +f 236 187 238 +f 183 186 237 +f 183 237 239 +f 238 187 185 +f 238 185 240 +f 184 183 239 +f 184 239 241 +f 240 185 184 +f 240 184 241 +f 241 239 242 +f 241 242 243 +f 244 240 241 +f 244 241 243 +f 239 237 245 +f 239 245 242 +f 246 238 240 +f 246 240 244 +f 237 235 247 +f 237 247 245 +f 248 236 238 +f 248 238 246 +f 235 234 249 +f 235 249 247 +f 249 234 236 +f 249 236 248 +f 249 243 242 +f 249 242 247 +f 244 243 249 +f 244 249 248 +f 247 242 245 +f 246 244 248 +f 181 175 250 +f 181 250 251 +f 252 177 182 +f 252 182 253 +f 178 181 251 +f 178 251 254 +f 253 182 179 +f 253 179 255 +f 155 178 254 +f 155 254 256 +f 255 179 158 +f 255 158 257 +f 175 173 258 +f 175 258 250 +f 259 174 177 +f 259 177 252 +f 173 171 260 +f 173 260 258 +f 261 172 174 +f 261 174 259 +f 171 169 262 +f 171 262 260 +f 263 170 172 +f 263 172 261 +f 169 167 264 +f 169 264 262 +f 265 168 170 +f 265 170 263 +f 167 165 266 +f 167 266 264 +f 267 166 168 +f 267 168 265 +f 165 163 268 +f 165 268 266 +f 269 164 166 +f 269 166 267 +f 163 161 270 +f 163 270 268 +f 271 162 164 +f 271 164 269 +f 161 159 272 +f 161 272 270 +f 273 160 162 +f 273 162 271 +f 159 156 274 +f 159 274 272 +f 275 157 160 +f 275 160 273 +f 156 155 256 +f 156 256 274 +f 257 158 157 +f 257 157 275 +f 274 256 276 +f 274 276 277 +f 278 257 275 +f 278 275 279 +f 272 274 277 +f 272 277 280 +f 279 275 273 +f 279 273 281 +f 270 272 280 +f 270 280 282 +f 281 273 271 +f 281 271 283 +f 268 270 282 +f 268 282 284 +f 283 271 269 +f 283 269 285 +f 266 268 284 +f 266 284 286 +f 285 269 267 +f 285 267 287 +f 264 266 286 +f 264 286 288 +f 287 267 265 +f 287 265 289 +f 262 264 288 +f 262 288 290 +f 289 265 263 +f 289 263 291 +f 260 262 290 +f 260 290 292 +f 291 263 261 +f 291 261 293 +f 258 260 292 +f 258 292 294 +f 293 261 259 +f 293 259 295 +f 250 258 294 +f 250 294 296 +f 295 259 252 +f 295 252 297 +f 256 254 298 +f 256 298 276 +f 299 255 257 +f 299 257 278 +f 254 251 300 +f 254 300 298 +f 301 253 255 +f 301 255 299 +f 251 250 296 +f 251 296 300 +f 297 252 253 +f 297 253 301 +f 153 149 302 +f 153 302 303 +f 304 152 153 +f 304 153 303 +f 149 145 305 +f 149 305 302 +f 306 148 152 +f 306 152 304 +f 145 141 307 +f 145 307 305 +f 308 144 148 +f 308 148 306 +f 141 137 309 +f 141 309 307 +f 310 140 144 +f 310 144 308 +f 137 133 311 +f 137 311 309 +f 312 136 140 +f 312 140 310 +f 133 129 313 +f 133 313 311 +f 314 132 136 +f 314 136 312 +f 129 125 315 +f 129 315 313 +f 316 128 132 +f 316 132 314 +f 125 121 317 +f 125 317 315 +f 318 124 128 +f 318 128 316 +f 121 114 319 +f 121 319 317 +f 320 118 124 +f 320 124 318 +f 321 322 323 +f 321 323 324 +f 325 322 321 +f 325 321 326 +f 327 321 324 +f 327 324 328 +f 326 321 327 +f 326 327 329 +f 330 327 328 +f 330 328 331 +f 329 327 330 +f 329 330 332 +f 91 94 330 +f 91 330 331 +f 330 94 96 +f 330 96 332 +f 97 91 331 +f 97 331 333 +f 332 96 100 +f 332 100 334 +f 101 97 333 +f 101 333 335 +f 334 100 104 +f 334 104 336 +f 105 101 335 +f 105 335 337 +f 336 104 108 +f 336 108 338 +f 335 328 324 +f 335 324 337 +f 326 329 336 +f 326 336 338 +f 335 333 331 +f 335 331 328 +f 332 334 336 +f 332 336 329 +f 339 337 324 +f 339 324 323 +f 326 338 340 +f 326 340 325 +f 109 105 337 +f 109 337 339 +f 338 108 112 +f 338 112 340 +f 230 341 342 +f 230 342 232 +f 343 344 231 +f 343 231 233 +f 109 339 341 +f 109 341 230 +f 344 340 112 +f 344 112 231 +f 113 232 342 +f 113 342 345 +f 343 233 119 +f 343 119 346 +f 113 345 319 +f 113 319 114 +f 320 346 119 +f 320 119 118 +f 347 348 349 +f 347 349 350 +f 351 352 347 +f 351 347 350 +f 350 349 353 +f 350 353 354 +f 355 351 350 +f 355 350 354 +f 354 353 356 +f 354 356 357 +f 358 355 354 +f 358 354 357 +f 357 356 323 +f 357 323 322 +f 325 358 357 +f 325 357 322 +f 339 323 356 +f 339 356 341 +f 358 325 340 +f 358 340 344 +f 315 317 359 +f 315 359 360 +f 361 318 316 +f 361 316 362 +f 363 364 348 +f 363 348 347 +f 352 365 363 +f 352 363 347 +f 366 367 368 +f 366 368 369 +f 370 371 366 +f 370 366 369 +f 369 368 372 +f 369 372 373 +f 374 370 369 +f 374 369 373 +f 373 372 364 +f 373 364 363 +f 365 374 373 +f 365 373 363 +f 311 313 375 +f 311 375 376 +f 377 314 312 +f 377 312 378 +f 376 375 379 +f 376 379 380 +f 381 377 378 +f 381 378 382 +f 380 379 383 +f 380 383 384 +f 385 381 382 +f 385 382 386 +f 384 383 387 +f 384 387 388 +f 389 385 386 +f 389 386 390 +f 391 392 388 +f 391 388 387 +f 390 393 394 +f 390 394 389 +f 364 372 388 +f 364 388 392 +f 390 374 365 +f 390 365 393 +f 372 368 384 +f 372 384 388 +f 386 370 374 +f 386 374 390 +f 368 367 380 +f 368 380 384 +f 382 371 370 +f 382 370 386 +f 367 395 376 +f 367 376 380 +f 378 396 371 +f 378 371 382 +f 309 311 376 +f 309 376 395 +f 378 312 310 +f 378 310 396 +f 397 395 367 +f 397 367 366 +f 371 396 397 +f 371 397 366 +f 302 305 307 +f 302 307 309 +f 308 306 304 +f 308 304 310 +f 302 309 395 +f 302 395 397 +f 396 310 304 +f 396 304 397 +f 303 302 397 +f 397 304 303 +f 313 315 360 +f 313 360 375 +f 362 316 314 +f 362 314 377 +f 360 398 379 +f 360 379 375 +f 381 399 362 +f 381 362 377 +f 398 400 383 +f 398 383 379 +f 385 401 399 +f 385 399 381 +f 391 387 383 +f 391 383 400 +f 385 389 394 +f 385 394 401 +f 356 353 402 +f 356 402 403 +f 404 355 358 +f 404 358 405 +f 359 403 402 +f 359 402 406 +f 404 405 361 +f 404 361 407 +f 317 319 403 +f 317 403 359 +f 405 320 318 +f 405 318 361 +f 319 342 341 +f 319 341 403 +f 344 343 320 +f 344 320 405 +f 341 356 403 +f 405 358 344 +f 319 345 342 +f 343 346 320 +f 391 408 409 +f 391 409 392 +f 410 411 394 +f 410 394 393 +f 364 392 409 +f 364 409 348 +f 410 393 365 +f 410 365 352 +f 406 402 409 +f 406 409 408 +f 410 404 407 +f 410 407 411 +f 353 349 409 +f 353 409 402 +f 410 351 355 +f 410 355 404 +f 348 409 349 +f 351 410 352 +f 412 413 414 +f 412 414 415 +f 416 417 418 +f 416 418 419 +f 412 415 420 +f 412 420 421 +f 422 419 418 +f 422 418 423 +f 421 420 424 +f 421 424 425 +f 426 422 423 +f 426 423 427 +f 425 424 428 +f 425 428 429 +f 430 426 427 +f 430 427 431 +f 429 428 432 +f 429 432 433 +f 434 430 431 +f 434 431 435 +f 433 432 436 +f 433 436 437 +f 438 434 435 +f 438 435 439 +f 432 440 441 +f 432 441 436 +f 442 443 434 +f 442 434 438 +f 428 444 440 +f 428 440 432 +f 443 445 430 +f 443 430 434 +f 424 446 444 +f 424 444 428 +f 445 447 426 +f 445 426 430 +f 420 448 446 +f 420 446 424 +f 447 449 422 +f 447 422 426 +f 415 450 448 +f 415 448 420 +f 449 451 419 +f 449 419 422 +f 415 414 452 +f 415 452 450 +f 453 416 419 +f 453 419 451 +f 359 406 454 +f 359 454 455 +f 456 407 361 +f 456 361 457 +f 406 437 436 +f 406 436 454 +f 438 439 407 +f 438 407 456 +f 360 359 455 +f 360 455 398 +f 457 361 362 +f 457 362 399 +f 400 458 414 +f 400 414 413 +f 416 459 401 +f 416 401 417 +f 436 441 460 +f 436 460 454 +f 461 442 438 +f 461 438 456 +f 462 463 454 +f 462 454 460 +f 456 464 465 +f 456 465 461 +f 466 463 462 +f 466 462 467 +f 465 464 468 +f 465 468 469 +f 470 471 463 +f 470 463 466 +f 464 472 473 +f 464 473 468 +f 458 471 470 +f 458 470 474 +f 473 472 459 +f 473 459 475 +f 414 458 474 +f 414 474 452 +f 475 459 416 +f 475 416 453 +f 398 471 458 +f 398 458 400 +f 459 472 399 +f 459 399 401 +f 398 455 463 +f 398 463 471 +f 464 457 399 +f 464 399 472 +f 455 454 463 +f 464 456 457 +f 452 474 476 +f 452 476 477 +f 478 475 453 +f 478 453 479 +f 474 470 480 +f 474 480 476 +f 481 473 475 +f 481 475 478 +f 470 466 482 +f 470 482 480 +f 483 468 473 +f 483 473 481 +f 466 467 484 +f 466 484 482 +f 485 469 468 +f 485 468 483 +f 467 462 486 +f 467 486 484 +f 487 465 469 +f 487 469 485 +f 462 460 488 +f 462 488 486 +f 489 461 465 +f 489 465 487 +f 460 441 490 +f 460 490 488 +f 491 442 461 +f 491 461 489 +f 450 452 477 +f 450 477 492 +f 479 453 451 +f 479 451 493 +f 448 450 492 +f 448 492 494 +f 493 451 449 +f 493 449 495 +f 446 448 494 +f 446 494 496 +f 495 449 447 +f 495 447 497 +f 444 446 496 +f 444 496 498 +f 497 447 445 +f 497 445 499 +f 440 444 498 +f 440 498 500 +f 499 445 443 +f 499 443 501 +f 441 440 500 +f 441 500 490 +f 501 443 442 +f 501 442 491 +f 484 486 502 +f 484 502 503 +f 504 487 485 +f 504 485 505 +f 503 502 506 +f 503 506 507 +f 508 504 505 +f 508 505 509 +f 507 506 510 +f 507 510 511 +f 512 508 509 +f 512 509 513 +f 511 510 514 +f 511 514 515 +f 516 512 513 +f 516 513 517 +f 492 477 511 +f 492 511 515 +f 513 479 493 +f 513 493 517 +f 476 507 511 +f 476 511 477 +f 513 509 478 +f 513 478 479 +f 476 480 503 +f 476 503 507 +f 505 481 478 +f 505 478 509 +f 484 503 480 +f 484 480 482 +f 481 505 485 +f 481 485 483 +f 488 490 502 +f 488 502 486 +f 504 491 489 +f 504 489 487 +f 500 506 502 +f 500 502 490 +f 504 508 501 +f 504 501 491 +f 498 510 506 +f 498 506 500 +f 508 512 499 +f 508 499 501 +f 496 514 510 +f 496 510 498 +f 512 516 497 +f 512 497 499 +f 494 515 514 +f 494 514 496 +f 516 517 495 +f 516 495 497 +f 492 515 494 +f 495 517 493 +f 433 437 518 +f 433 518 519 +f 520 439 435 +f 520 435 521 +f 429 433 519 +f 429 519 522 +f 521 435 431 +f 521 431 523 +f 425 429 522 +f 425 522 524 +f 523 431 427 +f 523 427 525 +f 421 425 524 +f 421 524 526 +f 525 427 423 +f 525 423 527 +f 412 421 526 +f 412 526 528 +f 527 423 418 +f 527 418 529 +f 413 412 528 +f 413 528 530 +f 529 418 417 +f 529 417 531 +f 528 519 518 +f 528 518 530 +f 520 521 529 +f 520 529 531 +f 528 526 522 +f 528 522 519 +f 523 527 529 +f 523 529 521 +f 526 524 522 +f 523 525 527 +f 391 400 413 +f 391 413 530 +f 417 401 394 +f 417 394 531 +f 391 530 518 +f 391 518 408 +f 520 531 394 +f 520 394 411 +f 406 408 518 +f 406 518 437 +f 520 411 407 +f 520 407 439 diff --git a/examples/raytrace/nanort.cc b/examples/raytrace/nanort.cc new file mode 100644 index 0000000..0877ad6 --- /dev/null +++ b/examples/raytrace/nanort.cc @@ -0,0 +1 @@ +#include "nanort.h" diff --git a/examples/raytrace/nanort.h b/examples/raytrace/nanort.h new file mode 100644 index 0000000..169e464 --- /dev/null +++ b/examples/raytrace/nanort.h @@ -0,0 +1,2313 @@ +// +// NanoRT, single header only modern ray tracing kernel. +// + +/* +The MIT License (MIT) + +Copyright (c) 2015 - 2016 Light Transport Entertainment, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef NANORT_H_ +#define NANORT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nanort { + +#ifdef __clang__ +#pragma clang diagnostic push +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif +#endif + +// Parallelized BVH build is not yet fully tested, +// thus turn off if you face a problem when building BVH. +#define NANORT_ENABLE_PARALLEL_BUILD (1) + +// ---------------------------------------------------------------------------- +// Small vector class useful for multi-threaded environment. +// +// stack_container.h +// +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This allocator can be used with STL containers to provide a stack buffer +// from which to allocate memory and overflows onto the heap. This stack buffer +// would be allocated on the stack and allows us to avoid heap operations in +// some situations. +// +// STL likes to make copies of allocators, so the allocator itself can't hold +// the data. Instead, we make the creator responsible for creating a +// StackAllocator::Source which contains the data. Copying the allocator +// merely copies the pointer to this shared source, so all allocators created +// based on our allocator will share the same stack buffer. +// +// This stack buffer implementation is very simple. The first allocation that +// fits in the stack buffer will use the stack buffer. Any subsequent +// allocations will not use the stack buffer, even if there is unused room. +// This makes it appropriate for array-like containers, but the caller should +// be sure to reserve() in the container up to the stack buffer size. Otherwise +// the container will allocate a small array which will "use up" the stack +// buffer. +template +class StackAllocator : public std::allocator { + public: + typedef typename std::allocator::pointer pointer; + typedef typename std::allocator::size_type size_type; + + // Backing store for the allocator. The container owner is responsible for + // maintaining this for as long as any containers using this allocator are + // live. + struct Source { + Source() : used_stack_buffer_(false) {} + + // Casts the buffer in its right type. + T *stack_buffer() { return reinterpret_cast(stack_buffer_); } + const T *stack_buffer() const { + return reinterpret_cast(stack_buffer_); + } + + // + // IMPORTANT: Take care to ensure that stack_buffer_ is aligned + // since it is used to mimic an array of T. + // Be careful while declaring any unaligned types (like bool) + // before stack_buffer_. + // + + // The buffer itself. It is not of type T because we don't want the + // constructors and destructors to be automatically called. Define a POD + // buffer of the right size instead. + char stack_buffer_[sizeof(T[stack_capacity])]; + + // Set when the stack buffer is used for an allocation. We do not track + // how much of the buffer is used, only that somebody is using it. + bool used_stack_buffer_; + }; + + // Used by containers when they want to refer to an allocator of type U. + template + struct rebind { + typedef StackAllocator other; + }; + + // For the straight up copy c-tor, we can share storage. + StackAllocator(const StackAllocator &rhs) + : source_(rhs.source_) {} + + // ISO C++ requires the following constructor to be defined, + // and std::vector in VC++2008SP1 Release fails with an error + // in the class _Container_base_aux_alloc_real (from ) + // if the constructor does not exist. + // For this constructor, we cannot share storage; there's + // no guarantee that the Source buffer of Ts is large enough + // for Us. + // TODO(Google): If we were fancy pants, perhaps we could share storage + // iff sizeof(T) == sizeof(U). + template + StackAllocator(const StackAllocator &other) + : source_(NULL) { + (void)other; + } + + explicit StackAllocator(Source *source) : source_(source) {} + + // Actually do the allocation. Use the stack buffer if nobody has used it yet + // and the size requested fits. Otherwise, fall through to the standard + // allocator. + pointer allocate(size_type n, void *hint = 0) { + if (source_ != NULL && !source_->used_stack_buffer_ && + n <= stack_capacity) { + source_->used_stack_buffer_ = true; + return source_->stack_buffer(); + } else { + return std::allocator::allocate(n, hint); + } + } + + // Free: when trying to free the stack buffer, just mark it as free. For + // non-stack-buffer pointers, just fall though to the standard allocator. + void deallocate(pointer p, size_type n) { + if (source_ != NULL && p == source_->stack_buffer()) + source_->used_stack_buffer_ = false; + else + std::allocator::deallocate(p, n); + } + + private: + Source *source_; +}; + +// A wrapper around STL containers that maintains a stack-sized buffer that the +// initial capacity of the vector is based on. Growing the container beyond the +// stack capacity will transparently overflow onto the heap. The container must +// support reserve(). +// +// WATCH OUT: the ContainerType MUST use the proper StackAllocator for this +// type. This object is really intended to be used only internally. You'll want +// to use the wrappers below for different types. +template +class StackContainer { + public: + typedef TContainerType ContainerType; + typedef typename ContainerType::value_type ContainedType; + typedef StackAllocator Allocator; + + // Allocator must be constructed before the container! + StackContainer() : allocator_(&stack_data_), container_(allocator_) { + // Make the container use the stack allocation by reserving our buffer size + // before doing anything else. + container_.reserve(stack_capacity); + } + + // Getters for the actual container. + // + // Danger: any copies of this made using the copy constructor must have + // shorter lifetimes than the source. The copy will share the same allocator + // and therefore the same stack buffer as the original. Use std::copy to + // copy into a "real" container for longer-lived objects. + ContainerType &container() { return container_; } + const ContainerType &container() const { return container_; } + + // Support operator-> to get to the container. This allows nicer syntax like: + // StackContainer<...> foo; + // std::sort(foo->begin(), foo->end()); + ContainerType *operator->() { return &container_; } + const ContainerType *operator->() const { return &container_; } + +#ifdef UNIT_TEST + // Retrieves the stack source so that that unit tests can verify that the + // buffer is being used properly. + const typename Allocator::Source &stack_data() const { return stack_data_; } +#endif + + protected: + typename Allocator::Source stack_data_; + unsigned char pad_[7]; + Allocator allocator_; + ContainerType container_; + + // DISALLOW_EVIL_CONSTRUCTORS(StackContainer); + StackContainer(const StackContainer &); + void operator=(const StackContainer &); +}; + +// StackVector +// +// Example: +// StackVector foo; +// foo->push_back(22); // we have overloaded operator-> +// foo[0] = 10; // as well as operator[] +template +class StackVector + : public StackContainer >, + stack_capacity> { + public: + StackVector() + : StackContainer >, + stack_capacity>() {} + + // We need to put this in STL containers sometimes, which requires a copy + // constructor. We can't call the regular copy constructor because that will + // take the stack buffer from the original. Here, we create an empty object + // and make a stack buffer of its own. + StackVector(const StackVector &other) + : StackContainer >, + stack_capacity>() { + this->container().assign(other->begin(), other->end()); + } + + StackVector &operator=( + const StackVector &other) { + this->container().assign(other->begin(), other->end()); + return *this; + } + + // Vectors are commonly indexed, which isn't very convenient even with + // operator-> (using "->at()" does exception stuff we don't want). + T &operator[](size_t i) { return this->container().operator[](i); } + const T &operator[](size_t i) const { + return this->container().operator[](i); + } +}; + +// ---------------------------------------------------------------------------- + +template +class real3 { + public: + real3() {} + real3(T x) { + v[0] = x; + v[1] = x; + v[2] = x; + } + real3(T xx, T yy, T zz) { + v[0] = xx; + v[1] = yy; + v[2] = zz; + } + explicit real3(const T *p) { + v[0] = p[0]; + v[1] = p[1]; + v[2] = p[2]; + } + + inline T x() const { return v[0]; } + inline T y() const { return v[1]; } + inline T z() const { return v[2]; } + + real3 operator*(T f) const { return real3(x() * f, y() * f, z() * f); } + real3 operator-(const real3 &f2) const { + return real3(x() - f2.x(), y() - f2.y(), z() - f2.z()); + } + real3 operator*(const real3 &f2) const { + return real3(x() * f2.x(), y() * f2.y(), z() * f2.z()); + } + real3 operator+(const real3 &f2) const { + return real3(x() + f2.x(), y() + f2.y(), z() + f2.z()); + } + real3 &operator+=(const real3 &f2) { + v[0] += f2.x(); + v[1] += f2.y(); + v[2] += f2.z(); + return (*this); + } + real3 operator/(const real3 &f2) const { + return real3(x() / f2.x(), y() / f2.y(), z() / f2.z()); + } + real3 operator-() const { return real3(-x(), -y(), -z()); } + T operator[](int i) const { return v[i]; } + T &operator[](int i) { return v[i]; } + + T v[3]; + // T pad; // for alignment(when T = float) +}; + +template +inline real3 operator*(T f, const real3 &v) { + return real3(v.x() * f, v.y() * f, v.z() * f); +} + +template +inline real3 vneg(const real3 &rhs) { + return real3(-rhs.x(), -rhs.y(), -rhs.z()); +} + +template +inline T vlength(const real3 &rhs) { + return std::sqrt(rhs.x() * rhs.x() + rhs.y() * rhs.y() + rhs.z() * rhs.z()); +} + +template +inline real3 vnormalize(const real3 &rhs) { + real3 v = rhs; + T len = vlength(rhs); + if (std::fabs(len) > static_cast(1.0e-6)) { + T inv_len = static_cast(1.0) / len; + v.v[0] *= inv_len; + v.v[1] *= inv_len; + v.v[2] *= inv_len; + } + return v; +} + +template +inline real3 vcross(real3 a, real3 b) { + real3 c; + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; + return c; +} + +template +inline T vdot(real3 a, real3 b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +template +inline const real *get_vertex_addr(const real *p, const size_t idx, + const size_t stride_bytes) { + return reinterpret_cast( + reinterpret_cast(p) + idx * stride_bytes); +} + +template +class Ray { + public: + Ray() : min_t(static_cast(0.0)), max_t(std::numeric_limits::max()) { + org[0] = static_cast(0.0); + org[1] = static_cast(0.0); + org[2] = static_cast(0.0); + dir[0] = static_cast(0.0); + dir[1] = static_cast(0.0); + dir[2] = static_cast(-1.0); + } + + T org[3]; // must set + T dir[3]; // must set + T min_t; // minimum ray hit distance. + T max_t; // maximum ray hit distance. + T inv_dir[3]; // filled internally + int dir_sign[3]; // filled internally +}; + +template +class BVHNode { + public: + BVHNode() {} + BVHNode(const BVHNode &rhs) { + bmin[0] = rhs.bmin[0]; + bmin[1] = rhs.bmin[1]; + bmin[2] = rhs.bmin[2]; + flag = rhs.flag; + + bmax[0] = rhs.bmax[0]; + bmax[1] = rhs.bmax[1]; + bmax[2] = rhs.bmax[2]; + axis = rhs.axis; + + data[0] = rhs.data[0]; + data[1] = rhs.data[1]; + } + + BVHNode &operator=(const BVHNode &rhs) { + bmin[0] = rhs.bmin[0]; + bmin[1] = rhs.bmin[1]; + bmin[2] = rhs.bmin[2]; + flag = rhs.flag; + + bmax[0] = rhs.bmax[0]; + bmax[1] = rhs.bmax[1]; + bmax[2] = rhs.bmax[2]; + axis = rhs.axis; + + data[0] = rhs.data[0]; + data[1] = rhs.data[1]; + + return (*this); + } + + ~BVHNode() {} + + T bmin[3]; + T bmax[3]; + + int flag; // 1 = leaf node, 0 = branch node + int axis; + + // leaf + // data[0] = npoints + // data[1] = index + // + // branch + // data[0] = child[0] + // data[1] = child[1] + unsigned int data[2]; +}; + +template +class IntersectComparator { + public: + bool operator()(const H &a, const H &b) const { return a.t < b.t; } +}; + +/// BVH build option. +template +struct BVHBuildOptions { + T cost_t_aabb; + unsigned int min_leaf_primitives; + unsigned int max_tree_depth; + unsigned int bin_size; + unsigned int shallow_depth; + unsigned int min_primitives_for_parallel_build; + + // Cache bounding box computation. + // Requires more memory, but BVHbuild can be faster. + bool cache_bbox; + unsigned char pad[3]; + + // Set default value: Taabb = 0.2 + BVHBuildOptions() + : cost_t_aabb(0.2f), + min_leaf_primitives(4), + max_tree_depth(256), + bin_size(64), + shallow_depth(3), + min_primitives_for_parallel_build(1024 * 128), + cache_bbox(false) {} +}; + +/// BVH build statistics. +class BVHBuildStatistics { + public: + unsigned int max_tree_depth; + unsigned int num_leaf_nodes; + unsigned int num_branch_nodes; + float build_secs; + + // Set default value: Taabb = 0.2 + BVHBuildStatistics() + : max_tree_depth(0), + num_leaf_nodes(0), + num_branch_nodes(0), + build_secs(0.0f) {} +}; + +/// BVH trace option. +class BVHTraceOptions { + public: + // Hit only for face IDs in indexRange. + // This feature is good to mimic something like glDrawArrays() + unsigned int prim_ids_range[2]; + bool cull_back_face; + unsigned char pad[3]; ///< Padding(not used) + + BVHTraceOptions() { + prim_ids_range[0] = 0; + prim_ids_range[1] = 0x7FFFFFFF; // Up to 2G face IDs. + cull_back_face = false; + } +}; + +template +class BBox { + public: + real3 bmin; + real3 bmax; + + BBox() { + bmin[0] = bmin[1] = bmin[2] = std::numeric_limits::max(); + bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits::max(); + } +}; + +template +class NodeHit { + public: + NodeHit() + : t_min(std::numeric_limits::max()), + t_max(-std::numeric_limits::max()), + node_id(static_cast(-1)) {} + + NodeHit(const NodeHit &rhs) { + t_min = rhs.t_min; + t_max = rhs.t_max; + node_id = rhs.node_id; + } + + NodeHit &operator=(const NodeHit &rhs) { + t_min = rhs.t_min; + t_max = rhs.t_max; + node_id = rhs.node_id; + + return (*this); + } + + ~NodeHit() {} + + T t_min; + T t_max; + unsigned int node_id; +}; + +template +class NodeHitComparator { + public: + inline bool operator()(const NodeHit &a, const NodeHit &b) { + return a.t_min < b.t_min; + } +}; + +template +class BVHAccel { + public: + BVHAccel() : pad0_(0) { (void)pad0_; } + ~BVHAccel() {} + + /// + /// Build BVH for input primitives. + /// + template + bool Build(const unsigned int num_primitives, const P &p, const Pred &pred, + const BVHBuildOptions &options = BVHBuildOptions()); + + /// + /// Get statistics of built BVH tree. Valid after Build() + /// + BVHBuildStatistics GetStatistics() const { return stats_; } + + /// + /// Dump built BVH to the file. + /// + bool Dump(const char *filename); + + /// + /// Load BVH binary + /// + bool Load(const char *filename); + + void Debug(); + + /// + /// Traverse into BVH along ray and find closest hit point & primitive if + /// found + /// + template + bool Traverse(const Ray &ray, const I &intersector, H *isect, + const BVHTraceOptions &options = BVHTraceOptions()) const; + +#if 0 + /// Multi-hit ray traversal + /// Returns `max_intersections` frontmost intersections + template + bool MultiHitTraverse(const Ray &ray, + int max_intersections, + const I &intersector, + StackVector *isects, + const BVHTraceOptions &options = BVHTraceOptions()) const; +#endif + + /// + /// List up nodes which intersects along the ray. + /// This function is useful for two-level BVH traversal. + /// + template + bool ListNodeIntersections(const Ray &ray, int max_intersections, + const I &intersector, + StackVector, 128> *hits) const; + + const std::vector > &GetNodes() const { return nodes_; } + const std::vector &GetIndices() const { return indices_; } + + /// + /// Returns bounding box of built BVH. + /// + void BoundingBox(T bmin[3], T bmax[3]) const { + if (nodes_.empty()) { + bmin[0] = bmin[1] = bmin[2] = std::numeric_limits::max(); + bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits::max(); + } else { + bmin[0] = nodes_[0].bmin[0]; + bmin[1] = nodes_[0].bmin[1]; + bmin[2] = nodes_[0].bmin[2]; + bmax[0] = nodes_[0].bmax[0]; + bmax[1] = nodes_[0].bmax[1]; + bmax[2] = nodes_[0].bmax[2]; + } + } + + bool IsValid() const { return nodes_.size() > 0; } + + private: +#if NANORT_ENABLE_PARALLEL_BUILD + typedef struct { + unsigned int left_idx; + unsigned int right_idx; + unsigned int offset; + } ShallowNodeInfo; + + // Used only during BVH construction + std::vector shallow_node_infos_; + + /// Builds shallow BVH tree recursively. + template + unsigned int BuildShallowTree(std::vector > *out_nodes, + unsigned int left_idx, unsigned int right_idx, + unsigned int depth, + unsigned int max_shallow_depth, const P &p, + const Pred &pred); +#endif + + /// Builds BVH tree recursively. + template + unsigned int BuildTree(BVHBuildStatistics *out_stat, + std::vector > *out_nodes, + unsigned int left_idx, unsigned int right_idx, + unsigned int depth, const P &p, const Pred &pred); + + template + bool TestLeafNode(const BVHNode &node, const Ray &ray, + const I &intersector) const; + + template + bool TestLeafNodeIntersections( + const BVHNode &node, const Ray &ray, const int max_intersections, + const I &intersector, + std::priority_queue, std::vector >, + NodeHitComparator > *isect_pq) const; + +#if 0 + template + bool MultiHitTestLeafNode(std::priority_queue, Comp> *isect_pq, + int max_intersections, + const BVHNode &node, const Ray &ray, + const I &intersector) const; +#endif + + std::vector > nodes_; + std::vector indices_; // max 4G triangles. + std::vector > bboxes_; + BVHBuildOptions options_; + BVHBuildStatistics stats_; + unsigned int pad0_; +}; + +// Predefined SAH predicator for triangle. +template +class TriangleSAHPred { + public: + TriangleSAHPred( + const T *vertices, const unsigned int *faces, + size_t vertex_stride_bytes) // e.g. 12 for sizeof(float) * XYZ + : axis_(0), + pos_(0.0f), + vertices_(vertices), + faces_(faces), + vertex_stride_bytes_(vertex_stride_bytes) {} + + void Set(int axis, T pos) const { + axis_ = axis; + pos_ = pos; + } + + bool operator()(unsigned int i) const { + int axis = axis_; + T pos = pos_; + + unsigned int i0 = faces_[3 * i + 0]; + unsigned int i1 = faces_[3 * i + 1]; + unsigned int i2 = faces_[3 * i + 2]; + + real3 p0(get_vertex_addr(vertices_, i0, vertex_stride_bytes_)); + real3 p1(get_vertex_addr(vertices_, i1, vertex_stride_bytes_)); + real3 p2(get_vertex_addr(vertices_, i2, vertex_stride_bytes_)); + + T center = p0[axis] + p1[axis] + p2[axis]; + + return (center < pos * static_cast(3.0)); + } + + private: + mutable int axis_; + mutable T pos_; + const T *vertices_; + const unsigned int *faces_; + const size_t vertex_stride_bytes_; +}; + +// Predefined Triangle mesh geometry. +template +class TriangleMesh { + public: + TriangleMesh( + const T *vertices, const unsigned int *faces, + const size_t vertex_stride_bytes) // e.g. 12 for sizeof(float) * XYZ + : vertices_(vertices), + faces_(faces), + vertex_stride_bytes_(vertex_stride_bytes) {} + + /// Compute bounding box for `prim_index`th triangle. + /// This function is called for each primitive in BVH build. + void BoundingBox(real3 *bmin, real3 *bmax, + unsigned int prim_index) const { + (*bmin)[0] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[0]; + (*bmin)[1] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[1]; + (*bmin)[2] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[2]; + (*bmax)[0] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[0]; + (*bmax)[1] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[1]; + (*bmax)[2] = get_vertex_addr(vertices_, faces_[3 * prim_index + 0], + vertex_stride_bytes_)[2]; + + for (unsigned int i = 1; i < 3; i++) { + for (unsigned int k = 0; k < 3; k++) { + if ((*bmin)[static_cast(k)] > + get_vertex_addr(vertices_, faces_[3 * prim_index + i], + vertex_stride_bytes_)[k]) { + (*bmin)[static_cast(k)] = get_vertex_addr( + vertices_, faces_[3 * prim_index + i], vertex_stride_bytes_)[k]; + } + if ((*bmax)[static_cast(k)] < + get_vertex_addr(vertices_, faces_[3 * prim_index + i], + vertex_stride_bytes_)[k]) { + (*bmax)[static_cast(k)] = get_vertex_addr( + vertices_, faces_[3 * prim_index + i], vertex_stride_bytes_)[k]; + } + } + } + } + + const T *vertices_; + const unsigned int *faces_; + const size_t vertex_stride_bytes_; +}; + +template +class TriangleIntersection { + public: + T u; + T v; + + // Required member variables. + T t; + unsigned int prim_id; +}; + +template > +class TriangleIntersector { + public: + TriangleIntersector(const T *vertices, const unsigned int *faces, + const size_t vertex_stride_bytes) // e.g. + // vertex_stride_bytes + // = 12 = sizeof(float) + // * 3 + : vertices_(vertices), + faces_(faces), + vertex_stride_bytes_(vertex_stride_bytes) {} + + // For Watertight Ray/Triangle Intersection. + typedef struct { + T Sx; + T Sy; + T Sz; + int kx; + int ky; + int kz; + } RayCoeff; + + /// Do ray interesection stuff for `prim_index` th primitive and return hit + /// distance `t`, + /// varycentric coordinate `u` and `v`. + /// Returns true if there's intersection. + bool Intersect(T *t_inout, const unsigned int prim_index) const { + if ((prim_index < trace_options_.prim_ids_range[0]) || + (prim_index >= trace_options_.prim_ids_range[1])) { + return false; + } + + const unsigned int f0 = faces_[3 * prim_index + 0]; + const unsigned int f1 = faces_[3 * prim_index + 1]; + const unsigned int f2 = faces_[3 * prim_index + 2]; + + const real3 p0(get_vertex_addr(vertices_, f0 + 0, vertex_stride_bytes_)); + const real3 p1(get_vertex_addr(vertices_, f1 + 0, vertex_stride_bytes_)); + const real3 p2(get_vertex_addr(vertices_, f2 + 0, vertex_stride_bytes_)); + + const real3 A = p0 - ray_org_; + const real3 B = p1 - ray_org_; + const real3 C = p2 - ray_org_; + + const T Ax = A[ray_coeff_.kx] - ray_coeff_.Sx * A[ray_coeff_.kz]; + const T Ay = A[ray_coeff_.ky] - ray_coeff_.Sy * A[ray_coeff_.kz]; + const T Bx = B[ray_coeff_.kx] - ray_coeff_.Sx * B[ray_coeff_.kz]; + const T By = B[ray_coeff_.ky] - ray_coeff_.Sy * B[ray_coeff_.kz]; + const T Cx = C[ray_coeff_.kx] - ray_coeff_.Sx * C[ray_coeff_.kz]; + const T Cy = C[ray_coeff_.ky] - ray_coeff_.Sy * C[ray_coeff_.kz]; + + T U = Cx * By - Cy * Bx; + T V = Ax * Cy - Ay * Cx; + T W = Bx * Ay - By * Ax; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#endif + + // Fall back to test against edges using double precision. + if (U == static_cast(0.0) || V == static_cast(0.0) || W == static_cast(0.0)) { + double CxBy = static_cast(Cx) * static_cast(By); + double CyBx = static_cast(Cy) * static_cast(Bx); + U = static_cast(CxBy - CyBx); + + double AxCy = static_cast(Ax) * static_cast(Cy); + double AyCx = static_cast(Ay) * static_cast(Cx); + V = static_cast(AxCy - AyCx); + + double BxAy = static_cast(Bx) * static_cast(Ay); + double ByAx = static_cast(By) * static_cast(Ax); + W = static_cast(BxAy - ByAx); + } + + if (trace_options_.cull_back_face) { + if (U < static_cast(0.0) || V < static_cast(0.0) || W < static_cast(0.0)) return false; + } else { + if ((U < static_cast(0.0) || V < static_cast(0.0) || W < static_cast(0.0)) && (U > static_cast(0.0) || V > static_cast(0.0) || W > static_cast(0.0))) { + return false; + } + } + + T det = U + V + W; + if (det == static_cast(0.0)) return false; + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + const T Az = ray_coeff_.Sz * A[ray_coeff_.kz]; + const T Bz = ray_coeff_.Sz * B[ray_coeff_.kz]; + const T Cz = ray_coeff_.Sz * C[ray_coeff_.kz]; + const T D = U * Az + V * Bz + W * Cz; + + const T rcpDet = static_cast(1.0) / det; + T tt = D * rcpDet; + + if (tt > (*t_inout)) { + return false; + } + + if (tt < t_min_) { + return false; + } + + (*t_inout) = tt; + // Use Thomas-Mueller style barycentric coord. + // U + V + W = 1.0 and interp(p) = U * p0 + V * p1 + W * p2 + // We want interp(p) = (1 - u - v) * p0 + u * v1 + v * p2; + // => u = V, v = W. + u_ = V * rcpDet; + v_ = W * rcpDet; + + return true; + } + + /// Returns the nearest hit distance. + T GetT() const { return t_; } + + /// Update is called when initializing intesection and nearest hit is found. + void Update(T t, unsigned int prim_idx) const { + t_ = t; + prim_id_ = prim_idx; + } + + /// Prepare BVH traversal(e.g. compute inverse ray direction) + /// This function is called only once in BVH traversal. + void PrepareTraversal(const Ray &ray, + const BVHTraceOptions &trace_options) const { + ray_org_[0] = ray.org[0]; + ray_org_[1] = ray.org[1]; + ray_org_[2] = ray.org[2]; + + // Calculate dimension where the ray direction is maximal. + ray_coeff_.kz = 0; + T absDir = std::fabs(ray.dir[0]); + if (absDir < std::fabs(ray.dir[1])) { + ray_coeff_.kz = 1; + absDir = std::fabs(ray.dir[1]); + } + if (absDir < std::fabs(ray.dir[2])) { + ray_coeff_.kz = 2; + absDir = std::fabs(ray.dir[2]); + } + + ray_coeff_.kx = ray_coeff_.kz + 1; + if (ray_coeff_.kx == 3) ray_coeff_.kx = 0; + ray_coeff_.ky = ray_coeff_.kx + 1; + if (ray_coeff_.ky == 3) ray_coeff_.ky = 0; + + // Swap kx and ky dimention to preserve widing direction of triangles. + if (ray.dir[ray_coeff_.kz] < 0.0f) std::swap(ray_coeff_.kx, ray_coeff_.ky); + + // Claculate shear constants. + ray_coeff_.Sx = ray.dir[ray_coeff_.kx] / ray.dir[ray_coeff_.kz]; + ray_coeff_.Sy = ray.dir[ray_coeff_.ky] / ray.dir[ray_coeff_.kz]; + ray_coeff_.Sz = 1.0f / ray.dir[ray_coeff_.kz]; + + trace_options_ = trace_options; + + t_min_ = ray.min_t; + + u_ = 0.0f; + v_ = 0.0f; + } + + /// Post BVH traversal stuff. + /// Fill `isect` if there is a hit. + void PostTraversal(const Ray &ray, bool hit, H *isect) const { + if (hit && isect) { + (*isect).t = t_; + (*isect).u = u_; + (*isect).v = v_; + (*isect).prim_id = prim_id_; + } + (void)ray; + } + + private: + const T *vertices_; + const unsigned int *faces_; + const size_t vertex_stride_bytes_; + + mutable real3 ray_org_; + mutable RayCoeff ray_coeff_; + mutable BVHTraceOptions trace_options_; + mutable T t_min_; + + mutable T t_; + mutable T u_; + mutable T v_; + mutable unsigned int prim_id_; + int _pad_; +}; + +// +// Robust BVH Ray Traversal : http://jcgt.org/published/0002/02/02/paper.pdf +// + +// NaN-safe min and max function. +template +const T &safemin(const T &a, const T &b) { + return (a < b) ? a : b; +} +template +const T &safemax(const T &a, const T &b) { + return (a > b) ? a : b; +} + +// +// SAH functions +// +struct BinBuffer { + explicit BinBuffer(unsigned int size) { + bin_size = size; + bin.resize(2 * 3 * size); + clear(); + } + + void clear() { memset(&bin[0], 0, sizeof(size_t) * 2 * 3 * bin_size); } + + std::vector bin; // (min, max) * xyz * binsize + unsigned int bin_size; + unsigned int pad0; +}; + +template +inline T CalculateSurfaceArea(const real3 &min, const real3 &max) { + real3 box = max - min; + return static_cast(2.0) * + (box[0] * box[1] + box[1] * box[2] + box[2] * box[0]); +} + +template +inline void GetBoundingBoxOfTriangle(real3 *bmin, real3 *bmax, + const T *vertices, + const unsigned int *faces, + unsigned int index) { + unsigned int f0 = faces[3 * index + 0]; + unsigned int f1 = faces[3 * index + 1]; + unsigned int f2 = faces[3 * index + 2]; + + real3 p[3]; + + p[0] = real3(&vertices[3 * f0]); + p[1] = real3(&vertices[3 * f1]); + p[2] = real3(&vertices[3 * f2]); + + (*bmin) = p[0]; + (*bmax) = p[0]; + + for (int i = 1; i < 3; i++) { + (*bmin)[0] = std::min((*bmin)[0], p[i][0]); + (*bmin)[1] = std::min((*bmin)[1], p[i][1]); + (*bmin)[2] = std::min((*bmin)[2], p[i][2]); + + (*bmax)[0] = std::max((*bmax)[0], p[i][0]); + (*bmax)[1] = std::max((*bmax)[1], p[i][1]); + (*bmax)[2] = std::max((*bmax)[2], p[i][2]); + } +} + +template +inline void ContributeBinBuffer(BinBuffer *bins, // [out] + const real3 &scene_min, + const real3 &scene_max, + unsigned int *indices, unsigned int left_idx, + unsigned int right_idx, const P &p) { + T bin_size = static_cast(bins->bin_size); + + // Calculate extent + real3 scene_size, scene_inv_size; + scene_size = scene_max - scene_min; + for (int i = 0; i < 3; ++i) { + assert(scene_size[i] >= static_cast(0.0)); + + if (scene_size[i] > static_cast(0.0)) { + scene_inv_size[i] = bin_size / scene_size[i]; + } else { + scene_inv_size[i] = static_cast(0.0); + } + } + + // Clear bin data + std::fill(bins->bin.begin(), bins->bin.end(), 0); + // memset(&bins->bin[0], 0, sizeof(2 * 3 * bins->bin_size)); + + size_t idx_bmin[3]; + size_t idx_bmax[3]; + + for (size_t i = left_idx; i < right_idx; i++) { + // + // Quantize the position into [0, BIN_SIZE) + // + // q[i] = (int)(p[i] - scene_bmin) / scene_size + // + real3 bmin; + real3 bmax; + + p.BoundingBox(&bmin, &bmax, indices[i]); + // GetBoundingBoxOfTriangle(&bmin, &bmax, vertices, faces, indices[i]); + + real3 quantized_bmin = (bmin - scene_min) * scene_inv_size; + real3 quantized_bmax = (bmax - scene_min) * scene_inv_size; + + // idx is now in [0, BIN_SIZE) + for (int j = 0; j < 3; ++j) { + int q0 = static_cast(quantized_bmin[j]); + if (q0 < 0) q0 = 0; + int q1 = static_cast(quantized_bmax[j]); + if (q1 < 0) q1 = 0; + + idx_bmin[j] = static_cast(q0); + idx_bmax[j] = static_cast(q1); + + if (idx_bmin[j] >= bin_size) + idx_bmin[j] = static_cast(bin_size) - 1; + if (idx_bmax[j] >= bin_size) + idx_bmax[j] = static_cast(bin_size) - 1; + + assert(idx_bmin[j] < bin_size); + assert(idx_bmax[j] < bin_size); + + // Increment bin counter + bins->bin[0 * (bins->bin_size * 3) + + static_cast(j) * bins->bin_size + idx_bmin[j]] += 1; + bins->bin[1 * (bins->bin_size * 3) + + static_cast(j) * bins->bin_size + idx_bmax[j]] += 1; + } + } +} + +template +inline T SAH(size_t ns1, T leftArea, size_t ns2, T rightArea, T invS, T Taabb, + T Ttri) { + T sah; + + sah = static_cast(2.0) * Taabb + + (leftArea * invS) * static_cast(ns1) * Ttri + + (rightArea * invS) * static_cast(ns2) * Ttri; + + return sah; +} + +template +inline bool FindCutFromBinBuffer(T *cut_pos, // [out] xyz + int *minCostAxis, // [out] + const BinBuffer *bins, const real3 &bmin, + const real3 &bmax, size_t num_primitives, + T costTaabb) { // should be in [0.0, 1.0] + const T kEPS = std::numeric_limits::epsilon(); // * epsScale; + + size_t left, right; + real3 bsize, bstep; + real3 bminLeft, bmaxLeft; + real3 bminRight, bmaxRight; + T saLeft, saRight, saTotal; + T pos; + T minCost[3]; + + T costTtri = static_cast(1.0) - costTaabb; + + (*minCostAxis) = 0; + + bsize = bmax - bmin; + bstep = bsize * (static_cast(1.0) / bins->bin_size); + saTotal = CalculateSurfaceArea(bmin, bmax); + + T invSaTotal = static_cast(0.0); + if (saTotal > kEPS) { + invSaTotal = static_cast(1.0) / saTotal; + } + + for (int j = 0; j < 3; ++j) { + // + // Compute SAH cost for the right side of each cell of the bbox. + // Exclude both extreme side of the bbox. + // + // i: 0 1 2 3 + // +----+----+----+----+----+ + // | | | | | | + // +----+----+----+----+----+ + // + + T minCostPos = bmin[j] + static_cast(1.0) * bstep[j]; + minCost[j] = std::numeric_limits::max(); + + left = 0; + right = num_primitives; + bminLeft = bminRight = bmin; + bmaxLeft = bmaxRight = bmax; + + for (int i = 0; i < static_cast(bins->bin_size) - 1; ++i) { + left += bins->bin[0 * (3 * bins->bin_size) + + static_cast(j) * bins->bin_size + + static_cast(i)]; + right -= bins->bin[1 * (3 * bins->bin_size) + + static_cast(j) * bins->bin_size + + static_cast(i)]; + + assert(left <= num_primitives); + assert(right <= num_primitives); + + // + // Split pos bmin + (i + 1) * (bsize / BIN_SIZE) + // +1 for i since we want a position on right side of the cell. + // + + pos = bmin[j] + (i + static_cast(1.0)) * bstep[j]; + bmaxLeft[j] = pos; + bminRight[j] = pos; + + saLeft = CalculateSurfaceArea(bminLeft, bmaxLeft); + saRight = CalculateSurfaceArea(bminRight, bmaxRight); + + T cost = + SAH(left, saLeft, right, saRight, invSaTotal, costTaabb, costTtri); + if (cost < minCost[j]) { + // + // Update the min cost + // + minCost[j] = cost; + minCostPos = pos; + // minCostAxis = j; + } + } + + cut_pos[j] = minCostPos; + } + + // cut_axis = minCostAxis; + // cut_pos = minCostPos; + + // Find min cost axis + T cost = minCost[0]; + (*minCostAxis) = 0; + if (cost > minCost[1]) { + (*minCostAxis) = 1; + cost = minCost[1]; + } + if (cost > minCost[2]) { + (*minCostAxis) = 2; + cost = minCost[2]; + } + + return true; +} + +#ifdef _OPENMP +template +void ComputeBoundingBoxOMP(real3 *bmin, real3 *bmax, + const unsigned int *indices, unsigned int left_index, + unsigned int right_index, const P &p) { + { p.BoundingBox(bmin, bmax, indices[left_index]); } + + T local_bmin[3] = {(*bmin)[0], (*bmin)[1], (*bmin)[2]}; + T local_bmax[3] = {(*bmax)[0], (*bmax)[1], (*bmax)[2]}; + + unsigned int n = right_index - left_index; + +#pragma omp parallel firstprivate(local_bmin, local_bmax) if (n > (1024 * 128)) + { +#pragma omp for + for (int i = left_index; i < right_index; i++) { // for each faces + unsigned int idx = indices[i]; + + real3 bbox_min, bbox_max; + p.BoundingBox(&bbox_min, &bbox_max, idx); + for (int k = 0; k < 3; k++) { // xyz + if ((*bmin)[k] > bbox_min[k]) (*bmin)[k] = bbox_min[k]; + if ((*bmax)[k] < bbox_max[k]) (*bmax)[k] = bbox_max[k]; + } + } + +#pragma omp critical + { + for (int k = 0; k < 3; k++) { + if (local_bmin[k] < (*bmin)[k]) { + { + if (local_bmin[k] < (*bmin)[k]) (*bmin)[k] = local_bmin[k]; + } + } + + if (local_bmax[k] > (*bmax)[k]) { + { + if (local_bmax[k] > (*bmax)[k]) (*bmax)[k] = local_bmax[k]; + } + } + } + } + } +} +#endif + +template +inline void ComputeBoundingBox(real3 *bmin, real3 *bmax, + const unsigned int *indices, + unsigned int left_index, + unsigned int right_index, const P &p) { + { + unsigned int idx = indices[left_index]; + p.BoundingBox(bmin, bmax, idx); + } + + { + for (unsigned int i = left_index + 1; i < right_index; + i++) { // for each primitives + unsigned int idx = indices[i]; + real3 bbox_min, bbox_max; + p.BoundingBox(&bbox_min, &bbox_max, idx); + for (int k = 0; k < 3; k++) { // xyz + if ((*bmin)[k] > bbox_min[k]) (*bmin)[k] = bbox_min[k]; + if ((*bmax)[k] < bbox_max[k]) (*bmax)[k] = bbox_max[k]; + } + } + } +} + +template +inline void GetBoundingBox(real3 *bmin, real3 *bmax, + const std::vector > &bboxes, + unsigned int *indices, unsigned int left_index, + unsigned int right_index) { + { + unsigned int i = left_index; + unsigned int idx = indices[i]; + (*bmin)[0] = bboxes[idx].bmin[0]; + (*bmin)[1] = bboxes[idx].bmin[1]; + (*bmin)[2] = bboxes[idx].bmin[2]; + (*bmax)[0] = bboxes[idx].bmax[0]; + (*bmax)[1] = bboxes[idx].bmax[1]; + (*bmax)[2] = bboxes[idx].bmax[2]; + } + + T local_bmin[3] = {(*bmin)[0], (*bmin)[1], (*bmin)[2]}; + T local_bmax[3] = {(*bmax)[0], (*bmax)[1], (*bmax)[2]}; + + { + for (unsigned int i = left_index; i < right_index; i++) { // for each faces + unsigned int idx = indices[i]; + + for (int k = 0; k < 3; k++) { // xyz + T minval = bboxes[idx].bmin[k]; + T maxval = bboxes[idx].bmax[k]; + if (local_bmin[k] > minval) local_bmin[k] = minval; + if (local_bmax[k] < maxval) local_bmax[k] = maxval; + } + } + + for (int k = 0; k < 3; k++) { + (*bmin)[k] = local_bmin[k]; + (*bmax)[k] = local_bmax[k]; + } + } +} + +// +// -- +// + +#if NANORT_ENABLE_PARALLEL_BUILD +template +template +unsigned int BVHAccel::BuildShallowTree(std::vector > *out_nodes, + unsigned int left_idx, + unsigned int right_idx, + unsigned int depth, + unsigned int max_shallow_depth, + const P &p, const Pred &pred) { + assert(left_idx <= right_idx); + + unsigned int offset = static_cast(out_nodes->size()); + + if (stats_.max_tree_depth < depth) { + stats_.max_tree_depth = depth; + } + + real3 bmin, bmax; + ComputeBoundingBox(&bmin, &bmax, &indices_.at(0), left_idx, right_idx, p); + + unsigned int n = right_idx - left_idx; + if ((n <= options_.min_leaf_primitives) || + (depth >= options_.max_tree_depth)) { + // Create leaf node. + BVHNode leaf; + + leaf.bmin[0] = bmin[0]; + leaf.bmin[1] = bmin[1]; + leaf.bmin[2] = bmin[2]; + + leaf.bmax[0] = bmax[0]; + leaf.bmax[1] = bmax[1]; + leaf.bmax[2] = bmax[2]; + + assert(left_idx < std::numeric_limits::max()); + + leaf.flag = 1; // leaf + leaf.data[0] = n; + leaf.data[1] = left_idx; + + out_nodes->push_back(leaf); // atomic update + + stats_.num_leaf_nodes++; + + return offset; + } + + // + // Create branch node. + // + if (depth >= max_shallow_depth) { + // Delay to build tree + ShallowNodeInfo info; + info.left_idx = left_idx; + info.right_idx = right_idx; + info.offset = offset; + shallow_node_infos_.push_back(info); + + // Add dummy node. + BVHNode node; + node.axis = -1; + node.flag = -1; + out_nodes->push_back(node); + + return offset; + + } else { + // + // Compute SAH and find best split axis and position + // + int min_cut_axis = 0; + T cut_pos[3] = {0.0, 0.0, 0.0}; + + BinBuffer bins(options_.bin_size); + ContributeBinBuffer(&bins, bmin, bmax, &indices_.at(0), left_idx, right_idx, + p); + FindCutFromBinBuffer(cut_pos, &min_cut_axis, &bins, bmin, bmax, n, + options_.cost_t_aabb); + + // Try all 3 axis until good cut position avaiable. + unsigned int mid_idx = left_idx; + int cut_axis = min_cut_axis; + for (int axis_try = 0; axis_try < 3; axis_try++) { + unsigned int *begin = &indices_[left_idx]; + unsigned int *end = + &indices_[right_idx - 1] + 1; // mimics end() iterator. + unsigned int *mid = 0; + + // try min_cut_axis first. + cut_axis = (min_cut_axis + axis_try) % 3; + + // @fixme { We want some thing like: std::partition(begin, end, + // pred(cut_axis, cut_pos[cut_axis])); } + pred.Set(cut_axis, cut_pos[cut_axis]); + // + // Split at (cut_axis, cut_pos) + // indices_ will be modified. + // + mid = std::partition(begin, end, pred); + + mid_idx = left_idx + static_cast((mid - begin)); + if ((mid_idx == left_idx) || (mid_idx == right_idx)) { + // Can't split well. + // Switch to object median(which may create unoptimized tree, but + // stable) + mid_idx = left_idx + (n >> 1); + + // Try another axis if there's axis to try. + + } else { + // Found good cut. exit loop. + break; + } + } + + BVHNode node; + node.axis = cut_axis; + node.flag = 0; // 0 = branch + + out_nodes->push_back(node); + + unsigned int left_child_index = 0; + unsigned int right_child_index = 0; + + left_child_index = BuildShallowTree(out_nodes, left_idx, mid_idx, depth + 1, + max_shallow_depth, p, pred); + + right_child_index = BuildShallowTree(out_nodes, mid_idx, right_idx, + depth + 1, max_shallow_depth, p, pred); + + (*out_nodes)[offset].data[0] = left_child_index; + (*out_nodes)[offset].data[1] = right_child_index; + + (*out_nodes)[offset].bmin[0] = bmin[0]; + (*out_nodes)[offset].bmin[1] = bmin[1]; + (*out_nodes)[offset].bmin[2] = bmin[2]; + + (*out_nodes)[offset].bmax[0] = bmax[0]; + (*out_nodes)[offset].bmax[1] = bmax[1]; + (*out_nodes)[offset].bmax[2] = bmax[2]; + } + + stats_.num_branch_nodes++; + + return offset; +} +#endif + +template +template +unsigned int BVHAccel::BuildTree(BVHBuildStatistics *out_stat, + std::vector > *out_nodes, + unsigned int left_idx, + unsigned int right_idx, unsigned int depth, + const P &p, const Pred &pred) { + assert(left_idx <= right_idx); + + unsigned int offset = static_cast(out_nodes->size()); + + if (out_stat->max_tree_depth < depth) { + out_stat->max_tree_depth = depth; + } + + real3 bmin, bmax; + if (!bboxes_.empty()) { + GetBoundingBox(&bmin, &bmax, bboxes_, &indices_.at(0), left_idx, right_idx); + } else { + ComputeBoundingBox(&bmin, &bmax, &indices_.at(0), left_idx, right_idx, p); + } + + unsigned int n = right_idx - left_idx; + if ((n <= options_.min_leaf_primitives) || + (depth >= options_.max_tree_depth)) { + // Create leaf node. + BVHNode leaf; + + leaf.bmin[0] = bmin[0]; + leaf.bmin[1] = bmin[1]; + leaf.bmin[2] = bmin[2]; + + leaf.bmax[0] = bmax[0]; + leaf.bmax[1] = bmax[1]; + leaf.bmax[2] = bmax[2]; + + assert(left_idx < std::numeric_limits::max()); + + leaf.flag = 1; // leaf + leaf.data[0] = n; + leaf.data[1] = left_idx; + + out_nodes->push_back(leaf); // atomic update + + out_stat->num_leaf_nodes++; + + return offset; + } + + // + // Create branch node. + // + + // + // Compute SAH and find best split axis and position + // + int min_cut_axis = 0; + T cut_pos[3] = {0.0, 0.0, 0.0}; + + BinBuffer bins(options_.bin_size); + ContributeBinBuffer(&bins, bmin, bmax, &indices_.at(0), left_idx, right_idx, + p); + FindCutFromBinBuffer(cut_pos, &min_cut_axis, &bins, bmin, bmax, n, + options_.cost_t_aabb); + + // Try all 3 axis until good cut position avaiable. + unsigned int mid_idx = left_idx; + int cut_axis = min_cut_axis; + for (int axis_try = 0; axis_try < 3; axis_try++) { + unsigned int *begin = &indices_[left_idx]; + unsigned int *end = &indices_[right_idx - 1] + 1; // mimics end() iterator. + unsigned int *mid = 0; + + // try min_cut_axis first. + cut_axis = (min_cut_axis + axis_try) % 3; + + pred.Set(cut_axis, cut_pos[cut_axis]); + + // + // Split at (cut_axis, cut_pos) + // indices_ will be modified. + // + mid = std::partition(begin, end, pred); + + mid_idx = left_idx + static_cast((mid - begin)); + if ((mid_idx == left_idx) || (mid_idx == right_idx)) { + // Can't split well. + // Switch to object median(which may create unoptimized tree, but + // stable) + mid_idx = left_idx + (n >> 1); + + // Try another axis to find better cut. + + } else { + // Found good cut. exit loop. + break; + } + } + + BVHNode node; + node.axis = cut_axis; + node.flag = 0; // 0 = branch + + out_nodes->push_back(node); + + unsigned int left_child_index = 0; + unsigned int right_child_index = 0; + + left_child_index = + BuildTree(out_stat, out_nodes, left_idx, mid_idx, depth + 1, p, pred); + + right_child_index = + BuildTree(out_stat, out_nodes, mid_idx, right_idx, depth + 1, p, pred); + + { + (*out_nodes)[offset].data[0] = left_child_index; + (*out_nodes)[offset].data[1] = right_child_index; + + (*out_nodes)[offset].bmin[0] = bmin[0]; + (*out_nodes)[offset].bmin[1] = bmin[1]; + (*out_nodes)[offset].bmin[2] = bmin[2]; + + (*out_nodes)[offset].bmax[0] = bmax[0]; + (*out_nodes)[offset].bmax[1] = bmax[1]; + (*out_nodes)[offset].bmax[2] = bmax[2]; + } + + out_stat->num_branch_nodes++; + + return offset; +} + +template +template +bool BVHAccel::Build(unsigned int num_primitives, const P &p, + const Pred &pred, const BVHBuildOptions &options) { + options_ = options; + stats_ = BVHBuildStatistics(); + + nodes_.clear(); + bboxes_.clear(); + + assert(options_.bin_size > 1); + + if (num_primitives == 0) { + return false; + } + + unsigned int n = num_primitives; + + // + // 1. Create triangle indices(this will be permutated in BuildTree) + // + indices_.resize(n); + +#ifdef _OPENMP +#pragma omp parallel for +#endif + for (int i = 0; i < static_cast(n); i++) { + indices_[static_cast(i)] = static_cast(i); + } + + // + // 2. Compute bounding box(optional). + // + real3 bmin, bmax; + if (options.cache_bbox) { + bmin[0] = bmin[1] = bmin[2] = std::numeric_limits::max(); + bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits::max(); + + bboxes_.resize(n); + for (size_t i = 0; i < n; i++) { // for each primitived + unsigned int idx = indices_[i]; + + BBox bbox; + p.BoundingBox(&(bbox.bmin), &(bbox.bmax), static_cast(i)); + bboxes_[idx] = bbox; + + for (int k = 0; k < 3; k++) { // xyz + if (bmin[k] > bbox.bmin[k]) { + bmin[k] = bbox.bmin[k]; + } + if (bmax[k] < bbox.bmax[k]) { + bmax[k] = bbox.bmax[k]; + } + } + } + + } else { +#ifdef _OPENMP + ComputeBoundingBoxOMP(&bmin, &bmax, &indices_.at(0), 0, n, p); +#else + ComputeBoundingBox(&bmin, &bmax, &indices_.at(0), 0, n, p); +#endif + } + +// +// 3. Build tree +// +#ifdef _OPENMP +#if NANORT_ENABLE_PARALLEL_BUILD + + // Do parallel build for enoughly large dataset. + if (n > options.min_primitives_for_parallel_build) { + BuildShallowTree(&nodes_, 0, n, /* root depth */ 0, options.shallow_depth, + p, pred); // [0, n) + + assert(shallow_node_infos_.size() > 0); + + // Build deeper tree in parallel + std::vector > > local_nodes( + shallow_node_infos_.size()); + std::vector local_stats(shallow_node_infos_.size()); + +#pragma omp parallel for + for (int i = 0; i < static_cast(shallow_node_infos_.size()); i++) { + unsigned int left_idx = shallow_node_infos_[i].left_idx; + unsigned int right_idx = shallow_node_infos_[i].right_idx; + BuildTree(&(local_stats[i]), &(local_nodes[i]), left_idx, right_idx, + options.shallow_depth, p, pred); + } + + // Join local nodes + for (int i = 0; i < static_cast(local_nodes.size()); i++) { + assert(!local_nodes[i].empty()); + size_t offset = nodes_.size(); + + // Add offset to child index(for branch node). + for (size_t j = 0; j < local_nodes[i].size(); j++) { + if (local_nodes[i][j].flag == 0) { // branch + local_nodes[i][j].data[0] += offset - 1; + local_nodes[i][j].data[1] += offset - 1; + } + } + + // replace + nodes_[shallow_node_infos_[i].offset] = local_nodes[i][0]; + + // Skip root element of the local node. + nodes_.insert(nodes_.end(), local_nodes[i].begin() + 1, + local_nodes[i].end()); + } + + // Join statistics + for (int i = 0; i < static_cast(local_nodes.size()); i++) { + stats_.max_tree_depth = + std::max(stats_.max_tree_depth, local_stats[i].max_tree_depth); + stats_.num_leaf_nodes += local_stats[i].num_leaf_nodes; + stats_.num_branch_nodes += local_stats[i].num_branch_nodes; + } + + } else { + BuildTree(&stats_, &nodes_, 0, n, + /* root depth */ 0, p, pred); // [0, n) + } + +#else // !NANORT_ENABLE_PARALLEL_BUILD + { + BuildTree(&stats_, &nodes_, 0, n, + /* root depth */ 0, p, pred); // [0, n) + } +#endif +#else // !_OPENMP + { + BuildTree(&stats_, &nodes_, 0, n, + /* root depth */ 0, p, pred); // [0, n) + } +#endif + + return true; +} + +template +void BVHAccel::Debug() { + for (size_t i = 0; i < indices_.size(); i++) { + printf("index[%d] = %d\n", int(i), int(indices_[i])); + } + + for (size_t i = 0; i < nodes_.size(); i++) { + printf("node[%d] : bmin %f, %f, %f, bmax %f, %f, %f\n", int(i), + nodes_[i].bmin[0], nodes_[i].bmin[1], nodes_[i].bmin[1], + nodes_[i].bmax[0], nodes_[i].bmax[1], nodes_[i].bmax[1]); + } +} + +template +bool BVHAccel::Dump(const char *filename) { + FILE *fp = fopen(filename, "wb"); + if (!fp) { + // fprintf(stderr, "[BVHAccel] Cannot write a file: %s\n", filename); + return false; + } + + size_t numNodes = nodes_.size(); + assert(nodes_.size() > 0); + + size_t numIndices = indices_.size(); + + size_t r = 0; + r = fwrite(&numNodes, sizeof(size_t), 1, fp); + assert(r == 1); + + r = fwrite(&nodes_.at(0), sizeof(BVHNode), numNodes, fp); + assert(r == numNodes); + + r = fwrite(&numIndices, sizeof(size_t), 1, fp); + assert(r == 1); + + r = fwrite(&indices_.at(0), sizeof(unsigned int), numIndices, fp); + assert(r == numIndices); + + fclose(fp); + + return true; +} + +template +bool BVHAccel::Load(const char *filename) { + FILE *fp = fopen(filename, "rb"); + if (!fp) { + // fprintf(stderr, "Cannot open file: %s\n", filename); + return false; + } + + size_t numNodes; + size_t numIndices; + + size_t r = 0; + r = fread(&numNodes, sizeof(size_t), 1, fp); + assert(r == 1); + assert(numNodes > 0); + + nodes_.resize(numNodes); + r = fread(&nodes_.at(0), sizeof(BVHNode), numNodes, fp); + assert(r == numNodes); + + r = fread(&numIndices, sizeof(size_t), 1, fp); + assert(r == 1); + + indices_.resize(numIndices); + + r = fread(&indices_.at(0), sizeof(unsigned int), numIndices, fp); + assert(r == numIndices); + + fclose(fp); + + return true; +} + +template +inline bool IntersectRayAABB(T *tminOut, // [out] + T *tmaxOut, // [out] + T min_t, T max_t, const T bmin[3], const T bmax[3], + real3 ray_org, real3 ray_inv_dir, + int ray_dir_sign[3]) { + T tmin, tmax; + + const T min_x = ray_dir_sign[0] ? bmax[0] : bmin[0]; + const T min_y = ray_dir_sign[1] ? bmax[1] : bmin[1]; + const T min_z = ray_dir_sign[2] ? bmax[2] : bmin[2]; + const T max_x = ray_dir_sign[0] ? bmin[0] : bmax[0]; + const T max_y = ray_dir_sign[1] ? bmin[1] : bmax[1]; + const T max_z = ray_dir_sign[2] ? bmin[2] : bmax[2]; + + // X + const T tmin_x = (min_x - ray_org[0]) * ray_inv_dir[0]; + // MaxMult robust BVH traversal(up to 4 ulp). + // 1.0000000000000004 for double precision. + const T tmax_x = (max_x - ray_org[0]) * ray_inv_dir[0] * 1.00000024f; + + // Y + const T tmin_y = (min_y - ray_org[1]) * ray_inv_dir[1]; + const T tmax_y = (max_y - ray_org[1]) * ray_inv_dir[1] * 1.00000024f; + + // Z + const T tmin_z = (min_z - ray_org[2]) * ray_inv_dir[2]; + const T tmax_z = (max_z - ray_org[2]) * ray_inv_dir[2] * 1.00000024f; + + tmin = safemax(tmin_z, safemax(tmin_y, safemax(tmin_x, min_t))); + tmax = safemin(tmax_z, safemin(tmax_y, safemin(tmax_x, max_t))); + + if (tmin <= tmax) { + (*tminOut) = tmin; + (*tmaxOut) = tmax; + + return true; + } + + return false; // no hit +} + +template +template +inline bool BVHAccel::TestLeafNode(const BVHNode &node, const Ray &ray, + const I &intersector) const { + bool hit = false; + + unsigned int num_primitives = node.data[0]; + unsigned int offset = node.data[1]; + + T t = intersector.GetT(); // current hit distance + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + real3 ray_dir; + ray_dir[0] = ray.dir[0]; + ray_dir[1] = ray.dir[1]; + ray_dir[2] = ray.dir[2]; + + for (unsigned int i = 0; i < num_primitives; i++) { + unsigned int prim_idx = indices_[i + offset]; + + T local_t = t; + if (intersector.Intersect(&local_t, prim_idx)) { + // Update isect state + t = local_t; + + intersector.Update(t, prim_idx); + hit = true; + } + } + + return hit; +} + +#if 0 // TODO(LTE): Implement +template template +bool BVHAccel::MultiHitTestLeafNode( + std::priority_queue, Comp> *isect_pq, + int max_intersections, + const BVHNode &node, + const Ray &ray, + const I &intersector) const { + bool hit = false; + + unsigned int num_primitives = node.data[0]; + unsigned int offset = node.data[1]; + + T t = std::numeric_limits::max(); + if (isect_pq->size() >= static_cast(max_intersections)) { + t = isect_pq->top().t; // current furthest hit distance + } + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + real3 ray_dir; + ray_dir[0] = ray.dir[0]; + ray_dir[1] = ray.dir[1]; + ray_dir[2] = ray.dir[2]; + + for (unsigned int i = 0; i < num_primitives; i++) { + unsigned int prim_idx = indices_[i + offset]; + + T local_t = t, u = 0.0f, v = 0.0f; + if (intersector.Intersect(&local_t, &u, &v, prim_idx)) { + // Update isect state + if ((local_t > ray.min_t)) { + if (isect_pq->size() < static_cast(max_intersections)) { + H isect; + t = local_t; + isect.t = t; + isect.u = u; + isect.v = v; + isect.prim_id = prim_idx; + isect_pq->push(isect); + + // Update t to furthest distance. + t = ray.max_t; + + hit = true; + } else { + if (local_t < isect_pq->top().t) { + // delete furthest intersection and add new intersection. + isect_pq->pop(); + + H hit; + hit.t = local_t; + hit.u = u; + hit.v = v; + hit.prim_id = prim_idx; + isect_pq->push(hit); + + // Update furthest hit distance + t = isect_pq->top().t; + + hit = true; + } + } + } + } + } + + return hit; +} +#endif + +template +template +bool BVHAccel::Traverse(const Ray &ray, const I &intersector, H *isect, + const BVHTraceOptions &options) const { + const int kMaxStackDepth = 512; + + T hit_t = ray.max_t; + + int node_stack_index = 0; + unsigned int node_stack[512]; + node_stack[0] = 0; + + // Init isect info as no hit + intersector.Update(hit_t, static_cast(-1)); + + intersector.PrepareTraversal(ray, options); + + int dir_sign[3]; + dir_sign[0] = ray.dir[0] < 0.0f ? 1 : 0; + dir_sign[1] = ray.dir[1] < 0.0f ? 1 : 0; + dir_sign[2] = ray.dir[2] < 0.0f ? 1 : 0; + + // @fixme { Check edge case; i.e., 1/0 } + real3 ray_inv_dir; + ray_inv_dir[0] = 1.0f / (ray.dir[0] + 1.0e-12f); + ray_inv_dir[1] = 1.0f / (ray.dir[1] + 1.0e-12f); + ray_inv_dir[2] = 1.0f / (ray.dir[2] + 1.0e-12f); + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + T min_t = std::numeric_limits::max(); + T max_t = -std::numeric_limits::max(); + + while (node_stack_index >= 0) { + unsigned int index = node_stack[node_stack_index]; + const BVHNode &node = nodes_[index]; + + node_stack_index--; + + bool hit = IntersectRayAABB(&min_t, &max_t, ray.min_t, hit_t, node.bmin, + node.bmax, ray_org, ray_inv_dir, dir_sign); + + if (node.flag == 0) { // branch node + if (hit) { + int order_near = dir_sign[node.axis]; + int order_far = 1 - order_near; + + // Traverse near first. + node_stack[++node_stack_index] = node.data[order_far]; + node_stack[++node_stack_index] = node.data[order_near]; + } + } else { // leaf node + if (hit) { + if (TestLeafNode(node, ray, intersector)) { + hit_t = intersector.GetT(); + } + } + } + } + + assert(node_stack_index < kMaxStackDepth); + + bool hit = (intersector.GetT() < ray.max_t); + intersector.PostTraversal(ray, hit, isect); + + return hit; +} + +template +template +inline bool BVHAccel::TestLeafNodeIntersections( + const BVHNode &node, const Ray &ray, const int max_intersections, + const I &intersector, + std::priority_queue, std::vector >, + NodeHitComparator > *isect_pq) const { + bool hit = false; + + unsigned int num_primitives = node.data[0]; + unsigned int offset = node.data[1]; + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + real3 ray_dir; + ray_dir[0] = ray.dir[0]; + ray_dir[1] = ray.dir[1]; + ray_dir[2] = ray.dir[2]; + + intersector.PrepareTraversal(ray); + + for (unsigned int i = 0; i < num_primitives; i++) { + unsigned int prim_idx = indices_[i + offset]; + + T min_t, max_t; + if (intersector.Intersect(&min_t, &max_t, prim_idx)) { + // Always add to isect lists. + NodeHit isect; + isect.t_min = min_t; + isect.t_max = max_t; + isect.node_id = prim_idx; + + if (isect_pq->size() < static_cast(max_intersections)) { + isect_pq->push(isect); + + } else { + if (min_t < isect_pq->top().t_min) { + // delete the furthest intersection and add a new intersection. + isect_pq->pop(); + + isect_pq->push(isect); + } + } + } + } + + return hit; +} + +template +template +bool BVHAccel::ListNodeIntersections( + const Ray &ray, int max_intersections, const I &intersector, + StackVector, 128> *hits) const { + const int kMaxStackDepth = 512; + + T hit_t = ray.max_t; + + int node_stack_index = 0; + unsigned int node_stack[512]; + node_stack[0] = 0; + + // Stores furthest intersection at top + std::priority_queue, std::vector >, + NodeHitComparator > + isect_pq; + + (*hits)->clear(); + + int dir_sign[3]; + dir_sign[0] = + ray.dir[0] < static_cast(0.0) ? 1 : 0; + dir_sign[1] = + ray.dir[1] < static_cast(0.0) ? 1 : 0; + dir_sign[2] = + ray.dir[2] < static_cast(0.0) ? 1 : 0; + + // @fixme { Check edge case; i.e., 1/0 } + real3 ray_inv_dir; + ray_inv_dir[0] = static_cast(1.0) / ray.dir[0]; + ray_inv_dir[1] = static_cast(1.0) / ray.dir[1]; + ray_inv_dir[2] = static_cast(1.0) / ray.dir[2]; + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + T min_t, max_t; + while (node_stack_index >= 0) { + unsigned int index = node_stack[node_stack_index]; + const BVHNode &node = nodes_[static_cast(index)]; + + node_stack_index--; + + bool hit = IntersectRayAABB(&min_t, &max_t, ray.min_t, hit_t, node.bmin, + node.bmax, ray_org, ray_inv_dir, dir_sign); + + if (node.flag == 0) { // branch node + if (hit) { + int order_near = dir_sign[node.axis]; + int order_far = 1 - order_near; + + // Traverse near first. + node_stack[++node_stack_index] = node.data[order_far]; + node_stack[++node_stack_index] = node.data[order_near]; + } + + } else { // leaf node + if (hit) { + TestLeafNodeIntersections(node, ray, max_intersections, intersector, + &isect_pq); + } + } + } + + assert(node_stack_index < kMaxStackDepth); + (void)kMaxStackDepth; + + if (!isect_pq.empty()) { + // Store intesection in reverse order(make it frontmost order) + size_t n = isect_pq.size(); + (*hits)->resize(n); + for (size_t i = 0; i < n; i++) { + const NodeHit &isect = isect_pq.top(); + (*hits)[n - i - 1] = isect; + isect_pq.pop(); + } + + return true; + } + + return false; +} + +#if 0 // TODO(LTE): Implement +template template +bool BVHAccel::MultiHitTraverse(const Ray &ray, + int max_intersections, + const I &intersector, + StackVector *hits, + const BVHTraceOptions& options) const { + const int kMaxStackDepth = 512; + + T hit_t = ray.max_t; + + int node_stack_index = 0; + unsigned int node_stack[512]; + node_stack[0] = 0; + + // Stores furthest intersection at top + std::priority_queue, Comp> isect_pq; + + (*hits)->clear(); + + // Init isect info as no hit + intersector.Update(hit_t, static_cast(-1)); + + intersector.PrepareTraversal(ray, options); + + int dir_sign[3]; + dir_sign[0] = ray.dir[0] < static_cast(0.0) ? static_cast(1) : static_cast(0); + dir_sign[1] = ray.dir[1] < static_cast(0.0) ? static_cast(1) : static_cast(0); + dir_sign[2] = ray.dir[2] < static_cast(0.0) ? static_cast(1) : static_cast(0); + + // @fixme { Check edge case; i.e., 1/0 } + real3 ray_inv_dir; + ray_inv_dir[0] = static_cast(1.0) / ray.dir[0]; + ray_inv_dir[1] = static_cast(1.0) / ray.dir[1]; + ray_inv_dir[2] = static_cast(1.0) / ray.dir[2]; + + real3 ray_org; + ray_org[0] = ray.org[0]; + ray_org[1] = ray.org[1]; + ray_org[2] = ray.org[2]; + + T min_t, max_t; + while (node_stack_index >= 0) { + unsigned int index = node_stack[node_stack_index]; + const BVHNode &node = nodes_[static_cast(index)]; + + node_stack_index--; + + bool hit = IntersectRayAABB(&min_t, &max_t, ray.min_t, hit_t, node.bmin, + node.bmax, ray_org, ray_inv_dir, dir_sign); + + if (node.flag == 0) { // branch node + if (hit) { + int order_near = dir_sign[node.axis]; + int order_far = 1 - order_near; + + // Traverse near first. + node_stack[++node_stack_index] = node.data[order_far]; + node_stack[++node_stack_index] = node.data[order_near]; + } + + } else { // leaf node + if (hit) { + if (MultiHitTestLeafNode(&isect_pq, max_intersections, node, ray, intersector)) { + // Only update `hit_t` when queue is full. + if (isect_pq.size() >= static_cast(max_intersections)) { + hit_t = isect_pq.top().t; + } + } + } + } + } + + assert(node_stack_index < kMaxStackDepth); + (void)kMaxStackDepth; + + if (!isect_pq.empty()) { + // Store intesection in reverse order(make it frontmost order) + size_t n = isect_pq.size(); + (*hits)->resize(n); + for (size_t i = 0; i < n; i++) { + const H &isect = isect_pq.top(); + (*hits)[n - i - 1] = isect; + isect_pq.pop(); + } + + return true; + } + + return false; +} +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // namespace nanort + +#endif // NANORT_H_ diff --git a/examples/raytrace/obj-loader.cc b/examples/raytrace/obj-loader.cc index 7ebc9b9..bbda161 100644 --- a/examples/raytrace/obj-loader.cc +++ b/examples/raytrace/obj-loader.cc @@ -1,5 +1,5 @@ #include "obj-loader.h" -#include "../../nanort.h" // for float3 +#include "nanort.h" // for float3 #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" diff --git a/examples/raytrace/render.cc b/examples/raytrace/render.cc index a1b47ea..de1c1f2 100644 --- a/examples/raytrace/render.cc +++ b/examples/raytrace/render.cc @@ -41,7 +41,7 @@ THE SOFTWARE. #include -#include "../../nanort.h" +#include "nanort.h" #include "matrix.h" #include "material.h" #include "mesh.h"