BVHs that apparently don't work!

main
Brett 2022-10-18 23:11:51 -04:00
parent 36b250a66b
commit 32ad30592c
46 changed files with 1089 additions and 269 deletions

View File

@ -1,6 +1,14 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
<option name="clangTidyCheckOptions">
<list>
<ClangTidyCheckOption />
</list>
</option>
<option name="clangTidyChecks" value="-*,mpi-*,bugprone-*,-bugprone-signal-handler,-bugprone-narrowing-conversions,-bugprone-unchecked-optional-access,-bugprone-signed-char-misuse,-bugprone-unhandled-exception-at-new,-bugprone-easily-swappable-parameters,-bugprone-stringview-nullptr,cert-err52-cpp,cert-err60-cpp,cert-err34-c,cert-str34-c,cert-dcl21-cpp,cert-msc50-cpp,cert-msc51-cpp,cert-dcl58-cpp,cert-flp30-c,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-slicing,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-narrowing-conversions,google-default-arguments,google-runtime-operator,google-explicit-constructor,hicpp-multiway-paths-covered,hicpp-exception-baseclass,misc-unconventional-assign-operator,misc-misplaced-const,misc-new-delete-overloads,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-uniqueptr-reset-release,modernize-*,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,-modernize-use-override,-modernize-use-using,-modernize-use-default-member-init,-modernize-macro-to-enum,openmp-use-default-none,performance-*,-performance-no-int-to-ptr,portability-simd-intrinsics,readability-*,-readability-redundant-preprocessor,-readability-named-parameter,-readability-function-size,-readability-simplify-boolean-expr,-readability-identifier-length,-readability-duplicate-include,-readability-magic-numbers,-readability-braces-around-statements,-readability-redundant-member-init,-readability-suspicious-call-argument,-readability-qualified-auto,-readability-isolate-declaration,-readability-uppercase-literal-suffix,-readability-container-data-pointer,-readability-else-after-return,-readability-redundant-access-specifiers,-readability-function-cognitive-complexity,-readability-implicit-bool-conversion,-readability-container-contains,-readability-identifier-naming" />
</inspection_tool>
<inspection_tool class="Clazy" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="Clazy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSTestFailedLine" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="JSTestFailedLine" enabled="false" level="WARNING" enabled_by_default="false" />
</profile> </profile>

View File

@ -3,11 +3,11 @@ project(Step_2)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
#if (UNIX AND (CMAKE_BUILD_TYPE MATCHES Debug)) if (UNIX AND (CMAKE_BUILD_TYPE MATCHES Debug))
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
# add_compile_options(-fsanitize=address) add_compile_options(-fsanitize=address)
# add_link_options(-fsanitize=address) add_link_options(-fsanitize=address)
#endif() endif()
#Setup project source compilation #Setup project source compilation
set(source_dir "${PROJECT_SOURCE_DIR}/src/") set(source_dir "${PROJECT_SOURCE_DIR}/src/")

View File

@ -39,7 +39,7 @@
{ {
"directoryIndex" : 0, "directoryIndex" : 0,
"id" : "Step_2::@6890427a1f51a3e7e1df", "id" : "Step_2::@6890427a1f51a3e7e1df",
"jsonFile" : "target-Step_2-Debug-c817dd65f416e821189b.json", "jsonFile" : "target-Step_2-Debug-b0871e2c8ceabdb41cb5.json",
"name" : "Step_2", "name" : "Step_2",
"projectIndex" : 0 "projectIndex" : 0
} }

View File

@ -26,7 +26,7 @@
"objects" : "objects" :
[ [
{ {
"jsonFile" : "codemodel-v2-cd07775fdd2e364d3d72.json", "jsonFile" : "codemodel-v2-ca2b9c3b4517daeec0b9.json",
"kind" : "codemodel", "kind" : "codemodel",
"version" : "version" :
{ {
@ -86,7 +86,7 @@
}, },
"codemodel-v2" : "codemodel-v2" :
{ {
"jsonFile" : "codemodel-v2-cd07775fdd2e364d3d72.json", "jsonFile" : "codemodel-v2-ca2b9c3b4517daeec0b9.json",
"kind" : "codemodel", "kind" : "codemodel",
"version" : "version" :
{ {

View File

@ -11,6 +11,8 @@
"commands" : "commands" :
[ [
"add_executable", "add_executable",
"add_link_options",
"add_compile_options",
"include_directories" "include_directories"
], ],
"files" : "files" :
@ -31,6 +33,18 @@
{ {
"command" : 1, "command" : 1,
"file" : 0, "file" : 0,
"line" : 9,
"parent" : 0
},
{
"command" : 2,
"file" : 0,
"line" : 8,
"parent" : 0
},
{
"command" : 3,
"file" : 0,
"line" : 18, "line" : 18,
"parent" : 0 "parent" : 0
} }
@ -42,7 +56,11 @@
"compileCommandFragments" : "compileCommandFragments" :
[ [
{ {
"fragment" : "-g" "fragment" : " -fsanitize=address -g -g"
},
{
"backtrace" : 3,
"fragment" : "-fsanitize=address"
}, },
{ {
"fragment" : "-std=gnu++20" "fragment" : "-std=gnu++20"
@ -51,7 +69,7 @@
"includes" : "includes" :
[ [
{ {
"backtrace" : 2, "backtrace" : 4,
"path" : "/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" "path" : "/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
} }
], ],
@ -73,7 +91,8 @@
4, 4,
5, 5,
6, 6,
7 7,
8
] ]
} }
], ],
@ -83,12 +102,17 @@
"commandFragments" : "commandFragments" :
[ [
{ {
"fragment" : "-g", "fragment" : "-fsanitize=address -g -g",
"role" : "flags" "role" : "flags"
}, },
{ {
"fragment" : "", "fragment" : "",
"role" : "flags" "role" : "flags"
},
{
"backtrace" : 2,
"fragment" : "-fsanitize=address",
"role" : "flags"
} }
], ],
"language" : "CXX" "language" : "CXX"
@ -113,7 +137,8 @@
4, 4,
5, 5,
6, 6,
7 7,
8
] ]
} }
], ],
@ -149,6 +174,12 @@
"path" : "src/raytracing.cpp", "path" : "src/raytracing.cpp",
"sourceGroupIndex" : 0 "sourceGroupIndex" : 0
}, },
{
"backtrace" : 1,
"compileGroupIndex" : 0,
"path" : "src/util/debug.cpp",
"sourceGroupIndex" : 0
},
{ {
"backtrace" : 1, "backtrace" : 1,
"compileGroupIndex" : 0, "compileGroupIndex" : 0,

Binary file not shown.

View File

@ -1,15 +1,73 @@
# ninja log v5 # ninja log v5
1 1043 1666064132960672809 CMakeFiles/Step_2.dir/src/main.cpp.o 2fb1ddffcef25127 1 1226 1666137807547706006 CMakeFiles/Step_2.dir/src/main.cpp.o 2fb1ddffcef25127
1 754 1666063960682945134 CMakeFiles/Step_2.dir/src/math/colliders.cpp.o a8a5f894b3fe853c 1 1267 1666137493803063763 CMakeFiles/Step_2.dir/src/math/colliders.cpp.o a8a5f894b3fe853c
1 943 1666053389345551413 CMakeFiles/Step_2.dir/src/util/parser.cpp.o dc1044c577ff67b5 2 1042 1666119401958989993 CMakeFiles/Step_2.dir/src/util/parser.cpp.o dc1044c577ff67b5
1 848 1666063960778948360 CMakeFiles/Step_2.dir/src/raytracing.cpp.o cfda37b51895cd7e 1 907 1666137807227691822 CMakeFiles/Step_2.dir/src/raytracing.cpp.o cfda37b51895cd7e
1043 1115 1666064133032675183 Step_2 a444ddadd61997d2 1227 1315 1666137807635709904 Step_2 a4a11c3e604093b2
1 923 1666063960854950913 CMakeFiles/Step_2.dir/src/util/models.cpp.o 637cb95d94c45aa5 1 889 1666120427784383680 CMakeFiles/Step_2.dir/src/util/debug.cpp.o bb1e92ec93606b34
0 10 1666063876984117759 CMakeFiles/Step_2.dir/src/globals.cpp.o 9579c877d4b65af0 1 985 1666137807307695367 CMakeFiles/Step_2.dir/src/util/models.cpp.o 637cb95d94c45aa5
1 869 1666064119040213917 CMakeFiles/Step_2.dir/src/world.cpp.o abef135c83fe5bb1 1 765 1666120427660380125 CMakeFiles/Step_2.dir/src/globals.cpp.o 9579c877d4b65af0
0 883 1666053389289549931 CMakeFiles/Step_2.dir/src/image/image.cpp.o 13adbb05fcabbeec 1 1075 1666137807395699266 CMakeFiles/Step_2.dir/src/world.cpp.o abef135c83fe5bb1
0 891 1666065564826630786 CMakeFiles/Step_2.dir/src/util/models.cpp.o 637cb95d94c45aa5 1 1271 1666119402186996525 CMakeFiles/Step_2.dir/src/image/image.cpp.o 13adbb05fcabbeec
0 823 1666065649113302898 CMakeFiles/Step_2.dir/src/raytracing.cpp.o cfda37b51895cd7e 1 894 1666137931540979015 CMakeFiles/Step_2.dir/src/math/colliders.cpp.o 961741316937a4a5
0 851 1666065649141303787 CMakeFiles/Step_2.dir/src/world.cpp.o abef135c83fe5bb1 1 951 1666137931596981302 CMakeFiles/Step_2.dir/src/globals.cpp.o 5bebf7bde55fd4af
0 1014 1666065649305308983 CMakeFiles/Step_2.dir/src/main.cpp.o 2fb1ddffcef25127 1 961 1666137931608981794 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1014 1084 1666065649373311137 Step_2 a444ddadd61997d2 1 1250 1666137931896993564 CMakeFiles/Step_2.dir/src/util/debug.cpp.o da2051938d8a4958
1 1302 1666137931948995690 CMakeFiles/Step_2.dir/src/image/image.cpp.o a6a5848b13043c30
2 1340 1666137931984997161 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
2 1408 1666137932052999939 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
2 1433 1666137932077000920 CMakeFiles/Step_2.dir/src/util/parser.cpp.o e9d3901d3a711cd
1 1509 1666137932153004024 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1509 1601 1666137932245007783 Step_2 ba935c9c2d26b32e
0 946 1666137973998692682 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
0 1065 1666137974118697465 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1245 1666137974294704480 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
0 1410 1666137974462711175 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1410 1495 1666137974546714524 Step_2 ba935c9c2d26b32e
1 949 1666145509856515246 CMakeFiles/Step_2.dir/src/math/colliders.cpp.o 961741316937a4a5
1 1015 1666145509920516639 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1124 1666145510028518987 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1326 1666145510228523340 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
0 1489 1666145510392526908 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1489 1592 1666145510496529172 Step_2 ba935c9c2d26b32e
1 949 1666145677992183942 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1067 1666145678112186566 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1262 1666145678304190767 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1433 1666145678476194526 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1433 1521 1666145678564196453 Step_2 ba935c9c2d26b32e
1 903 1666145713360957883 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1011 1666145713468960248 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1143 1666145713600963137 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1350 1666145713808967689 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1350 1437 1666145713896969617 Step_2 ba935c9c2d26b32e
1 886 1666145918908143778 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 991 1666145919012154044 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1117 1666145919136166272 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1353 1666145919372189538 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1353 1439 1666145919460198214 Step_2 ba935c9c2d26b32e
0 918 1666145941034295533 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
0 1000 1666145941114303198 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1168 1666145941282319295 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
0 1383 1666145941498339991 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1383 1470 1666145941586348422 Step_2 ba935c9c2d26b32e
1 904 1666146018509369816 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1084 1666146018693385822 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1169 1666146018773392781 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1322 1666146018929406350 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1322 1407 1666146019013413658 Step_2 ba935c9c2d26b32e
1 1050 1666146255207394610 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1335 1666146255487413328 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1543 1666146255699427499 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1543 1642 1666146255795433918 Step_2 ba935c9c2d26b32e
1 908 1666147600903596279 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1037 1666147601031600780 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1397 1666147601391613427 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1 1143 1666147615064093392 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1143 1234 1666147615156096617 Step_2 ba935c9c2d26b32e
1 917 1666147894448951725 CMakeFiles/Step_2.dir/src/raytracing.cpp.o f57e640d9f276756
1 1006 1666147894536953463 CMakeFiles/Step_2.dir/src/util/models.cpp.o 507adcdc012771a9
1 1137 1666147894664955988 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1 1342 1666147894872960096 CMakeFiles/Step_2.dir/src/main.cpp.o 6490b92c9a765459
1342 1428 1666147894956961753 Step_2 ba935c9c2d26b32e
1 1075 1666147964142379106 CMakeFiles/Step_2.dir/src/world.cpp.o 528709b06ba304b9
1075 1160 1666147964226380888 Step_2 ba935c9c2d26b32e

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

View File

@ -1,3 +1,3 @@
Start testing: Oct 18 00:00 EDT Start testing: Oct 18 22:52 EDT
---------------------------------------------------------- ----------------------------------------------------------
End testing: Oct 18 00:00 EDT End testing: Oct 18 22:52 EDT

View File

@ -51,56 +51,63 @@ build cmake_object_order_depends_target_Step_2: phony || CMakeFiles/Step_2.dir
build CMakeFiles/Step_2.dir/src/globals.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/globals.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/globals.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/globals.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/globals.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/globals.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src
build CMakeFiles/Step_2.dir/src/image/image.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/image/image.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/image/image.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/image/image.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/image/image.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/image/image.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/image OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/image
build CMakeFiles/Step_2.dir/src/main.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/main.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/main.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/main.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/main.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/main.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src
build CMakeFiles/Step_2.dir/src/math/colliders.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/math/colliders.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/math/colliders.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/math/colliders.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/math/colliders.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/math/colliders.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/math OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/math
build CMakeFiles/Step_2.dir/src/raytracing.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/raytracing.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/raytracing.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/raytracing.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/raytracing.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/raytracing.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src
build CMakeFiles/Step_2.dir/src/util/debug.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/debug.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/util/debug.cpp.o.d
FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util
build CMakeFiles/Step_2.dir/src/util/models.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/models.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/util/models.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/models.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/util/models.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/util/models.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util
build CMakeFiles/Step_2.dir/src/util/parser.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/parser.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/util/parser.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/parser.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/util/parser.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/util/parser.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util
build CMakeFiles/Step_2.dir/src/world.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/world.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/world.cpp.o: CXX_COMPILER__Step_2_Debug /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/world.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/world.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/world.cpp.o.d
FLAGS = -g -std=gnu++20 FLAGS = -fsanitize=address -g -g -fsanitize=address -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include" INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src
@ -113,8 +120,9 @@ build CMakeFiles/Step_2.dir/src/world.cpp.o: CXX_COMPILER__Step_2_Debug /home/br
############################################# #############################################
# Link the executable Step_2 # Link the executable Step_2
build Step_2: CXX_EXECUTABLE_LINKER__Step_2_Debug CMakeFiles/Step_2.dir/src/globals.cpp.o CMakeFiles/Step_2.dir/src/image/image.cpp.o CMakeFiles/Step_2.dir/src/main.cpp.o CMakeFiles/Step_2.dir/src/math/colliders.cpp.o CMakeFiles/Step_2.dir/src/raytracing.cpp.o CMakeFiles/Step_2.dir/src/util/models.cpp.o CMakeFiles/Step_2.dir/src/util/parser.cpp.o CMakeFiles/Step_2.dir/src/world.cpp.o build Step_2: CXX_EXECUTABLE_LINKER__Step_2_Debug CMakeFiles/Step_2.dir/src/globals.cpp.o CMakeFiles/Step_2.dir/src/image/image.cpp.o CMakeFiles/Step_2.dir/src/main.cpp.o CMakeFiles/Step_2.dir/src/math/colliders.cpp.o CMakeFiles/Step_2.dir/src/raytracing.cpp.o CMakeFiles/Step_2.dir/src/util/debug.cpp.o CMakeFiles/Step_2.dir/src/util/models.cpp.o CMakeFiles/Step_2.dir/src/util/parser.cpp.o CMakeFiles/Step_2.dir/src/world.cpp.o
FLAGS = -g FLAGS = -fsanitize=address -g -g
LINK_FLAGS = -fsanitize=address
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
POST_BUILD = : POST_BUILD = :
PRE_LINK = : PRE_LINK = :

View File

@ -0,0 +1,255 @@
# Blender 3.3.1
# www.blender.org
mtllib house.mtl
o Cube
v -0.800000 -1.000000 1.000000
v -0.800000 1.000000 1.000000
v -0.800000 -1.000000 -1.000000
v -0.800000 1.000000 -1.000000
v 0.800000 -1.000000 1.000000
v 0.800000 1.000000 1.000000
v 0.800000 -1.000000 -1.000000
v 0.800000 1.000000 -1.000000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 2/4/1 3/8/1 1/1/1
f 4/9/2 7/13/2 3/8/2
f 8/14/3 5/11/3 7/13/3
f 6/12/4 1/2/4 5/11/4
f 7/13/5 1/3/5 3/7/5
f 4/10/6 6/12/6 8/14/6
f 2/4/1 4/9/1 3/8/1
f 4/9/2 8/14/2 7/13/2
f 8/14/3 6/12/3 5/11/3
f 6/12/4 2/5/4 1/2/4
f 7/13/5 5/11/5 1/3/5
f 4/10/6 2/6/6 6/12/6
o Cube.001
v -1.000000 1.719057 0.057522
v -1.000000 1.832386 -0.037572
v -1.000000 0.433482 -1.474567
v -1.000000 0.546811 -1.569661
v 1.000000 1.719057 0.057522
v 1.000000 1.832386 -0.037572
v 1.000000 0.433482 -1.474567
v 1.000000 0.546811 -1.569661
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.6428 -0.7660
vn 1.0000 -0.0000 -0.0000
vn -0.0000 0.6428 0.7660
vn -0.0000 -0.7660 0.6428
vn -0.0000 0.7660 -0.6428
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 10/18/7 11/22/7 9/15/7
f 12/23/8 15/27/8 11/22/8
f 16/28/9 13/25/9 15/27/9
f 14/26/10 9/16/10 13/25/10
f 15/27/11 9/17/11 11/21/11
f 12/24/12 14/26/12 16/28/12
f 10/18/7 12/23/7 11/22/7
f 12/23/8 16/28/8 15/27/8
f 16/28/9 14/26/9 13/25/9
f 14/26/10 10/19/10 9/16/10
f 15/27/11 13/25/11 9/17/11
f 12/24/12 10/20/12 14/26/12
o Cube.002
v -1.000000 0.433482 1.461952
v -1.000000 0.546811 1.557046
v -1.000000 1.719057 -0.070137
v -1.000000 1.832386 0.024957
v 1.000000 0.433482 1.461952
v 1.000000 0.546811 1.557046
v 1.000000 1.719057 -0.070137
v 1.000000 1.832386 0.024957
vn -1.0000 -0.0000 -0.0000
vn -0.0000 0.6428 -0.7660
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.6428 0.7660
vn -0.0000 -0.7660 -0.6428
vn -0.0000 0.7660 0.6428
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 18/32/13 19/36/13 17/29/13
f 20/37/14 23/41/14 19/36/14
f 24/42/15 21/39/15 23/41/15
f 22/40/16 17/30/16 21/39/16
f 23/41/17 17/31/17 19/35/17
f 20/38/18 22/40/18 24/42/18
f 18/32/13 20/37/13 19/36/13
f 20/37/14 24/42/14 23/41/14
f 24/42/15 22/40/15 21/39/15
f 22/40/16 18/33/16 17/30/16
f 23/41/17 21/39/17 17/31/17
f 20/38/18 18/34/18 22/40/18
o Cube.003
v 0.787552 -0.999883 0.157434
v 0.787552 -0.426687 0.157434
v 0.787552 -0.999883 -0.157434
v 0.787552 -0.426687 -0.157434
v 0.836243 -0.999883 0.157434
v 0.836243 -0.426687 0.157434
v 0.836243 -0.999883 -0.157434
v 0.836243 -0.426687 -0.157434
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 26/46/19 27/50/19 25/43/19
f 28/51/20 31/55/20 27/50/20
f 32/56/21 29/53/21 31/55/21
f 30/54/22 25/44/22 29/53/22
f 31/55/23 25/45/23 27/49/23
f 28/52/24 30/54/24 32/56/24
f 26/46/19 28/51/19 27/50/19
f 28/51/20 32/56/20 31/55/20
f 32/56/21 30/54/21 29/53/21
f 30/54/22 26/47/22 25/44/22
f 31/55/23 29/53/23 25/45/23
f 28/52/24 26/48/24 30/54/24
o Cube.004
v 0.787552 -0.090162 0.721031
v 0.787552 0.409838 0.721031
v 0.787552 -0.090162 0.221031
v 0.787552 0.409838 0.221031
v 0.836243 -0.090162 0.721031
v 0.836243 0.409838 0.721031
v 0.836243 -0.090162 0.221031
v 0.836243 0.409838 0.221031
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 34/60/25 35/64/25 33/57/25
f 36/65/26 39/69/26 35/64/26
f 40/70/27 37/67/27 39/69/27
f 38/68/28 33/58/28 37/67/28
f 39/69/29 33/59/29 35/63/29
f 36/66/30 38/68/30 40/70/30
f 34/60/25 36/65/25 35/64/25
f 36/65/26 40/70/26 39/69/26
f 40/70/27 38/68/27 37/67/27
f 38/68/28 34/61/28 33/58/28
f 39/69/29 37/67/29 33/59/29
f 36/66/30 34/62/30 38/68/30
o Cube.005
v 0.787552 -0.090162 -0.227981
v 0.787552 0.409838 -0.227981
v 0.787552 -0.090162 -0.727981
v 0.787552 0.409838 -0.727981
v 0.836243 -0.090162 -0.227981
v 0.836243 0.409838 -0.227981
v 0.836243 -0.090162 -0.727981
v 0.836243 0.409838 -0.727981
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.625000 0.000000
vt 0.625000 1.000000
vt 0.875000 0.750000
vt 0.125000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.500000
vt 0.625000 0.500000
s 0
f 42/74/31 43/78/31 41/71/31
f 44/79/32 47/83/32 43/78/32
f 48/84/33 45/81/33 47/83/33
f 46/82/34 41/72/34 45/81/34
f 47/83/35 41/73/35 43/77/35
f 44/80/36 46/82/36 48/84/36
f 42/74/31 44/79/31 43/78/31
f 44/79/32 48/84/32 47/83/32
f 48/84/33 46/82/33 45/81/33
f 46/82/34 42/75/34 41/72/34
f 47/83/35 45/81/35 41/73/35
f 44/80/36 42/76/36 46/82/36

View File

@ -39,7 +39,7 @@
{ {
"directoryIndex" : 0, "directoryIndex" : 0,
"id" : "Step_2::@6890427a1f51a3e7e1df", "id" : "Step_2::@6890427a1f51a3e7e1df",
"jsonFile" : "target-Step_2-Release-447fa4d814ec7f408004.json", "jsonFile" : "target-Step_2-Release-ade4af94c9ab4405e102.json",
"name" : "Step_2", "name" : "Step_2",
"projectIndex" : 0 "projectIndex" : 0
} }

View File

@ -26,7 +26,7 @@
"objects" : "objects" :
[ [
{ {
"jsonFile" : "codemodel-v2-7b5e10a772884891e931.json", "jsonFile" : "codemodel-v2-35c33b176d8a13b67c67.json",
"kind" : "codemodel", "kind" : "codemodel",
"version" : "version" :
{ {
@ -86,7 +86,7 @@
}, },
"codemodel-v2" : "codemodel-v2" :
{ {
"jsonFile" : "codemodel-v2-7b5e10a772884891e931.json", "jsonFile" : "codemodel-v2-35c33b176d8a13b67c67.json",
"kind" : "codemodel", "kind" : "codemodel",
"version" : "version" :
{ {

View File

@ -73,7 +73,8 @@
4, 4,
5, 5,
6, 6,
7 7,
8
] ]
} }
], ],
@ -113,7 +114,8 @@
4, 4,
5, 5,
6, 6,
7 7,
8
] ]
} }
], ],
@ -149,6 +151,12 @@
"path" : "src/raytracing.cpp", "path" : "src/raytracing.cpp",
"sourceGroupIndex" : 0 "sourceGroupIndex" : 0
}, },
{
"backtrace" : 1,
"compileGroupIndex" : 0,
"path" : "src/util/debug.cpp",
"sourceGroupIndex" : 0
},
{ {
"backtrace" : 1, "backtrace" : 1,
"compileGroupIndex" : 0, "compileGroupIndex" : 0,

View File

@ -84,6 +84,13 @@ build CMakeFiles/Step_2.dir/src/raytracing.cpp.o: CXX_COMPILER__Step_2_Release /
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src
build CMakeFiles/Step_2.dir/src/util/debug.cpp.o: CXX_COMPILER__Step_2_Release /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/debug.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/util/debug.cpp.o.d
FLAGS = -O3 -DNDEBUG -std=gnu++20
INCLUDES = -I"/home/brett/Documents/Brock/CS 3P93/Project/Step 2/include"
OBJECT_DIR = CMakeFiles/Step_2.dir
OBJECT_FILE_DIR = CMakeFiles/Step_2.dir/src/util
build CMakeFiles/Step_2.dir/src/util/models.cpp.o: CXX_COMPILER__Step_2_Release /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/models.cpp || cmake_object_order_depends_target_Step_2 build CMakeFiles/Step_2.dir/src/util/models.cpp.o: CXX_COMPILER__Step_2_Release /home/brett/Documents/Brock/CS$ 3P93/Project/Step$ 2/src/util/models.cpp || cmake_object_order_depends_target_Step_2
DEP_FILE = CMakeFiles/Step_2.dir/src/util/models.cpp.o.d DEP_FILE = CMakeFiles/Step_2.dir/src/util/models.cpp.o.d
FLAGS = -O3 -DNDEBUG -std=gnu++20 FLAGS = -O3 -DNDEBUG -std=gnu++20
@ -113,7 +120,7 @@ build CMakeFiles/Step_2.dir/src/world.cpp.o: CXX_COMPILER__Step_2_Release /home/
############################################# #############################################
# Link the executable Step_2 # Link the executable Step_2
build Step_2: CXX_EXECUTABLE_LINKER__Step_2_Release CMakeFiles/Step_2.dir/src/globals.cpp.o CMakeFiles/Step_2.dir/src/image/image.cpp.o CMakeFiles/Step_2.dir/src/main.cpp.o CMakeFiles/Step_2.dir/src/math/colliders.cpp.o CMakeFiles/Step_2.dir/src/raytracing.cpp.o CMakeFiles/Step_2.dir/src/util/models.cpp.o CMakeFiles/Step_2.dir/src/util/parser.cpp.o CMakeFiles/Step_2.dir/src/world.cpp.o build Step_2: CXX_EXECUTABLE_LINKER__Step_2_Release CMakeFiles/Step_2.dir/src/globals.cpp.o CMakeFiles/Step_2.dir/src/image/image.cpp.o CMakeFiles/Step_2.dir/src/main.cpp.o CMakeFiles/Step_2.dir/src/math/colliders.cpp.o CMakeFiles/Step_2.dir/src/raytracing.cpp.o CMakeFiles/Step_2.dir/src/util/debug.cpp.o CMakeFiles/Step_2.dir/src/util/models.cpp.o CMakeFiles/Step_2.dir/src/util/parser.cpp.o CMakeFiles/Step_2.dir/src/world.cpp.o
FLAGS = -O3 -DNDEBUG FLAGS = -O3 -DNDEBUG
OBJECT_DIR = CMakeFiles/Step_2.dir OBJECT_DIR = CMakeFiles/Step_2.dir
POST_BUILD = : POST_BUILD = :

View File

@ -1,13 +0,0 @@
/*
* Created by Brett Terpstra 6920201 on 17/10/22.
* Copyright (c) 2022 Brett Terpstra. All Rights Reserved.
*/
#ifndef STEP_2_GLOBALS_H
#define STEP_2_GLOBALS_H
namespace Raytracing {
}
#endif //STEP_2_GLOBALS_H

View File

@ -15,17 +15,17 @@ namespace Raytracing {
private: private:
int width; int width;
int height; int height;
vec4 *pixelData; Vec4 *pixelData;
public: public:
Image(int width, int height); Image(int width, int height);
Image(const Image &image); Image(const Image &image);
Image(const Image&& image) = delete; Image(const Image&& image) = delete;
inline void setPixelColor(int x, int y, const vec4 &color) { inline void setPixelColor(int x, int y, const Vec4 &color) {
pixelData[(x * height) + y] = color; pixelData[(x * height) + y] = color;
} }
[[nodiscard]] inline vec4 getPixelColor(int x, int y) const { [[nodiscard]] inline Vec4 getPixelColor(int x, int y) const {
return pixelData[(x * height) + y]; return pixelData[(x * height) + y];
} }

View File

@ -9,44 +9,149 @@
#include <util/std.h> #include <util/std.h>
#include <types.h> #include <types.h>
#include <utility>
// A currently pure header implementation of a BVH. TODO: make source file. // A currently pure header implementation of a BVH. TODO: make source file.
// this is also for testing and might not make it into the step 2. // this is also for testing and might not make it into the step 2.
namespace Raytracing { namespace Raytracing {
class BVHNode { struct BVHNode {
private: public:
void* obj; std::vector<Object*> objs;
AABB aabb; AABB aabb;
BVHNode* left; BVHNode* left;
BVHNode* right; BVHNode* right;
public: BVHNode(std::vector<Object*> objs, AABB aabb, BVHNode* left, BVHNode* right): objs(std::move(objs)), aabb(std::move(aabb)),
BVHNode(void* obj, AABB aabb, BVHNode* left, BVHNode* right): obj(obj), aabb(std::move(aabb)), left(left), right(right) {} left(left), right(right) {}
~BVHNode() { ~BVHNode() {
delete(left); delete (left);
delete(right); delete (right);
} }
}; };
class BVHTree { class BVHTree {
private: private:
const int MAX_TREE_DEPTH = 50;
BVHNode* root = nullptr; BVHNode* root = nullptr;
public:
explicit BVHTree(const std::vector<Object*>& objectsInWorld) { void del() {
// create a volume for the entire world. // delete copied objects
AABB world; for (auto* obj : root->objs)
for (const auto& obj : objectsInWorld) delete(obj);
if (!obj->getAABB().isEmpty()) delete (root);
world.expand(obj->getAABB());
// world sized bvh node isn't associated with a specific object
// only leafs should be non-null, and we might need to change it to a vector.
root = new BVHNode(nullptr, world, nullptr, nullptr);
} }
~BVHTree(){
delete(root); // splits the objs in the vector based on the provided AABBs
static std::pair<std::vector<Object*>, std::vector<Object*>>
partition(const std::pair<AABB, AABB>& aabbs, const std::vector<Object*>& objs) {
std::vector<Object*> a1;
std::vector<Object*> a2;
for (auto* obj: objs) {
// if this object doesn't have an AABB, we cannot use a BVH on it
if (obj->getAABB().isEmpty()) {
throw std::runtime_error("Invalid AABB provided to the BVH! (Your implementation is flawed)");
}
if (obj->getAABB().intersects(aabbs.first)) {
a1.push_back(obj);
} else if (obj->getAABB().intersects(aabbs.second)) {
a2.push_back(obj);
}
//tlog << "OBJ: " << obj->getAABB() << " " << obj->getAABB().intersects(aabbs.first) << " " << obj->getAABB().intersects(aabbs.second) << " " << objs.size() << "\n";
}
//tlog << "we split into two of sizes: " << a1.size() << " " << a2.size() << " orig size: " << (a1.size() + a2.size()) << "\n";
return {a1, a2};
}
BVHNode* addObjectsRecur(const std::vector<Object*>& objects, unsigned long prevSize) {
//ilog << "size: " << objects.size() << "\n";
// prevSize was required to solve some really weird bugs
// which are a TODO:
if ((objects.size() <= 2 && !objects.empty()) || prevSize == objects.size()) {
AABB local;
for (const auto& obj: objects)
local = local.expand(obj->getAABB());
return new BVHNode(objects, local, nullptr, nullptr);
} else if (objects.empty()) // should never reach here!!
return nullptr;
// create a volume for the entire world.
// yes, we could use the recursion provided AABB,
// but that wouldn't be minimum, only half.
// this ensures that we have a minimum AABB.
AABB world;
for (const auto& obj: objects) {
//tlog << obj->getAABB();
world = world.expand(obj->getAABB());
}
//tlog << "\n";
// then split and partition the world
auto spltAABB = world.splitByLongestAxis();
//dlog << "We have " << world << " being split into: \n\t" << spltAABB.first << "\n\t" << spltAABB.second << "\n";
auto partitionedObjs = partition(spltAABB, objects);
BVHNode* left = nullptr;
BVHNode* right = nullptr;
// don't try to explore nodes which don't have anything in them.
if (!partitionedObjs.first.empty())
left = addObjectsRecur(partitionedObjs.first, objects.size());
if (!partitionedObjs.second.empty())
right = addObjectsRecur(partitionedObjs.second, objects.size());
return new BVHNode(objects, world, left, right);
}
static std::vector<Object*>
traverseFindRayIntersection(BVHNode* node, const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) {
// check for intersections on both sides of the tree
if (node->left != nullptr) {
if (node->left->aabb.intersects(ray, min, max))
return traverseFindRayIntersection(node->left, ray, min, max);
}
// since each aabb should be minimum, we shouldn't have to traverse both sides.
// we want to reduce our problem size by half each iteration anyways
// divide and conquer and so on
if (node->right != nullptr)
if (node->right->aabb.intersects(ray, min, max))
return traverseFindRayIntersection(node->left, ray, min, max);
// return the objects of the lowest BVH node we can find
// if this is implemented properly this should only contain one, maybe two objects
// which is much faster! (especially when dealing with triangles)
return node->objs;
}
public:
std::vector<Object*> noAABBObjects;
explicit BVHTree(const std::vector<Object*>& objectsInWorld) {
addObjects(objectsInWorld);
}
void addObjects(const std::vector<Object*>& objects) {
if (root != nullptr)
del();
// move all the object's aabb's into world position
std::vector<Object*> objs;
for (auto* obj: objects) {
// we don't want to store all the AABBs which don't exist
// ie spheres
if (obj->getAABB().isEmpty()) {
//tlog << "Goodbye\n";
noAABBObjects.push_back(obj);
continue;
}
Object* objCopy = obj->clone();
objCopy->setAABB(obj->getAABB().translate(obj->getPosition()));
objs.push_back(objCopy);
}
root = addObjectsRecur(objs, -1);
}
std::vector<Object*> rayIntersect(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) {
return traverseFindRayIntersection(root, ray, min, max);
}
~BVHTree() {
del();
} }
}; };
} }
#endif //STEP_2_BVH_H #endif //STEP_2_BVH_H

View File

@ -12,8 +12,8 @@ namespace Raytracing {
// 3D Axis Aligned Bounding Box // 3D Axis Aligned Bounding Box
class AABB { class AABB {
protected: protected:
vec4 min; Vec4 min;
vec4 max; Vec4 max;
bool empty = false; bool empty = false;
public: public:
AABB() { AABB() {
@ -24,7 +24,7 @@ namespace Raytracing {
min{minX, minY, minZ}, max{maxX, maxY, maxZ} { min{minX, minY, minZ}, max{maxX, maxY, maxZ} {
} }
AABB(const vec4& min, const vec4& max): min(min), max(max) {} AABB(const Vec4& min, const Vec4& max): min(min), max(max) {}
// creates an AABB extending of size centered on x, y, z // creates an AABB extending of size centered on x, y, z
AABB(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z, PRECISION_TYPE size): AABB(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z, PRECISION_TYPE size):
@ -33,7 +33,12 @@ namespace Raytracing {
// translates the AABB to position x,y,z for world collision detection // translates the AABB to position x,y,z for world collision detection
[[nodiscard]] AABB translate(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z) const { [[nodiscard]] AABB translate(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z) const {
vec4 pos = {x, y, z}; Vec4 pos = {x, y, z};
return {min + pos, max + pos};
}
[[nodiscard]] AABB translate(const Vec4& vec) const {
Vec4 pos = {vec.x(), vec.y(), vec.z()};
return {min + pos, max + pos}; return {min + pos, max + pos};
} }
@ -48,12 +53,13 @@ namespace Raytracing {
return {minX, minY, minZ, maxX, maxY, maxZ}; return {minX, minY, minZ, maxX, maxY, maxZ};
} }
[[nodiscard]] inline bool intersects(PRECISION_TYPE minX, PRECISION_TYPE minY, PRECISION_TYPE minZ, PRECISION_TYPE maxX, PRECISION_TYPE maxY, [[nodiscard]] inline bool
intersects(PRECISION_TYPE minX, PRECISION_TYPE minY, PRECISION_TYPE minZ, PRECISION_TYPE maxX, PRECISION_TYPE maxY,
PRECISION_TYPE maxZ) const { PRECISION_TYPE maxZ) const {
return min.x() < maxX && max.x() > minX && min.y() < maxY && max.y() > minY && min.z() < maxZ && max.z() > minZ; return min.x() <= maxX && max.x() >= minX && min.y() <= maxY && max.y() >= minY && min.z() <= maxZ && max.z() >= minZ;
} }
[[nodiscard]] inline bool intersects(const vec4& minV, const vec4& maxV) const { [[nodiscard]] inline bool intersects(const Vec4& minV, const Vec4& maxV) const {
return intersects(minV.x(), minV.y(), minV.z(), maxV.x(), maxV.y(), maxV.z()); return intersects(minV.x(), minV.y(), minV.z(), maxV.x(), maxV.y(), maxV.z());
} }
@ -61,8 +67,11 @@ namespace Raytracing {
return intersects(other.min, other.max); return intersects(other.min, other.max);
} }
bool intersects(const Ray& ray, PRECISION_TYPE tmin, PRECISION_TYPE tmax);
bool simpleSlabRayAABBMethod(const Ray& ray, PRECISION_TYPE tmin, PRECISION_TYPE tmax);
[[nodiscard]] inline bool isInside(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z) const { [[nodiscard]] inline bool isInside(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z) const {
return x > min.x() && x < max.x() && y > min.y() && y < max.y() && z > min.z() && z < max.z(); return x >= min.x() && x <= max.x() && y >= min.y() && y <= max.y() && z >= min.z() && z <= max.z();
} }
[[nodiscard]] inline bool intersectsWithYZ(PRECISION_TYPE y, PRECISION_TYPE z) const { [[nodiscard]] inline bool intersectsWithYZ(PRECISION_TYPE y, PRECISION_TYPE z) const {
@ -77,7 +86,7 @@ namespace Raytracing {
return x >= min.x() && x <= max.x() && y >= min.y() && y <= max.y(); return x >= min.x() && x <= max.x() && y >= min.y() && y <= max.y();
} }
[[nodiscard]] inline vec4 getCenter() const { [[nodiscard]] inline Vec4 getCenter() const {
return {min.x() + (max.x() - min.x()) * 0.5, min.y() + (max.y() - min.y()) * 0.5, min.z() + (max.z() - min.z()) * 0.5}; return {min.x() + (max.x() - min.x()) * 0.5, min.y() + (max.y() - min.y()) * 0.5, min.z() + (max.z() - min.z()) * 0.5};
} }
@ -87,13 +96,22 @@ namespace Raytracing {
// 2 - z // 2 - z
[[nodiscard]] int longestAxis() const; [[nodiscard]] int longestAxis() const;
[[nodiscard]] PRECISION_TYPE longestAxisLength() const; [[nodiscard]] PRECISION_TYPE longestAxisLength() const;
[[nodiscard]] std::vector<AABB> splitByLongestAxis() const; [[nodiscard]] std::pair<AABB, AABB> splitByLongestAxis();
[[nodiscard]] PRECISION_TYPE avgDistanceFromCenter() const; [[nodiscard]] PRECISION_TYPE avgDistanceFromCenter() const;
[[nodiscard]] inline bool isEmpty() const {return empty;} [[nodiscard]] inline bool isEmpty() const { return empty; }
[[nodiscard]] Vec4 getMin() const { return min; }
[[nodiscard]] Vec4 getMax() const { return max; }
}; };
inline std::ostream& operator<<(std::ostream& out, const AABB& v) {
return out << "AABB{min{" << v.getMin().x() << ", " << v.getMin().y() << ", " << v.getMin().z() << "}, max{" << v.getMax().x() << ", " << v.getMax().y()
<< ", " << v.getMax().z() << "}} ";
}
} }
#endif //STEP_2_COLLIDERS_H #endif //STEP_2_COLLIDERS_H

View File

@ -17,7 +17,7 @@ namespace Raytracing {
// since GPUs generally are far more optimized for floats // since GPUs generally are far more optimized for floats
typedef double PRECISION_TYPE; typedef double PRECISION_TYPE;
class vec4 { class Vec4 {
private: private:
union xType { union xType {
PRECISION_TYPE x; PRECISION_TYPE x;
@ -50,10 +50,10 @@ namespace Raytracing {
// and floating point units (especially on GPUs) tend to be aligned to 4*sizeof(float) // and floating point units (especially on GPUs) tend to be aligned to 4*sizeof(float)
valueType value; valueType value;
public: public:
vec4(): value{0, 0, 0, 0} {} Vec4(): value{0, 0, 0, 0} {}
vec4(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z): value{x, y, z, 0} {} Vec4(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z): value{x, y, z, 0} {}
vec4(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z, PRECISION_TYPE w): value{x, y, z, w} {} Vec4(PRECISION_TYPE x, PRECISION_TYPE y, PRECISION_TYPE z, PRECISION_TYPE w): value{x, y, z, w} {}
vec4(const vec4& vec): value{vec.x(), vec.y(), vec.z(), vec.w()} {} Vec4(const Vec4& vec): value{vec.x(), vec.y(), vec.z(), vec.w()} {}
// most of the modern c++ here is because clang tidy was annoying me // most of the modern c++ here is because clang tidy was annoying me
@ -74,7 +74,7 @@ namespace Raytracing {
[[nodiscard]] inline PRECISION_TYPE a() const { return value.v4.a; } [[nodiscard]] inline PRECISION_TYPE a() const { return value.v4.a; }
// negation operator // negation operator
vec4 operator-() const { return {-x(), -y(), -z(), -w()}; } Vec4 operator-() const { return {-x(), -y(), -z(), -w()}; }
[[nodiscard]] inline PRECISION_TYPE magnitude() const { [[nodiscard]] inline PRECISION_TYPE magnitude() const {
return sqrt(lengthSquared()); return sqrt(lengthSquared());
@ -85,7 +85,7 @@ namespace Raytracing {
} }
// returns the unit-vector. // returns the unit-vector.
[[nodiscard]] inline vec4 normalize() const { [[nodiscard]] inline Vec4 normalize() const {
PRECISION_TYPE mag = magnitude(); PRECISION_TYPE mag = magnitude();
return {x() / mag, y() / mag, z() / mag, w() / mag}; return {x() / mag, y() / mag, z() / mag, w() / mag};
} }
@ -96,7 +96,7 @@ namespace Raytracing {
} }
// preforms the dot product of left * right // preforms the dot product of left * right
static inline PRECISION_TYPE dot(const vec4& left, const vec4& right) { static inline PRECISION_TYPE dot(const Vec4& left, const Vec4& right) {
return left.x() * right.x() return left.x() * right.x()
+ left.y() * right.y() + left.y() * right.y()
+ left.z() * right.z(); + left.z() * right.z();
@ -105,7 +105,7 @@ namespace Raytracing {
// preforms the cross product of left X right // preforms the cross product of left X right
// since a general solution to the cross product doesn't exist in 4d // since a general solution to the cross product doesn't exist in 4d
// we are going to ignore the w. // we are going to ignore the w.
static inline vec4 cross(const vec4& left, const vec4& right) { static inline Vec4 cross(const Vec4& left, const Vec4& right) {
return {left.y() * right.z() - left.z() * right.y(), return {left.y() * right.z() - left.z() * right.y(),
left.z() * right.x() - left.x() * right.z(), left.z() * right.x() - left.x() * right.z(),
left.x() * right.y() - left.y() * right.x()}; left.x() * right.y() - left.y() * right.x()};
@ -116,63 +116,77 @@ namespace Raytracing {
// Utility Functions // Utility Functions
// useful for printing out the vector to stdout // useful for printing out the vector to stdout
inline std::ostream& operator<<(std::ostream& out, const vec4& v) { inline std::ostream& operator<<(std::ostream& out, const Vec4& v) {
return out << "vec4{" << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << "} "; return out << "Vec4{" << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << "} ";
} }
// adds the two vectors left and right // adds the two vectors left and right
inline const vec4 operator+(const vec4& left, const vec4& right) { inline Vec4 operator+(const Vec4& left, const Vec4& right) {
return vec4(left.x() + right.x(), left.y() + right.y(), left.z() + right.z(), left.w() + right.w()); return {left.x() + right.x(), left.y() + right.y(), left.z() + right.z(), left.w() + right.w()};
} }
// subtracts the right vector from the left. // subtracts the right vector from the left.
inline const vec4 operator-(const vec4& left, const vec4& right) { inline Vec4 operator-(const Vec4& left, const Vec4& right) {
return vec4(left.x() - right.x(), left.y() - right.y(), left.z() - right.z(), left.w() - right.w()); return {left.x() - right.x(), left.y() - right.y(), left.z() - right.z(), left.w() - right.w()};
} }
// multiples the left with the right // multiples the left with the right
inline const vec4 operator*(const vec4& left, const vec4& right) { inline Vec4 operator*(const Vec4& left, const Vec4& right) {
return vec4(left.x() * right.x(), left.y() * right.y(), left.z() * right.z(), left.w() * right.w()); return {left.x() * right.x(), left.y() * right.y(), left.z() * right.z(), left.w() * right.w()};
}
// divides each element individually
inline Vec4 operator/(const Vec4& left, const Vec4& right) {
return {left.x() / right.x(), left.y() / right.y(), left.z() / right.z(), left.w() / right.w()};
} }
// multiplies the const c with each element in the vector v // multiplies the const c with each element in the vector v
inline const vec4 operator*(const PRECISION_TYPE c, const vec4& v) { inline Vec4 operator*(const PRECISION_TYPE c, const Vec4& v) {
return vec4(c * v.x(), c * v.y(), c * v.z(), c * v.w()); return {c * v.x(), c * v.y(), c * v.z(), c * v.w()};
} }
// same as above but for right sided constants // same as above but for right sided constants
inline const vec4 operator*(const vec4& v, PRECISION_TYPE c) { inline Vec4 operator*(const Vec4& v, PRECISION_TYPE c) {
return c * v; return c * v;
} }
// divides the vector by the constant c // divides the vector by the constant c
inline const vec4 operator/(const vec4& v, PRECISION_TYPE c) { inline Vec4 operator/(const Vec4& v, PRECISION_TYPE c) {
return vec4(v.x() / c, v.y() / c, v.z() / c, v.w() / c); return {v.x() / c, v.y() / c, v.z() / c, v.w() / c};
} }
// divides the constant by the magnitude of the vector // divides each element in the vector by over the constant
inline const PRECISION_TYPE operator/(PRECISION_TYPE c, const vec4& v) { inline Vec4 operator/(PRECISION_TYPE c, const Vec4& v) {
return c / +v; return {c / v.x(), c / v.y(), c / v.z(), c / v.w()};
} }
class Ray { class Ray {
private: private:
// the starting point for our ray // the starting point for our ray
vec4 start; Vec4 start;
// and the direction it is currently traveling // and the direction it is currently traveling
vec4 direction; Vec4 direction;
Vec4 inverseDirection;
public: public:
Ray(const vec4& start, const vec4& direction): start(start), direction(direction) {} Ray(const Vec4& start, const Vec4& direction): start(start), direction(direction), inverseDirection(1 / direction) {}
[[nodiscard]] vec4 getStartingPoint() const { return start; } [[nodiscard]] Vec4 getStartingPoint() const { return start; }
[[nodiscard]] vec4 getDirection() const { return direction; } [[nodiscard]] Vec4 getDirection() const { return direction; }
// not always needed, but it's good to not have to calculate the inverse inside the intersection
// as that would be very every AABB, and that is expensive
[[nodiscard]] Vec4 getInverseDirection() const {return inverseDirection; }
// returns a point along the ray, extended away from start by the length. // returns a point along the ray, extended away from start by the length.
[[nodiscard]] inline vec4 along(PRECISION_TYPE length) const { return start + length * direction; } [[nodiscard]] inline Vec4 along(PRECISION_TYPE length) const { return start + length * direction; }
}; };
inline std::ostream& operator<<(std::ostream& out, const Ray& v) {
return out << "Ray{" << v.getStartingPoint() << " " << v.getDirection() << "} ";
}
} }
#endif //STEP_2_VECTORS_H #endif //STEP_2_VECTORS_H

View File

@ -28,18 +28,18 @@ namespace Raytracing {
PRECISION_TYPE viewportWidth; PRECISION_TYPE viewportWidth;
PRECISION_TYPE focalLength = 1.0; PRECISION_TYPE focalLength = 1.0;
vec4 position{0, 0, 0}; Vec4 position{0, 0, 0};
vec4 horizontalAxis; Vec4 horizontalAxis;
vec4 verticalAxis; Vec4 verticalAxis;
vec4 imageOrigin; Vec4 imageOrigin;
public: public:
Camera(PRECISION_TYPE fov, const Image& image): image(image), Camera(PRECISION_TYPE fov, const Image& image): image(image),
aspectRatio(double(image.getWidth()) / double(image.getHeight())) { aspectRatio(double(image.getWidth()) / double(image.getHeight())) {
viewportHeight = (2.0 * tan(degreeeToRadian(fov) / 2)); viewportHeight = (2.0 * tan(degreeeToRadian(fov) / 2));
viewportWidth = (aspectRatio * viewportHeight); viewportWidth = (aspectRatio * viewportHeight);
horizontalAxis = (vec4{viewportWidth, 0, 0, 0}); horizontalAxis = (Vec4{viewportWidth, 0, 0, 0});
verticalAxis = (vec4{0, viewportHeight, 0, 0}); verticalAxis = (Vec4{0, viewportHeight, 0, 0});
imageOrigin = (position - horizontalAxis / 2 - verticalAxis / 2 - vec4(0, 0, focalLength, 0)); imageOrigin = (position - horizontalAxis / 2 - verticalAxis / 2 - Vec4(0, 0, focalLength, 0));
tlog << viewportHeight << "\n"; tlog << viewportHeight << "\n";
tlog << viewportWidth << "\n"; tlog << viewportWidth << "\n";
@ -52,9 +52,9 @@ namespace Raytracing {
Ray projectRay(PRECISION_TYPE x, PRECISION_TYPE y); Ray projectRay(PRECISION_TYPE x, PRECISION_TYPE y);
// makes the camera look at the lookatpos from the position p, with respects to the up direction up. (set to 0,1,0) // makes the camera look at the lookatpos from the position p, with respects to the up direction up. (set to 0,1,0)
void lookAt(const vec4& pos, const vec4& lookAtPos, const vec4& up); void lookAt(const Vec4& pos, const Vec4& lookAtPos, const Vec4& up);
void setPosition(const vec4& pos) { this->position = pos; } void setPosition(const Vec4& pos) { this->position = pos; }
void setRotation(PRECISION_TYPE yaw, PRECISION_TYPE pitch, PRECISION_TYPE roll); void setRotation(PRECISION_TYPE yaw, PRECISION_TYPE pitch, PRECISION_TYPE roll);
@ -71,16 +71,16 @@ namespace Raytracing {
Image& image; Image& image;
World& world; World& world;
vec4 raycast(const Ray& ray, int depth); Vec4 raycast(const Ray& ray, int depth);
public: public:
inline static vec4 randomUnitVector() { inline static Vec4 randomUnitVector() {
// there are two methods to generating a random unit sphere // there are two methods to generating a random unit sphere
// one which is fast and approximate: // one which is fast and approximate:
//auto v = vec4(rnd.getDouble(), rnd.getDouble(), rnd.getDouble()); //auto v = vec4(rnd.getDouble(), rnd.getDouble(), rnd.getDouble());
//return v.normalize(); //return v.normalize();
// and the one which generates an actual unit vector // and the one which generates an actual unit vector
while (true) { while (true) {
auto v = vec4(rnd.getDouble(), rnd.getDouble(), rnd.getDouble()); auto v = Vec4(rnd.getDouble(), rnd.getDouble(), rnd.getDouble());
if (v.lengthSquared() >= 1) if (v.lengthSquared() >= 1)
continue; continue;
return v; return v;
@ -89,14 +89,16 @@ namespace Raytracing {
// likely due to not over generating unit vectors biased towards the corners // likely due to not over generating unit vectors biased towards the corners
} }
// unused but provides another method of diffuse rendering // unused but provides another method of diffuse rendering
inline static vec4 randomUnitHemisphere(const vec4& normal){ inline static Vec4 randomUnitHemisphere(const Vec4& normal){
vec4 v = randomUnitVector().normalize(); Vec4 v = randomUnitVector().normalize();
if (vec4::dot(v, normal) > 0.0) if (Vec4::dot(v, normal) > 0.0)
return v; return v;
else else
return -v; return -v;
} }
Raycaster(Camera& c, Image& i, World& world, const Parser& p): camera(c), image(i), world(world) {} Raycaster(Camera& c, Image& i, World& world, const Parser& p): camera(c), image(i), world(world) {
world.generateBVH();
}
void run(); void run();

View File

@ -9,18 +9,21 @@
#include <math/vectors.h> #include <math/vectors.h>
#include <math/colliders.h> #include <math/colliders.h>
#include <utility>
// there were some files which needed access to these types // there were some files which needed access to these types
// but including them from world.h would've resulted in circular includes, // but including them from world.h would've resulted in circular includes,
// so I moved them here. // so I moved them here.
namespace Raytracing { namespace Raytracing {
struct HitData { struct HitData {
// all the other values only matter if this is true // all the other values only matter if this is true
bool hit{false}; bool hit{false};
// the hit point on the object // the hit point on the object
vec4 hitPoint{}; Vec4 hitPoint{};
// the normal of that hit point // the normal of that hit point
vec4 normal{}; Vec4 normal{};
// the length of the vector from its origin in its direction. // the length of the vector from its origin in its direction.
PRECISION_TYPE length{0}; PRECISION_TYPE length{0};
}; };
@ -31,39 +34,93 @@ namespace Raytracing {
// the new ray to be cast if scattered // the new ray to be cast if scattered
Ray newRay; Ray newRay;
// the color of the material // the color of the material
vec4 attenuationColor; Vec4 attenuationColor;
};
// triangle type for model loading
struct Triangle {
public:
Vec4 vertex1, vertex2, vertex3;
bool hasNormals = false;
Vec4 normal1, normal2, normal3;
Vec4 uv1, uv2, uv3;
AABB aabb;
Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3): vertex1(v1), vertex2(v2), vertex3(v3) {}
Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3,
const Vec4& n1, const Vec4& n2, const Vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3),
hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {}
Triangle(const Vec4& v1, const Vec4& v2, const Vec4& v3,
const Vec4& uv1, const Vec4& uv2, const Vec4& uv3,
const Vec4& n1, const Vec4& n2, const Vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3),
uv1(uv1), uv2(uv2), uv3(uv3),
hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {}
// slow method, not really required as all normals should be equal
[[nodiscard]] Vec4 findClosestNormal(const Vec4& point) const {
// no need to sqrt as exact distance doesn't matter
auto n1Dist = (point - normal1).lengthSquared();
auto n2Dist = (point - normal2).lengthSquared();
auto n3Dist = (point - normal3).lengthSquared();
return (n1Dist < n2Dist && n1Dist < n3Dist) ? normal1 : (n2Dist < n3Dist ? normal2 : normal3);
}
};
// face type for model loading
struct face {
int v1, v2, v3;
int uv1, uv2, uv3;
int n1, n2, n3;
}; };
class Material { class Material {
private: private:
// most materials will need an albedo // most materials will need an albedo
vec4 baseColor; Vec4 baseColor;
public: public:
explicit Material(const vec4& baseColor): baseColor(baseColor) {} explicit Material(const Vec4& baseColor): baseColor(baseColor) {}
// returns true if the ray was scattered along with the scattered ray, otherwise will return false with empty ray. // returns true if the ray was scattered along with the scattered ray, otherwise will return false with empty ray.
// the returned vec4 is the attenuation color // the returned vec4 is the attenuation color
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const = 0; [[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const = 0;
[[nodiscard]] vec4 getBaseColor() const { return baseColor; } [[nodiscard]] Vec4 getBaseColor() const { return baseColor; }
virtual ~Material() = default;
}; };
class Object { class Object {
protected: protected:
vec4 position;
Material* material;
AABB aabb; AABB aabb;
Vec4 position;
Material* material;
public: public:
explicit Object(Material* material, const vec4& position): material(material), position(position) {}; Object(Material* material, const Vec4& position): material(material), position(position), aabb({}) {};
// return true if the ray intersects with this object, only between min and max // return true if the ray intersects with this object, only between min and max
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const = 0; [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const = 0;
[[nodiscard]] Material* getMaterial() const { return material; } [[nodiscard]] Material* getMaterial() const { return material; }
[[nodiscard]] vec4 getPosition() const {return position;} virtual Object* clone() = 0;
[[nodiscard]] AABB getAABB() const {return aabb;} virtual AABB& getAABB() { return aabb; }
virtual void setAABB(const AABB& ab) { this->aabb = ab; }
[[nodiscard]] Vec4 getPosition() const { return position; }
virtual ~Object() = default; virtual ~Object() = default;
}; };
// used for using an object, mostly BVH
class EmptyObject : public Object {
protected:
public:
Triangle& tri;
EmptyObject(const Vec4& position, const AABB& a, Triangle& tri): Object(nullptr, position), tri(tri) {this->aabb = a;};
// unused
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const {
wlog << "Warning! A empty object has made its way into the raycaster!\n";
return {};
}
virtual Object* clone(){return new EmptyObject(position, aabb, tri);}
};
} }
#endif //STEP_2_TYPES_H #endif //STEP_2_TYPES_H

View File

@ -0,0 +1,84 @@
/*
* Created by Brett Terpstra 6920201 on 18/10/22.
* Copyright (c) 2022 Brett Terpstra. All Rights Reserved.
*
* this is a direct one-to-one copy of the profiler class used in my Game Engine
* it functions very well especially when used in a GUI context,
* so why reinvent the wheel right?
* So to avoid any kind of self plagiarism, I fully credit the source which is here:
* https://github.com/Tri11Paragon/Trapdoor-Engine/tree/dev/C%2B%2B%20Engine
*/
#ifndef STEP_2_DEBUG_H
#define STEP_2_DEBUG_H
#include <util/std.h>
namespace Raytracing {
class profiler;
extern std::unordered_map<std::string, profiler*> profiles;
class DebugTab{
protected:
std::string name;
public:
virtual void render() {}
std::string getName() {
return name;
}
};
class profiler : public DebugTab {
private:
long _start = 0;
long _end = 0;
std::unordered_map<std::string, std::pair<long, long>> timings;
public:
explicit profiler(std::string name);
void start();
void start(const std::string& name);
static void start(const std::string& name, const std::string& tabName) {
auto p = new profiler(name);
profiles.insert(std::pair(name, p));
p->start(tabName);
}
void end();
void end(const std::string& name);
static void end(const std::string& name, const std::string& tabName){
try {
profiles.at(name)->end(tabName);
} catch (std::exception& e){}
}
void print();
static void print(const std::string& name){
try {
profiles.at(name)->print();
delete(profiles.at(name));
} catch (std::exception& e){}
}
void endAndPrint();
static void endAndPrint(const std::string& name, const std::string& tabName){
profiler::end(name, tabName);
profiler::print(name);
}
void render();
static void render(int count) {
for (auto p : profiles)
p.second->render();
}
~profiler();
static void cleanup(){
for (const auto& p : profiles)
delete(p.second);
}
};
}
#endif //STEP_2_DEBUG_H

View File

@ -9,67 +9,33 @@
#include <util/std.h> #include <util/std.h>
#include <math/vectors.h> #include <math/vectors.h>
#include <math/colliders.h> #include <math/colliders.h>
#include <math/bvh.h>
namespace Raytracing { namespace Raytracing {
struct Triangle {
public:
vec4 vertex1, vertex2, vertex3;
bool hasNormals = false;
vec4 normal1, normal2, normal3;
vec4 uv1, uv2, uv3;
AABB aabb;
Triangle(const vec4& v1, const vec4& v2, const vec4& v3): vertex1(v1), vertex2(v2), vertex3(v3) {}
Triangle(const vec4& v1, const vec4& v2, const vec4& v3,
const vec4& n1, const vec4& n2, const vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3),
hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {}
Triangle(const vec4& v1, const vec4& v2, const vec4& v3,
const vec4& uv1, const vec4& uv2, const vec4& uv3,
const vec4& n1, const vec4& n2, const vec4& n3): vertex1(v1), vertex2(v2), vertex3(v3),
uv1(uv1), uv2(uv2), uv3(uv3),
hasNormals(true), normal1(n1), normal2(n2), normal3(n3) {}
[[nodiscard]] vec4 findClosestNormal(const vec4& point) const {
// no need to sqrt as exact distance doesn't matter
auto n1Dist = (point - normal1).lengthSquared();
auto n2Dist = (point - normal2).lengthSquared();
auto n3Dist = (point - normal3).lengthSquared();
return (n1Dist < n2Dist && n1Dist < n3Dist) ? normal1 : (n2Dist < n3Dist ? normal2 : normal3);
}
};
struct face {
int v1, v2, v3;
int uv1, uv2, uv3;
int n1, n2, n3;
};
struct ModelData { struct ModelData {
public: public:
// storing all this data is memory inefficient // storing all this data is memory inefficient
// since normals and vertices are only vec3s // since normals and vertices are only vec3s
// and uvs are vec2s // and uvs are vec2s
// TODO: create lower order vector classes // TODO: create lower order vector classes
std::vector<vec4> vertices; std::vector<Vec4> vertices;
std::vector<vec4> uvs; std::vector<Vec4> uvs;
std::vector<vec4> normals; std::vector<Vec4> normals;
std::vector<face> faces; std::vector<face> faces;
AABB aabb; AABB aabb;
std::vector<Triangle> toTriangles() { std::vector<Triangle> toTriangles() {
std::vector<Triangle> triangles; std::vector<Triangle> triangles;
PRECISION_TYPE minX = INFINITY, minY = INFINITY, minZ = INFINITY, maxX = -INFINITY, maxY = -INFINITY, maxZ = -INFINITY; PRECISION_TYPE minX = infinity, minY = infinity, minZ = infinity, maxX = ninfinity, maxY = ninfinity, maxZ = ninfinity;
for (face f: faces) { for (face f: faces) {
Triangle t {vertices[f.v1], vertices[f.v2], vertices[f.v3], Triangle t {vertices[f.v1], vertices[f.v2], vertices[f.v3],
uvs[f.uv1], uvs[f.uv2], uvs[f.uv3], uvs[f.uv1], uvs[f.uv2], uvs[f.uv3],
normals[f.n1], normals[f.n2], normals[f.n3]}; normals[f.n1], normals[f.n2], normals[f.n3]};
PRECISION_TYPE tMinX = INFINITY, tMinY = INFINITY, tMinZ = INFINITY, tMaxX = -INFINITY, tMaxY = -INFINITY, tMaxZ = -INFINITY; PRECISION_TYPE tMinX = infinity, tMinY = infinity, tMinZ = infinity, tMaxX = ninfinity, tMaxY = ninfinity, tMaxZ = ninfinity;
// find the min and max of all the triangles // find the min and max of all the triangles
tMinX = std::min(t.vertex1.x(), std::min(t.vertex2.x(), std::min(t.vertex3.x(), tMinX))); tMinX = std::min(t.vertex1.x(), std::min(t.vertex2.x(), std::min(t.vertex3.x(), tMinX)));
tMinY = std::min(t.vertex1.y(), std::min(t.vertex2.y(), std::min(t.vertex3.y(), tMinY))); tMinY = std::min(t.vertex1.y(), std::min(t.vertex2.y(), std::min(t.vertex3.y(), tMinY)));
@ -98,6 +64,16 @@ namespace Raytracing {
return triangles; return triangles;
} }
// creates a BVH tree and returns the list of objects we created. make sure to delete them.
static std::vector<Object*> createBVHTree(std::vector<Triangle>& triangles, const Vec4& pos) {
std::vector<Object*> objects;
for (auto& tri : triangles){
Object* obj = new EmptyObject(pos, tri.aabb, tri);
objects.push_back(obj);
}
return objects;
}
}; };
class ModelLoader { class ModelLoader {

View File

@ -38,6 +38,7 @@
* Constants * Constants
*/ */
const double infinity = std::numeric_limits<double>::infinity(); const double infinity = std::numeric_limits<double>::infinity();
const double ninfinity = -std::numeric_limits<double>::infinity();
// PI, to a large # of digits // PI, to a large # of digits
const double PI = 3.1415926535897932385; const double PI = 3.1415926535897932385;
// very small number // very small number

View File

@ -20,47 +20,68 @@ namespace Raytracing {
private: private:
PRECISION_TYPE radius; PRECISION_TYPE radius;
public: public:
SphereObject(const vec4& position, PRECISION_TYPE radius, Material* material): radius(radius), Object(material, position) {} SphereObject(const Vec4& position, PRECISION_TYPE radius, Material* material): radius(radius), Object(material, position) {}
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const; [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
virtual Object* clone(){
return new SphereObject(position, radius, material);
}
}; };
class TriangleObject : public Object { class TriangleObject : public Object {
private: private:
Triangle theTriangle; Triangle theTriangle;
public: public:
TriangleObject(const vec4& position, Triangle theTriangle, Material* material): Object(material, position), TriangleObject(const Vec4& position, Triangle theTriangle, Material* material): Object(material, position),
theTriangle(std::move(theTriangle)) {} theTriangle(std::move(theTriangle)) {}
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const; [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
virtual Object* clone() {
return new TriangleObject(position, theTriangle, material);
}
}; };
class ModelObject : public Object { class ModelObject : public Object {
private: private:
std::vector<Triangle> triangles; std::vector<Triangle> triangles;
ModelData& data;
// basically we have to store this crap here because c++ loves to copy stuff
std::vector<Object*> createdTreeObjects;
BVHTree* tree;
public: public:
ModelObject(const vec4& position, ModelData data, Material* material): Object(material, position) { ModelObject(const Vec4& position, ModelData& data, Material* material): Object(material, position), data(data) {
// since all of this occurs before the main ray tracing algorithm it's fine to do sequentially
triangles = data.toTriangles(); triangles = data.toTriangles();
this->aabb = data.aabb; this->aabb = data.aabb;
createdTreeObjects = Raytracing::ModelData::createBVHTree(triangles, position);
tree = new BVHTree(createdTreeObjects);
} }
[[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const; [[nodiscard]] virtual HitData checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const;
virtual Object* clone() {
return new ModelObject(position, data, material);
}
virtual ~ModelObject() {
for (auto* p : createdTreeObjects)
delete(p);
delete(tree);
}
}; };
class DiffuseMaterial : public Material { class DiffuseMaterial : public Material {
private: private:
public: public:
explicit DiffuseMaterial(const vec4& scatterColor): Material(scatterColor) {} explicit DiffuseMaterial(const Vec4& scatterColor): Material(scatterColor) {}
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const; [[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
}; };
class MetalMaterial : public Material { class MetalMaterial : public Material {
protected: protected:
static inline vec4 reflect(const vec4& incomingVector, const vec4& normal) { static inline Vec4 reflect(const Vec4& incomingVector, const Vec4& normal) {
return incomingVector - 2 * vec4::dot(incomingVector, normal) * normal; return incomingVector - 2 * Vec4::dot(incomingVector, normal) * normal;
} }
public: public:
explicit MetalMaterial(const vec4& metalColor): Material(metalColor) {} explicit MetalMaterial(const Vec4& metalColor): Material(metalColor) {}
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const; [[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
}; };
@ -69,7 +90,7 @@ namespace Raytracing {
private: private:
PRECISION_TYPE fuzzyness; PRECISION_TYPE fuzzyness;
public: public:
explicit BrushedMetalMaterial(const vec4& metalColor, PRECISION_TYPE fuzzyness): MetalMaterial(metalColor), fuzzyness(fuzzyness) {} explicit BrushedMetalMaterial(const Vec4& metalColor, PRECISION_TYPE fuzzyness): MetalMaterial(metalColor), fuzzyness(fuzzyness) {}
[[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const; [[nodiscard]] virtual ScatterResults scatter(const Ray& ray, const HitData& hitData) const;
}; };
@ -82,12 +103,17 @@ namespace Raytracing {
* this way we can easily tell if a ray is near and object or not * this way we can easily tell if a ray is near and object or not
* saving on computation * saving on computation
*/ */
// TODO: the above todo has been done, now we need to test the performance advantage of the BVH
BVHTree* bvhTree = nullptr;
std::unordered_map<std::string, Material*> materials; std::unordered_map<std::string, Material*> materials;
public: public:
World() = default; World() = default;
World(const World& world) = delete; World(const World& world) = delete;
World(const World&& world) = delete; World(const World&& world) = delete;
// call this after you've added all the objects to the world. (Called by the raycaster class)
void generateBVH();
inline void add(Object* object) { objects.push_back(object); } inline void add(Object* object) { objects.push_back(object); }
inline void addMaterial(const std::string& materialName, Material* mat) { materials.insert({materialName, mat}); } inline void addMaterial(const std::string& materialName, Material* mat) { materials.insert({materialName, mat}); }

View File

@ -3,6 +3,8 @@
* Copyright (c) 2022 Brett Terpstra. All Rights Reserved. * Copyright (c) 2022 Brett Terpstra. All Rights Reserved.
*/ */
// Yes, globals are bad. // Yes, globals are bad.
namespace Raytracing { #include <util/debug.h>
namespace Raytracing {
std::unordered_map<std::string, profiler*> profiles;
} }

View File

@ -11,11 +11,11 @@
namespace Raytracing { namespace Raytracing {
Image::Image(int width, int height) : width(width), height(height) { Image::Image(int width, int height) : width(width), height(height) {
pixelData = new vec4[width * height]; pixelData = new Vec4[width * height];
} }
Image::Image(const Image& image) : width(image.width), height(image.height) { Image::Image(const Image& image) : width(image.width), height(image.height) {
pixelData = new vec4[image.width * image.height]; pixelData = new Vec4[image.width * image.height];
for (int i = 0; i < image.width; i++) { for (int i = 0; i < image.width; i++) {
for (int j = 0; j < image.height; j++) { for (int j = 0; j < image.height; j++) {
this->setPixelColor(i, j, image.pixelData[i * image.height + j]); this->setPixelColor(i, j, image.pixelData[i * image.height + j]);

View File

@ -3,6 +3,7 @@
#include "image/image.h" #include "image/image.h"
#include <raytracing.h> #include <raytracing.h>
#include <world.h> #include <world.h>
#include <chrono>
/** /**
* Brett Terpstra 6920201 * Brett Terpstra 6920201
@ -32,7 +33,7 @@ int main(int argc, char** args) {
parser.addOption("--output", "Output Directory\n" parser.addOption("--output", "Output Directory\n"
"\tSet the output directory for the rendered image. Defaults to the local directory.\n", "./"); "\tSet the output directory for the rendered image. Defaults to the local directory.\n", "./");
parser.addOption("--format", "Output Format\n" parser.addOption("--format", "Output Format\n"
"\tSets the output format to PPM, PNG, or JPEG. Currently only PPM is supported.", "PPM"); "\tSets the output format to PPM, PNG, or JPEG. ", "PNG");
// if the parser returns non-zero then it wants us to stop execution // if the parser returns non-zero then it wants us to stop execution
// likely due to a help function being called. // likely due to a help function being called.
@ -45,37 +46,56 @@ int main(int argc, char** args) {
Raytracing::Image image(445, 256); Raytracing::Image image(445, 256);
Raytracing::Camera camera(140, image); Raytracing::Camera camera(90, image);
camera.setPosition({0, 0, 1}); //camera.setPosition({0, 0, 1});
//camera.lookAt(Raytracing::vec4(0,1,0), Raytracing::vec4(0, 0, -1), Raytracing::vec4(0, 1, 0)); camera.lookAt(Raytracing::Vec4(-3,3,3), Raytracing::Vec4(0, 0, 0), Raytracing::Vec4(0, 1, 0));
Raytracing::World world; Raytracing::World world;
Raytracing::OBJLoader loader; Raytracing::OBJLoader loader;
Raytracing::ModelData testData = loader.loadModel("spider.obj"); Raytracing::ModelData spider = loader.loadModel("spider.obj");
Raytracing::ModelData house = loader.loadModel("house.obj");
world.addMaterial("greenDiffuse", new Raytracing::DiffuseMaterial{Raytracing::vec4{0, 1.0, 0, 1}}); world.addMaterial("greenDiffuse", new Raytracing::DiffuseMaterial{Raytracing::Vec4{0, 1.0, 0, 1}});
world.addMaterial("redDiffuse", new Raytracing::DiffuseMaterial{Raytracing::vec4{1.0, 0, 0, 1}}); world.addMaterial("redDiffuse", new Raytracing::DiffuseMaterial{Raytracing::Vec4{1.0, 0, 0, 1}});
world.addMaterial("blueDiffuse", new Raytracing::DiffuseMaterial{Raytracing::vec4{0, 0, 1.0, 1}}); world.addMaterial("blueDiffuse", new Raytracing::DiffuseMaterial{Raytracing::Vec4{0, 0, 1.0, 1}});
world.addMaterial("greenMetal", new Raytracing::MetalMaterial{Raytracing::vec4{0.4, 1.0, 0.4, 1}}); world.addMaterial("greenMetal", new Raytracing::MetalMaterial{Raytracing::Vec4{0.4, 1.0, 0.4, 1}});
world.addMaterial("redMetal", new Raytracing::BrushedMetalMaterial{Raytracing::vec4{1.0, 0.4, 0.4, 1}, 0.6f}); world.addMaterial("redMetal", new Raytracing::BrushedMetalMaterial{Raytracing::Vec4{1.0, 0.4, 0.4, 1}, 0.6f});
world.addMaterial("blueMetal", new Raytracing::MetalMaterial{Raytracing::vec4{0.4, 0.4, 1.0, 1}}); world.addMaterial("blueMetal", new Raytracing::MetalMaterial{Raytracing::Vec4{0.4, 0.4, 1.0, 1}});
//world.add(new Raytracing::SphereObject(Raytracing::vec4(0,0,-1,0), 0.5, world.getMaterial("redDiffuse"))); //world.add(new Raytracing::SphereObject(Raytracing::vec4(0,0,-1,0), 0.5, world.getMaterial("redDiffuse")));
//world.add(new Raytracing::SphereObject(Raytracing::vec4(-1,0,-1,0), 0.5, world.getMaterial("blueMetal"))); //world.add(new Raytracing::SphereObject(Raytracing::vec4(-1,0,-1,0), 0.5, world.getMaterial("blueMetal")));
//world.add(new Raytracing::SphereObject(Raytracing::vec4(1,0,-1,0), 0.5, world.getMaterial("redMetal"))); //world.add(new Raytracing::SphereObject(Raytracing::vec4(1,0,-1,0), 0.5, world.getMaterial("redMetal")));
//world.add(new Raytracing::SphereObject(Raytracing::vec4(0,-100.5,-1,0), 100, world.getMaterial("greenDiffuse"))); world.add(new Raytracing::SphereObject(Raytracing::Vec4(0,-100.5,-1,0), 100, world.getMaterial("greenDiffuse")));
//world.add(new Raytracing::TriangleObject(Raytracing::vec4(0,0.1,-0.5f,0), {{-0.5, -0.5, 0.0}, {0.5, -0.5, 0.0}, {0.0, 0.5, 0}}, world.getMaterial("greenDiffuse"))); //world.add(new Raytracing::TriangleObject(Raytracing::vec4(0,0.1,-0.5f,0), {{-0.5, -0.5, 0.0}, {0.5, -0.5, 0.0}, {0.0, 0.5, 0}}, world.getMaterial("greenDiffuse")));
world.add(new Raytracing::ModelObject({0, 0, -1}, testData, world.getMaterial("redDiffuse"))); world.add(new Raytracing::ModelObject({0, 0, -1}, spider, world.getMaterial("redDiffuse")));
world.add(new Raytracing::ModelObject({2, 0, 0}, house, world.getMaterial("blueDiffuse")));
world.add(new Raytracing::ModelObject({5, 0, 0}, house, world.getMaterial("blueDiffuse")));
world.add(new Raytracing::ModelObject({5, 0, -5}, house, world.getMaterial("blueDiffuse")));
world.add(new Raytracing::ModelObject({-5, 5, 5}, house, world.getMaterial("blueDiffuse")));
Raytracing::Raycaster raycaster {camera, image, world, parser}; Raytracing::Raycaster raycaster {camera, image, world, parser};
raycaster.run(); raycaster.run();
Raytracing::ImageOutput imageOutput(image); Raytracing::ImageOutput imageOutput(image);
imageOutput.write("test", "png"); auto t = std::time(nullptr);
auto now = std::localtime(&t);
std::stringstream timeString;
timeString << (1900 + now->tm_year);
timeString << "-";
timeString << (1 + now->tm_mon);
timeString << "-";
timeString << now->tm_mday;
timeString << " ";
timeString << now->tm_hour;
timeString << ":";
timeString << now->tm_min;
timeString << ":";
timeString << now->tm_sec;
imageOutput.write(parser.getOptionValue("--output") + timeString.str(), parser.getOptionValue("--format"));
return 0; return 0;
} }

View File

@ -7,7 +7,7 @@
namespace Raytracing { namespace Raytracing {
PRECISION_TYPE AABB::longestDistanceFromCenter() const { PRECISION_TYPE AABB::longestDistanceFromCenter() const {
vec4 center = getCenter(); Vec4 center = getCenter();
PRECISION_TYPE maxX = std::abs(max.x() - center.x()); PRECISION_TYPE maxX = std::abs(max.x() - center.x());
PRECISION_TYPE minX = std::abs(min.x() - center.x()); PRECISION_TYPE minX = std::abs(min.x() - center.x());
PRECISION_TYPE maxY = std::abs(max.y() - center.y()); PRECISION_TYPE maxY = std::abs(max.y() - center.y());
@ -18,7 +18,7 @@ namespace Raytracing {
} }
PRECISION_TYPE AABB::avgDistanceFromCenter() const { PRECISION_TYPE AABB::avgDistanceFromCenter() const {
vec4 center = getCenter(); Vec4 center = getCenter();
PRECISION_TYPE maxX = std::abs(max.x() - center.x()); PRECISION_TYPE maxX = std::abs(max.x() - center.x());
PRECISION_TYPE minX = std::abs(min.x() - center.x()); PRECISION_TYPE minX = std::abs(min.x() - center.x());
PRECISION_TYPE maxY = std::abs(max.y() - center.y()); PRECISION_TYPE maxY = std::abs(max.y() - center.y());
@ -48,17 +48,59 @@ namespace Raytracing {
return X > Y && X > Z ? X : Y > Z ? Y : Z; return X > Y && X > Z ? X : Y > Z ? Y : Z;
} }
std::vector<AABB> AABB::splitByLongestAxis() const { std::pair<AABB, AABB> AABB::splitByLongestAxis() {
PRECISION_TYPE X = std::abs(max.x() - min.x()); PRECISION_TYPE X = std::abs(max.x() - min.x());
PRECISION_TYPE X2 = X/2;
PRECISION_TYPE Y = std::abs(max.y() - min.y()); PRECISION_TYPE Y = std::abs(max.y() - min.y());
PRECISION_TYPE Y2 = Y/2;
PRECISION_TYPE Z = std::abs(max.z() - min.z()); PRECISION_TYPE Z = std::abs(max.z() - min.z());
PRECISION_TYPE Z2 = Z/2;
// return the new split AABBs based on the calculated max lengths, but only in their respective axis.
if (X > Y && X > Z) { if (X > Y && X > Z) {
PRECISION_TYPE x2 = X/2.0; return {{min.x(), min.y(), min.z(), max.x()-X2, max.y(), max.z()},
// start the second AABB at the end of the first AABB.
{min.x()+X2, min.y(), min.z(), max.x(), max.y(), max.z()}};
} else if (Y > Z) { } else if (Y > Z) {
return {{min.x(), min.y(), min.z(), max.x(), max.y()-Y2, max.z()}, {min.x(), min.y()+Y2, min.z(), max.x(), max.y(), max.z()}};
} else { } else {
return {{min.x(), min.y(), min.z(), max.x(), max.y(), max.z()-Z2}, {min.x(), min.y(), min.z()+Z2, max.x(), max.y(), max.z()}};
} }
} }
/*
* Sources for designing these various algorithms
* https://www.realtimerendering.com/intersections.html
* https://web.archive.org/web/20090803054252/http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c
* https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection
* https://tavianator.com/2011/ray_box.html
* https://medium.com/@bromanz/another-view-on-the-classic-ray-aabb-intersection-algorithm-for-bvh-traversal-41125138b525
*/
bool AABB::simpleSlabRayAABBMethod(const Ray& ray, PRECISION_TYPE tmin, PRECISION_TYPE tmax){
// branch less design
// adapted from 2d to fit our 3d scene.
PRECISION_TYPE tx1 = (min.x() - ray.getStartingPoint().x())*ray.getInverseDirection().x();
PRECISION_TYPE tx2 = (max.x() - ray.getStartingPoint().x())*ray.getInverseDirection().x();
tmin = std::min(tmin, std::min(tx1, tx2));
tmax = std::max(tmax, std::max(tx1, tx2));
PRECISION_TYPE ty1 = (min.y() - ray.getStartingPoint().y())*ray.getInverseDirection().y();
PRECISION_TYPE ty2 = (max.y() - ray.getStartingPoint().y())*ray.getInverseDirection().y();
tmin = std::max(tmin, std::min(ty1, ty2));
tmax = std::min(tmax, std::max(ty1, ty2));
PRECISION_TYPE tz1 = (min.z() - ray.getStartingPoint().z())*ray.getInverseDirection().z();
PRECISION_TYPE tz2 = (max.z() - ray.getStartingPoint().z())*ray.getInverseDirection().z();
tmin = std::max(tmin, std::min(tz1, tz2));
tmax = std::min(tmax, std::max(tz1, tz2));
return tmax > std::max(tmin, 0.0);
}
bool AABB::intersects(const Ray& ray, PRECISION_TYPE tmin, PRECISION_TYPE tmax) {
return simpleSlabRayAABBMethod(ray, tmin, tmax);
}
} }

View File

@ -15,11 +15,11 @@ namespace Raytracing {
return {position, imageOrigin + transformedX * horizontalAxis + transformedY * verticalAxis - position}; return {position, imageOrigin + transformedX * horizontalAxis + transformedY * verticalAxis - position};
} }
void Camera::lookAt(const vec4& pos, const vec4& lookAtPos, const vec4& up) { void Camera::lookAt(const Vec4& pos, const Vec4& lookAtPos, const Vec4& up) {
// standard camera lookAt function // standard camera lookAt function
auto w = (pos - lookAtPos).normalize(); auto w = (pos - lookAtPos).normalize();
auto u = (vec4::cross(up, w)).normalize(); auto u = (Vec4::cross(up, w)).normalize();
auto v = vec4::cross(w, u); auto v = Vec4::cross(w, u);
position = pos; position = pos;
horizontalAxis = viewportWidth * u; horizontalAxis = viewportWidth * u;
@ -34,7 +34,7 @@ namespace Raytracing {
void Raycaster::run() { void Raycaster::run() {
for (int i = 0; i < image.getWidth(); i++){ for (int i = 0; i < image.getWidth(); i++){
for (int j = 0; j < image.getHeight(); j++){ for (int j = 0; j < image.getHeight(); j++){
Raytracing::vec4 color; Raytracing::Vec4 color;
// TODO: profile for speed; // TODO: profile for speed;
for (int s = 0; s < raysPerPixel; s++){ for (int s = 0; s < raysPerPixel; s++){
// simulate anti aliasing by generating rays with very slight random directions // simulate anti aliasing by generating rays with very slight random directions
@ -47,7 +47,7 @@ namespace Raytracing {
} }
} }
vec4 Raycaster::raycast(const Ray& ray, int depth) { Vec4 Raycaster::raycast(const Ray& ray, int depth) {
if (depth > maxBounceDepth) if (depth > maxBounceDepth)
return {0,0,0}; return {0,0,0};
@ -63,8 +63,8 @@ namespace Raytracing {
return {0,0,0}; return {0,0,0};
} }
vec4 dir = ray.getDirection().normalize(); Vec4 dir = ray.getDirection().normalize();
auto t = 0.5f * (dir.y() + 1.0); auto t = 0.5f * (dir.y() + 1.0);
return (1.0 - t) * vec4(1.0, 1.0, 1.0) + t * vec4(0.5, 0.7, 1.0); return (1.0 - t) * Vec4(1.0, 1.0, 1.0) + t * Vec4(0.5, 0.7, 1.0);
} }
} }

61
Step 2/src/util/debug.cpp Normal file
View File

@ -0,0 +1,61 @@
/*
* Created by Brett Terpstra 6920201 on 18/10/22.
* Copyright (c) 2022 Brett Terpstra. All Rights Reserved.
*/
#include <util/debug.h>
#include <chrono>
namespace Raytracing {
profiler::profiler(std::string name) {
this->name = name;
// currently unused as we don't have a UI yet.
//TD::debugUI::addTab(this);
}
void profiler::start() {
start("Unnamed");
}
void profiler::start(const std::string& name) {
auto p1 = std::chrono::high_resolution_clock::now();
_start = std::chrono::duration_cast<std::chrono::nanoseconds>(p1.time_since_epoch()).count();
timings[name] = std::pair<long, long>(_start, 0);
}
void profiler::end() {
end("Unnamed");
}
void profiler::end(const std::string& name) {
auto p1 = std::chrono::high_resolution_clock::now();
_end = std::chrono::duration_cast<std::chrono::nanoseconds>(p1.time_since_epoch()).count();
timings[name] = std::pair<long, long>(timings[name].first, _end);
}
void profiler::print() {
ilog << "Profiler " << name << " recorded: ";
for (std::pair<std::string, std::pair<long, long>> e : timings){
ilog << "\t" << e.first << " took " << ((double)(e.second.second - e.second.first) / 1000000.0) << "ms to run!";
}
}
void profiler::endAndPrint() {
end();
print();
}
void profiler::render() {
// currently unused as we don't have a UI yet.
/*ImGui::Text("CPU Timings:");
ImGui::Indent();
for (std::pair<std::string, std::pair<long, long>> e : timings) {
ImGui::Text("Elapsed Time(%s): %fms", e.first.c_str(), (double) ((e.second.second - e.second.first) / 1000000.0));
}
ImGui::Unindent();
ImGui::NewLine();*/
}
profiler::~profiler() {
// currently unused as we don't have a UI yet.
//TD::debugUI::deleteTab(this);
}
}

View File

@ -12,15 +12,16 @@ namespace Raytracing {
delete (p); delete (p);
for (const auto& p: materials) for (const auto& p: materials)
delete (p.second); delete (p.second);
delete(bvhTree);
} }
HitData SphereObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const { HitData SphereObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const {
PRECISION_TYPE radiusSquared = radius * radius; PRECISION_TYPE radiusSquared = radius * radius;
// move the ray to be with respects to the sphere // move the ray to be with respects to the sphere
vec4 RayWRTSphere = ray.getStartingPoint() - position; Vec4 RayWRTSphere = ray.getStartingPoint() - position;
// now determine the discriminant for the quadratic formula for the function of line sphere intercept // now determine the discriminant for the quadratic formula for the function of line sphere intercept
PRECISION_TYPE a = ray.getDirection().lengthSquared(); PRECISION_TYPE a = ray.getDirection().lengthSquared();
PRECISION_TYPE b = Raytracing::vec4::dot(RayWRTSphere, ray.getDirection()); PRECISION_TYPE b = Raytracing::Vec4::dot(RayWRTSphere, ray.getDirection());
PRECISION_TYPE c = RayWRTSphere.lengthSquared() - radiusSquared; PRECISION_TYPE c = RayWRTSphere.lengthSquared() - radiusSquared;
// > 0: the hit has two roots, meaning we hit both sides of the sphere // > 0: the hit has two roots, meaning we hit both sides of the sphere
// = 0: the ray has one root, we hit the edge of the sphere // = 0: the ray has one root, we hit the edge of the sphere
@ -29,7 +30,7 @@ namespace Raytracing {
// < 0: ray isn't inside the sphere. Don't need to bother calculating the roots. // < 0: ray isn't inside the sphere. Don't need to bother calculating the roots.
if (discriminant < 0) if (discriminant < 0)
return {false, vec4(), vec4(), 0}; return {false, Vec4(), Vec4(), 0};
// now we have to find the root which exists inside our range [min,max] // now we have to find the root which exists inside our range [min,max]
auto root = (-b - std::sqrt(discriminant)) / a; auto root = (-b - std::sqrt(discriminant)) / a;
@ -39,7 +40,7 @@ namespace Raytracing {
root = (-b + std::sqrt(discriminant)) / a; root = (-b + std::sqrt(discriminant)) / a;
if (root < min || root > max) { if (root < min || root > max) {
// if the second isn't in the range then we also must return false. // if the second isn't in the range then we also must return false.
return {false, vec4(), vec4(), 0}; return {false, Vec4(), Vec4(), 0};
} }
} }
// the hit point is where the ray is when extended to the root // the hit point is where the ray is when extended to the root
@ -56,22 +57,58 @@ namespace Raytracing {
} }
std::pair<HitData, Object*> World::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const { std::pair<HitData, Object*> World::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const {
auto hResult = HitData{false, vec4(), vec4(), max}; if (bvhTree != nullptr){
Object* objPtr = nullptr; auto hResult = HitData{false, Vec4(), Vec4(), max};
for (auto* obj: objects) { Object* objPtr = nullptr;
// check up to the point of the last closest hit,
// will give the closest object's hit result auto intersected = bvhTree->rayIntersect(ray, min, max);
auto cResult = obj->checkIfHit(ray, min, hResult.length);
if (cResult.hit) { //dlog << "Intersections " << intersected.size() << " " << ray << "\n";
hResult = cResult;
objPtr = obj; for (auto* ptr : intersected) {
auto cResult = ptr->checkIfHit(ray, min, hResult.length);
if (cResult.hit) {
hResult = cResult;
objPtr = ptr;
}
} }
// after we check the BVH, we have to check for other missing objects
// since stuff like spheres currently don't have AABB and AABB isn't a requirement
// for the object class (to be assigned)
for (auto* obj: bvhTree->noAABBObjects) {
// check up to the point of the last closest hit,
// will give the closest object's hit result
auto cResult = obj->checkIfHit(ray, min, hResult.length);
if (cResult.hit) {
hResult = cResult;
objPtr = obj;
}
}
return {hResult, objPtr};
} else {
// rejection algo without using a binary space partitioning data structure
auto hResult = HitData{false, Vec4(), Vec4(), max};
Object* objPtr = nullptr;
for (auto* obj: objects) {
// check up to the point of the last closest hit,
// will give the closest object's hit result
auto cResult = obj->checkIfHit(ray, min, hResult.length);
if (cResult.hit) {
hResult = cResult;
objPtr = obj;
}
}
return {hResult, objPtr};
} }
return {hResult, objPtr}; }
void World::generateBVH() {
bvhTree = new BVHTree(objects);
} }
ScatterResults DiffuseMaterial::scatter(const Ray& ray, const HitData& hitData) const { ScatterResults DiffuseMaterial::scatter(const Ray& ray, const HitData& hitData) const {
vec4 newRay = hitData.normal + Raytracing::Raycaster::randomUnitVector().normalize(); Vec4 newRay = hitData.normal + Raytracing::Raycaster::randomUnitVector().normalize();
// rays that are close to zero are liable to floating point precision errors // rays that are close to zero are liable to floating point precision errors
if (newRay.x() < EPSILON && newRay.y() < EPSILON && newRay.z() < EPSILON && newRay.w() < EPSILON) if (newRay.x() < EPSILON && newRay.y() < EPSILON && newRay.z() < EPSILON && newRay.w() < EPSILON)
@ -82,63 +119,63 @@ namespace Raytracing {
ScatterResults MetalMaterial::scatter(const Ray& ray, const HitData& hitData) const { ScatterResults MetalMaterial::scatter(const Ray& ray, const HitData& hitData) const {
// create a ray reflection // create a ray reflection
vec4 newRay = reflect(ray.getDirection().normalize(), hitData.normal); Vec4 newRay = reflect(ray.getDirection().normalize(), hitData.normal);
// make sure our reflected ray is outside the sphere and doesn't point inwards // make sure our reflected ray is outside the sphere and doesn't point inwards
bool shouldReflect = vec4::dot(newRay, hitData.normal) > 0; bool shouldReflect = Vec4::dot(newRay, hitData.normal) > 0;
return {shouldReflect, Ray{hitData.hitPoint, newRay}, getBaseColor()}; return {shouldReflect, Ray{hitData.hitPoint, newRay}, getBaseColor()};
} }
ScatterResults BrushedMetalMaterial::scatter(const Ray& ray, const HitData& hitData) const { ScatterResults BrushedMetalMaterial::scatter(const Ray& ray, const HitData& hitData) const {
// create a ray reflection // create a ray reflection
vec4 newRay = reflect(ray.getDirection().normalize(), hitData.normal); Vec4 newRay = reflect(ray.getDirection().normalize(), hitData.normal);
// make sure our reflected ray is outside the sphere and doesn't point inwards // make sure our reflected ray is outside the sphere and doesn't point inwards
bool shouldReflect = vec4::dot(newRay, hitData.normal) > 0; bool shouldReflect = Vec4::dot(newRay, hitData.normal) > 0;
return {shouldReflect, Ray{hitData.hitPoint, newRay + Raycaster::randomUnitVector() * fuzzyness}, getBaseColor()}; return {shouldReflect, Ray{hitData.hitPoint, newRay + Raycaster::randomUnitVector() * fuzzyness}, getBaseColor()};
} }
static HitData checkIfTriangleGotHit(Triangle theTriangle, vec4 position, const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) { static HitData checkIfTriangleGotHit(const Triangle& theTriangle, const Vec4& position, const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) {
// MöllerTrumbore intersection algorithm // MöllerTrumbore intersection algorithm
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
vec4 edge1, edge2, h, s, q; Vec4 edge1, edge2, h, s, q;
PRECISION_TYPE a, f, u, v; PRECISION_TYPE a, f, u, v;
edge1 = (theTriangle.vertex2 + position) - (theTriangle.vertex1 + position); edge1 = (theTriangle.vertex2 + position) - (theTriangle.vertex1 + position);
edge2 = (theTriangle.vertex3 + position) - (theTriangle.vertex1 + position); edge2 = (theTriangle.vertex3 + position) - (theTriangle.vertex1 + position);
h = vec4::cross(ray.getDirection(), edge2); h = Vec4::cross(ray.getDirection(), edge2);
a = vec4::dot(edge1, h); a = Vec4::dot(edge1, h);
if (a > -EPSILON && a < EPSILON) if (a > -EPSILON && a < EPSILON)
return {false, vec4(), vec4(), 0}; //parallel to triangle return {false, Vec4(), Vec4(), 0}; //parallel to triangle
f = 1.0 / a; f = 1.0 / a;
s = ray.getStartingPoint() - (theTriangle.vertex1 + position); s = ray.getStartingPoint() - (theTriangle.vertex1 + position);
u = f * vec4::dot(s, h); u = f * Vec4::dot(s, h);
if (u < 0.0 || u > 1.0) if (u < 0.0 || u > 1.0)
return {false, vec4(), vec4(), 0}; return {false, Vec4(), Vec4(), 0};
q = vec4::cross(s, edge1); q = Vec4::cross(s, edge1);
v = f * vec4::dot(ray.getDirection(), q); v = f * Vec4::dot(ray.getDirection(), q);
if (v < 0.0 || u + v > 1.0) if (v < 0.0 || u + v > 1.0)
return {false, vec4(), vec4(), 0}; return {false, Vec4(), Vec4(), 0};
// At this stage we can compute t to find out where the intersection point is on the line. // At this stage we can compute t to find out where the intersection point is on the line.
PRECISION_TYPE t = f * vec4::dot(edge2, q); PRECISION_TYPE t = f * Vec4::dot(edge2, q);
if (t > EPSILON) { if (t > EPSILON) {
// ray intersects // ray intersects
vec4 rayIntersectionPoint = ray.along(t); Vec4 rayIntersectionPoint = ray.along(t);
vec4 normal; Vec4 normal;
// normal = theTriangle.findClosestNormal(rayIntersectionPoint - position); // normal = theTriangle.findClosestNormal(rayIntersectionPoint - position);
if (theTriangle.hasNormals) // returning the closest normal is extra computation when n1 would likely be fine. if (theTriangle.hasNormals) // returning the closest normal is extra computation when n1 would likely be fine.
normal = theTriangle.normal1; normal = theTriangle.normal1;
else { else {
// standard points to normal algorithm but using already computed edges // standard points to normal algorithm but using already computed edges
normal = vec4{edge1.y() * edge2.z(), edge1.z() * edge2.x(), edge1.x() * edge2.y()} - normal = Vec4{edge1.y() * edge2.z(), edge1.z() * edge2.x(), edge1.x() * edge2.y()} -
vec4{edge1.z() * edge2.y(), edge1.x() * edge2.z(), edge1.y() * edge2.x()}; Vec4{edge1.z() * edge2.y(), edge1.x() * edge2.z(), edge1.y() * edge2.x()};
} }
return {true, rayIntersectionPoint, normal, t}; return {true, rayIntersectionPoint, normal, t};
} }
return {false, vec4(), vec4(), 0}; return {false, Vec4(), Vec4(), 0};
} }
HitData TriangleObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const { HitData TriangleObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const {
@ -146,12 +183,25 @@ namespace Raytracing {
} }
HitData ModelObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const { HitData ModelObject::checkIfHit(const Ray& ray, PRECISION_TYPE min, PRECISION_TYPE max) const {
auto hResult = HitData{false, vec4(), vec4(), max}; /*auto hResult = HitData{false, Vec4(), Vec4(), max};
for (const Triangle& t : triangles) { for (const Triangle& t : triangles) {
auto cResult = checkIfTriangleGotHit(t, position, ray, min, hResult.length); auto cResult = checkIfTriangleGotHit(t, position, ray, min, hResult.length);
if (cResult.hit) if (cResult.hit)
hResult = cResult; hResult = cResult;
}*/
auto hResult = HitData{false, Vec4(), Vec4(), max};
auto intersected = tree->rayIntersect(ray, min, max);
for (auto t : intersected){
// apparently this kind of casting is okay
// which makes sense since the actual data behind it is a empty object
// just this is really bad and im too annoyed to figure out a better way. TODO:.
auto cResult = checkIfTriangleGotHit(((EmptyObject*)(t))->tri, position, ray, min, hResult.length);
if (cResult.hit)
hResult = cResult;
} }
return hResult; return hResult;
} }
} }