├── .gitattributes ├── .gitignore ├── README.md ├── Screenshot (25).png ├── build.xml ├── manifest.mf ├── nbproject ├── build-impl.xml ├── configs │ ├── Run_as_WebStart.properties │ └── Run_in_Browser.properties ├── genfiles.properties ├── jfx-impl.xml ├── private │ ├── configs │ │ ├── Run_as_WebStart.properties │ │ └── Run_in_Browser.properties │ ├── private.properties │ └── private.xml ├── project.properties └── project.xml └── src ├── AbsObject.java ├── Camera.java ├── Colour.java ├── Floor.java ├── Intersect.java ├── LightSource.java ├── Material.java ├── Materials.java ├── Ray.java ├── RayTracer.java ├── Render.java ├── Sphere.java ├── Vector.java ├── View.java └── rayTraceRender.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaFX-Ray-Tracer 2 | A ray tracer with a JavaFX front end and Java backend. 3 | 4 | Supports: 5 | - Diffusion 6 | - Specularity 7 | - Super, Adaptive, and Stochastic(Monte Carlo) Antialiasing 8 | - Camera manipulation 9 | - Custom materials (no uv mapping) 10 | - Custom point source lighting 11 | - Custom objects (only spheres currently) 12 | - Render previews 13 | 14 | Upcoming: 15 | -Finish refraction 16 | - * ray splitting for reflection, and refraction 17 | - * total internal reflection 18 | - * Fresnel reflectivity 19 | - Add normal mapping 20 | - Add displacement mapping 21 | - Add Fresnel reflectivity 22 | - Add Depth of Field 23 | - Add area light sources 24 | - Add diffuse inter-reflection 25 | - Add surface and object caustics 26 | - Add transparency 27 | - Add soft shadows 28 | -------------------------------------------------------------------------------- /Screenshot (25).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coelacant1/JavaFX-Ray-Tracer/4c339a22dc9c1b8ab8ecdea612d2b7f2672596c7/Screenshot (25).png -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | Builds, tests, and runs the project rowland005_renderApp. 3 | 4 | 53 | 54 | -------------------------------------------------------------------------------- /manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /nbproject/build-impl.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | Must set src.dir 234 | Must set test.src.dir 235 | Must set build.dir 236 | Must set dist.dir 237 | Must set build.classes.dir 238 | Must set dist.javadoc.dir 239 | Must set build.test.classes.dir 240 | Must set build.test.results.dir 241 | Must set build.classes.excludes 242 | Must set dist.jar 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | Must set javac.includes 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | No tests executed. 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | Must set JVM to use for profiling in profiler.info.jvm 723 | Must set profiler agent JVM arguments in profiler.info.jvmargs.agent 724 | 725 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | Must select some files in the IDE or set javac.includes 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | To run this application from the command line without Ant, try: 1002 | 1003 | java -jar "${dist.jar.resolved}" 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | Must select one file in the IDE or set run.class 1051 | 1052 | 1053 | 1054 | Must select one file in the IDE or set run.class 1055 | 1056 | 1057 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | Must select one file in the IDE or set debug.class 1082 | 1083 | 1084 | 1085 | 1086 | Must select one file in the IDE or set debug.class 1087 | 1088 | 1089 | 1090 | 1091 | Must set fix.includes 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1103 | 1106 | 1107 | This target only works when run from inside the NetBeans IDE. 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | Must select one file in the IDE or set profile.class 1117 | This target only works when run from inside the NetBeans IDE. 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | This target only works when run from inside the NetBeans IDE. 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | This target only works when run from inside the NetBeans IDE. 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | Must select one file in the IDE or set run.class 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | Must select some files in the IDE or set test.includes 1184 | 1185 | 1186 | 1187 | 1188 | Must select one file in the IDE or set run.class 1189 | 1190 | 1191 | 1192 | 1193 | Must select one file in the IDE or set applet.url 1194 | 1195 | 1196 | 1197 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | Must select some files in the IDE or set javac.includes 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | Some tests failed; see details above. 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | Must select some files in the IDE or set test.includes 1306 | 1307 | 1308 | 1309 | Some tests failed; see details above. 1310 | 1311 | 1312 | 1313 | Must select some files in the IDE or set test.class 1314 | Must select some method in the IDE or set test.method 1315 | 1316 | 1317 | 1318 | Some tests failed; see details above. 1319 | 1320 | 1321 | 1326 | 1327 | Must select one file in the IDE or set test.class 1328 | 1329 | 1330 | 1331 | Must select one file in the IDE or set test.class 1332 | Must select some method in the IDE or set test.method 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1349 | 1350 | Must select one file in the IDE or set applet.url 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1362 | 1363 | Must select one file in the IDE or set applet.url 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | -------------------------------------------------------------------------------- /nbproject/configs/Run_as_WebStart.properties: -------------------------------------------------------------------------------- 1 | # Do not modify this property in this configuration. It can be re-generated. 2 | $label=Run as WebStart 3 | -------------------------------------------------------------------------------- /nbproject/configs/Run_in_Browser.properties: -------------------------------------------------------------------------------- 1 | # Do not modify this property in this configuration. It can be re-generated. 2 | $label=Run in Browser 3 | -------------------------------------------------------------------------------- /nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=c1691376 2 | build.xml.script.CRC32=2c3e14dc 3 | build.xml.stylesheet.CRC32=8064a381@1.79.1.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=58402082 7 | nbproject/build-impl.xml.script.CRC32=ba6c94b9 8 | nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 9 | -------------------------------------------------------------------------------- /nbproject/private/configs/Run_as_WebStart.properties: -------------------------------------------------------------------------------- 1 | # Do not modify this property in this configuration. It can be re-generated. 2 | javafx.run.as=webstart 3 | -------------------------------------------------------------------------------- /nbproject/private/configs/Run_in_Browser.properties: -------------------------------------------------------------------------------- 1 | # Do not modify this property in this configuration. It can be re-generated. 2 | javafx.run.as=embedded 3 | -------------------------------------------------------------------------------- /nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | auxiliary.org-netbeans-modules-projectapi.issue214819_5f_fx_5f_enabled=true 2 | # No need to modify this property unless customizing JavaFX Ant task infrastructure 3 | endorsed.javafx.ant.classpath=. 4 | javafx.run.inbrowser= 5 | javafx.run.inbrowser.path=C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE 6 | user.properties.file=C:\\Users\\Rollie\\AppData\\Roaming\\NetBeans\\8.1\\build.properties 7 | -------------------------------------------------------------------------------- /nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Material.java 7 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Render.java 8 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/LightSource.java 9 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/rayTraceRender.java 10 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/AbsObject.java 11 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Floor.java 12 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Intersect.java 13 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Materials.java 14 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/View.java 15 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Camera.java 16 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/RayTracer.java 17 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Sphere.java 18 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Ray.java 19 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Colour.java 20 | file:/C:/Users/Rollie/Documents/NetBeansProjects/rowland005_renderApp/src/Vector.java 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=false 3 | annotation.processing.processor.options= 4 | annotation.processing.processors.list= 5 | annotation.processing.run.all.processors=true 6 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 7 | application.title=rayTracer 8 | application.vendor=Rollie 9 | build.classes.dir=${build.dir}/classes 10 | build.classes.excludes=**/*.java,**/*.form 11 | # This directory is removed when the project is cleaned: 12 | build.dir=build 13 | build.generated.dir=${build.dir}/generated 14 | build.generated.sources.dir=${build.dir}/generated-sources 15 | # Only compile against the classpath explicitly listed here: 16 | build.sysclasspath=ignore 17 | build.test.classes.dir=${build.dir}/test/classes 18 | build.test.results.dir=${build.dir}/test/results 19 | compile.on.save=true 20 | compile.on.save.unsupported.javafx=true 21 | # Uncomment to specify the preferred debugger connection transport: 22 | #debug.transport=dt_socket 23 | debug.classpath=\ 24 | ${run.classpath} 25 | debug.test.classpath=\ 26 | ${run.test.classpath} 27 | # This directory is removed when the project is cleaned: 28 | dist.dir=dist 29 | dist.jar=${dist.dir}/rayTracer.jar 30 | dist.javadoc.dir=${dist.dir}/javadoc 31 | endorsed.classpath= 32 | excludes= 33 | includes=** 34 | # Non-JavaFX jar file creation is deactivated in JavaFX 2.0+ projects 35 | jar.archive.disabled=true 36 | jar.compress=false 37 | javac.classpath=\ 38 | ${javafx.classpath.extension} 39 | # Space-separated list of extra javac options 40 | javac.compilerargs= 41 | javac.deprecation=false 42 | javac.processorpath=\ 43 | ${javac.classpath} 44 | javac.source=1.8 45 | javac.target=1.8 46 | javac.test.classpath=\ 47 | ${javac.classpath}:\ 48 | ${build.classes.dir} 49 | javac.test.processorpath=\ 50 | ${javac.test.classpath} 51 | javadoc.additionalparam= 52 | javadoc.author=false 53 | javadoc.encoding=${source.encoding} 54 | javadoc.noindex=false 55 | javadoc.nonavbar=false 56 | javadoc.notree=false 57 | javadoc.private=false 58 | javadoc.splitindex=true 59 | javadoc.use=true 60 | javadoc.version=false 61 | javadoc.windowtitle= 62 | javafx.application.implementation.version=1.0 63 | javafx.binarycss=false 64 | javafx.classpath.extension=\ 65 | ${java.home}/lib/javaws.jar:\ 66 | ${java.home}/lib/deploy.jar:\ 67 | ${java.home}/lib/plugin.jar 68 | javafx.deploy.allowoffline=true 69 | # If true, application update mode is set to 'background', if false, update mode is set to 'eager' 70 | javafx.deploy.backgroundupdate=false 71 | javafx.deploy.embedJNLP=true 72 | javafx.deploy.includeDT=true 73 | # Set true to prevent creation of temporary copy of deployment artifacts before each run (disables concurrent runs) 74 | javafx.disable.concurrent.runs=false 75 | # Set true to enable multiple concurrent runs of the same WebStart or Run-in-Browser project 76 | javafx.enable.concurrent.external.runs=false 77 | # This is a JavaFX project 78 | javafx.enabled=true 79 | javafx.fallback.class=com.javafx.main.NoJavaFXFallback 80 | # Main class for JavaFX 81 | javafx.main.class=rayTraceRender 82 | javafx.preloader.class= 83 | # This project does not use Preloader 84 | javafx.preloader.enabled=false 85 | javafx.preloader.jar.filename= 86 | javafx.preloader.jar.path= 87 | javafx.preloader.project.path= 88 | javafx.preloader.type=none 89 | # Set true for GlassFish only. Rebases manifest classpaths of JARs in lib dir. Not usable with signed JARs. 90 | javafx.rebase.libs=false 91 | javafx.run.height=600 92 | javafx.run.width=800 93 | # Pre-JavaFX 2.0 WebStart is deactivated in JavaFX 2.0+ projects 94 | jnlp.enabled=false 95 | # Main class for Java launcher 96 | main.class=com.javafx.main.Main 97 | # For improved security specify narrower Codebase manifest attribute to prevent RIAs from being repurposed 98 | manifest.custom.codebase=* 99 | # Specify Permissions manifest attribute to override default (choices: sandbox, all-permissions) 100 | manifest.custom.permissions= 101 | manifest.file=manifest.mf 102 | meta.inf.dir=${src.dir}/META-INF 103 | platform.active=default_platform 104 | run.classpath=\ 105 | ${dist.jar}:\ 106 | ${javac.classpath}:\ 107 | ${build.classes.dir} 108 | run.test.classpath=\ 109 | ${javac.test.classpath}:\ 110 | ${build.test.classes.dir} 111 | source.encoding=UTF-8 112 | src.dir=src 113 | test.src.dir=test 114 | -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | rayTracer 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | antialiasing 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/AbsObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public abstract class AbsObject { 13 | public Material material; 14 | public String name; 15 | 16 | public abstract Vector normal(Vector _vector); 17 | public abstract Intersect intersect(Ray ray); 18 | } -------------------------------------------------------------------------------- /src/Camera.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Camera { 13 | public Vector position; 14 | public Vector above; 15 | public Vector front; 16 | public Vector right; 17 | 18 | public static Camera create(Vector target, Vector _position){ 19 | Vector tempM, _front, _bottom, tempCFD, tempNormCFD, _right, tempCFR, tempNormCFR, _above; 20 | tempM = Vector.subtract(target, _position); 21 | _front = Vector.normal(tempM); 22 | 23 | _bottom = new Vector(0, -1, 0); 24 | 25 | tempCFD = Vector.crossP(_front, _bottom); 26 | tempNormCFD = Vector.normal(tempCFD); 27 | _right = Vector.multiply(2.0, tempNormCFD); 28 | 29 | tempCFR = Vector.crossP(_front, _right); 30 | tempNormCFR = Vector.normal(tempCFR); 31 | _above = Vector.multiply(2.0, tempNormCFR); 32 | 33 | return new Camera() {{ 34 | this.position = _position; 35 | this.front = _front; 36 | this.above = _above; 37 | this.right = _right; 38 | }}; 39 | } 40 | 41 | public static Camera create(Vector target, Vector _position, double x, double y){ 42 | Vector tempM, _front, _bottom, tempCFD, tempNormCFD, _right, tempCFR, tempNormCFR, _above; 43 | double ratio = y / x; 44 | 45 | tempM = Vector.subtract(target, _position); 46 | _front = Vector.normal(tempM); 47 | 48 | _bottom = new Vector(0, -1, 0); 49 | 50 | tempCFD = Vector.crossP(_front, _bottom); 51 | tempNormCFD = Vector.normal(tempCFD); 52 | _right = Vector.multiply(2.0, tempNormCFD); 53 | 54 | tempCFR = Vector.crossP(_front, _right); 55 | tempNormCFR = Vector.normal(tempCFR); 56 | _above = Vector.multiply(2.0 * ratio, tempNormCFR); 57 | 58 | return new Camera() {{ 59 | this.position = _position; 60 | this.front = _front; 61 | this.above = _above; 62 | this.right = _right; 63 | }}; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Colour.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | import java.awt.Color; 8 | 9 | /** 10 | * 11 | * @author Rollie 12 | */ 13 | 14 | public class Colour 15 | { 16 | public double R, G, B; 17 | 18 | public Colour(double r, double g, double b) 19 | { 20 | R = r; G = g; B = b; 21 | } 22 | 23 | public static Colour def = create(0, 0, 0); 24 | 25 | public static Colour create(double r, double g, double b) 26 | { 27 | return new Colour(r, g, b); 28 | } 29 | 30 | public static Colour multiply(double k, Colour _colour) 31 | { 32 | return new Colour((k * _colour.R), (k * _colour.G), (k * _colour.B)); 33 | } 34 | 35 | public static Colour multiply(Colour _colourO, Colour _colourT) 36 | { 37 | return new Colour((_colourO.R * _colourT.R), (_colourO.G * _colourT.G), (_colourO.B * _colourT.B)); 38 | } 39 | 40 | public static Colour add(Colour _colourO, Colour _colourT) 41 | { 42 | return new Colour(_colourO.R + _colourT.R, _colourO.G + _colourT.G, _colourO.B + _colourT.B); 43 | } 44 | 45 | public static Colour average(Colour _colourO, Colour _colourT) 46 | { 47 | return new Colour((_colourO.R + _colourT.R) / 2, (_colourO.G + _colourT.G) / 2, (_colourO.B + _colourT.B) / 2); 48 | } 49 | 50 | public static Colour subtract(Colour _colourO, Colour _colourT) 51 | { 52 | return new Colour(_colourO.R - _colourT.R, _colourO.G - _colourT.G, _colourO.B - _colourT.B); 53 | } 54 | 55 | public double checkColour(double _colour) 56 | { 57 | if (_colour < 0){ 58 | _colour = 0; 59 | } 60 | else if (_colour > 1){ 61 | _colour = 1; 62 | } 63 | 64 | return _colour; 65 | } 66 | 67 | Color toColour() 68 | { 69 | return (new Color((int)(checkColour(R) * 255), (int)(checkColour(G) * 255), (int)(checkColour(B) * 255))); 70 | } 71 | } -------------------------------------------------------------------------------- /src/Floor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Floor extends AbsObject 13 | { 14 | public double displacement; 15 | public Vector objectPosition; 16 | 17 | @Override 18 | public Vector normal(Vector position) 19 | { 20 | return objectPosition; 21 | } 22 | 23 | @Override 24 | public Intersect intersect(Ray _ray) 25 | { 26 | double _vectorD = Vector.dotProduct(objectPosition, _ray.direction); 27 | double _distance; 28 | 29 | if (_vectorD <= 0) 30 | { 31 | _distance = (displacement + Vector.dotProduct(objectPosition, _ray.begin)) / (-_vectorD); 32 | Floor floor = this; 33 | 34 | return new Intersect(){{ 35 | object = floor; 36 | ray = _ray; 37 | distance = _distance; 38 | }}; 39 | } 40 | else 41 | { 42 | return null; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Intersect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Intersect { 13 | public AbsObject object; 14 | public double distance; 15 | public Ray ray; 16 | } 17 | -------------------------------------------------------------------------------- /src/LightSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class LightSource { 13 | public String name; 14 | public Colour color; 15 | public Vector position; 16 | } 17 | -------------------------------------------------------------------------------- /src/Material.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Material{ 13 | public java.util.function.Function specular; 14 | public java.util.function.Function reflect; 15 | public java.util.function.Function diffuse; 16 | public java.util.function.Function refractiveIndex; 17 | public double transparency; 18 | public double specularWidth; 19 | public String name; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Materials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Materials { 13 | public static Material[] materials; 14 | 15 | public static Material Default = 16 | new Material(){{ 17 | name = "Default"; 18 | refractiveIndex = (Vector position) -> 0.0; 19 | reflect = (Vector position) -> 0.25; 20 | diffuse = (Vector position) -> Colour.create(0.25, 0.25, 0.25); 21 | specular = (Vector position) -> Colour.create(0.25, 0.25, 0.25); 22 | specularWidth = 0; 23 | transparency = 0.1; 24 | }}; 25 | 26 | public static Material Floor = 27 | new Material(){{ 28 | name = "Floor"; 29 | //reflect = position -> 0.15; 30 | refractiveIndex = (Vector position) -> 0.0; 31 | reflect = (Vector position) -> 0.65; 32 | diffuse = (Vector position) -> Colour.create(0.25, 0.25, 0.25); 33 | specular = (Vector position) -> Colour.create(0.5, 0.5, 0.5); 34 | specularWidth = 15; 35 | transparency = 0.0; 36 | }}; 37 | 38 | public static Material Mirror = 39 | new Material(){{ 40 | name = "Mirror"; 41 | refractiveIndex = (Vector position) -> 0.0; 42 | reflect = (Vector position) -> 1.0; 43 | diffuse = (Vector position) -> Colour.create(1.0, 1.0, 1.0); 44 | specular = (Vector position) -> Colour.create(0.75, 0.75, 0.75); 45 | specularWidth = 25; 46 | transparency = 0.1; 47 | }}; 48 | 49 | public static Material Glass = 50 | new Material(){{ 51 | name = "Glass"; 52 | refractiveIndex = (Vector position) -> 1.0; 53 | reflect = (Vector position) -> 0.0; 54 | diffuse = (Vector position) -> Colour.create(0.0, 0.0, 0.0); 55 | specular = (Vector position) -> Colour.create(0.5, 0.5, 0.5); 56 | specularWidth = 100; 57 | transparency = 0.95; 58 | }}; 59 | } -------------------------------------------------------------------------------- /src/Ray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Ray { 13 | public Vector direction; 14 | public Vector begin; 15 | } 16 | -------------------------------------------------------------------------------- /src/RayTracer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.Collections; 10 | import java.awt.image.BufferedImage; 11 | 12 | /** 13 | * /EXTERNAL SOURCES/ located at lines 108 and 110 14 | * 15 | * /TODO/: 16 | * Finish refraction 17 | * ray splitting for reflection, and refraction 18 | * total internal reflection 19 | * Fresnel reflectivity 20 | * Add normal mapping 21 | * Add displacement mapping 22 | * Add Fresnel reflectivity 23 | * -Add super sampling, adaptive sampling, and stochastic sampling modes 24 | * Add Depth of Field 25 | * Add area light sources 26 | * Add diffuse inter-reflection 27 | * Add surface and object caustics 28 | * Add transparency 29 | * Add soft shadows 30 | * 31 | * @author Rollie 32 | */ 33 | 34 | public class RayTracer { 35 | private final int bmpWidth; 36 | private final int bmpHeight; 37 | private final int amount = 4; 38 | 39 | public RayTracer(int w, int h){ 40 | bmpWidth = w; 41 | bmpHeight = h; 42 | } 43 | 44 | private Iterable intersections(Ray ray, View view) 45 | { 46 | ArrayList rayIntersections = new ArrayList<>(); 47 | 48 | for (AbsObject i : view.objects){ 49 | Intersect temp = i.intersect(ray); 50 | if (temp != null){ 51 | rayIntersections.add(temp); 52 | } 53 | } 54 | 55 | Collections.sort(rayIntersections, (Intersect x, Intersect y) -> Double.valueOf(x.distance).compareTo(y.distance)); 56 | 57 | Iterable temp; 58 | Intersect[] tempL = new Intersect[rayIntersections.toArray().length]; 59 | 60 | for (int i = 0; i < tempL.length; i++){ 61 | tempL[i] = (Intersect)rayIntersections.toArray()[i]; 62 | } 63 | 64 | temp = Arrays.asList(tempL); 65 | 66 | return temp; 67 | } 68 | 69 | private double shadowTest(Ray ray, View view) 70 | { 71 | Iterable intersections = intersections(ray, view); 72 | Intersect intersect = null; 73 | 74 | if(intersections.iterator().hasNext()){ 75 | intersect = intersections.iterator().next(); 76 | } 77 | 78 | if (intersect == null){ 79 | return 0; 80 | } 81 | else{ 82 | return intersect.distance; 83 | } 84 | } 85 | 86 | private Colour trace(Ray ray, View view, int amount) 87 | { 88 | Iterable intersections = intersections(ray, view); 89 | Intersect intersect = null; 90 | 91 | if(intersections.iterator().hasNext()){ 92 | intersect = intersections.iterator().next(); 93 | } 94 | 95 | if (intersect == null){ 96 | return Colour.def; 97 | } 98 | else{ 99 | return getShade(intersect, view, amount); 100 | } 101 | } 102 | 103 | private Colour getShade(Intersect intersect, View view, int _amount) 104 | { 105 | Vector direction = intersect.ray.direction; 106 | Vector position = Vector.add(Vector.multiply(intersect.distance, intersect.ray.direction), intersect.ray.begin); 107 | Vector normal = intersect.object.normal(position); 108 | //http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf - SOURCE for reflectDirection vector + equation 109 | Vector reflectDirection = Vector.subtract(direction, Vector.multiply(2 * Vector.dotProduct(normal, direction), normal)); 110 | //http://web.cse.ohio-state.edu/~hwshen/681/Site/Slides_files/reflection_refraction.pdf - SOURCE for refractDirection vector + equation 111 | //nr -> object refractive index 112 | //(nr(Norm . direction) - sqrt(1 - nr^2(1 - (normal . direction)^2)) * Normal) - normal*direction 113 | Vector refractDirection = 114 | Vector.subtract( 115 | //Vector.multiply(intersect.object.material.refractiveIndex.apply(position), Vector.dotProduct(normal, direction)), 116 | Vector.multiply( 117 | ( 118 | (intersect.object.material.refractiveIndex.apply(position) * Vector.dotProduct(normal, direction))- 119 | Math.sqrt(1 - Math.pow(intersect.object.material.refractiveIndex.apply(position), 2) * (1 - Math.pow(Vector.dotProduct(normal, direction), 2))) 120 | ), 121 | normal 122 | ), 123 | Vector.multiply(intersect.object.material.refractiveIndex.apply(position), direction) 124 | ); 125 | 126 | Colour outColor = Colour.def; 127 | 128 | outColor = Colour.add(outColor, getColour(intersect.object, position, normal, reflectDirection, view)); 129 | //outColor = Colour.add(outColor, getColour(intersect.object, position, normal, refractDirection, view)); 130 | //outColor = Colour.add(outColor, Colour.average(getColour(intersect.object, position, normal, reflectDirection, view), getColour(intersect.object, position, normal, refractDirection, view))); 131 | 132 | if (_amount < amount){ 133 | Colour reflect = outColor; 134 | Colour refract = outColor; 135 | // Vector.add(position, Vector.multiply(0.001, refractDirection)) -> epsilon correction 136 | //return Colour.add(outColor, getReflectColor(intersect.object, Vector.add(position, Vector.multiply(0.001, reflectDirection)), reflectDirection, view, _amount)); 137 | //return Colour.add(outColor, getRefractColor(intersect.object, Vector.add(position, Vector.multiply(0.001, refractDirection)), refractDirection, view, _amount)); 138 | 139 | if (intersect.object.material.refractiveIndex.apply(normal) < 1){ 140 | //Vector refractDir = Vector.normal(refract()); 141 | //refract = getRefractColor(intersect.object, Vector.add(normal, Vector.multiply(0.001, refractDirection)), refractDirection, view, _amount); 142 | } 143 | 144 | reflect = getReflectColor(intersect.object, Vector.add(position, Vector.multiply(0.001, reflectDirection)), reflectDirection, view, _amount); 145 | refract = getRefractColor(intersect.object, Vector.add(normal, Vector.multiply(0.001, refractDirection)), refractDirection, view, _amount); 146 | 147 | reflect = Colour.multiply((1 - intersect.object.material.transparency), reflect); 148 | refract = Colour.multiply((intersect.object.material.transparency), refract); 149 | 150 | return Colour.add(outColor, Colour.add(reflect, refract)); 151 | } 152 | else 153 | { 154 | return outColor; 155 | } 156 | } 157 | 158 | private Colour getReflectColor(AbsObject object, Vector position, Vector rayDirection, View view, int _amount) 159 | { 160 | return Colour.multiply(object.material.reflect.apply(position), trace( 161 | new Ray() {{ 162 | begin = position; 163 | direction = rayDirection; 164 | }}, 165 | view, 166 | _amount + 1 167 | )); 168 | } 169 | 170 | //NOT FINISHED 171 | private Colour getRefractColor(AbsObject object, Vector normal, Vector rayDirection, View view, int _amount){ 172 | //double tempFresnel = fresnel(rayDirection, normal, object, 1.5); 173 | 174 | return Colour.multiply(object.material.refractiveIndex.apply(normal), trace( 175 | new Ray() {{ 176 | begin = normal; 177 | direction = rayDirection; 178 | }}, 179 | view, 180 | _amount + 1 181 | )); 182 | } 183 | 184 | private double fresnel(Vector direction, Vector normal, AbsObject object, double indexRefraction){ 185 | double cosineDirection = Vector.dotProduct(direction, normal); 186 | double etaDirection = 1; 187 | double etaT = object.material.refractiveIndex.apply(normal); 188 | 189 | if (cosineDirection > 1){ 190 | cosineDirection = 1; 191 | } 192 | else if (cosineDirection < -1){ 193 | cosineDirection = -1; 194 | } 195 | 196 | if(cosineDirection > 0){ 197 | etaDirection = etaT; 198 | etaT = 1; 199 | } 200 | 201 | double sinT = (etaDirection / etaT) * Math.sqrt(Math.max(0.d, 1 - Math.pow(cosineDirection, 2))); 202 | 203 | if (sinT >= 1){ 204 | indexRefraction = 1; 205 | } 206 | else{ 207 | double cosT = Math.sqrt(Math.max(0.d, 1 - Math.pow(sinT, 2))); 208 | cosineDirection = Math.abs(cosineDirection); 209 | 210 | double rS = ((etaT * cosineDirection) - (etaDirection * cosT)) / ((etaT * cosineDirection) + (etaDirection * cosT)); 211 | double rP = ((etaDirection * cosineDirection) - (etaT * cosT)) / ((etaDirection * cosineDirection) + (etaT * cosT)); 212 | indexRefraction = (Math.pow(rS, 2) + Math.pow(rP, 2)) / 2; 213 | } 214 | 215 | return indexRefraction; 216 | } 217 | 218 | private Colour getColour(AbsObject object, Vector position, Vector normal, Vector rayDirection, View view) 219 | { 220 | Colour outColor = Colour.create(0, 0, 0); 221 | 222 | for (LightSource light : view.lightSource) 223 | { 224 | Vector lightDistance = Vector.subtract(light.position, position); 225 | Vector normalLD = Vector.normal(lightDistance); 226 | 227 | double cleanIntersection = shadowTest( 228 | new Ray() {{ 229 | begin = position; 230 | direction = normalLD; 231 | }} 232 | , view); 233 | 234 | boolean notInShadow = ((cleanIntersection > Vector.magn(lightDistance)) || (cleanIntersection == 0)); 235 | 236 | if (notInShadow) 237 | { 238 | double illumination = Vector.dotProduct(normalLD, normal); 239 | Colour lightColor = illumination > 0 ? Colour.multiply(illumination, light.color) : Colour.create(0, 0, 0); 240 | double specular = Vector.dotProduct(normalLD, Vector.normal(rayDirection)); 241 | Colour specularColor = specular > 0 ? Colour.multiply(Math.pow(specular, object.material.specularWidth), light.color) : Colour.create(0, 0, 0); 242 | outColor = Colour.add(outColor, Colour.add(Colour.multiply(object.material.diffuse.apply(position), lightColor), Colour.multiply(object.material.specular.apply(position), specularColor))); 243 | } 244 | } 245 | 246 | return outColor; 247 | } 248 | 249 | private Vector getLocation(double x, double y, Camera camera) 250 | { 251 | return Vector.normal(Vector.add(camera.front, Vector.add(Vector.multiply(centerHorizontal(x), camera.right), Vector.multiply(centerVertical(y), camera.above)))); 252 | } 253 | 254 | private double centerHorizontal(double horizontal) 255 | { 256 | double temp; 257 | 258 | temp = (horizontal - (bmpWidth / 2.0)) / (2.0 * bmpWidth); 259 | 260 | return temp; 261 | } 262 | 263 | private double centerVertical(double vertical) 264 | { 265 | double temp; 266 | 267 | temp = -(vertical - (bmpHeight / 2.0)) / (2.0 * bmpHeight); 268 | 269 | return temp; 270 | } 271 | 272 | BufferedImage render(View view) 273 | { 274 | final BufferedImage image = new BufferedImage( bmpWidth, bmpHeight, BufferedImage.TYPE_INT_RGB ); 275 | 276 | for (int y = 0; y < bmpHeight; y++) 277 | { 278 | for (int x = 0; x < bmpWidth; x++) 279 | { 280 | Vector _direction = getLocation(x, y, view.camera); 281 | 282 | Colour colour = trace( 283 | new Ray() {{ 284 | begin = view.camera.position; 285 | direction = _direction; 286 | }}, 287 | view, 288 | 0); 289 | 290 | image.setRGB(x, y, colour.toColour().getRGB()); 291 | } 292 | } 293 | 294 | return image; 295 | } 296 | 297 | BufferedImage renderPreview(View view, int quality){ 298 | final BufferedImage image = new BufferedImage( bmpWidth, bmpHeight, BufferedImage.TYPE_INT_RGB ); 299 | int incrementVal = bmpWidth / quality; 300 | 301 | for (int y = 0; y < bmpHeight; y += bmpHeight / incrementVal) 302 | { 303 | for (int x = 0; x < bmpWidth; x += bmpHeight / incrementVal) 304 | { 305 | Vector _direction = getLocation(x, y, view.camera); 306 | 307 | Colour colour = trace( 308 | new Ray() {{ 309 | begin = view.camera.position; 310 | direction = _direction; 311 | }}, 312 | view, 313 | 0); 314 | 315 | for (int yM = 0; yM < bmpHeight / incrementVal; yM++) 316 | { 317 | for(int xM = 0; xM < bmpWidth / incrementVal; xM++) 318 | { 319 | image.setRGB(xM + x, yM + y, colour.toColour().getRGB()); 320 | } 321 | } 322 | } 323 | 324 | rayTraceRender.setImage(image); 325 | } 326 | 327 | return image; 328 | } 329 | 330 | BufferedImage renderSuperSample(View view, int depth, double filterSize) 331 | { 332 | final BufferedImage image = new BufferedImage( bmpWidth, bmpHeight, BufferedImage.TYPE_INT_RGB ); 333 | double increment = filterSize / (double)depth; 334 | 335 | for (int y = 0; y < bmpHeight; y++) 336 | { 337 | for (int x = 0; x < bmpWidth; x++) 338 | { 339 | ArrayList tempVectors = new ArrayList<>(); 340 | Vector[] vectors = null; 341 | 342 | for (double yV = -(filterSize / 2); yV <= (filterSize / 2); yV += increment){ 343 | for (double xV = -(filterSize / 2); xV <= (filterSize / 2); xV += increment){ 344 | tempVectors.add(getLocation(x + xV, y + yV, view.camera)); 345 | } 346 | } 347 | 348 | vectors = tempVectors.toArray(new Vector[0]); 349 | 350 | Colour colour = null; 351 | 352 | for (int i = 0; i < vectors.length; i++){ 353 | Vector tempVector = vectors[i]; 354 | 355 | if (i == 0){ 356 | colour = trace( 357 | new Ray() {{ 358 | begin = view.camera.position; 359 | direction = tempVector; 360 | }}, 361 | view, 362 | 0 363 | ); 364 | } 365 | else{ 366 | colour = Colour.average(colour, trace( 367 | new Ray() {{ 368 | begin = view.camera.position; 369 | direction = tempVector; 370 | }}, 371 | view, 0 372 | )); 373 | } 374 | } 375 | 376 | image.setRGB(x, y, colour.toColour().getRGB()); 377 | } 378 | 379 | rayTraceRender.setImage(image); 380 | } 381 | 382 | return image; 383 | } 384 | 385 | BufferedImage renderAdaptiveSample(View view, int maxDepth, double filterSize) 386 | { 387 | final BufferedImage image = new BufferedImage( bmpWidth, bmpHeight, BufferedImage.TYPE_INT_RGB ); 388 | 389 | for (int y = 0; y < bmpHeight; y++) 390 | { 391 | for (int x = 0; x < bmpWidth; x++) 392 | { 393 | int iterator = 1; 394 | double increment = filterSize; 395 | Colour tempAvgColour = null; 396 | Vector[] vectors = null; 397 | 398 | while(iterator <= maxDepth){ 399 | ArrayList tempVectors = new ArrayList<>(); 400 | 401 | for (double yV = -(filterSize / 2); yV <= (filterSize / 2); yV += increment){ 402 | for (double xV = -(filterSize / 2); xV <= (filterSize / 2); xV += increment){ 403 | tempVectors.add(getLocation(x + xV, y + yV, view.camera)); 404 | } 405 | } 406 | 407 | vectors = tempVectors.toArray(new Vector[0]); 408 | 409 | Colour[] colourArr = new Colour[vectors.length]; 410 | 411 | for (int i = 0; i < vectors.length; i++){ 412 | Vector tempVector = vectors[i]; 413 | colourArr[i] = trace( 414 | new Ray() {{ 415 | begin = view.camera.position; 416 | direction = tempVector; 417 | }}, 418 | view, 419 | 0 420 | ); 421 | } 422 | 423 | double averageChange = 0.0; 424 | 425 | boolean wasSet = false; 426 | 427 | for(int i = 0; i < colourArr.length; i++){ 428 | for (int j = 0; i < colourArr.length; i++){ 429 | if(!wasSet){ 430 | averageChange = (((double)colourArr[i].R + (double)colourArr[i].G + (double)colourArr[i].B) / 3.0) - ((double)colourArr[j].R + (double)colourArr[j].G + (double)colourArr[j].B) / 3.0; 431 | wasSet = true; 432 | } 433 | else if(i != j){ 434 | averageChange = (((((double)colourArr[i].R + (double)colourArr[i].G + (double)colourArr[i].B) / 3.0) - ((double)colourArr[j].R + (double)colourArr[j].G + (double)colourArr[j].B) / 3.0) + averageChange) / 2.0; 435 | } 436 | } 437 | } 438 | 439 | if (averageChange < 0.1 && averageChange > -0.1){ 440 | break; 441 | } 442 | else{ 443 | iterator *= 2; 444 | increment /= iterator; 445 | } 446 | } 447 | 448 | for (int i = 0; i < vectors.length; i++){ 449 | Vector tempVector = vectors[i]; 450 | 451 | if (i == 0){ 452 | tempAvgColour = trace( 453 | new Ray() {{ 454 | begin = view.camera.position; 455 | direction = tempVector; 456 | }}, 457 | view, 458 | 0 459 | ); 460 | } 461 | else{ 462 | tempAvgColour = Colour.average(tempAvgColour, trace( 463 | new Ray() {{ 464 | begin = view.camera.position; 465 | direction = tempVector; 466 | }}, 467 | view, 0 468 | )); 469 | } 470 | } 471 | 472 | image.setRGB(x, y, tempAvgColour.toColour().getRGB()); 473 | } 474 | 475 | rayTraceRender.setImage(image); 476 | } 477 | 478 | return image; 479 | } 480 | 481 | BufferedImage renderStochasticSample(View view, int depth, double filterSize) 482 | { 483 | final BufferedImage image = new BufferedImage( bmpWidth, bmpHeight, BufferedImage.TYPE_INT_RGB ); 484 | 485 | double increment = filterSize / (double)depth; 486 | 487 | for (int y = 0; y < bmpHeight; y++) 488 | { 489 | for (int x = 0; x < bmpWidth; x++) 490 | { 491 | ArrayList tempVectors = new ArrayList<>(); 492 | Vector[] vectors = null; 493 | 494 | for (double yV = -(filterSize / 2); yV <= (filterSize / 2); yV += increment){ 495 | for (double xV = -(filterSize / 2); xV <= (filterSize / 2); xV += increment){ 496 | double randX = Math.random() * increment * (Math.random() < 0.5 ? -1 : 1) + xV; 497 | double randY = Math.random() * increment * (Math.random() < 0.5 ? -1 : 1) + yV; 498 | 499 | tempVectors.add(getLocation(x + randX, y + randY, view.camera)); 500 | } 501 | } 502 | 503 | vectors = tempVectors.toArray(new Vector[0]); 504 | 505 | Colour colour = null; 506 | 507 | for (int i = 0; i < vectors.length; i++){ 508 | Vector tempVector = vectors[i]; 509 | 510 | if (i == 0){ 511 | colour = trace( 512 | new Ray() {{ 513 | begin = view.camera.position; 514 | direction = tempVector; 515 | }}, 516 | view, 517 | 0 518 | ); 519 | } 520 | else{ 521 | colour = Colour.average(colour, trace( 522 | new Ray() {{ 523 | begin = view.camera.position; 524 | direction = tempVector; 525 | }}, 526 | view, 0 527 | )); 528 | } 529 | } 530 | 531 | image.setRGB(x, y, colour.toColour().getRGB()); 532 | } 533 | 534 | rayTraceRender.setImage(image); 535 | } 536 | 537 | return image; 538 | } 539 | } -------------------------------------------------------------------------------- /src/Render.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | import java.awt.image.BufferedImage; 8 | import javafx.embed.swing.SwingFXUtils; 9 | import javafx.scene.image.Image; 10 | 11 | /** 12 | * 13 | * @author Rollie 14 | */ 15 | 16 | public class Render { 17 | public static Image render(int x, int y, View view){ 18 | RayTracer rayTracer = new RayTracer(x, y); 19 | BufferedImage temp = rayTracer.render(view); 20 | Image image = SwingFXUtils.toFXImage(temp, null); 21 | 22 | //System.out.println("Standard render complete."); 23 | 24 | return image; 25 | } 26 | 27 | public static Image renderPreview(int x, int y, View view, int accuracy){ 28 | RayTracer rayTracer = new RayTracer(x, y); 29 | BufferedImage temp = rayTracer.renderPreview(view, accuracy); 30 | Image image = SwingFXUtils.toFXImage(temp, null); 31 | 32 | //System.out.println("Render preview complete."); 33 | 34 | return image; 35 | } 36 | 37 | public static Image renderSuperSample(int x, int y, View view, int depth, double filterSize){ 38 | RayTracer rayTracer = new RayTracer(x, y); 39 | BufferedImage temp = rayTracer.renderSuperSample(view, depth, filterSize); 40 | Image image = SwingFXUtils.toFXImage(temp, null); 41 | 42 | //System.out.println("Super sampled render complete."); 43 | 44 | return image; 45 | } 46 | 47 | public static Image renderAdaptiveSample(int x, int y, View view, int depth, double filterSize){ 48 | RayTracer rayTracer = new RayTracer(x, y); 49 | BufferedImage temp = rayTracer.renderAdaptiveSample(view, depth, filterSize); 50 | Image image = SwingFXUtils.toFXImage(temp, null); 51 | 52 | //System.out.println("Adaptive sampled render complete."); 53 | 54 | return image; 55 | } 56 | 57 | public static Image renderStochasticSample(int x, int y, View view, int depth, double filterSize){ 58 | RayTracer rayTracer = new RayTracer(x, y); 59 | BufferedImage temp = rayTracer.renderStochasticSample(view, depth, filterSize); 60 | Image image = SwingFXUtils.toFXImage(temp, null); 61 | 62 | //System.out.println("Stochastic sampled render complete."); 63 | 64 | return image; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Sphere.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Sphere extends AbsObject 13 | { 14 | public double radius; 15 | public Vector objectPosition; 16 | 17 | @Override 18 | public Vector normal(Vector position) 19 | { 20 | return Vector.normal(Vector.subtract(position, objectPosition)); 21 | } 22 | 23 | @Override 24 | public Intersect intersect(Ray _ray) 25 | { 26 | Vector centerOrigin = Vector.subtract(objectPosition, _ray.begin); 27 | 28 | double _vectorD = Vector.dotProduct(centerOrigin, _ray.direction); 29 | double _distance; 30 | double tempVal; 31 | 32 | if (_vectorD >= 0){ 33 | tempVal = Math.pow(radius, 2) - (Vector.dotProduct(centerOrigin, centerOrigin) - Math.pow(_vectorD, 2)); 34 | _distance = tempVal < 0 ? 0 : _vectorD - Math.sqrt(tempVal); 35 | 36 | if (_distance == 0){ 37 | return null; 38 | } 39 | else{ 40 | Sphere sphere = this; 41 | 42 | return new Intersect(){{ 43 | object = sphere; 44 | ray = _ray; 45 | distance = _distance; 46 | }}; 47 | } 48 | } 49 | else{ 50 | _distance = 0; 51 | 52 | return null; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Vector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | /** 8 | * 9 | * @author Rollie 10 | */ 11 | 12 | public class Vector { 13 | public double X; 14 | public double Y; 15 | public double Z; 16 | 17 | public Vector(double x, double y, double z) 18 | { 19 | X = x; Y = y; Z = z; 20 | } 21 | 22 | public static Vector create(double x, double y, double z) 23 | { 24 | return new Vector(x, y, z); 25 | } 26 | 27 | public static Vector normal(Vector _vector) 28 | { 29 | double magn = magn(_vector); 30 | double mult = magn == 0 ? Double.POSITIVE_INFINITY : 1 / magn; 31 | 32 | return multiply(mult, _vector); 33 | } 34 | 35 | public static boolean isEqual(Vector _vectorO, Vector _vectorT) 36 | { 37 | return (_vectorO.X == _vectorT.X) && (_vectorO.Y == _vectorT.Y) && (_vectorO.Z == _vectorT.Z); 38 | } 39 | 40 | public static Vector multiply(double k, Vector _vector) 41 | { 42 | return new Vector((_vector.X * k), (_vector.Y * k), (_vector.Z * k)); 43 | } 44 | 45 | public static Vector multiply(Vector _vectorO, Vector _vectorT) 46 | { 47 | return new Vector((_vectorO.X * _vectorT.Y), (_vectorO.Y * _vectorT.Y), (_vectorO.Z * _vectorT.Z)); 48 | } 49 | 50 | public static Vector multiply(double k, double i) 51 | { 52 | return new Vector((k * i), (k * i), (k * i)); 53 | } 54 | 55 | public static Vector subtract(Vector _vectorO, Vector _vectorT) 56 | { 57 | return new Vector(_vectorO.X - _vectorT.X, _vectorO.Y - _vectorT.Y, _vectorO.Z - _vectorT.Z); 58 | } 59 | 60 | public static Vector add(Vector _vectorO, Vector _vectorT) 61 | { 62 | return new Vector(_vectorO.X + _vectorT.X, _vectorO.Y + _vectorT.Y, _vectorO.Z + _vectorT.Z); 63 | } 64 | 65 | public static double dotProduct(Vector _vectorO, Vector _vectorT) 66 | { 67 | return (_vectorO.X * _vectorT.X) + (_vectorO.Y * _vectorT.Y) + (_vectorO.Z * _vectorT.Z); 68 | } 69 | 70 | public static Vector crossP(Vector _vectorO, Vector _vectorT) 71 | { 72 | return new Vector(((_vectorO.Y * _vectorT.Z) - (_vectorO.Z * _vectorT.Y)), ((_vectorO.Z * _vectorT.X) - (_vectorO.X * _vectorT.Z)), ((_vectorO.X * _vectorT.Y) - (_vectorO.Y * _vectorT.X))); 73 | } 74 | 75 | public static double magn(Vector _vector) 76 | { 77 | return Math.sqrt(dotProduct(_vector, _vector)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/View.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | import java.util.Arrays; 8 | 9 | /** 10 | * 11 | * @author Rollie 12 | */ 13 | 14 | abstract class View { 15 | public AbsObject[] objects; 16 | public Camera camera; 17 | public LightSource[] lightSource; 18 | 19 | public Iterable intersect(Ray ray){ 20 | Iterable temp; 21 | Intersect[] tempL = new Intersect[objects.length]; 22 | 23 | for (int i = 0; i < tempL.length; i++){ 24 | tempL[i] = objects[i].intersect(ray); 25 | } 26 | 27 | temp = Arrays.asList(tempL); 28 | 29 | return temp; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/rayTraceRender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | import javafx.application.Application; 8 | import javafx.event.ActionEvent; 9 | import javafx.scene.Scene; 10 | import javafx.scene.control.Button; 11 | import javafx.stage.Stage; 12 | import java.awt.image.BufferedImage; 13 | import java.util.ArrayList; 14 | import java.util.Arrays; 15 | import javafx.collections.FXCollections; 16 | import javafx.collections.ObservableList; 17 | import javafx.scene.image.Image; 18 | import javafx.scene.image.ImageView; 19 | import javafx.embed.swing.SwingFXUtils; 20 | import javafx.geometry.Insets; 21 | import javafx.scene.control.Alert; 22 | import javafx.scene.control.CheckBox; 23 | import javafx.scene.control.ComboBox; 24 | import javafx.scene.control.ListView; 25 | import javafx.scene.layout.GridPane; 26 | import javafx.scene.control.Label; 27 | import javafx.scene.control.TextField; 28 | import javafx.scene.layout.HBox; 29 | import javafx.scene.layout.VBox; 30 | import javafx.stage.Modality; 31 | 32 | /** 33 | * 34 | * @author Rollie 35 | */ 36 | 37 | public class rayTraceRender extends Application { 38 | static ImageView imageView = new ImageView(); 39 | boolean isFloorOn = true; 40 | boolean antialiasing = false; 41 | int antialiasType = 1;//init supersampling 42 | int objectIterator = 0; 43 | int lightIterator = 0; 44 | int materialIterator = 0; 45 | int antialiasingDepth = 2; 46 | int previewAccuracy = 4; 47 | double antialiasFilterWidth = 1.0; 48 | double tX = 0, tY = 1, tZ = 0, pX = 5, pY = 5, pZ = 5; 49 | Alert alert = new Alert(Alert.AlertType.INFORMATION); 50 | 51 | View view; 52 | View materialView; 53 | View lightView; 54 | Floor floor; 55 | Sphere rmFloor; 56 | 57 | ListView objectList = new ListView<>(); 58 | ListView lightList = new ListView<>(); 59 | ListView materialList = new ListView<>(); 60 | 61 | ObservableList objectListItems = FXCollections.observableArrayList(); 62 | ObservableList lightListItems = FXCollections.observableArrayList(); 63 | ObservableList materialListItems = FXCollections.observableArrayList(); 64 | 65 | public rayTraceRender() { 66 | this.floor = new Floor() {{ 67 | material = Materials.Floor; 68 | objectPosition = Vector.create(0, 1, 0); 69 | displacement = 0; 70 | name = "Floor"; 71 | }}; 72 | 73 | this.rmFloor = new Sphere() {{ 74 | material = Materials.Floor; 75 | objectPosition = Vector.create(0, -10000, 0); 76 | radius = 0.0000001; 77 | name = "Floor"; 78 | }}; 79 | 80 | this.view = new View() 81 | {{ 82 | objects = new AbsObject[] { 83 | floor, 84 | new Sphere() {{ 85 | material = Materials.Glass; 86 | objectPosition = Vector.create(0, 3, 1); 87 | radius = 1.0; 88 | name = "Sphere." + objectIterator; 89 | objectIterator++; 90 | }}, 91 | new Sphere() {{ 92 | material = Materials.Glass; 93 | objectPosition = Vector.create(4, 3, 1); 94 | radius = 1.5; 95 | name = "Sphere." + objectIterator; 96 | objectIterator++; 97 | }}, 98 | new Sphere() {{ 99 | material = Materials.Mirror; 100 | objectPosition = Vector.create(0, 1, 0); 101 | radius = 0.5; 102 | name = "Sphere." + objectIterator; 103 | objectIterator++; 104 | }}, 105 | new Sphere() {{ 106 | material = Materials.Mirror; 107 | objectPosition = Vector.create(-4, 5, 2); 108 | radius = 2.0; 109 | name = "Sphere." + objectIterator; 110 | objectIterator++; 111 | }}, 112 | new Sphere() {{ 113 | material = Materials.Mirror; 114 | objectPosition = Vector.create(3, 2, 6); 115 | radius = 1.75; 116 | name = "Sphere." + objectIterator; 117 | objectIterator++; 118 | }}, 119 | new Sphere() {{ 120 | material = Materials.Mirror; 121 | objectPosition = Vector.create(-5, 5, -6); 122 | radius = 4.0; 123 | name = "Sphere." + objectIterator; 124 | objectIterator++; 125 | }} 126 | }; 127 | lightSource = new LightSource[] { 128 | new LightSource() {{ 129 | color = Colour.create(0.5, 0.3, 0.75); 130 | position = Vector.create(-2, 5, 0); 131 | name = "Light." + lightIterator; 132 | lightIterator++; 133 | }}, 134 | new LightSource() {{ 135 | color = Colour.create(0.5, 0.5, 0.5); 136 | position = Vector.create(-10, 12, -7.5); 137 | name = "Light." + lightIterator; 138 | lightIterator++; 139 | }}, 140 | new LightSource() {{ 141 | color = Colour.create(0.5, 0.6, 0.3); 142 | position = Vector.create(-6, 8, 5); 143 | name = "Light." + lightIterator; 144 | lightIterator++; 145 | }}, 146 | new LightSource() {{ 147 | color = Colour.create(0.5, 0.1, 0.1); 148 | position = Vector.create(4, 2.5, -5); 149 | name = "Light." + lightIterator; 150 | lightIterator++; 151 | }}}; 152 | camera = Camera.create(Vector.create(0, 1, 0), Vector.create(5, 5, 5)); 153 | }}; 154 | 155 | this.materialView = new View(){{ 156 | objects = new AbsObject[]{ 157 | new Sphere() {{ 158 | material = Materials.Mirror; 159 | objectPosition = Vector.create(0, 1, 0); 160 | radius = 1.0; 161 | name = "Sphere"; 162 | }}, 163 | floor 164 | }; 165 | lightSource = new LightSource[] { 166 | new LightSource() {{ 167 | color = Colour.create(0.75, 0.75, 0.75); 168 | position = Vector.create(4, 3, 4); 169 | name = "Light"; 170 | }}, 171 | new LightSource() {{ 172 | color = Colour.create(0.75, 0.75, 0.75); 173 | position = Vector.create(4, 3, -4); 174 | name = "Light"; 175 | }}, 176 | new LightSource() {{ 177 | color = Colour.create(0.75, 0.75, 0.75); 178 | position = Vector.create(-4, 3, 4); 179 | name = "Light"; 180 | }}, 181 | new LightSource() {{ 182 | color = Colour.create(0.75, 0.75, 0.75); 183 | position = Vector.create(-4, 3, -4); 184 | name = "Light"; 185 | }} 186 | }; 187 | camera = Camera.create(Vector.create(0, 1, 0), Vector.create(3, 3, 3), 600, 450); 188 | }}; 189 | 190 | this.lightView = new View(){{ 191 | objects = new AbsObject[]{ 192 | floor 193 | }; 194 | lightSource = new LightSource[] { 195 | new LightSource() {{ 196 | color = Colour.create(1.0, 1.0, 1.0); 197 | position = Vector.create(0, 1, 0); 198 | name = "Light"; 199 | }} 200 | }; 201 | camera = Camera.create(Vector.create(0, 1, 0), Vector.create(3, 3, 3), 600, 450); 202 | }}; 203 | } 204 | 205 | @Override 206 | public void start(Stage primaryStage) { 207 | alert.setTitle("Rendering previews..."); 208 | alert.setHeaderText("Rendering previews for main window, add material window,\nand add light window. Please wait..."); 209 | alert.initModality(Modality.NONE); 210 | alert.show(); 211 | 212 | Materials.materials = new Material[] { 213 | Materials.Default, 214 | Materials.Floor, 215 | Materials.Mirror, 216 | Materials.Glass 217 | }; 218 | 219 | ImageView imageViewLP = new ImageView(); 220 | ImageView imageViewMP = new ImageView(); 221 | 222 | Label colorLP = new Label("Color"); 223 | Label positionLP = new Label("Position"); 224 | Label nameLLP = new Label("Name"); 225 | Label emptyLP = new Label(""); 226 | Label emptyLP2 = new Label(""); 227 | Label specularMP = new Label("Specularity"); 228 | Label diffusionMP = new Label("Diffusion"); 229 | Label reflectionMP = new Label("Reflection"); 230 | Label accuracyMP = new Label("Specular Width"); 231 | Label nameLMP = new Label("Name"); 232 | Label emptyMP = new Label(""); 233 | Label emptyMP2 = new Label(""); 234 | Label materialOP = new Label("Material"); 235 | Label positionOP = new Label("Position"); 236 | Label sizeOP = new Label("Size"); 237 | Label nameLOP = new Label("Name"); 238 | Label objectLOP = new Label("Object"); 239 | Label empty = new Label(""); 240 | Label targetCP = new Label("Target"); 241 | Label positionCP = new Label("Position"); 242 | Label rendFlo = new Label("Render Floor"); 243 | Label anti = new Label("Antialiasing"); 244 | Label previewQ = new Label("Preview Quality"); 245 | Label antiType = new Label("Antialiasing Type"); 246 | Label antiDepth = new Label("Antialiasing Depth"); 247 | Label antiWidth = new Label("Antialiasing Width"); 248 | Label emptyLeftL = new Label(""); 249 | Label objectLabel = new Label("Objects"); 250 | Label lightLabel = new Label("Lights"); 251 | Label materialLabel = new Label("Materials"); 252 | 253 | Button removeLP = new Button("Delete"); 254 | Button saveLP = new Button("Save"); 255 | Button renderLP = new Button("Render"); 256 | Button removeMP = new Button("Delete"); 257 | Button saveMP = new Button("Save"); 258 | Button renderMP = new Button("Render"); 259 | Button removeOP = new Button("Delete"); 260 | Button saveOP = new Button("Save"); 261 | Button cancelCP = new Button("Cancel"); 262 | Button saveCP = new Button("Save"); 263 | Button cancelS = new Button("Cancel"); 264 | Button saveS = new Button("Save"); 265 | Button render = new Button("Render"); 266 | Button preview = new Button("Preview"); 267 | Button addMaterial = new Button("Add Material"); 268 | Button addObject = new Button("Add Object"); 269 | Button addLight = new Button("Add Light"); 270 | Button editCamera = new Button("Edit Camera"); 271 | Button settings = new Button("Settings"); 272 | Button deleteObject = new Button("Delete Object"); 273 | Button deleteLight = new Button("Delete Light"); 274 | Button deleteMaterial = new Button("Delete Material"); 275 | 276 | ComboBox cmbOP = new ComboBox<>(); 277 | ComboBox objectsOP = new ComboBox<>(); 278 | ComboBox antialiasingType = new ComboBox<>(); 279 | ComboBox antialiasingLevel = new ComboBox<>(); 280 | ComboBox previewQuality = new ComboBox<>(); 281 | 282 | CheckBox renderFloor = new CheckBox(); 283 | CheckBox antialias = new CheckBox(); 284 | 285 | HBox colorHLP = new HBox(5); 286 | HBox positionHLP = new HBox(5); 287 | HBox butLP = new HBox(5); 288 | HBox specularHMP = new HBox(5); 289 | HBox diffusionHMP = new HBox(5); 290 | HBox butMP = new HBox(5); 291 | HBox posOP = new HBox(5); 292 | HBox butOP = new HBox(5); 293 | HBox tarCP = new HBox(5); 294 | HBox posCP = new HBox(5); 295 | HBox butCP = new HBox(5); 296 | HBox butS = new HBox(5); 297 | HBox hBox = new HBox(5); 298 | 299 | HBox.setMargin(hBox, new Insets(10)); 300 | 301 | VBox vBox = new VBox(5); 302 | 303 | TextField nameLP = new TextField(); 304 | TextField rLP = new TextField(); 305 | TextField gLP = new TextField(); 306 | TextField bLP = new TextField(); 307 | TextField xLP = new TextField(); 308 | TextField yLP = new TextField(); 309 | TextField zLP = new TextField(); 310 | TextField nameMP = new TextField(); 311 | TextField specularRMP = new TextField(); 312 | TextField specularGMP = new TextField(); 313 | TextField specularBMP = new TextField(); 314 | TextField diffusionRMP = new TextField(); 315 | TextField diffusionGMP = new TextField(); 316 | TextField diffusionBMP = new TextField(); 317 | TextField reflectMP = new TextField(); 318 | TextField accurMP = new TextField(); 319 | TextField nameOP = new TextField(); 320 | TextField xOP = new TextField(); 321 | TextField yOP = new TextField(); 322 | TextField zOP = new TextField(); 323 | TextField radiusOP = new TextField(); 324 | TextField xCP = new TextField(); 325 | TextField yCP = new TextField(); 326 | TextField zCP = new TextField(); 327 | TextField xCPT = new TextField(); 328 | TextField yCPT = new TextField(); 329 | TextField zCPT = new TextField(); 330 | TextField antialiasWidth = new TextField(); 331 | 332 | GridPane addLightGP = new GridPane(); 333 | GridPane addMaterialGP = new GridPane(); 334 | GridPane addObjectGP = new GridPane(); 335 | GridPane editCameraGP = new GridPane(); 336 | GridPane settingsGP = new GridPane(); 337 | GridPane root = new GridPane(); 338 | 339 | GridPane.setConstraints(imageViewLP, 1, 0); 340 | GridPane.setConstraints(emptyLP2, 1, 1); 341 | GridPane.setConstraints(colorLP, 0, 2); 342 | GridPane.setConstraints(positionLP, 0, 3); 343 | GridPane.setConstraints(nameLLP, 0, 4); 344 | GridPane.setConstraints(colorHLP, 1, 2); 345 | GridPane.setConstraints(positionHLP, 1, 3); 346 | GridPane.setConstraints(nameLP, 1, 4); 347 | GridPane.setConstraints(emptyLP, 1, 5); 348 | GridPane.setConstraints(butLP, 1, 6); 349 | GridPane.setConstraints(imageViewMP, 1, 0); 350 | GridPane.setConstraints(emptyMP2, 1, 1); 351 | GridPane.setConstraints(specularMP, 0, 2); 352 | GridPane.setConstraints(diffusionMP, 0, 3); 353 | GridPane.setConstraints(reflectionMP, 0, 4); 354 | GridPane.setConstraints(specularHMP, 1, 2); 355 | GridPane.setConstraints(diffusionHMP, 1, 3); 356 | GridPane.setConstraints(reflectMP, 1, 4); 357 | GridPane.setConstraints(accuracyMP, 0, 5); 358 | GridPane.setConstraints(accurMP, 1, 5); 359 | GridPane.setConstraints(nameLMP, 0, 6); 360 | GridPane.setConstraints(nameMP, 1, 6); 361 | GridPane.setConstraints(emptyMP, 1, 7); 362 | GridPane.setConstraints(butMP, 1, 8); 363 | GridPane.setConstraints(materialOP, 0, 0); 364 | GridPane.setConstraints(cmbOP, 1, 0); 365 | GridPane.setConstraints(objectsOP, 1, 1); 366 | GridPane.setConstraints(objectLOP, 0, 1); 367 | GridPane.setConstraints(positionOP, 0, 2); 368 | GridPane.setConstraints(sizeOP, 0, 3); 369 | GridPane.setConstraints(posOP, 1, 2); 370 | GridPane.setConstraints(radiusOP, 1, 3); 371 | GridPane.setConstraints(nameLOP, 0, 4); 372 | GridPane.setConstraints(nameOP, 1, 4); 373 | GridPane.setConstraints(empty, 1, 5); 374 | GridPane.setConstraints(butOP, 1, 6); 375 | GridPane.setConstraints(targetCP, 0, 0); 376 | GridPane.setConstraints(tarCP, 1, 0); 377 | GridPane.setConstraints(positionCP, 0, 1); 378 | GridPane.setConstraints(posCP, 1, 1); 379 | GridPane.setConstraints(butCP, 1, 2); 380 | GridPane.setConstraints(rendFlo, 0, 0); 381 | GridPane.setConstraints(renderFloor, 1, 0); 382 | GridPane.setConstraints(anti, 0, 1); 383 | GridPane.setConstraints(antialias, 1, 1); 384 | GridPane.setConstraints(previewQ, 0, 2); 385 | GridPane.setConstraints(previewQuality, 1, 2); 386 | GridPane.setConstraints(antiWidth, 0, 3); 387 | GridPane.setConstraints(antialiasWidth, 1, 3); 388 | GridPane.setConstraints(antiType, 0, 4); 389 | GridPane.setConstraints(antialiasingType, 1, 4); 390 | GridPane.setConstraints(antiDepth, 0, 5); 391 | GridPane.setConstraints(antialiasingLevel, 1, 5); 392 | GridPane.setConstraints(butS, 1, 6); 393 | GridPane.setConstraints(imageView, 0, 0); 394 | GridPane.setConstraints(hBox, 0, 1); 395 | GridPane.setConstraints(vBox, 1, 0); 396 | 397 | addLightGP.setPadding(new Insets(10)); 398 | colorLP.setPadding(new Insets(10)); 399 | positionLP.setPadding(new Insets(10)); 400 | nameLLP.setPadding(new Insets(10)); 401 | nameLP.setPadding(new Insets(10)); 402 | colorHLP.setPadding(new Insets(5, 0, 0, 0)); 403 | positionHLP.setPadding(new Insets(5, 0, 0, 0)); 404 | removeLP.setPadding(new Insets(10, 82, 10, 82)); 405 | saveLP.setPadding(new Insets(10, 82, 10, 82)); 406 | renderLP.setPadding(new Insets(10, 82, 10, 82)); 407 | addMaterialGP.setPadding(new Insets(10)); 408 | specularMP.setPadding(new Insets(10)); 409 | diffusionMP.setPadding(new Insets(10)); 410 | reflectionMP.setPadding(new Insets(10)); 411 | accuracyMP.setPadding(new Insets(10)); 412 | nameLMP.setPadding(new Insets(10)); 413 | specularHMP.setPadding(new Insets(5, 0, 0, 0)); 414 | diffusionHMP.setPadding(new Insets(5, 0, 0, 0)); 415 | removeMP.setPadding(new Insets(10, 82, 10, 82)); 416 | saveMP.setPadding(new Insets(10, 82, 10, 82)); 417 | renderMP.setPadding(new Insets(10, 82, 10, 82)); 418 | addObjectGP.setPadding(new Insets(10)); 419 | materialOP.setPadding(new Insets(10)); 420 | positionOP.setPadding(new Insets(10)); 421 | sizeOP.setPadding(new Insets(10)); 422 | nameLOP.setPadding(new Insets(10)); 423 | objectLOP.setPadding(new Insets(10)); 424 | posOP.setPadding(new Insets(5, 0, 0, 0)); 425 | removeOP.setPadding(new Insets(10, 98, 10, 98)); 426 | saveOP.setPadding(new Insets(10, 98, 10, 98)); 427 | editCameraGP.setPadding(new Insets(10)); 428 | targetCP.setPadding(new Insets(10)); 429 | positionCP.setPadding(new Insets(10)); 430 | tarCP.setPadding(new Insets(5, 0, 0, 0)); 431 | posCP.setPadding(new Insets(5, 0, 0, 0)); 432 | cancelCP.setPadding(new Insets(10, 98, 10, 98)); 433 | saveCP.setPadding(new Insets(10, 98, 10, 98)); 434 | settingsGP.setPadding(new Insets(10)); 435 | rendFlo.setPadding(new Insets(10)); 436 | anti.setPadding(new Insets(10)); 437 | previewQ.setPadding(new Insets(10)); 438 | antiWidth.setPadding(new Insets(10)); 439 | antiType.setPadding(new Insets(10)); 440 | antiDepth.setPadding(new Insets(10)); 441 | cancelS.setPadding(new Insets(10, 30, 10, 30)); 442 | saveS.setPadding(new Insets(10, 30, 10, 30)); 443 | render.setPadding(new Insets(10, 25, 10, 25)); 444 | preview.setPadding(new Insets(10, 25, 10, 25)); 445 | addMaterial.setPadding(new Insets(10, 25, 10, 25)); 446 | addObject.setPadding(new Insets(10, 25, 10, 25)); 447 | addLight.setPadding(new Insets(10, 25, 10, 25)); 448 | editCamera.setPadding(new Insets(10, 25, 10, 25)); 449 | settings.setPadding(new Insets(10, 25, 10, 25)); 450 | hBox.setPadding(new Insets(5)); 451 | emptyLeftL.setPadding(new Insets(-10, 0, -10, 0)); 452 | objectLabel.setPadding(new Insets(5, 0, 0, 7)); 453 | lightLabel.setPadding(new Insets(5, 0, 0, 7)); 454 | materialLabel.setPadding(new Insets(5, 0, 0, 7)); 455 | deleteObject.setPadding(new Insets(10)); 456 | deleteLight.setPadding(new Insets(10)); 457 | deleteMaterial.setPadding(new Insets(10)); 458 | vBox.setPadding(new Insets(0, 0, 0, 5)); 459 | 460 | nameLP.setPromptText("Name"); 461 | rLP.setPromptText("R (0 -> 1)"); 462 | gLP.setPromptText("G (0 -> 1)"); 463 | bLP.setPromptText("B (0 -> 1)"); 464 | xLP.setPromptText("X (R)"); 465 | yLP.setPromptText("Y (R)"); 466 | zLP.setPromptText("Z (R)"); 467 | nameMP.setPromptText("Name"); 468 | specularRMP.setPromptText("R (0 -> 1)"); 469 | specularGMP.setPromptText("G (0 -> 1)"); 470 | specularBMP.setPromptText("B (0 -> 1)"); 471 | diffusionRMP.setPromptText("R (0 -> 1)"); 472 | diffusionGMP.setPromptText("G (0 -> 1)"); 473 | diffusionBMP.setPromptText("B (0 -> 1)"); 474 | reflectMP.setPromptText("Reflection (0 -> 1)"); 475 | accurMP.setPromptText("Accuracy (0 -> N)"); 476 | nameOP.setPromptText("Name"); 477 | xOP.setPromptText("X"); 478 | yOP.setPromptText("Y"); 479 | zOP.setPromptText("Z"); 480 | radiusOP.setPromptText("Radius (Sphere Only)"); 481 | xCP.setPromptText("X"); 482 | yCP.setPromptText("Y"); 483 | zCP.setPromptText("Z"); 484 | xCPT.setPromptText("X"); 485 | yCPT.setPromptText("Y"); 486 | zCPT.setPromptText("Z"); 487 | antialiasWidth.setPromptText("Cubic Filter (0.0 -> R)"); 488 | 489 | Scene lightScene = new Scene(addLightGP); 490 | Scene materialScene = new Scene(addMaterialGP); 491 | Scene objectScene = new Scene(addObjectGP); 492 | Scene cameraScene = new Scene(editCameraGP); 493 | Scene settingsScene = new Scene(settingsGP); 494 | Scene scene = new Scene(root, 1010, 850); 495 | 496 | Stage addLightPopup = new Stage(); 497 | Stage addMaterialPopup = new Stage(); 498 | Stage addObjectPopup = new Stage(); 499 | Stage editCameraPopup = new Stage(); 500 | Stage settingsPopup = new Stage(); 501 | 502 | addLightPopup.setAlwaysOnTop(true); 503 | addMaterialPopup.setAlwaysOnTop(true); 504 | addObjectPopup.setAlwaysOnTop(true); 505 | editCameraPopup.setAlwaysOnTop(true); 506 | settingsPopup.setAlwaysOnTop(true); 507 | 508 | addLightPopup.initModality(Modality.WINDOW_MODAL); 509 | addMaterialPopup.initModality(Modality.WINDOW_MODAL); 510 | addObjectPopup.initModality(Modality.WINDOW_MODAL); 511 | editCameraPopup.initModality(Modality.WINDOW_MODAL); 512 | settingsPopup.initModality(Modality.WINDOW_MODAL); 513 | 514 | colorHLP.getChildren().addAll(rLP, gLP, bLP); 515 | positionHLP.getChildren().addAll(xLP, yLP, zLP); 516 | butLP.getChildren().addAll(removeLP, saveLP, renderLP); 517 | addLightGP.getChildren().addAll(imageViewLP, emptyLP2, colorLP, positionLP, nameLLP, colorHLP, positionHLP, nameLP, emptyLP, butLP); 518 | specularHMP.getChildren().addAll(specularRMP, specularGMP, specularBMP); 519 | diffusionHMP.getChildren().addAll(diffusionRMP, diffusionGMP, diffusionBMP); 520 | butMP.getChildren().addAll(removeMP, saveMP, renderMP); 521 | addMaterialGP.getChildren().addAll(imageViewMP, specularMP, diffusionMP, specularHMP, diffusionHMP, reflectionMP, butMP, emptyMP, reflectMP, nameLMP, nameMP, accuracyMP, accurMP); 522 | posOP.getChildren().addAll(xOP, yOP, zOP); 523 | butOP.getChildren().addAll(removeOP, saveOP); 524 | addObjectGP.getChildren().addAll(materialOP, objectsOP, objectLOP, positionOP, sizeOP, butOP, empty, cmbOP, posOP, radiusOP, nameLOP, nameOP); 525 | tarCP.getChildren().addAll(xCPT, yCPT, zCPT); 526 | posCP.getChildren().addAll(xCP, yCP, zCP); 527 | butCP.getChildren().addAll(cancelCP, saveCP); 528 | editCameraGP.getChildren().addAll(targetCP, tarCP, positionCP, posCP, butCP); 529 | butS.getChildren().addAll(cancelS, saveS); 530 | settingsGP.getChildren().addAll(rendFlo, anti, previewQ, previewQuality, renderFloor, antialias, antiType, antialiasingType, antiDepth, antialiasingLevel, butS, antiWidth, antialiasWidth); 531 | hBox.getChildren().addAll(render, preview, addMaterial, addObject, addLight, editCamera, settings); 532 | vBox.getChildren().addAll(emptyLeftL, objectLabel, deleteObject, objectList, lightLabel, deleteLight, lightList, materialLabel, deleteMaterial, materialList); 533 | root.getChildren().addAll(imageView, hBox, vBox); 534 | 535 | addLightPopup.setTitle("Add Light"); 536 | addMaterialPopup.setTitle("Add Material"); 537 | addObjectPopup.setTitle("Add Object"); 538 | editCameraPopup.setTitle("Edit Camera"); 539 | settingsPopup.setTitle("Settings"); 540 | primaryStage.setTitle("Steven Rowland(rowland005) Ray Tracer"); 541 | 542 | addLightPopup.setScene(lightScene); 543 | addMaterialPopup.setScene(materialScene); 544 | addObjectPopup.setScene(objectScene); 545 | editCameraPopup.setScene(cameraScene); 546 | settingsPopup.setScene(settingsScene); 547 | primaryStage.setScene(scene); 548 | 549 | xCP.setText(String.valueOf(pX)); 550 | yCP.setText(String.valueOf(pY)); 551 | zCP.setText(String.valueOf(pZ)); 552 | 553 | xCPT.setText(String.valueOf(tX)); 554 | yCPT.setText(String.valueOf(tY)); 555 | zCPT.setText(String.valueOf(tZ)); 556 | 557 | 558 | renderFloor.setSelected(true); 559 | antialias.setSelected(false); 560 | 561 | antialiasingType.getItems().add("Super Sampling"); 562 | antialiasingType.getItems().add("Adaptive Sampling"); 563 | antialiasingType.getItems().add("Stochastic Sampling"); 564 | antialiasingType.setValue("Super Sampling"); 565 | 566 | antialiasingLevel.getItems().add("2"); 567 | antialiasingLevel.getItems().add("4"); 568 | antialiasingLevel.getItems().add("8"); 569 | antialiasingLevel.getItems().add("16"); 570 | antialiasingLevel.getItems().add("32"); 571 | antialiasingLevel.setValue("2"); 572 | 573 | previewQuality.getItems().add("50%"); 574 | previewQuality.getItems().add("25%"); 575 | previewQuality.getItems().add("12.5%"); 576 | previewQuality.getItems().add("6.25%"); 577 | previewQuality.getItems().add("3.125%"); 578 | previewQuality.setValue("25%"); 579 | 580 | objectsOP.getItems().add("Sphere"); 581 | objectsOP.setValue("Sphere"); 582 | 583 | for (AbsObject i : view.objects){ 584 | if(!"Floor".equals(i.name)){ 585 | objectListItems.add(i.name); 586 | } 587 | } 588 | 589 | for (LightSource i : view.lightSource){ 590 | lightListItems.add(i.name); 591 | } 592 | 593 | for (Material i : Materials.materials){ 594 | materialListItems.add(i.name); 595 | } 596 | 597 | for(Material i : Materials.materials){ 598 | cmbOP.getItems().add(i.name); 599 | } 600 | 601 | antialiasingType.setPrefWidth(185); 602 | antialiasingLevel.setPrefWidth(185); 603 | previewQuality.setPrefWidth(185); 604 | objectList.setItems(objectListItems); 605 | objectList.setPrefWidth(200); 606 | objectList.setPrefHeight(250); 607 | lightList.setItems(lightListItems); 608 | lightList.setPrefWidth(200); 609 | lightList.setPrefHeight(250); 610 | materialList.setItems(materialListItems); 611 | materialList.setPrefWidth(200); 612 | materialList.setPrefHeight(250); 613 | objectsOP.setPrefWidth(457); 614 | cmbOP.setPrefWidth(457); 615 | 616 | imageView.setImage(Render.renderPreview(800, 800, view, previewAccuracy)); 617 | imageViewMP.setImage(Render.render(600, 450, materialView)); 618 | imageViewLP.setImage(Render.render(600, 450, lightView)); 619 | 620 | 621 | renderLP.setOnAction((ActionEvent event) -> { 622 | double r, g, b; 623 | 624 | try{ 625 | r = Double.parseDouble(rLP.getText()); 626 | g = Double.parseDouble(gLP.getText()); 627 | b = Double.parseDouble(bLP.getText()); 628 | 629 | LightSource lightTemp = new LightSource(){{ 630 | name = "Temp"; 631 | color = Colour.create(r, g, b); 632 | position = Vector.create(0, 1, 0); 633 | }}; 634 | 635 | lightView.lightSource[0] = lightTemp; 636 | } 637 | catch (Exception ex){ 638 | 639 | } 640 | 641 | imageViewLP.setImage(Render.render(600, 450, lightView)); 642 | }); 643 | 644 | removeLP.setOnAction((ActionEvent event) -> { 645 | addLightPopup.hide(); 646 | rLP.setText(""); 647 | gLP.setText(""); 648 | bLP.setText(""); 649 | 650 | xLP.setText(""); 651 | yLP.setText(""); 652 | zLP.setText(""); 653 | 654 | nameLP.setText(""); 655 | }); 656 | 657 | saveLP.setOnAction((ActionEvent event) -> { 658 | String tempName; 659 | double r, g, b, x, y, z; 660 | 661 | try{ 662 | if ("".equals(nameLP.getText())){ 663 | tempName = "Light." + lightIterator; 664 | lightIterator++; 665 | } 666 | else{ 667 | tempName = nameLP.getText() + "." + lightIterator; 668 | lightIterator++; 669 | } 670 | 671 | r = Double.parseDouble(rLP.getText()); 672 | g = Double.parseDouble(gLP.getText()); 673 | b = Double.parseDouble(bLP.getText()); 674 | 675 | x = Double.parseDouble(xLP.getText()); 676 | y = Double.parseDouble(yLP.getText()); 677 | z = Double.parseDouble(zLP.getText()); 678 | 679 | LightSource lightTemp = new LightSource(){{ 680 | name = "Temp"; 681 | color = Colour.create(r, g, b); 682 | position = Vector.create(x, y, z); 683 | }}; 684 | 685 | addLight(lightTemp, tempName); 686 | 687 | rLP.setText(""); 688 | gLP.setText(""); 689 | bLP.setText(""); 690 | 691 | xLP.setText(""); 692 | yLP.setText(""); 693 | zLP.setText(""); 694 | 695 | nameLP.setText(""); 696 | } 697 | catch (Exception ex){ 698 | 699 | } 700 | 701 | addLightPopup.hide(); 702 | }); 703 | 704 | renderMP.setOnAction((ActionEvent event) -> { 705 | double spr, spg, spb, dir, dig, dib, ref; 706 | int acc; 707 | 708 | try{ 709 | spr = Double.parseDouble(specularRMP.getText()); 710 | spg = Double.parseDouble(specularGMP.getText()); 711 | spb = Double.parseDouble(specularBMP.getText()); 712 | 713 | dir = Double.parseDouble(diffusionRMP.getText()); 714 | dig = Double.parseDouble(diffusionGMP.getText()); 715 | dib = Double.parseDouble(diffusionBMP.getText()); 716 | 717 | ref = Double.parseDouble(reflectMP.getText()); 718 | acc = Integer.parseInt(accurMP.getText()); 719 | 720 | Material materialTemp = new Material(){{ 721 | name = "Temp"; 722 | reflect = (Vector position) -> ref; 723 | diffuse = (Vector position) -> Colour.create(dir, dig, dib); 724 | specular = (Vector position) -> Colour.create(spr, spg, spb); 725 | specular = (Vector position) -> Colour.create(0.5, 0.5, 0.5); 726 | specularWidth = 15; 727 | specularWidth = acc; 728 | }}; 729 | 730 | materialView.objects[0].material = materialTemp; 731 | } 732 | catch (Exception ex){ 733 | 734 | } 735 | 736 | imageViewMP.setImage(Render.render(600, 450, materialView)); 737 | }); 738 | 739 | removeMP.setOnAction((ActionEvent event) -> { 740 | addMaterialPopup.hide(); 741 | specularRMP.setText(""); 742 | specularGMP.setText(""); 743 | specularBMP.setText(""); 744 | 745 | diffusionRMP.setText(""); 746 | diffusionGMP.setText(""); 747 | diffusionBMP.setText(""); 748 | 749 | reflectMP.setText(""); 750 | accurMP.setText(""); 751 | }); 752 | 753 | saveMP.setOnAction((ActionEvent event) -> { 754 | String tempName; 755 | double spr, spg, spb, dir, dig, dib, ref; 756 | int acc; 757 | 758 | try{ 759 | if ("".equals(nameMP.getText())){ 760 | tempName = "Material." + materialIterator; 761 | materialIterator++; 762 | } 763 | else{ 764 | tempName = nameMP.getText() + "." + materialIterator; 765 | materialIterator++; 766 | } 767 | 768 | spr = Double.parseDouble(specularRMP.getText()); 769 | spg = Double.parseDouble(specularGMP.getText()); 770 | spb = Double.parseDouble(specularBMP.getText()); 771 | 772 | dir = Double.parseDouble(diffusionRMP.getText()); 773 | dig = Double.parseDouble(diffusionGMP.getText()); 774 | dib = Double.parseDouble(diffusionBMP.getText()); 775 | 776 | ref = Double.parseDouble(reflectMP.getText()); 777 | acc = Integer.parseInt(accurMP.getText()); 778 | 779 | Material materialTemp = new Material(){{ 780 | name = tempName; 781 | reflect = (Vector position) -> ref; 782 | diffuse = (Vector position) -> Colour.create(dir, dig, dib); 783 | specular = (Vector position) -> Colour.create(spr, spg, spb); 784 | specularWidth = acc; 785 | }}; 786 | 787 | materialView.objects[0].material = materialTemp; 788 | 789 | addMaterial(materialTemp, tempName); 790 | 791 | specularRMP.setText(""); 792 | specularGMP.setText(""); 793 | specularBMP.setText(""); 794 | 795 | diffusionRMP.setText(""); 796 | diffusionGMP.setText(""); 797 | diffusionBMP.setText(""); 798 | 799 | reflectMP.setText(""); 800 | accurMP.setText(""); 801 | } 802 | catch (Exception ex){ 803 | 804 | } 805 | 806 | addMaterialPopup.hide(); 807 | }); 808 | 809 | removeOP.setOnAction((ActionEvent event) -> { 810 | addObjectPopup.hide(); 811 | xOP.setText(""); 812 | yOP.setText(""); 813 | zOP.setText(""); 814 | radiusOP.setText(""); 815 | }); 816 | 817 | saveOP.setOnAction((ActionEvent event) -> { 818 | Material material = new Material(); 819 | String name; 820 | 821 | String object = objectsOP.getValue(); 822 | 823 | try{ 824 | if(null != object)switch (object) { 825 | case "Sphere": 826 | //do nothing yet 827 | break; 828 | default: 829 | //set sphere 830 | break; 831 | } 832 | 833 | if ("".equals(cmbOP.getValue())){ 834 | material = Materials.Default; 835 | } 836 | else{ 837 | for(Material i : Materials.materials){ 838 | if (i.name.equals(cmbOP.getValue())){ 839 | material = i; 840 | } 841 | } 842 | } 843 | 844 | if ("".equals(nameOP.getText())){ 845 | name = "Object." + objectIterator; 846 | objectIterator++; 847 | } 848 | else{ 849 | name = nameOP.getText() + "." + objectIterator; 850 | objectIterator++; 851 | } 852 | 853 | name = name + "." + objectIterator; 854 | objectIterator++; 855 | 856 | addSphere( 857 | name, 858 | Double.parseDouble(xOP.getText()), 859 | Double.parseDouble(yOP.getText()), 860 | Double.parseDouble(zOP.getText()), 861 | Double.parseDouble(radiusOP.getText()), 862 | material 863 | ); 864 | } 865 | catch(Exception ex){ 866 | 867 | } 868 | 869 | addObjectPopup.hide(); 870 | xOP.setText(""); 871 | yOP.setText(""); 872 | zOP.setText(""); 873 | radiusOP.setText(""); 874 | }); 875 | 876 | cancelCP.setOnAction((ActionEvent event) -> { 877 | editCameraPopup.hide(); 878 | }); 879 | 880 | saveCP.setOnAction((ActionEvent event) -> { 881 | try{ 882 | 883 | tX = Double.parseDouble(xCPT.getText()); 884 | tY = Double.parseDouble(yCPT.getText()); 885 | tZ = Double.parseDouble(zCPT.getText()); 886 | 887 | pX = Double.parseDouble(xCP.getText()); 888 | pY = Double.parseDouble(yCP.getText()); 889 | pZ = Double.parseDouble(zCP.getText()); 890 | 891 | view.camera = Camera.create(Vector.create(tX, tY, tZ), Vector.create(pX, pY, pZ)); 892 | } 893 | catch(Exception ex){} 894 | 895 | editCameraPopup.hide(); 896 | }); 897 | 898 | cancelS.setOnAction((ActionEvent event) -> { 899 | settingsPopup.hide(); 900 | }); 901 | 902 | saveS.setOnAction((ActionEvent event) -> { 903 | try{ 904 | isFloorOn = renderFloor.isSelected(); 905 | 906 | if (!isFloorOn){ 907 | view.objects[0] = rmFloor; 908 | } 909 | else{ 910 | view.objects[0] = floor; 911 | } 912 | 913 | antialiasing = antialias.isSelected(); 914 | 915 | if (!"".equals(antialiasingLevel.getValue())){ 916 | antialiasingDepth = Integer.parseInt(antialiasingLevel.getValue()); 917 | } 918 | 919 | String previewQual = previewQuality.getValue(); 920 | 921 | if(null != previewQual)switch (previewQual) { 922 | case "50%": 923 | previewAccuracy = 2; 924 | break; 925 | case "25%": 926 | previewAccuracy = 4; 927 | break; 928 | case "12.5%": 929 | previewAccuracy = 8; 930 | break; 931 | case "6.25%": 932 | previewAccuracy = 16; 933 | break; 934 | case "3.125%": 935 | previewAccuracy = 32; 936 | break; 937 | default: 938 | previewAccuracy = 4; 939 | break; 940 | } 941 | 942 | String antiSwitchType = antialiasingType.getValue(); 943 | 944 | if(null != antiSwitchType)switch (antiSwitchType) { 945 | case "Super Sampling": 946 | antialiasType = 1; 947 | break; 948 | case "Adaptive Sampling": 949 | antialiasType = 2; 950 | break; 951 | case "Stochastic Sampling": 952 | antialiasType = 3; 953 | break; 954 | default: 955 | previewAccuracy = 1; 956 | break; 957 | } 958 | 959 | if ("".equals(antialiasWidth.getText())){ 960 | antialiasFilterWidth = 1.0; 961 | } 962 | else{ 963 | antialiasFilterWidth = Double.parseDouble(antialiasWidth.getText()); 964 | 965 | antialiasFilterWidth = Math.abs(antialiasFilterWidth); 966 | } 967 | } 968 | catch(Exception ex){} 969 | 970 | settingsPopup.hide(); 971 | }); 972 | 973 | render.setOnAction((ActionEvent) -> { 974 | alert.setTitle("Rendering..."); 975 | 976 | if (antialiasing){ 977 | //imageView.setImage(renderPreview(800, 800, view, previewAccuracy)); 978 | 979 | switch(antialiasType){ 980 | case 1: 981 | alert.setHeaderText("Rendering camera view with Super Sampling. Please wait..."); 982 | alert.show(); 983 | 984 | imageView.setImage(Render.renderSuperSample(800, 800, view, antialiasingDepth, antialiasFilterWidth)); 985 | break; 986 | case 2: 987 | alert.setHeaderText("Rendering camera view with Adaptive Sampling. Please wait..."); 988 | alert.show(); 989 | 990 | imageView.setImage(Render.renderAdaptiveSample(800, 800, view, antialiasingDepth, antialiasFilterWidth)); 991 | break; 992 | case 3: 993 | alert.setHeaderText("Rendering camera view with Stochastic(Monte Carlo) Sampling. Please wait..."); 994 | alert.show(); 995 | 996 | imageView.setImage(Render.renderStochasticSample(800, 800, view, antialiasingDepth, antialiasFilterWidth)); 997 | break; 998 | } 999 | } 1000 | else{ 1001 | //imageView.setImage(renderPreview(800, 800, view, previewAccuracy)); 1002 | 1003 | alert.setHeaderText("Rendering camera view. Please wait..."); 1004 | alert.show(); 1005 | 1006 | imageView.setImage(Render.render(800, 800, view)); 1007 | } 1008 | 1009 | alert.hide(); 1010 | }); 1011 | 1012 | preview.setOnAction((ActionEvent) -> { 1013 | alert.setTitle("Rendering..."); 1014 | alert.setHeaderText("Rendering preview. Please wait..."); 1015 | alert.show(); 1016 | 1017 | imageView.setImage(Render.renderPreview(800, 800, view, previewAccuracy)); 1018 | 1019 | alert.hide(); 1020 | }); 1021 | 1022 | addMaterial.setOnAction((ActionEvent event) -> { 1023 | materialView.objects[0].material = new Material(){{ 1024 | name = "Mirror"; 1025 | reflect = (Vector position) -> 1.0; 1026 | diffuse = (Vector position) -> Colour.create(1.0, 1.0, 1.0); 1027 | specular = (Vector position) -> Colour.create(0.5, 0.5, 0.5); 1028 | specularWidth = 100; 1029 | }}; 1030 | 1031 | addMaterialPopup.show(); 1032 | }); 1033 | 1034 | addObject.setOnAction((ActionEvent event) -> { 1035 | cmbOP.getItems().clear(); 1036 | 1037 | for(Material i : Materials.materials){ 1038 | cmbOP.getItems().add(i.name); 1039 | } 1040 | 1041 | addObjectPopup.show(); 1042 | }); 1043 | 1044 | addLight.setOnAction((ActionEvent) -> { 1045 | addLightPopup.show(); 1046 | }); 1047 | 1048 | editCamera.setOnAction((ActionEvent) -> { 1049 | editCameraPopup.show(); 1050 | }); 1051 | 1052 | settings.setOnAction((ActionEvent) -> { 1053 | settingsPopup.show(); 1054 | }); 1055 | 1056 | deleteObject.setOnAction((ActionEvent) -> { 1057 | String temp = objectList.getSelectionModel().getSelectedItem(); 1058 | 1059 | if(temp != null){ 1060 | for (AbsObject object : view.objects) { 1061 | if (temp.equals(object.name)) { 1062 | ArrayList tempList = new ArrayList<>(Arrays.asList(view.objects)); 1063 | tempList.remove(object); 1064 | view.objects = tempList.toArray(new AbsObject[0]); 1065 | break; 1066 | } 1067 | } 1068 | 1069 | objectListItems.clear(); 1070 | 1071 | for (AbsObject i : view.objects){ 1072 | if(!"Floor".equals(i.name)){ 1073 | objectListItems.add(i.name); 1074 | } 1075 | } 1076 | 1077 | objectList.setItems(objectListItems); 1078 | } 1079 | }); 1080 | 1081 | deleteLight.setOnAction((ActionEvent) -> { 1082 | String temp = lightList.getSelectionModel().getSelectedItem(); 1083 | 1084 | if(temp != null){ 1085 | for (LightSource lightSource : view.lightSource) { 1086 | if (temp.equals(lightSource.name)) { 1087 | ArrayList tempList = new ArrayList<>(Arrays.asList(view.lightSource)); 1088 | tempList.remove(lightSource); 1089 | view.lightSource = tempList.toArray(new LightSource[0]); 1090 | break; 1091 | } 1092 | } 1093 | 1094 | lightListItems.clear(); 1095 | 1096 | for (LightSource i : view.lightSource){ 1097 | lightListItems.add(i.name); 1098 | } 1099 | 1100 | lightList.setItems(lightListItems); 1101 | } 1102 | }); 1103 | 1104 | deleteMaterial.setOnAction((ActionEvent) -> { 1105 | String temp = materialList.getSelectionModel().getSelectedItem(); 1106 | 1107 | if(temp != null){ 1108 | for (Material material : Materials.materials) { 1109 | if (temp.equals(material.name)) { 1110 | ArrayList tempList = new ArrayList<>(Arrays.asList(Materials.materials)); 1111 | tempList.remove(material); 1112 | Materials.materials = tempList.toArray(new Material[0]); 1113 | break; 1114 | } 1115 | } 1116 | 1117 | materialListItems.clear(); 1118 | 1119 | for (Material i : Materials.materials){ 1120 | materialListItems.add(i.name); 1121 | } 1122 | 1123 | materialList.setItems(materialListItems); 1124 | } 1125 | }); 1126 | 1127 | alert.hide(); 1128 | 1129 | primaryStage.setMaxHeight(885);//.setResizable(false); 1130 | primaryStage.setMaxWidth(1025); 1131 | 1132 | primaryStage.setMinHeight(885);//.setResizable(false); 1133 | primaryStage.setMinWidth(1025); 1134 | 1135 | primaryStage.show(); 1136 | 1137 | Alert message = new Alert(Alert.AlertType.INFORMATION); 1138 | message.setTitle("Welcome"); 1139 | message.setHeaderText( 1140 | "This ray tracer supports:\n" 1141 | + " -Diffusion\n" 1142 | + " -Specularity\n" 1143 | + " -Reflection\n" 1144 | + " -Super, Adaptive, and Stochastic(Monte Carlo) Antialiasing\n" 1145 | + " -Camera manipulation(target and position)\n" 1146 | + " -Custom materials\n" 1147 | + " -Custom point source lighting\n" 1148 | + " -Custom objects(currently only a sphere)\n" 1149 | + " -Render previews\n" 1150 | + " -Inward only refraction(no transparency)\n\n" 1151 | + "Press OK to begin." 1152 | ); 1153 | message.setGraphic(null); 1154 | message.initModality(Modality.NONE); 1155 | message.show(); 1156 | } 1157 | 1158 | /** 1159 | * @param args the command line arguments 1160 | */ 1161 | public static void main(String[] args) { 1162 | launch(args); 1163 | } 1164 | 1165 | private void addLight(LightSource tempLight, String _name){ 1166 | int tempLength = view.lightSource.length + 1; 1167 | 1168 | LightSource[] tempLightSources = new LightSource[tempLength]; 1169 | 1170 | System.arraycopy(view.lightSource, 0, tempLightSources, 0, tempLength - 1); 1171 | 1172 | tempLightSources[tempLength - 1] = tempLight; 1173 | 1174 | view.lightSource = tempLightSources; 1175 | 1176 | lightListItems.add(_name); 1177 | } 1178 | 1179 | private void addSphere(String _name, double x, double y, double z, double _radius, Material _material){ 1180 | int tempLength = view.objects.length + 1; 1181 | 1182 | AbsObject[] tempObjects = new AbsObject[tempLength]; 1183 | 1184 | System.arraycopy(view.objects, 0, tempObjects, 0, tempLength - 1); 1185 | 1186 | Sphere tempSphere = new Sphere() {{ 1187 | material = _material; 1188 | objectPosition = Vector.create(x, y, z); 1189 | radius = _radius; 1190 | name = _name; 1191 | }}; 1192 | 1193 | tempObjects[tempLength - 1] = tempSphere; 1194 | 1195 | view.objects = tempObjects; 1196 | 1197 | objectListItems.add(_name); 1198 | } 1199 | 1200 | private void addMaterial(Material material, String _name){ 1201 | int tempLength = Materials.materials.length + 1; 1202 | 1203 | Material[] tempMat = new Material[tempLength]; 1204 | 1205 | System.arraycopy(Materials.materials, 0, tempMat, 0, tempLength - 1); 1206 | 1207 | tempMat[tempLength - 1] = material; 1208 | 1209 | Materials.materials = tempMat; 1210 | 1211 | materialListItems.add(_name); 1212 | } 1213 | 1214 | public static void setImage(BufferedImage bImage){ 1215 | Image image = SwingFXUtils.toFXImage(bImage, null); 1216 | 1217 | imageView.setImage(image); 1218 | } 1219 | } --------------------------------------------------------------------------------