├── .clang-format ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── data ├── comic.ttf ├── french_script_regular.ttf └── input_bindings.config ├── editor ├── CMakeLists.txt ├── private │ ├── content_browser │ │ ├── asset_guid.cpp │ │ ├── asset_importing.cpp │ │ └── importers │ │ │ ├── common.cpp │ │ │ ├── common.hpp │ │ │ ├── image.hpp │ │ │ ├── mesh.hpp │ │ │ ├── obj.cpp │ │ │ ├── obj.hpp │ │ │ ├── png.cpp │ │ │ ├── png.hpp │ │ │ ├── tga.cpp │ │ │ └── tga.hpp │ ├── editor.cpp │ ├── editor.hpp │ ├── editor_preferences.cpp │ ├── editor_preferences.hpp │ ├── imgui │ │ └── imgui.cpp │ ├── level_editor │ │ ├── gizmo │ │ │ ├── gizmo.cpp │ │ │ └── gizmo_types.cpp │ │ ├── gizmo_context.cpp │ │ ├── viewport.cpp │ │ └── viewport_camera.cpp │ ├── log_viewer │ │ ├── CMakeLists.txt │ │ └── log_viewer.cpp │ ├── outliner │ │ ├── CMakeLists.txt │ │ ├── outliner.cpp │ │ ├── outliner_header.cpp │ │ └── outliner_item.cpp │ └── rendering │ │ └── imgui_rendering.cpp └── public │ ├── content_browser │ ├── asset_guid.hpp │ ├── asset_importing.hpp │ └── postprocess.hpp │ ├── imgui │ └── imgui.hpp │ ├── level_editor │ ├── gizmo │ │ ├── arrow_3d.hpp │ │ ├── dial_3d.hpp │ │ └── gizmo.hpp │ ├── gizmo_context.hpp │ ├── viewport.hpp │ └── viewport_camera.hpp │ ├── log_viewer │ ├── CMakeLists.txt │ └── log_viewer.hpp │ ├── outliner │ ├── CMakeLists.txt │ ├── outliner.hpp │ ├── outliner_header.hpp │ └── outliner_item.hpp │ └── rendering │ ├── builtin_editor_shaders.hpp │ └── imgui_rendering.hpp ├── engine ├── CMakeLists.txt ├── private │ ├── core │ │ ├── json.cpp │ │ ├── logging.cpp │ │ ├── paths.cpp │ │ ├── paths_internal.hpp │ │ ├── random.cpp │ │ ├── serialization │ │ │ └── archives │ │ │ │ └── binary.cpp │ │ ├── threads.cpp │ │ ├── utils │ │ │ └── filesystem.cpp │ │ └── windows │ │ │ ├── common.cpp │ │ │ ├── common.hpp │ │ │ ├── debugging.cpp │ │ │ └── debugging.hpp │ ├── engine │ │ ├── assets.cpp │ │ ├── ecs │ │ │ ├── component_serialization.cpp │ │ │ ├── ecs.cpp │ │ │ ├── jobs.cpp │ │ │ ├── jobs_management.cpp │ │ │ ├── jobs_management.hpp │ │ │ ├── system.cpp │ │ │ └── system_management.hpp │ │ ├── input │ │ │ ├── input.cpp │ │ │ └── input_internal.hpp │ │ ├── key.cpp │ │ ├── mesh.cpp │ │ ├── time.cpp │ │ └── time_internal.hpp │ ├── physics │ │ ├── intersection_tests.cpp │ │ ├── line.cpp │ │ ├── obb.cpp │ │ └── ray.cpp │ ├── rendering │ │ ├── fonts.cpp │ │ ├── framebuffer.cpp │ │ ├── opengl.cpp │ │ ├── renderer.cpp │ │ └── texture_format.hpp │ ├── scripts │ │ ├── camera_movement.cpp │ │ └── debug_hotkeys.cpp │ ├── shaders │ │ ├── builtin_shaders.cpp │ │ ├── shader.cpp │ │ ├── shader_exceptions.cpp │ │ └── shader_stage.cpp │ └── windowing │ │ ├── window.cpp │ │ └── window.hpp └── public │ ├── core │ ├── class_macros.hpp │ ├── color.hpp │ ├── diagnostic_macros.hpp │ ├── exception.hpp │ ├── handle.hpp │ ├── integer_sequence_generator.hpp │ ├── json.hpp │ ├── logging.hpp │ ├── memory │ │ └── stack_allocate.hpp │ ├── paths.hpp │ ├── random.hpp │ ├── serialization │ │ ├── archives │ │ │ └── binary.hpp │ │ ├── serialization.hpp │ │ └── types │ │ │ ├── array.hpp │ │ │ └── string.hpp │ ├── threads.hpp │ ├── types.hpp │ └── utils │ │ ├── enum.hpp │ │ └── filesystem.hpp │ ├── engine.cpp │ ├── engine.hpp │ ├── engine │ ├── assets.hpp │ ├── components │ │ ├── camera.hpp │ │ ├── directional_light_component.hpp │ │ ├── entity_name.hpp │ │ ├── hierarchy.hpp │ │ ├── line_component.hpp │ │ ├── ortographic_camera.hpp │ │ ├── point_light_component.hpp │ │ ├── spot_light_component.hpp │ │ ├── static_mesh_component.hpp │ │ └── transform.hpp │ ├── ecs │ │ ├── component_container.hpp │ │ ├── component_container_iterator.hpp │ │ ├── component_serialization.hpp │ │ ├── component_view.hpp │ │ ├── ecs.hpp │ │ ├── entity.hpp │ │ ├── jobs.hpp │ │ └── system.hpp │ ├── input.hpp │ ├── key.hpp │ ├── material.hpp │ ├── mesh.hpp │ ├── resource_manager.hpp │ └── time.hpp │ ├── main.cpp │ ├── module_loader.cpp │ ├── module_loader.hpp │ ├── physics │ ├── intersection_tests.hpp │ ├── intersections_common.hpp │ ├── line.hpp │ ├── obb.hpp │ └── ray.hpp │ ├── rendering │ ├── fonts.hpp │ ├── framebuffer.hpp │ ├── glad.hpp │ ├── opengl.hpp │ ├── opengl_enums_defs.hpp │ ├── opengl_enums_undefs.hpp │ └── renderer.hpp │ ├── scripts │ ├── camera_movement.hpp │ └── debug_hotkeys.hpp │ └── shaders │ ├── builtin_shaders.hpp │ ├── shader.hpp │ ├── shader_exceptions.hpp │ └── shader_stage.hpp ├── gifs ├── engine_dock_multiviewport.gif ├── engine_multiviewport.gif ├── layout.gif ├── multiviewport.gif ├── new_drag_preview.gif ├── window_better_tabs.gif └── window_docking.gif ├── shaders ├── basicfrag.1.frag ├── basicfrag.2.frag ├── basicfrag.frag ├── basicvertex.vert ├── deferred_shading.frag ├── editor │ ├── gizmo_billboard.frag │ ├── gizmo_billboard.vert │ ├── gizmo_line.frag │ ├── gizmo_line.vert │ ├── grid.frag │ ├── grid.vert │ ├── imgui.frag │ ├── imgui.vert │ └── outline_mix.frag ├── normals.frag ├── normals.geom ├── normals.vert ├── postprocessing │ ├── blur.frag │ ├── gamma_correction.frag │ └── postprocess_vertex.vert ├── quad.frag ├── quad.vert ├── shadow_map.frag ├── shadow_map.vert ├── skybox.frag ├── skybox.vert ├── tangents.frag ├── tangents.geom ├── tangents.vert ├── uniform_color.frag ├── uniform_color.vert ├── uniform_color_line.vert ├── unlit_default.frag └── unlit_default.vert └── tools ├── CMakeLists.txt └── codegen ├── component_serialization_generator.cpp ├── private ├── CMakeLists.txt ├── component_header_parser.cpp └── file.cpp └── public ├── CMakeLists.txt ├── component_header_parser.hpp └── file.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | Standard: Cpp11 3 | AccessModifierOffset: -2 4 | #AlignArraysOfStructures: Right 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: false 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: true 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: Empty 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakBeforeMultilineStrings: true 18 | AlwaysBreakTemplateDeclarations: true 19 | BinPackArguments: true 20 | BreakBeforeBinaryOperators: false 21 | BreakBeforeBraces: WebKit 22 | BreakBeforeTernaryOperators: true 23 | BreakConstructorInitializers: BeforeColon 24 | BreakInheritanceList: BeforeColon 25 | #BreakStringLiterals: true 26 | ColumnLimit: 80 27 | CommentPragmas: '^[^ ]' 28 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 29 | ConstructorInitializerIndentWidth: 2 30 | ContinuationIndentWidth: 2 31 | Cpp11BracedListStyle: true 32 | DerivePointerAlignment: false 33 | DisableFormat: false 34 | IndentPPDirectives: BeforeHash 35 | IndentWidth: 2 36 | IndentCaseLabels: false 37 | IndentWrappedFunctionNames: false 38 | KeepEmptyLinesAtTheStartOfBlocks: false 39 | MaxEmptyLinesToKeep: 1 40 | NamespaceIndentation: All 41 | PointerAlignment: Left 42 | ReflowComments: true 43 | SortIncludes: true 44 | SpaceAfterCStyleCast: false 45 | SpaceBeforeAssignmentOperators: true 46 | SpaceBeforeCtorInitializerColon: false 47 | SpaceBeforeInheritanceColon: false 48 | SpaceBeforeParens: Never 49 | SpaceBeforeRangeBasedForLoopColon: false 50 | SpaceAfterTemplateKeyword: false 51 | SpaceInEmptyParentheses: false 52 | SpacesBeforeTrailingComments: 1 53 | SpacesInAngles: false 54 | SpacesInCStyleCastParentheses: false 55 | SpacesInParentheses: false 56 | SpacesInSquareBrackets: false 57 | TabWidth: 2 58 | UseTab: Never 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # IDE files 35 | ## VSCode 36 | .vscode 37 | ## Visual Studio 38 | .vs 39 | CMakeSettings.json 40 | ## Qt Creator 41 | *.user 42 | 43 | # Don't ask me, just don't push 44 | dump 45 | engine/buildtools 46 | 47 | # Tutorial things 48 | assets_main 49 | 50 | build/ 51 | 52 | .cache/ 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 kociap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameEngine 2 | ## Progress GIFs 3 | ### IMGUI implemented in editor 4 | ![Engine Docking](gifs/engine_dock_multiviewport.gif) 5 | ![Engine Multiviewport](gifs/engine_multiviewport.gif) 6 | ### IMGUI docking preview 7 | ![IMGUI drag preview](gifs/new_drag_preview.gif) 8 | ### IMGUI layout 9 | ![IMGUI layout](gifs/layout.gif) 10 | ### IMGUI multiviewport 11 | ![IMGUI multiviewport](gifs/multiviewport.gif) 12 | ### IMGUI improved tabs 13 | ![IMGUI Improved Tabs](gifs/window_better_tabs.gif) 14 | ### IMGUI window docking 15 | ![IMGUI Window Docking](gifs/window_docking.gif) 16 | -------------------------------------------------------------------------------- /data/comic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/data/comic.ttf -------------------------------------------------------------------------------- /data/french_script_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/data/french_script_regular.ttf -------------------------------------------------------------------------------- /data/input_bindings.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(anton_engine 2 | PRIVATE 3 | "${CMAKE_CURRENT_SOURCE_DIR}/private/editor.hpp" 4 | "${CMAKE_CURRENT_SOURCE_DIR}/private/editor.cpp" 5 | "${CMAKE_CURRENT_SOURCE_DIR}/private/editor_preferences.hpp" 6 | "${CMAKE_CURRENT_SOURCE_DIR}/private/editor_preferences.cpp" 7 | "${CMAKE_CURRENT_SOURCE_DIR}/private/rendering/imgui_rendering.cpp" 8 | "${CMAKE_CURRENT_SOURCE_DIR}/private/level_editor/gizmo/gizmo_types.cpp" 9 | "${CMAKE_CURRENT_SOURCE_DIR}/private/level_editor/gizmo/gizmo.cpp" 10 | "${CMAKE_CURRENT_SOURCE_DIR}/private/level_editor/gizmo_context.cpp" 11 | "${CMAKE_CURRENT_SOURCE_DIR}/private/level_editor/viewport_camera.cpp" 12 | "${CMAKE_CURRENT_SOURCE_DIR}/private/level_editor/viewport.cpp" 13 | "${CMAKE_CURRENT_SOURCE_DIR}/private/imgui/imgui.cpp" 14 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/common.hpp" 15 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/image.hpp" 16 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/mesh.hpp" 17 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/obj.hpp" 18 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/png.hpp" 19 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/tga.hpp" 20 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/common.cpp" 21 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/obj.cpp" 22 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/png.cpp" 23 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/importers/tga.cpp" 24 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/asset_guid.cpp" 25 | "${CMAKE_CURRENT_SOURCE_DIR}/private/content_browser/asset_importing.cpp" 26 | "${CMAKE_CURRENT_SOURCE_DIR}/public/content_browser/asset_guid.hpp" 27 | "${CMAKE_CURRENT_SOURCE_DIR}/public/content_browser/asset_importing.hpp" 28 | "${CMAKE_CURRENT_SOURCE_DIR}/public/content_browser/postprocess.hpp" 29 | "${CMAKE_CURRENT_SOURCE_DIR}/public/imgui/imgui.hpp" 30 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/gizmo/arrow_3d.hpp" 31 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/gizmo/dial_3d.hpp" 32 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/gizmo/gizmo.hpp" 33 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/gizmo_context.hpp" 34 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/viewport_camera.hpp" 35 | "${CMAKE_CURRENT_SOURCE_DIR}/public/level_editor/viewport.hpp" 36 | "${CMAKE_CURRENT_SOURCE_DIR}/public/rendering/builtin_editor_shaders.hpp" 37 | "${CMAKE_CURRENT_SOURCE_DIR}/public/rendering/imgui_rendering.hpp" 38 | ) 39 | 40 | target_include_directories(anton_engine 41 | PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/private" 42 | PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/public" 43 | ) 44 | -------------------------------------------------------------------------------- /editor/private/content_browser/asset_guid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine::asset_importing { 4 | u64 generate_asset_guid() 5 | { 6 | // TODO: Save last used guid in project files. 7 | static u64 guid = 0; 8 | return ++guid; 9 | } 10 | } // namespace anton_engine::asset_importing 11 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/common.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine::importers { 4 | u8 read_uint8(u8 const* const stream, i64& pos) 5 | { 6 | pos += 1; 7 | return *(stream + pos - 1); 8 | } 9 | 10 | // Little-endian read functions 11 | 12 | u16 read_uint16_le(u8 const* const stream) 13 | { 14 | return static_cast(stream[0]) | (static_cast(stream[1]) << 8); 15 | } 16 | 17 | u32 read_uint32_le(u8 const* const stream) 18 | { 19 | return static_cast(stream[0]) | (static_cast(stream[1]) << 8) | 20 | (static_cast(stream[2]) << 16) | 21 | (static_cast(stream[3]) << 24); 22 | } 23 | 24 | u64 read_uint64_le(u8 const* const stream) 25 | { 26 | return static_cast(stream[0]) | (static_cast(stream[1]) << 8) | 27 | (static_cast(stream[2]) << 16) | 28 | (static_cast(stream[3]) << 24) | 29 | (static_cast(stream[4]) << 32) | 30 | (static_cast(stream[5]) << 40) | 31 | (static_cast(stream[6]) << 48) | 32 | (static_cast(stream[7]) << 56); 33 | } 34 | 35 | u16 read_uint16_le(u8 const* const stream, i64& pos) 36 | { 37 | pos += 2; 38 | return read_uint16_le(stream + pos - 2); 39 | } 40 | 41 | u32 read_uint32_le(u8 const* const stream, i64& pos) 42 | { 43 | pos += 4; 44 | return read_uint32_le(stream + pos - 4); 45 | } 46 | 47 | u64 read_uint64_le(u8 const* const stream, i64& pos) 48 | { 49 | pos += 8; 50 | return read_uint64_le(stream + pos - 8); 51 | } 52 | 53 | // Big endian read functions 54 | 55 | u16 read_uint16_be(u8 const* const stream) 56 | { 57 | return (static_cast(stream[0]) << 8) | static_cast(stream[1]); 58 | } 59 | 60 | u32 read_uint32_be(u8 const* const stream) 61 | { 62 | return (static_cast(stream[0]) << 24) | 63 | (static_cast(stream[1]) << 16) | 64 | (static_cast(stream[2]) << 8) | static_cast(stream[3]); 65 | } 66 | 67 | u64 read_uint64_be(u8 const* const stream) 68 | { 69 | return (static_cast(stream[0]) << 56) | 70 | (static_cast(stream[1]) << 48) | 71 | (static_cast(stream[2]) << 40) | 72 | (static_cast(stream[3]) << 32) | 73 | (static_cast(stream[4]) << 24) | 74 | (static_cast(stream[5]) << 16) | 75 | (static_cast(stream[6]) << 8) | static_cast(stream[7]); 76 | } 77 | 78 | u16 read_uint16_be(u8 const* const stream, i64& pos) 79 | { 80 | pos += 2; 81 | return read_uint16_be(stream + pos - 2); 82 | } 83 | 84 | u32 read_uint32_be(u8 const* const stream, i64& pos) 85 | { 86 | pos += 4; 87 | return read_uint32_be(stream + pos - 4); 88 | } 89 | 90 | u64 read_uint64_be(u8 const* const stream, i64& pos) 91 | { 92 | pos += 8; 93 | return read_uint64_be(stream + pos - 8); 94 | } 95 | } // namespace anton_engine::importers 96 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::importers { 6 | u8 read_uint8(u8 const* const stream, i64& pos); 7 | 8 | // Little-endian read functions 9 | 10 | u16 read_uint16_le(u8 const* const stream); 11 | u32 read_uint32_le(u8 const* const stream); 12 | u64 read_uint64_le(u8 const* const stream); 13 | 14 | u16 read_uint16_le(u8 const* const stream, i64& pos); 15 | u32 read_uint32_le(u8 const* const stream, i64& pos); 16 | u64 read_uint64_le(u8 const* const stream, i64& pos); 17 | 18 | // Big endian read functions 19 | 20 | u16 read_uint16_be(u8 const* const stream); 21 | u32 read_uint32_be(u8 const* const stream); 22 | u64 read_uint64_be(u8 const* const stream); 23 | 24 | u16 read_uint16_be(u8 const* const stream, i64& pos); 25 | u32 read_uint32_be(u8 const* const stream, i64& pos); 26 | u64 read_uint64_be(u8 const* const stream, i64& pos); 27 | } // namespace anton_engine::importers 28 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/image.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine::importers { 8 | constexpr u64 jpeg_header = 0xFFD8; 9 | 10 | class Unknown_Critical_Chunk: public Exception { 11 | public: 12 | Unknown_Critical_Chunk(): Exception("") {} 13 | }; 14 | 15 | class Invalid_Image_File: public Exception { 16 | using Exception::Exception; 17 | }; 18 | 19 | class Decompression_Failure: public Exception { 20 | using Exception::Exception; 21 | }; 22 | 23 | enum class Image_Pixel_Format { 24 | grey8, 25 | grey16, 26 | grey8_alpha8, 27 | grey16_alpha16, 28 | rgb8, 29 | rgb16, 30 | rgba8, 31 | rgba16, 32 | }; 33 | 34 | enum Image_Color_Space { 35 | gamma_encoded, 36 | srgb, 37 | linear, 38 | }; 39 | 40 | class Image { 41 | public: 42 | u32 width; 43 | u32 height; 44 | float gamma; 45 | Image_Pixel_Format pixel_format; 46 | Image_Color_Space color_space; 47 | anton::Array data; 48 | 49 | Image() {} 50 | Image(u32 width, u32 height, Image_Pixel_Format pixel_format, 51 | Image_Color_Space color_space, float gamma, anton::Array&& data) 52 | : width(width), height(height), gamma(gamma), pixel_format(pixel_format), 53 | color_space(color_space), data(ANTON_MOV(data)) 54 | { 55 | } 56 | }; 57 | } // namespace anton_engine::importers 58 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine::importers { 10 | class Face { 11 | public: 12 | anton::Array indices; 13 | }; 14 | 15 | class Mesh { 16 | public: 17 | anton::String name; 18 | anton::Array faces; 19 | anton::Array vertices; 20 | anton::Array normals; 21 | anton::Array texture_coordinates; 22 | }; 23 | } // namespace anton_engine::importers 24 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/obj.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine::importers { 9 | [[nodiscard]] bool test_obj(anton::String_View file_extension, 10 | anton::Slice obj_data); 11 | [[nodiscard]] anton::Array import_obj(anton::Array const& obj_data); 12 | } // namespace anton_engine::importers 13 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/png.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::importers { 6 | bool test_png(anton::Array const&); 7 | Image import_png(anton::Array const&); 8 | } // namespace anton_engine::importers 9 | -------------------------------------------------------------------------------- /editor/private/content_browser/importers/tga.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::importers { 6 | // TGA2 test 7 | bool test_tga(anton::Array const&); 8 | // Supports only 8, 16, 24 and 32 bit images 9 | Image import_tga(anton::Array const&); 10 | } // namespace anton_engine::importers 11 | -------------------------------------------------------------------------------- /editor/private/editor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace anton_engine { 4 | class ECS; 5 | class Shader; 6 | class Mesh; 7 | class Material; 8 | template 9 | class Resource_Manager; 10 | } // namespace anton_engine 11 | 12 | namespace anton_engine { 13 | void quit(); 14 | 15 | class Editor { 16 | public: 17 | static Resource_Manager& get_mesh_manager(); 18 | static Resource_Manager& get_shader_manager(); 19 | static Resource_Manager& get_material_manager(); 20 | static ECS& get_ecs(); 21 | }; 22 | } // namespace anton_engine 23 | -------------------------------------------------------------------------------- /editor/private/editor_preferences.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | static Editor_Preferences editor_preferences; 5 | 6 | Editor_Preferences& get_editor_preferences() 7 | { 8 | return editor_preferences; 9 | } 10 | 11 | void load_default_editor_preferences() 12 | { 13 | editor_preferences.grid_settings.axis_x_color = {179.f / 255.f, 14 | 20.f / 255.f, 5.f / 255.f}; 15 | editor_preferences.grid_settings.axis_y_color = {0.545f, 0.863f, 0.0f}; 16 | // Color const axis_green = {0.1416f, 0.26953f, 0.02417f}; 17 | // Color const axis_green = {0, 220.0f / 255.0f, 0}; 18 | editor_preferences.grid_settings.axis_z_color = {15.f / 255.f, 77.f / 255.f, 19 | 186.f / 255.f}; 20 | editor_preferences.grid_settings.grid_flags = 21 | grid_enabled | grid_axis_x | grid_axis_z; 22 | 23 | editor_preferences.gizmo_settings.axis_x_color = { 24 | 179.f / 255.f, 20.f / 255.f, 5.f / 255.f, 0.7f}; 25 | editor_preferences.gizmo_settings.axis_y_color = {0, 220.0f / 255.0f, 0, 26 | 0.7f}; 27 | editor_preferences.gizmo_settings.axis_z_color = { 28 | 15.f / 255.f, 77.f / 255.f, 186.f / 255.f, 0.7f}; 29 | editor_preferences.gizmo_settings.size = 125; 30 | } 31 | } // namespace anton_engine 32 | -------------------------------------------------------------------------------- /editor/private/editor_preferences.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | u32 constexpr static grid_axis_x = 1 << 0; 7 | u32 constexpr static grid_axis_y = 1 << 1; 8 | u32 constexpr static grid_axis_z = 1 << 2; 9 | u32 constexpr static grid_enabled = 1 << 5; 10 | 11 | class Grid_Settings { 12 | public: 13 | Color axis_x_color; 14 | Color axis_y_color; 15 | Color axis_z_color; 16 | u32 grid_flags; 17 | }; 18 | 19 | class Gizmo_Settings { 20 | public: 21 | Color axis_x_color; 22 | Color axis_y_color; 23 | Color axis_z_color; 24 | // Size in pixels 25 | u32 size; 26 | }; 27 | 28 | class Editor_Preferences { 29 | public: 30 | Grid_Settings grid_settings; 31 | Gizmo_Settings gizmo_settings; 32 | }; 33 | 34 | [[nodiscard]] Editor_Preferences& get_editor_preferences(); 35 | // TODO: set function and no by-reference return 36 | // void set_editor_preferences(Editor_Preferences); 37 | void load_default_editor_preferences(); 38 | } // namespace anton_engine 39 | -------------------------------------------------------------------------------- /editor/private/level_editor/gizmo/gizmo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine::gizmo { 4 | float compute_scale(Mat4 const world_transform, u32 const target_size, 5 | Mat4 const pers_mat, Vec2 const viewport_size) 6 | { 7 | float const pixel_size = 1 / viewport_size.y; 8 | float const projected_w_comp = (pers_mat * world_transform[3]).w; 9 | return /* scale_basis * */ target_size * pixel_size * projected_w_comp; 10 | } 11 | } // namespace anton_engine::gizmo 12 | -------------------------------------------------------------------------------- /editor/private/level_editor/gizmo_context.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | static Gizmo_Context construct_default() 5 | { 6 | Gizmo_Context gizmo_ctx; 7 | gizmo_ctx.type = Gizmo_Transform_Type::translate; 8 | gizmo_ctx.space = Gizmo_Transform_Space::world; 9 | gizmo_ctx.grab.grabbed = false; 10 | return gizmo_ctx; 11 | } 12 | 13 | static Gizmo_Context ctx = construct_default(); 14 | 15 | Gizmo_Context& get_gizmo_context() 16 | { 17 | return ctx; 18 | } 19 | } // namespace anton_engine 20 | -------------------------------------------------------------------------------- /editor/private/level_editor/viewport_camera.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace anton_engine { 12 | void Viewport_Camera::update(Viewport_Camera& camera, Transform& transform) 13 | { 14 | // Look around 15 | float horizontal_rotation = input::get_axis("mouse_x"); 16 | float vertical_rotation = input::get_axis("mouse_y"); 17 | transform.rotate(Vec3{0.0f, 1.0f, 0.0f}, 18 | math::radians(-horizontal_rotation)); 19 | camera.camera_side = 20 | Vec3(math::rotate_y(math::radians(horizontal_rotation)) * 21 | Vec4(camera.camera_side)); 22 | transform.rotate(camera.camera_side, math::radians(vertical_rotation)); 23 | 24 | // Move 25 | Vec3 camera_front = get_camera_front(transform); 26 | float camera_speed = 0.15f * 60 * get_delta_time(); 27 | float forward = input::get_axis("move_forward"); 28 | transform.translate(camera_front * camera_speed * forward); 29 | float sideways = input::get_axis("move_sideways"); 30 | transform.translate(camera.camera_side * camera_speed * sideways); 31 | float vertical = input::get_axis("move_vertical"); 32 | transform.translate(Vec3{0.0f, 1.0f, 0.0f} * camera_speed * vertical); 33 | 34 | float scroll = input::get_axis("scroll"); 35 | transform.translate(camera_front * scroll); 36 | } 37 | } // namespace anton_engine 38 | -------------------------------------------------------------------------------- /editor/private/log_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_FILES 2 | ${SOURCE_FILES} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/log_viewer.cpp" 4 | PARENT_SCOPE 5 | ) 6 | 7 | set(HEADER_FILES 8 | ${HEADER_FILES} 9 | PARENT_SCOPE 10 | ) 11 | 12 | set(PRIVATE_INCLUDE_DIRECTORIES 13 | ${PRIVATE_INCLUDE_DIRECTORIES} 14 | "${CMAKE_CURRENT_SOURCE_DIR}" 15 | PARENT_SCOPE 16 | ) 17 | -------------------------------------------------------------------------------- /editor/private/log_viewer/log_viewer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | ANTON_DISABLE_WARNINGS(); 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | ANTON_RESTORE_WARNINGS(); 13 | 14 | namespace anton_engine { 15 | Log_Message::Log_Message(anton_engine::Log_Message_Severity severity, 16 | anton::String_View str, QWidget* parent) 17 | : QWidget(parent) 18 | { 19 | setMinimumHeight(32); 20 | message = new QLabel(str.data(), this); 21 | message->show(); 22 | } 23 | 24 | Log_Message::Log_Message(Log_Message&& other) noexcept: message(other.message) 25 | { 26 | other.message = nullptr; 27 | 28 | message->setParent(this); 29 | 30 | setParent(other.parentWidget()); 31 | other.setParent(nullptr); 32 | 33 | show(); 34 | other.hide(); 35 | } 36 | 37 | Log_Message& Log_Message::operator=(Log_Message&& other) noexcept 38 | { 39 | using anton::swap; 40 | swap(message, other.message); 41 | message->setParent(this); 42 | other.message->setParent(&other); 43 | setParent(other.parentWidget()); 44 | other.setParent(nullptr); 45 | return *this; 46 | } 47 | 48 | Log_Message::~Log_Message() {} 49 | 50 | void Log_Message::resizeEvent(QResizeEvent*) 51 | { 52 | message->setGeometry(0, 0, width(), height()); 53 | } 54 | 55 | Log_Viewer::Log_Viewer(QWidget* parent): QWidget(parent) 56 | { 57 | layout = new QVBoxLayout(this); 58 | scroll_area = new QScrollArea(); 59 | scroll_area->setWidgetResizable(true); 60 | content = new QWidget(); 61 | content_layout = new QVBoxLayout(content); 62 | 63 | message_list = new List_Widget; 64 | message_list->set_spacing(2); 65 | 66 | content_layout->addWidget(message_list); 67 | // content_layout->addStretch(1); 68 | 69 | scroll_area->setWidget(content); 70 | layout->addWidget(scroll_area); 71 | } 72 | 73 | // TODO: Implement 74 | Log_Viewer::Log_Viewer(Log_Viewer&&) noexcept {} 75 | 76 | // TODO: Implement 77 | Log_Viewer& Log_Viewer::operator=(Log_Viewer&&) noexcept 78 | { 79 | return *this; 80 | } 81 | 82 | // TODO: Implement 83 | Log_Viewer::~Log_Viewer() {} 84 | 85 | void Log_Viewer::add_message(anton_engine::Log_Message_Severity severity, 86 | anton::String_View date, 87 | anton::String_View message) 88 | { 89 | anton::String str(anton::reserve, 90 | date.size_bytes() + message.size_bytes() + 91 | 12); // 2 brackets, 2 spaces, strlen("warning"), colon 92 | str.append(u8"["); 93 | str.append(date); 94 | str.append(u8"] "); 95 | switch(severity) { 96 | case anton_engine::Log_Message_Severity::info: 97 | str.append(u8"Info: "); 98 | break; 99 | case anton_engine::Log_Message_Severity::warning: 100 | str.append(u8"Warning: "); 101 | break; 102 | default: 103 | str.append(u8"Error: "); 104 | break; 105 | } 106 | str.append(message); 107 | Log_Message& log_msg = message_list->emplace_back(severity, str); 108 | std::cout << str.data() << "\n"; 109 | log_msg.show(); 110 | // scroll_area->ensureWidgetVisible(&message); 111 | // scroll_area->verticalScrollBar()->setValue(scroll_area->verticalScrollBar()->maximum()); 112 | } 113 | 114 | void Log_Viewer::remove_all_messages() 115 | { 116 | message_list->erase(message_list->begin(), message_list->end()); 117 | } 118 | } // namespace anton_engine 119 | -------------------------------------------------------------------------------- /editor/private/outliner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_FILES 2 | ${SOURCE_FILES} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner_header.cpp" 4 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner_item.cpp" 5 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner.cpp" 6 | PARENT_SCOPE 7 | ) 8 | 9 | set(HEADER_FILES 10 | ${HEADER_FILES} 11 | PARENT_SCOPE 12 | ) 13 | 14 | set(PRIVATE_INCLUDE_DIRECTORIES 15 | ${PRIVATE_INCLUDE_DIRECTORIES} 16 | "${CMAKE_CURRENT_SOURCE_DIR}" 17 | PARENT_SCOPE 18 | ) 19 | -------------------------------------------------------------------------------- /editor/private/outliner/outliner.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | ANTON_DISABLE_WARNINGS(); 11 | #include 12 | #include 13 | ANTON_RESTORE_WARNINGS(); 14 | 15 | namespace anton_engine { 16 | static Entity find_entity_with_name(anton::String_View name) 17 | { 18 | ECS& ecs = Editor::get_ecs(); 19 | auto entities_with_names = ecs.view(); 20 | for(Entity const entity: entities_with_names) { 21 | Entity_Name& entity_name = entities_with_names.get(entity); 22 | if(name == entity_name.name) { 23 | return entity; 24 | } 25 | } 26 | 27 | return null_entity; 28 | } 29 | 30 | static anton::String create_unique_entity_name(anton::String base_name) {} 31 | 32 | Outliner::Outliner() 33 | { 34 | setMinimumHeight(100); 35 | layout = new QVBoxLayout(this); 36 | scroll_area = new QScrollArea; 37 | scroll_area->setWidgetResizable(true); 38 | list_widget = new List_Widget(); 39 | list_widget->set_spacing(2); 40 | scroll_area->setWidget(list_widget); 41 | layout->addWidget(scroll_area); 42 | } 43 | 44 | Outliner::~Outliner() 45 | { 46 | delete layout; 47 | } 48 | 49 | void Outliner::add_entity(Entity const entity) 50 | { 51 | ECS& ecs = Editor::get_ecs(); 52 | anton::String_View name; 53 | Entity_Name* entity_name = ecs.try_get_component(entity); 54 | if(entity_name) { 55 | name = entity_name->name; 56 | } else { 57 | name = u8""; 58 | } 59 | 60 | Outliner_Item& item = list_widget->emplace_back(entity, name); 61 | item.show(); 62 | } 63 | 64 | void Outliner::remove_entities(anton::Array const& entities_to_remove) 65 | { 66 | for(Entity const entity: entities_to_remove) { 67 | if(auto iter = anton::find_if(list_widget->begin(), list_widget->end(), 68 | [entity](Outliner_Item const& item) { 69 | return item.get_associated_entity() == 70 | entity; 71 | }); 72 | iter != list_widget->end()) { 73 | iter->setParent(nullptr); 74 | list_widget->erase(iter, iter + 1); 75 | } 76 | } 77 | } 78 | 79 | void Outliner::select_entities(anton::Array const& selected_entities) 80 | { 81 | for(Outliner_Item& item: *list_widget) { 82 | if(anton::any_of(selected_entities.begin(), selected_entities.end(), 83 | [&item](Entity const entity) { 84 | return item.get_associated_entity() == entity; 85 | })) { 86 | item.select(); 87 | } else { 88 | item.deselect(); 89 | } 90 | } 91 | } 92 | 93 | void Outliner::select_entity(Entity const entity) 94 | { 95 | for(Outliner_Item& item: *list_widget) { 96 | if(item.get_associated_entity() == entity) { 97 | item.select(); 98 | break; 99 | } 100 | } 101 | } 102 | 103 | void Outliner::deselect_entity(Entity const entity) 104 | { 105 | for(Outliner_Item& item: *list_widget) { 106 | if(item.get_associated_entity() == entity) { 107 | item.deselect(); 108 | break; 109 | } 110 | } 111 | } 112 | 113 | void Outliner::update() 114 | { 115 | ECS& ecs = Editor::get_ecs(); 116 | for(Outliner_Item& item: *list_widget) { 117 | Entity_Name* entity_name = 118 | ecs.try_get_component(item.get_associated_entity()); 119 | if(entity_name) { 120 | item.set_name(entity_name->name); 121 | } else { 122 | item.set_name(u8""); 123 | } 124 | } 125 | } 126 | } // namespace anton_engine 127 | -------------------------------------------------------------------------------- /editor/private/outliner/outliner_header.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/editor/private/outliner/outliner_header.cpp -------------------------------------------------------------------------------- /editor/private/outliner/outliner_item.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | ANTON_DISABLE_WARNINGS(); 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | ANTON_RESTORE_WARNINGS(); 16 | 17 | namespace anton_engine { 18 | Outliner_Item::Outliner_Item(Entity e, anton::String_View str, 19 | QWidget* parent) 20 | : QWidget(parent), entity(e) 21 | { 22 | setAutoFillBackground(true); 23 | setMinimumHeight(32); 24 | label = new QLabel(QString::fromUtf8(str.data()), this); 25 | label->setIndent(15); 26 | label->setMargin(0); 27 | label->show(); 28 | } 29 | 30 | Outliner_Item::Outliner_Item(Outliner_Item&& other) noexcept 31 | : label(other.label), entity(other.entity) 32 | { 33 | other.label = nullptr; 34 | other.entity = null_entity; 35 | 36 | setAutoFillBackground(true); 37 | label->setParent(this); 38 | 39 | if(QWidget* parent_widget = other.parentWidget()) { 40 | setParent(parent_widget); 41 | other.setParent(nullptr); 42 | } 43 | 44 | if(other.is_selected()) { 45 | select(); 46 | } 47 | 48 | show(); 49 | } 50 | 51 | Outliner_Item& Outliner_Item::operator=(Outliner_Item&& other) noexcept 52 | { 53 | using anton::swap; 54 | swap(label, other.label); 55 | label->setParent(this); 56 | other.label->setParent(&other); 57 | swap(entity, other.entity); 58 | 59 | if(QWidget* parent_widget = other.parentWidget()) { 60 | setParent(parent_widget); 61 | other.setParent(nullptr); 62 | } 63 | 64 | if(other.is_selected()) { 65 | select(); 66 | } else { 67 | deselect(); 68 | } 69 | 70 | return *this; 71 | } 72 | 73 | Outliner_Item::~Outliner_Item() {} 74 | 75 | Entity Outliner_Item::get_associated_entity() const 76 | { 77 | return entity; 78 | } 79 | 80 | void Outliner_Item::set_name(anton::String_View name) 81 | { 82 | label->setText(QString::fromUtf8(name.data())); 83 | } 84 | 85 | void Outliner_Item::select() 86 | { 87 | QPalette selected_palette; 88 | auto role = backgroundRole(); 89 | selected_palette.setColor(role, QColor(252, 175, 32)); 90 | setPalette(selected_palette); 91 | // setStyleSheet("background-color: #FCAF20;"); 92 | _selected = true; 93 | } 94 | 95 | void Outliner_Item::deselect() 96 | { 97 | QPalette selected_palette; 98 | auto role = backgroundRole(); 99 | selected_palette.setColor(role, QColor(25, 25, 25)); 100 | setPalette(selected_palette); 101 | _selected = false; 102 | } 103 | 104 | bool Outliner_Item::is_selected() const 105 | { 106 | return _selected; 107 | } 108 | 109 | void Outliner_Item::mouseReleaseEvent(QMouseEvent* event) 110 | { 111 | if(event->button() == Qt::LeftButton) { 112 | if(!is_selected()) { 113 | editor_events::entity_selected(entity, true); 114 | } 115 | } 116 | } 117 | 118 | void Outliner_Item::resizeEvent(QResizeEvent*) 119 | { 120 | label->setGeometry(0, 0, width(), height()); 121 | } 122 | 123 | void Outliner_Item::paintEvent(QPaintEvent*) 124 | { 125 | QStyleOption option; 126 | option.init(this); 127 | QPainter painter(this); 128 | QBrush brush(QColor{252, 175, 32}); 129 | painter.setBrush(brush); 130 | style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this); 131 | } 132 | } // namespace anton_engine 133 | -------------------------------------------------------------------------------- /editor/public/content_browser/asset_guid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::asset_importing { 6 | u64 generate_asset_guid(); 7 | } // namespace anton_engine::asset_importing 8 | -------------------------------------------------------------------------------- /editor/public/content_browser/asset_importing.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine::asset_importing { 10 | class Imported_Meshes { 11 | public: 12 | anton::Array hierarchy; 13 | anton::Array meshes; 14 | }; 15 | 16 | void import_image(anton::String_View path); 17 | Imported_Meshes import_mesh(anton::String_View path); 18 | 19 | void save_meshes(anton::String_View filename, anton::Slice guids, 20 | anton::Slice meshes); 21 | }; // namespace anton_engine::asset_importing 22 | -------------------------------------------------------------------------------- /editor/public/content_browser/postprocess.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | inline void 11 | flip_texture_coordinates(anton::Slice const texture_coordinates) 12 | { 13 | for(Vec3& coords: texture_coordinates) { 14 | coords.y = 1.0f - coords.y; 15 | } 16 | } 17 | 18 | inline void 19 | flip_texture_coordinates(anton::Slice const texture_coordinates) 20 | { 21 | for(Vec2& coords: texture_coordinates) { 22 | coords.y = 1.0f - coords.y; 23 | } 24 | } 25 | 26 | inline void flip_texture_coordinates(anton::Slice const vertices) 27 | { 28 | for(Vertex& vertex: vertices) { 29 | vertex.uv_coordinates.y = 1.0f - vertex.uv_coordinates.y; 30 | } 31 | } 32 | 33 | } // namespace anton_engine 34 | -------------------------------------------------------------------------------- /editor/public/imgui/imgui.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include // because of Font_Face; 12 | 13 | namespace anton_engine::imgui { 14 | class Context; 15 | class Viewport; 16 | 17 | class Widget_Style { 18 | public: 19 | Color background_color; 20 | }; 21 | 22 | class Font_Style { 23 | public: 24 | rendering::Font_Face* face; 25 | // Font size in points 26 | u32 size; 27 | u32 h_dpi; 28 | u32 v_dpi; 29 | }; 30 | 31 | class Button_Style { 32 | public: 33 | Color border_color; 34 | Color background_color; 35 | Vec4 border; 36 | Vec4 padding; 37 | Font_Style font; 38 | }; 39 | 40 | class Style { 41 | public: 42 | Color background_color; 43 | Color preview_guides_color; 44 | Color preview_color; 45 | Widget_Style widgets; 46 | Button_Style button; 47 | Button_Style hot_button; 48 | Button_Style active_button; 49 | }; 50 | 51 | class Settings { 52 | public: 53 | f32 window_drop_area_width; 54 | }; 55 | 56 | Context* create_context(Font_Style default_font); 57 | void destroy_context(Context*); 58 | 59 | // Main viewport's native window is not owned by imgui. 60 | void set_main_viewport_native_window(Context& ctx, windowing::Window*); 61 | 62 | void set_default_font(Context& ctx, Font_Style); 63 | void set_default_style_default_dark(Context& ctx); 64 | void set_default_style(Context& ctx, Style); 65 | Style get_default_style(Context& ctx); 66 | 67 | void begin_frame(Context& ctx); 68 | void end_frame(Context& ctx); 69 | 70 | class Input_State { 71 | public: 72 | Vec2 cursor_position; 73 | bool left_mouse_button; 74 | bool right_mouse_button; 75 | }; 76 | 77 | void set_input_state(Context& ctx, Input_State); 78 | Input_State get_input_state(Context& ctx); 79 | 80 | class Vertex { 81 | public: 82 | Vec2 position; 83 | Vec2 uv; 84 | struct Color { 85 | u8 r; 86 | u8 g; 87 | u8 b; 88 | u8 a; 89 | } color; 90 | }; 91 | 92 | class Draw_Command { 93 | public: 94 | u32 element_count; 95 | u32 vertex_offset; 96 | u32 index_offset; 97 | // texture 0 means no texture is associated with this draw command 98 | u64 texture; 99 | }; 100 | 101 | anton::Slice get_viewports(Context& ctx); 102 | windowing::Window* get_viewport_native_window(Context& ctx, Viewport&); 103 | anton::Slice get_viewport_draw_commands(Context& ctx, 104 | Viewport&); 105 | 106 | anton::Slice get_vertex_data(Context& ctx); 107 | anton::Slice get_index_data(Context& ctx); 108 | 109 | void begin_window(Context& ctx, anton::String_View); 110 | void end_window(Context& ctx); 111 | 112 | enum class Button_State { 113 | inactive, 114 | hot, 115 | clicked, 116 | }; 117 | 118 | // Generic widget to group other widgets and manage layout. 119 | void begin_widget(Context& ctx, anton::String_View identifier, 120 | Widget_Style options); 121 | void end_widget(Context& ctx); 122 | 123 | void text(Context& ctx, anton::String_View text, Font_Style font); 124 | Button_State button(Context& ctx, anton::String_View text); 125 | Button_State button(Context& ctx, anton::String_View text, Button_Style style, 126 | Button_Style hovered_style, Button_Style active_style); 127 | void image(Context& ctx, u64 texture, Vec2 size, Vec2 uv_top_left, 128 | Vec2 uv_bottom_right); 129 | 130 | // Modifiers 131 | 132 | // Get style of current widget or window. 133 | Style get_style(Context& ctx); 134 | // Set style of current widget or window. 135 | void set_style(Context& ctx, Style); 136 | 137 | void set_window_border_area(Context& ctx, f32); 138 | 139 | // Sets the content size of the current window. 140 | // This function has any effect only when the current window is the only one in 141 | // a viewport, in which case both the window and the viewport are resized. 142 | // Otherwise this function has no effect. 143 | // 144 | void set_window_size(Context& ctx, Vec2 size); 145 | 146 | // Sets the screen position of the current window. 147 | // This function has any effect only when the current window is the only one in 148 | // a viewport, in which case both the window and the viewport are repositioned. 149 | // Otherwise this function has no effect. 150 | // 151 | void set_window_pos(Context& ctx, Vec2 screen_pos); 152 | 153 | void set_width(Context& ctx, f32 width); 154 | void set_height(Context& ctx, f32 height); 155 | Vec2 get_window_dimensions(Context& ctx); 156 | Vec2 get_cursor_position(Context& ctx); 157 | 158 | // State queries 159 | 160 | bool is_window_hot(Context& ctx); 161 | bool is_window_active(Context& ctx); 162 | } // namespace anton_engine::imgui 163 | -------------------------------------------------------------------------------- /editor/public/level_editor/gizmo/arrow_3d.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace anton_engine::gizmo { 12 | // Arrow head style 13 | enum class Arrow_3D_Style { 14 | // none 15 | cone, 16 | cube, 17 | }; 18 | 19 | struct Arrow_3D { 20 | Arrow_3D_Style draw_style; 21 | Color color; 22 | // Size in pixels 23 | u32 size; 24 | }; 25 | 26 | // Renders an arrow from Vec3::zero to Vec3::forward that is transformed by world_transform. 27 | void draw_arrow_3d(Arrow_3D, Mat4 world_transform, 28 | Mat4 view_projection_matrix, Vec2 viewport_size, 29 | Vec3 camera_pos); 30 | // Tests the arrow for intersection and returns the distance to the intersection point along the ray if the ray intersects the bounding volumes. 31 | anton::Optional intersect_arrow_3d(Ray, Arrow_3D, Mat4 world_transform, 32 | Mat4 view_projection_matrix, 33 | Vec2 viewport_size); 34 | } // namespace anton_engine::gizmo 35 | -------------------------------------------------------------------------------- /editor/public/level_editor/gizmo/dial_3d.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine::gizmo { 9 | struct Dial_3D { 10 | Color color; 11 | // size in pixels 12 | u32 size; 13 | }; 14 | 15 | void draw_dial_3d(Dial_3D, Mat4 world_transform, Mat4 view_projection, 16 | Vec3 camera_pos, Vec2 viewport_size); 17 | // Tests the arrow for intersection and returns the distance to the intersection point along the ray if the ray intersects the bounding volumes. 18 | anton::Optional intersect_dial_3d(Ray, Dial_3D, Mat4 world_transform, 19 | Mat4 view_projection_matrix, 20 | Vec2 viewport_size); 21 | } // namespace anton_engine::gizmo 22 | -------------------------------------------------------------------------------- /editor/public/level_editor/gizmo/gizmo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace anton_engine::gizmo { 11 | enum Draw_Options { 12 | draw_options_no_scale = 1 << 0, 13 | }; 14 | 15 | [[nodiscard]] float compute_scale(Mat4 world_transform, u32 target_size, 16 | Mat4 pers_mat, Vec2 viewport_size); 17 | 18 | void debug_draw_line(Vec3 f, Vec3 l, float time); 19 | void debug_commit_draw_lines(Mat4 vp_mat, Vec3 camera_pos, float delta_time); 20 | } // namespace anton_engine::gizmo 21 | -------------------------------------------------------------------------------- /editor/public/level_editor/gizmo_context.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | enum class Gizmo_Transform_Type { 9 | translate, 10 | rotate, 11 | scale, 12 | }; 13 | 14 | enum class Gizmo_Transform_Space { 15 | world, 16 | local, 17 | // view, 18 | // gimbal, 19 | }; 20 | 21 | struct Gizmo_Grab_Data { 22 | // Transform before applying gizmo transformations 23 | Transform cached_transform; 24 | Vec3 grabbed_axis; 25 | // Point in the world where mouse originally grabbed gizmo 26 | Vec3 mouse_grab_point; 27 | Vec3 plane_normal; 28 | float plane_distance; 29 | // Point on screen where mouse originally grabbed gizmo 30 | Vec2 screen_mouse_pos; 31 | bool grabbed; 32 | }; 33 | 34 | struct Gizmo_Context { 35 | Gizmo_Transform_Type type; 36 | Gizmo_Transform_Space space; 37 | Gizmo_Grab_Data grab; 38 | }; 39 | 40 | Gizmo_Context& get_gizmo_context(); 41 | } // namespace anton_engine 42 | -------------------------------------------------------------------------------- /editor/public/level_editor/viewport.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace anton_engine { 15 | class Framebuffer; 16 | namespace imgui { 17 | class Context; 18 | } 19 | 20 | class Viewport { 21 | public: 22 | explicit Viewport(i32 viewport_index, i32 width, i32 height, 23 | imgui::Context*); 24 | ~Viewport(); 25 | 26 | void process_actions(Mat4 view_mat, Mat4 inv_view_mat, Mat4 proj_mat, 27 | Mat4 inv_proj_mat, Transform camera_transform, 28 | anton::Array& selected_entities); 29 | void render(Mat4 view_mat, Mat4 inv_view_mat, Mat4 proj_mat, 30 | Mat4 inv_proj_mat, Camera camera, Transform camera_transform, 31 | anton::Slice selected_entities); 32 | void resize_framebuffers(i32 width, i32 height); 33 | Vec2 get_size() const; 34 | bool is_active() const; 35 | 36 | private: 37 | Framebuffer* framebuffer = nullptr; 38 | Framebuffer* multisampled_framebuffer = nullptr; 39 | Framebuffer* deferred_framebuffer = nullptr; 40 | Framebuffer* front_framebuffer = nullptr; 41 | Framebuffer* back_framebuffer = nullptr; 42 | imgui::Context* ctx; 43 | 44 | Entity viewport_entity = null_entity; 45 | i32 index; 46 | }; 47 | } // namespace anton_engine 48 | -------------------------------------------------------------------------------- /editor/public/level_editor/viewport_camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // TODO: Temporarily moved to public due to generated code not being able to include this header 9 | 10 | namespace anton_engine { 11 | class Transform; 12 | 13 | class COMPONENT Viewport_Camera { 14 | public: 15 | static void update(Viewport_Camera&, Transform&); 16 | 17 | i32 viewport_index = 0; 18 | Vec3 camera_side = Vec3{1.0f, 0.0f, 0.0f}; 19 | }; 20 | } // namespace anton_engine 21 | 22 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Viewport_Camera) 23 | -------------------------------------------------------------------------------- /editor/public/log_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(HEADER_FILES 2 | ${HEADER_FILES} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/log_viewer.hpp" 4 | PARENT_SCOPE 5 | ) 6 | 7 | set(UI_FILES 8 | ${UI_FILES} 9 | PARENT_SCOPE 10 | ) 11 | 12 | set(PUBLIC_INCLUDE_DIRECTORIES 13 | ${PUBLIC_INCLUDE_DIRECTORIES} 14 | "${CMAKE_CURRENT_SOURCE_DIR}" 15 | PARENT_SCOPE 16 | ) 17 | -------------------------------------------------------------------------------- /editor/public/log_viewer/log_viewer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | ANTON_DISABLE_WARNINGS(); 10 | #include 11 | ANTON_RESTORE_WARNINGS(); 12 | 13 | class QLabel; 14 | class QVBoxLayout; 15 | class QScrollArea; 16 | class QResizeEvent; 17 | 18 | namespace anton_engine { 19 | class Log_Message: public QWidget { 20 | public: 21 | Log_Message(anton_engine::Log_Message_Severity, anton::String_View, 22 | QWidget* parent = nullptr); 23 | Log_Message(Log_Message&&) noexcept; 24 | Log_Message& operator=(Log_Message&&) noexcept; 25 | ~Log_Message() override; 26 | 27 | protected: 28 | void resizeEvent(QResizeEvent*) override; 29 | 30 | private: 31 | QLabel* message = nullptr; 32 | }; 33 | 34 | class Log_Viewer: public QWidget { 35 | public: 36 | Log_Viewer(QWidget* parent = nullptr); 37 | Log_Viewer(Log_Viewer&&) noexcept; 38 | Log_Viewer& operator=(Log_Viewer&&) noexcept; 39 | ~Log_Viewer() override; 40 | 41 | void add_message(anton_engine::Log_Message_Severity, 42 | anton::String_View time, anton::String_View message); 43 | void remove_all_messages(); 44 | 45 | private: 46 | QVBoxLayout* layout = nullptr; 47 | QScrollArea* scroll_area = nullptr; 48 | QWidget* content = nullptr; 49 | QVBoxLayout* content_layout = nullptr; 50 | List_Widget* message_list = nullptr; 51 | }; 52 | } // namespace anton_engine 53 | -------------------------------------------------------------------------------- /editor/public/outliner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(HEADER_FILES 2 | ${HEADER_FILES} 3 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner_header.hpp" 4 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner_item.hpp" 5 | "${CMAKE_CURRENT_SOURCE_DIR}/outliner.hpp" 6 | PARENT_SCOPE 7 | ) 8 | 9 | set(PUBLIC_INCLUDE_DIRECTORIES 10 | ${PUBLIC_INCLUDE_DIRECTORIES} 11 | "${CMAKE_CURRENT_SOURCE_DIR}" 12 | PARENT_SCOPE 13 | ) 14 | -------------------------------------------------------------------------------- /editor/public/outliner/outliner.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | ANTON_DISABLE_WARNINGS(); 12 | #include 13 | ANTON_RESTORE_WARNINGS(); 14 | 15 | class QVBoxLayout; 16 | class QScrollArea; 17 | 18 | namespace anton_engine { 19 | class Outliner: public QWidget { 20 | public: 21 | Outliner(); 22 | ~Outliner() override; 23 | 24 | void update(); 25 | void add_entity(Entity); 26 | void remove_entities(anton::Array const& entities_to_remove); 27 | void select_entities(anton::Array const&); 28 | void select_entity(Entity); 29 | void deselect_entity(Entity); 30 | 31 | i32 indentation() const; 32 | void set_indentation(i32); 33 | 34 | void sort_entities_by_name_ascending(); 35 | void sort_entities_by_name_descending(); 36 | 37 | private: 38 | Entity last_selected = null_entity; 39 | 40 | List_Widget* list_widget = nullptr; 41 | QVBoxLayout* layout = nullptr; 42 | QScrollArea* scroll_area; 43 | }; 44 | } // namespace anton_engine 45 | -------------------------------------------------------------------------------- /editor/public/outliner/outliner_header.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | ANTON_DISABLE_WARNINGS(); 5 | #include 6 | #include 7 | ANTON_RESTORE_WARNINGS(); 8 | 9 | namespace anton_engine { 10 | class Outliner_Header: public QWidget {}; 11 | } // namespace anton_engine 12 | -------------------------------------------------------------------------------- /editor/public/outliner/outliner_item.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | ANTON_DISABLE_WARNINGS(); 9 | #include 10 | ANTON_RESTORE_WARNINGS(); 11 | 12 | class QLabel; 13 | class QPaintEvent; 14 | class QMouseEvent; 15 | class QResizeEvent; 16 | 17 | namespace anton_engine { 18 | class Outliner_Item: public QWidget { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit Outliner_Item(Entity, anton::String_View, 23 | QWidget* parent = nullptr); 24 | Outliner_Item(Outliner_Item&&) noexcept; 25 | Outliner_Item& operator=(Outliner_Item&&) noexcept; 26 | ~Outliner_Item() override; 27 | 28 | Entity get_associated_entity() const; 29 | void set_name(anton::String_View); 30 | 31 | void select(); 32 | void deselect(); 33 | bool is_selected() const; 34 | 35 | Q_SIGNALS: 36 | void selected(Entity associated_entity, bool clear_previous_selection); 37 | void deselected(Entity associated_entity); 38 | 39 | protected: 40 | void mouseReleaseEvent(QMouseEvent*) override; 41 | void resizeEvent(QResizeEvent*) override; 42 | void paintEvent(QPaintEvent*) override; 43 | 44 | private: 45 | QLabel* label; 46 | Entity entity; 47 | bool _selected = false; 48 | }; 49 | } // namespace anton_engine 50 | -------------------------------------------------------------------------------- /editor/public/rendering/builtin_editor_shaders.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | enum class Builtin_Editor_Shader { 7 | outline_mix = 0, 8 | grid = 1, 9 | imgui = 2, 10 | }; 11 | 12 | Shader& get_builtin_shader(Builtin_Editor_Shader); 13 | } // namespace anton_engine 14 | -------------------------------------------------------------------------------- /editor/public/rendering/imgui_rendering.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine::imgui { 8 | class Draw_Elements_Command { 9 | public: 10 | u32 count; 11 | u32 instance_count; 12 | u32 first_index; 13 | u32 base_vertex; 14 | u32 base_instance; 15 | }; 16 | 17 | void setup_rendering(); 18 | void bind_buffers(); 19 | // Fills count, base_vertex and first_index 20 | Draw_Elements_Command write_geometry(anton::Slice, 21 | anton::Slice); 22 | void add_draw_command(Draw_Elements_Command); 23 | void commit_draw(); 24 | 25 | } // namespace anton_engine::imgui 26 | -------------------------------------------------------------------------------- /engine/private/core/logging.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #if ANTON_WITH_EDITOR 6 | #include 7 | #endif 8 | 9 | #include // TODO: Replace with format 10 | 11 | namespace anton_engine { 12 | void log_message(Log_Message_Severity severity, anton::String_View message) 13 | { 14 | // Higly advanced and complex logging code. 15 | #if ANTON_WITH_EDITOR 16 | System_Time sys_time = get_local_system_time(); 17 | char t[9] = {}; 18 | sprintf(t, "%02d:%02d:%02d", sys_time.hour, sys_time.minutes, 19 | sys_time.seconds); 20 | // editor.log_viewer->add_message(severity, t, message); 21 | fprintf(stdout, "%s Debug Message: %s\n", t, message.data()); 22 | #else 23 | System_Time sys_time = get_local_system_time(); 24 | if(severity == Log_Message_Severity::info) { 25 | fprintf(stdout, "[%02d:%02d:%02d] Info: %s\n", sys_time.hour, 26 | sys_time.minutes, sys_time.seconds, message.data()); 27 | } else if(severity == Log_Message_Severity::warning) { 28 | fprintf(stdout, "[%02d:%02d:%02d] Warning: %s\n", sys_time.hour, 29 | sys_time.minutes, sys_time.seconds, message.data()); 30 | } else { 31 | fprintf(stderr, "[%02d:%02d:%02d] Error: %s\n", sys_time.hour, 32 | sys_time.minutes, sys_time.seconds, message.data()); 33 | } 34 | #endif // ANTON_WITH_EDITOR 35 | } 36 | } // namespace anton_engine 37 | -------------------------------------------------------------------------------- /engine/private/core/paths.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine::paths { 9 | static anton::String _executable_name; 10 | static anton::String _executable_directory; 11 | static anton::String _assets_directory; 12 | static anton::String _shaders_directory; 13 | 14 | void set_executable_name(anton::String_View const name) 15 | { 16 | _executable_name = name; 17 | } 18 | 19 | void set_executable_directory(anton::String_View const path) 20 | { 21 | _executable_directory = path; 22 | _assets_directory = 23 | anton::fs::concat_paths(_executable_directory, "assets"); 24 | _shaders_directory = 25 | anton::fs::concat_paths(_executable_directory, "shaders"); 26 | } 27 | 28 | anton::String_View executable_name() 29 | { 30 | return _executable_name; 31 | } 32 | 33 | anton::String_View executable_directory() 34 | { 35 | return _executable_directory; 36 | } 37 | 38 | anton::String_View assets_directory() 39 | { 40 | return _assets_directory; 41 | } 42 | 43 | anton::String_View shaders_directory() 44 | { 45 | // TODO a different path 46 | return _shaders_directory; 47 | } 48 | 49 | #if ANTON_WITH_EDITOR 50 | static anton::String _project_directory; 51 | 52 | void set_project_directory(anton::String_View const path) 53 | { 54 | _project_directory = path; 55 | } 56 | 57 | anton::String_View project_directory() 58 | { 59 | return _project_directory; 60 | } 61 | #endif // ANTON_WITH_EDITOR 62 | } // namespace anton_engine::paths 63 | -------------------------------------------------------------------------------- /engine/private/core/paths_internal.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::paths { 6 | void set_executable_name(anton::String_View path); 7 | void set_executable_directory(anton::String_View path); 8 | 9 | // TODO: Move to editor paths 10 | #if ANTON_WITH_EDITOR 11 | void set_project_directory(anton::String_View path); 12 | #endif // ANTON_WITH_EDITOR 13 | } // namespace anton_engine::paths 14 | -------------------------------------------------------------------------------- /engine/private/core/random.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace anton_engine { 9 | static std::mt19937_64 mersenne_engine(278432434351ULL); 10 | 11 | template 12 | auto subtract_as_unsigned(T x, T y) -> anton::make_unsigned 13 | { 14 | if constexpr(anton::is_unsigned) { 15 | return x - y; 16 | } else { 17 | if(x >= 0 && y < 0) { 18 | return T(x) + T(-(y + 1)) + 1; 19 | } else { 20 | return T(x - y); 21 | } 22 | } 23 | } 24 | 25 | i64 random_i64(i64 min, i64 max) 26 | { 27 | u64 const engine_range = 28 | subtract_as_unsigned(mersenne_engine.max(), mersenne_engine.min()); 29 | u64 const range = subtract_as_unsigned(max, min); 30 | ANTON_ASSERT(max >= min, "max < min"); 31 | 32 | if(range == 0) { 33 | return min; 34 | } else if(range < engine_range) { 35 | u64 scale = engine_range / (range + 1); 36 | while(true) { 37 | u64 const number = mersenne_engine() / scale; 38 | if(number <= range) { 39 | if(min >= 0) { 40 | return i64(number) + min; 41 | } else if(number > u64(-(min + 1))) { 42 | return i64(number - u64(-(min + 1)) - 1); 43 | } else { 44 | return i64(number) + min; 45 | } 46 | } 47 | } 48 | } else { // range == engine_range 49 | u64 const number = mersenne_engine(); 50 | if(number >= (1ULL << 63)) { 51 | return number - (1ULL << 63); 52 | } else { 53 | return i64(number) - i64((1ULL << 63) - 1) - 1; 54 | } 55 | } 56 | } 57 | 58 | f32 random_f32(f32 min, f32 max) 59 | { 60 | return std::uniform_real_distribution(min, max)(mersenne_engine); 61 | } 62 | 63 | f64 random_f64(f64 min, f64 max) 64 | { 65 | return std::uniform_real_distribution(min, max)(mersenne_engine); 66 | } 67 | 68 | void seed_default_random_engine(u64 const s) 69 | { 70 | mersenne_engine.seed(s); 71 | } 72 | } // namespace anton_engine 73 | -------------------------------------------------------------------------------- /engine/private/core/serialization/archives/binary.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine::serialization { 4 | void Binary_Input_Archive::read_binary(void* p, i64 bytes) 5 | { 6 | char* ptr = reinterpret_cast(p); 7 | file.read(ptr, bytes); 8 | } 9 | 10 | void Binary_Output_Archive::write_binary(void const* p, i64 bytes) 11 | { 12 | char const* ptr = reinterpret_cast(p); 13 | file.write(ptr, bytes); 14 | } 15 | } // namespace anton_engine::serialization 16 | -------------------------------------------------------------------------------- /engine/private/core/threads.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #if defined(_WIN32) || defined(_WIN64) 8 | 9 | extern "C" { 10 | // xthreads.h 11 | 12 | struct xtime; 13 | 14 | void _Thrd_sleep(const xtime*); 15 | } 16 | 17 | namespace anton_engine::threads { 18 | void sleep(Timespec const& duration) 19 | { 20 | _Thrd_sleep(reinterpret_cast(&duration)); 21 | } 22 | } // namespace anton_engine::threads 23 | 24 | #else 25 | 26 | #include 27 | 28 | namespace anton_engine::threads { 29 | void sleep(Timespec const& duration) 30 | { 31 | ANTON_ASSERT(duration.nanoseconds >= 0 && duration.seconds >= 0, 32 | "duration must be a positive number"); 33 | ANTON_ASSERT(duration.nanoseconds < 1000000000, 34 | "nanoseconds must be less than 1 billion (1 second)"); 35 | timespec requested{duration.seconds, duration.nanoseconds}; 36 | timespec remaining{}; 37 | int result = nanosleep(&requested, &remaining); 38 | ANTON_UNUSED(result); 39 | } 40 | } // namespace anton_engine::threads 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /engine/private/core/utils/filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace anton_engine::utils { 6 | anton::Array read_file_binary(anton::String_View const path) 7 | { 8 | FILE* file = fopen(path.data(), "rb"); 9 | if(!file) { 10 | // TODO: More specific exception that will actually allow 11 | // me to dispaly useful information to the user. 12 | throw Exception(u8"Failed to read the file"); 13 | } 14 | 15 | fseek(file, 0, SEEK_END); 16 | i64 const file_size = ftell(file); 17 | fseek(file, 0, SEEK_SET); 18 | anton::Array file_contents(file_size); 19 | fread(reinterpret_cast(file_contents.data()), file_size, 1, file); 20 | fclose(file); 21 | return file_contents; 22 | } 23 | } // namespace anton_engine::utils 24 | -------------------------------------------------------------------------------- /engine/private/core/windows/common.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | 6 | namespace anton_engine::windows { 7 | u64 get_last_error() 8 | { 9 | return GetLastError(); 10 | } 11 | 12 | anton::String get_last_error_message() 13 | { 14 | DWORD error_code = GetLastError(); 15 | if(error_code == 0) { 16 | return {}; 17 | } 18 | 19 | LPWSTR message_buffer = nullptr; 20 | FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 21 | FORMAT_MESSAGE_IGNORE_INSERTS, 22 | nullptr, error_code, 23 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 24 | reinterpret_cast(&message_buffer), 0, nullptr); 25 | anton::String error_message = 26 | anton::String::from_utf16(reinterpret_cast(message_buffer)); 27 | LocalFree(message_buffer); 28 | return error_message; 29 | } 30 | } // namespace anton_engine::windows 31 | -------------------------------------------------------------------------------- /engine/private/core/windows/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine::windows { 7 | [[nodiscard]] u64 get_last_error(); 8 | [[nodiscard]] anton::String get_last_error_message(); 9 | } // namespace anton_engine::windows 10 | -------------------------------------------------------------------------------- /engine/private/core/windows/debugging.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine::windows::debugging { 7 | [[nodiscard]] anton::String get_type_as_string(void* process_handle, 8 | u64 module_base, u64 index); 9 | } // namespace anton_engine::windows::debugging 10 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/component_serialization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | get_component_serialization_funcs_t get_component_serialization_funcs = 5 | nullptr; 6 | } 7 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/ecs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #if ANTON_WITH_EDITOR 8 | #include 9 | #else 10 | #include 11 | #endif // ANTON_WITH_EDITOR 12 | 13 | namespace anton_engine { 14 | ECS::~ECS() 15 | { 16 | for(auto& container_data: containers) { 17 | anton::destruct(container_data.container); 18 | container_data.container = nullptr; 19 | } 20 | } 21 | 22 | Entity ECS::create() 23 | { 24 | // TODO: More clever entity creation (generations and reusing ids) 25 | return _entities.emplace_back(id_generator.next()); 26 | } 27 | 28 | static void 29 | serialize_component_container(u64 identifier, 30 | serialization::Binary_Output_Archive& archive, 31 | Component_Container_Base const* container) 32 | { 33 | ANTON_ASSERT( 34 | get_component_serialization_funcs != nullptr, 35 | "Function get_component_serialization_funcs has not been loaded"); 36 | auto& serialization_funcs = get_component_serialization_funcs(); 37 | auto iter = 38 | anton::find_if(serialization_funcs.begin(), serialization_funcs.end(), 39 | [identifier](Component_Serialization_Funcs const& funcs) { 40 | return funcs.identifier == identifier; 41 | }); 42 | ANTON_ASSERT(iter != serialization_funcs.end(), 43 | "Identifier was not found in the component registry"); 44 | iter->serialize(archive, container); 45 | } 46 | 47 | static void 48 | deserialize_component_container(u64 identifier, 49 | serialization::Binary_Input_Archive& archive, 50 | Component_Container_Base*& container) 51 | { 52 | ANTON_ASSERT( 53 | get_component_serialization_funcs != nullptr, 54 | "Function get_component_serialization_funcs has not been loaded"); 55 | auto& serialization_funcs = get_component_serialization_funcs(); 56 | auto iter = 57 | anton::find_if(serialization_funcs.begin(), serialization_funcs.end(), 58 | [identifier](Component_Serialization_Funcs const& funcs) { 59 | return funcs.identifier == identifier; 60 | }); 61 | ANTON_ASSERT(iter != serialization_funcs.end(), 62 | "Identifier was not found in the component registry"); 63 | iter->deserialize(archive, container); 64 | } 65 | 66 | void serialize(serialization::Binary_Output_Archive& archive, ECS const& ecs) 67 | { 68 | serialize(archive, ecs._entities); 69 | archive.write(ecs.containers.size()); 70 | for(auto const& data: ecs.containers) { 71 | archive.write(data.family); 72 | serialize_component_container(data.family, archive, data.container); 73 | } 74 | } 75 | 76 | void deserialize(serialization::Binary_Input_Archive& archive, ECS& ecs) 77 | { 78 | deserialize(archive, ecs._entities); 79 | i64 containers_count; 80 | archive.read(containers_count); 81 | ecs.containers.resize(containers_count); 82 | for(auto& data: ecs.containers) { 83 | archive.read(data.family); 84 | deserialize_component_container(data.family, archive, data.container); 85 | } 86 | } 87 | 88 | ECS& get_ecs() 89 | { 90 | #if ANTON_WITH_EDITOR 91 | return Editor::get_ecs(); 92 | #else 93 | return Engine::get_ecs(); 94 | #endif 95 | } 96 | } // namespace anton_engine 97 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/jobs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | } 5 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/jobs_management.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace anton_engine { 7 | static anton::Array jobs; 8 | 9 | i64 schedule_job(Job* job) 10 | { 11 | jobs.push_back(job); 12 | // TODO: Generate id 13 | return 0; 14 | } 15 | 16 | void execute_jobs() 17 | { 18 | for(Job* job: jobs) { 19 | job->execute(); 20 | } 21 | 22 | jobs.clear(); 23 | } 24 | } // namespace anton_engine 25 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/jobs_management.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace anton_engine { 4 | void execute_jobs(); 5 | } 6 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/system.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace anton_engine { 7 | static anton::Array systems; 8 | 9 | // From game dll 10 | create_systems_type create_systems = nullptr; 11 | 12 | void init_systems() 13 | { 14 | systems = create_systems(); 15 | } 16 | 17 | void start_systems() 18 | { 19 | for(System* system: systems) { 20 | system->start(); 21 | } 22 | } 23 | 24 | void update_systems() 25 | { 26 | for(System* system: systems) { 27 | system->update(); 28 | } 29 | } 30 | } // namespace anton_engine 31 | -------------------------------------------------------------------------------- /engine/private/engine/ecs/system_management.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace anton_engine { 5 | using create_systems_type = anton::Array (*)(); 6 | ENGINE_API extern create_systems_type create_systems; 7 | 8 | void init_systems(); 9 | void start_systems(); 10 | void update_systems(); 11 | } // namespace anton_engine 12 | -------------------------------------------------------------------------------- /engine/private/engine/input/input_internal.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine::input { 7 | void add_gamepad_event(i32 pad_index, Key, f32 value); 8 | void add_event(Key, f32 value); 9 | 10 | void process_events(); 11 | } // namespace anton_engine::input 12 | -------------------------------------------------------------------------------- /engine/private/engine/mesh.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | Mesh generate_plane() 5 | { 6 | // clang-format off 7 | return Mesh({anton::variadic_construct, 8 | Vertex({-1, 1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {0, 1}), Vertex({-1, -1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {0, 0}), 9 | Vertex({1, -1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 0}), Vertex({-1, 1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {0, 1}), 10 | Vertex({1, -1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 0}), Vertex({1, 1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}, {1, 1})}, 11 | {anton::variadic_construct, 0, 1, 2, 3, 4, 5}); 12 | // clang-format on 13 | } 14 | 15 | Mesh generate_cube() 16 | { 17 | // clang-format off 18 | return Mesh({anton::variadic_construct, 19 | // back 20 | Vertex({-1, -1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {1, 0}), Vertex({1, 1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {0, 1}), 21 | Vertex({1, -1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {0, 0}), Vertex({1, 1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {0, 1}), 22 | Vertex({-1, -1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {1, 0}), Vertex({-1, 1, -1}, {0, 0, -1}, {-1, 0, 0}, {0, 1, 0}, {1, 1}), 23 | // front 24 | Vertex({-1, -1, 1}, {0, 0, 1}, {1, 0.0, 0}, {0, 1, 0}, {0, 0}), Vertex({1, -1, 1}, {0, 0, 1},{1, 0.0, 0}, {0, 1, 0}, {1, 0}), 25 | Vertex({1, 1, 1}, {0, 0, 1}, {1, 0.0, 0}, {0, 1, 0}, {1, 1}), Vertex({1, 1, 1}, {0, 0, 1}, {1, 0.0, 0}, {0, 1, 0}, {1, 1}), 26 | Vertex({-1, 1, 1}, {0, 0, 1}, {1, 0.0, 0}, {0, 1, 0}, {0, 1}), Vertex({-1, -1, 1}, {0, 0, 1}, {1, 0.0, 0}, {0, 1, 0}, {0, 0}), 27 | // left 28 | Vertex({-1, 1, -1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1}), Vertex({-1, -1, -1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 0}), 29 | Vertex({-1, 1, 1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 1}), Vertex({-1, -1, -1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 0}), 30 | Vertex({-1, -1, 1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0}), Vertex({-1, 1, 1}, {-1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 1}), 31 | // right 32 | Vertex({1, 1, 1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {0, 1}), Vertex({1, -1, -1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {1, 0}), 33 | Vertex({1, 1, -1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {1, 1}), Vertex({1, -1, -1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {1, 0}), 34 | Vertex({1, 1, 1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {0, 1}), Vertex({1, -1, 1}, {1, 0, 0}, {0, 0, -1}, {0, 1, 0}, {0, 0}), 35 | // bottom 36 | Vertex({-1, -1, -1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0}), Vertex({1, -1, -1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {1, 0}), 37 | Vertex({1, -1, 1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {1, 1}), Vertex({1, -1, 1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {1, 1}), 38 | Vertex({-1, -1, 1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 1}), Vertex({-1, -1, -1}, {0, -1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0}), 39 | // top 40 | Vertex({-1, 1, -1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, 1}), Vertex({1, 1, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {1, 0}), 41 | Vertex({1, 1, -1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {1, 1}), Vertex({1, 1, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {1, 0}), 42 | Vertex({-1, 1, -1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, 1}), Vertex({-1, 1, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, 0})}, 43 | {anton::variadic_construct, 44 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}); 45 | // clang-format on 46 | } 47 | } // namespace anton_engine 48 | -------------------------------------------------------------------------------- /engine/private/engine/time.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | // The number of frames since the start of the game 8 | static u64 frame_count = 0; 9 | // The time it took to complete the previous frame 10 | static double delta_time = 0.01666666; 11 | // Scale independent time it took to complete the previous frame 12 | static double unscaled_delta_time = 0.01666666; 13 | static double time_scale = 1.0; 14 | // The time at the beginning of the current frame 15 | static double frame_time = 0; 16 | // The time at the beginning of the previous frame 17 | static double previous_frame_time = 0; 18 | // Scale independent time at the beginning of the current frame 19 | static double unscaled_frame_time = 0; 20 | // Scale independent time at the beginning of the previous frame 21 | static double unscaled_previous_frame_time = 0; 22 | 23 | static double frame_start_time = 0.0f; 24 | 25 | // (private) Time since init was called. 26 | static double time_offset = 0; 27 | 28 | void init_time() 29 | { 30 | time_offset = get_time(); 31 | } 32 | 33 | void update_time() 34 | { 35 | ++frame_count; 36 | double current_time = get_time() - time_offset; 37 | frame_start_time = current_time; 38 | unscaled_delta_time = current_time - unscaled_frame_time; 39 | unscaled_previous_frame_time = unscaled_frame_time; 40 | unscaled_frame_time = current_time; 41 | delta_time = unscaled_delta_time * time_scale; 42 | previous_frame_time = frame_time; 43 | frame_time += delta_time; 44 | } 45 | 46 | System_Time get_utc_system_time() 47 | { 48 | Mimas_System_Time t = mimas_get_utc_system_time(); 49 | return {t.year, t.month, t.day, t.day_of_week, 50 | t.hour, t.minutes, t.seconds, t.milliseconds}; 51 | } 52 | 53 | System_Time get_local_system_time() 54 | { 55 | Mimas_System_Time t = mimas_get_local_system_time(); 56 | return {t.year, t.month, t.day, t.day_of_week, 57 | t.hour, t.minutes, t.seconds, t.milliseconds}; 58 | } 59 | 60 | double get_time() 61 | { 62 | return mimas_get_time(); 63 | } 64 | 65 | double get_frame_start_time() 66 | { 67 | return frame_time; 68 | } 69 | 70 | double get_delta_time() 71 | { 72 | return delta_time; 73 | } 74 | 75 | double get_frame_time() 76 | { 77 | return frame_time; 78 | } 79 | 80 | double get_unscaled_delta_time() 81 | { 82 | return unscaled_delta_time; 83 | } 84 | 85 | double get_unscaled_time() 86 | { 87 | return unscaled_frame_time; 88 | } 89 | 90 | u64 get_frame_count() 91 | { 92 | return frame_count; 93 | } 94 | } // namespace anton_engine 95 | -------------------------------------------------------------------------------- /engine/private/engine/time_internal.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace anton_engine { 4 | void init_time(); 5 | void update_time(); 6 | } // namespace anton_engine 7 | -------------------------------------------------------------------------------- /engine/private/physics/line.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | Vec2 closest_points_on_lines(Line l1, Line l2) 8 | { 9 | Mat2 inv = math::inverse(Mat2({math::dot(l1.direction, l1.direction), 10 | math::dot(l1.direction, l2.direction)}, 11 | {-math::dot(l1.direction, l2.direction), 12 | -math::dot(l2.direction, l2.direction)})); 13 | Vec2 result = inv * Vec2(math::dot(l2.origin - l1.origin, l1.direction), 14 | math::dot(l2.origin - l1.origin, l2.direction)); 15 | return result; 16 | } 17 | } // namespace anton_engine 18 | -------------------------------------------------------------------------------- /engine/private/physics/obb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | bool test_ray_obb(Ray ray, OBB obb) 9 | { 10 | Mat4 rotation = Mat4(Vec4{obb.local_x, 0}, Vec4{obb.local_y, 0}, 11 | Vec4{obb.local_z, 0}, Vec4{0, 0, 0, 1}); 12 | // Center OBB at 0 13 | Mat4 obb_space = rotation * math::translate(-obb.center); 14 | Vec4 ray_dir = rotation * Vec4(ray.direction, 0); 15 | Vec4 ray_origin = obb_space * Vec4(ray.origin, 1); 16 | // AABB slab test 17 | f32 tmin = -math::infinity; 18 | f32 tmax = math::infinity; 19 | for(int i = 0; i < 3; ++i) { 20 | f32 tx1 = (obb.halfwidths[i] - ray_origin[i]) / ray_dir[i]; 21 | f32 tx2 = (-obb.halfwidths[i] - ray_origin[i]) / ray_dir[i]; 22 | tmax = math::min(tmax, math::max(tx1, tx2)); 23 | tmin = math::max(tmin, math::min(tx1, tx2)); 24 | } 25 | return tmax >= 0 && tmax >= tmin; 26 | } 27 | 28 | anton::Optional intersect_ray_obb(Ray ray, OBB obb) 29 | { 30 | Mat4 rotation = Mat4(Vec4{obb.local_x, 0}, Vec4{obb.local_y, 0}, 31 | Vec4{obb.local_z, 0}, Vec4{0, 0, 0, 1}); 32 | // Center OBB at 0 33 | Mat4 obb_space = rotation * math::translate(-obb.center); 34 | Vec4 ray_dir = rotation * Vec4(ray.direction, 0); 35 | Vec4 ray_origin = obb_space * Vec4(ray.origin, 1); 36 | // AABB slab test 37 | f32 tmin = -math::infinity; 38 | f32 tmax = math::infinity; 39 | for(i32 i = 0; i < 3; ++i) { 40 | f32 tx1 = (obb.halfwidths[i] - ray_origin[i]) / ray_dir[i]; 41 | f32 tx2 = (-obb.halfwidths[i] - ray_origin[i]) / ray_dir[i]; 42 | tmax = math::min(tmax, math::max(tx1, tx2)); 43 | tmin = math::max(tmin, math::min(tx1, tx2)); 44 | } 45 | 46 | if(tmax >= 0 && tmax >= tmin) { 47 | Raycast_Hit out; 48 | out.distance = tmax; 49 | out.hit_point = ray.origin + ray.direction * tmax; 50 | return out; 51 | } else { 52 | return anton::null_optional; 53 | } 54 | } 55 | } // namespace anton_engine 56 | -------------------------------------------------------------------------------- /engine/private/physics/ray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace anton_engine { 4 | Ray screen_to_ray(Mat4 inv_view, Mat4 inv_projection, i32 screen_width, 5 | i32 screen_height, Vec2 point) 6 | { 7 | // Transform screen point to normalized -1..1 coordinates 8 | float const normalized_x = 9 | 2.0f * point.x / static_cast(screen_width) - 1.0f; 10 | float const normalized_y = 11 | 2.0f * point.y / static_cast(screen_height) - 1.0f; 12 | 13 | Vec4 const ray_start = Vec4(normalized_x, normalized_y, -1.0f, 1.0f); 14 | Vec4 const ray_end = Vec4(normalized_x, normalized_y, 0.0f, 1.0f); 15 | 16 | Vec4 const ray_start_hg = inv_projection * ray_start; 17 | Vec4 const ray_end_hg = inv_projection * ray_end; 18 | 19 | Vec3 ray_start_homogenized = Vec3(ray_start_hg); 20 | Vec3 ray_end_homogenized = Vec3(ray_end_hg); 21 | 22 | if(ray_start_hg.w != 0.0f) { 23 | ray_start_homogenized /= ray_start_hg.w; 24 | } 25 | if(ray_end_hg.w != 0.0f) { 26 | ray_end_homogenized /= ray_end_hg.w; 27 | } 28 | 29 | Vec3 ray_direction_view_space = ray_end_homogenized - ray_start_homogenized; 30 | ray_direction_view_space = math::normalize(ray_direction_view_space); 31 | 32 | Vec3 ray_start_world_space = 33 | Vec3(inv_view * Vec4(ray_start_homogenized, 1.0f)); 34 | Vec3 ray_direction_world_space = 35 | Vec3(inv_view * Vec4(ray_direction_view_space, 0.0f)); 36 | ray_direction_world_space = math::normalize(ray_direction_world_space); 37 | 38 | return {ray_start_world_space, ray_direction_world_space}; 39 | } 40 | 41 | Ray screen_to_ray(Mat4 inv_view_projection_matrix, i32 screen_width, 42 | i32 screen_height, Vec2 point) 43 | { 44 | // Transform screen point to normalized -1..1 coordinates 45 | float const normalized_x = 46 | 2.0f * point.x / static_cast(screen_width) - 1.0f; 47 | float const normalized_y = 48 | 2.0f * point.y / static_cast(screen_height) - 1.0f; 49 | 50 | // Since z=1 is far and z=-1 is near in NDC, we use -1 for the start and 0 for the end to get better precision. 51 | Vec4 const ray_start = Vec4(normalized_x, normalized_y, -1.0f, 1.0f); 52 | Vec4 const ray_end = Vec4(normalized_x, normalized_y, 0.0f, 1.0f); 53 | 54 | Vec4 const ray_start_world_space = inv_view_projection_matrix * ray_start; 55 | Vec4 const ray_end_world_space = inv_view_projection_matrix * ray_end; 56 | 57 | Vec3 ray_start_homogenized = Vec3(ray_start_world_space); 58 | Vec3 ray_end_homogenized = Vec3(ray_end_world_space); 59 | 60 | if(ray_start_world_space.w != 0.0f) { 61 | ray_start_homogenized /= ray_start_world_space.w; 62 | } 63 | if(ray_end_world_space.w != 0.0f) { 64 | ray_end_homogenized /= ray_end_world_space.w; 65 | } 66 | 67 | Vec3 ray_direction = ray_end_homogenized - ray_start_homogenized; 68 | ray_direction = math::normalize(ray_direction); 69 | 70 | return {ray_start_homogenized, ray_direction}; 71 | } 72 | } // namespace anton_engine 73 | -------------------------------------------------------------------------------- /engine/private/rendering/texture_format.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | struct Texture_Format { 7 | u32 width; 8 | u32 height; 9 | u32 sized_internal_format; 10 | u32 pixel_format; 11 | u32 pixel_type; 12 | u32 filter; 13 | i32 mip_levels; 14 | i32 swizzle_mask[4]; 15 | }; 16 | } // namespace anton_engine 17 | -------------------------------------------------------------------------------- /engine/private/scripts/camera_movement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | void Camera_Movement::update(Camera_Movement& camera_mov, Camera&, 11 | Transform& transform) 12 | { 13 | // Look around 14 | float horizontal_rotation = input::get_axis("mouse_x"); 15 | float vertical_rotation = input::get_axis("mouse_y"); 16 | transform.rotate(Vec3{0.0f, 1.0f, 0.0f}, 17 | math::radians(-horizontal_rotation)); 18 | camera_mov.camera_side = 19 | Vec3(math::rotate_y(math::radians(horizontal_rotation)) * 20 | Vec4(camera_mov.camera_side)); 21 | transform.rotate(camera_mov.camera_side, math::radians(vertical_rotation)); 22 | 23 | // Move 24 | Vec3 camera_front = get_camera_front(transform); 25 | float camera_speed = 0.15f * 60.0f * get_delta_time(); 26 | float forward = input::get_axis("move_forward"); 27 | transform.translate(camera_front * camera_speed * forward); 28 | float sideways = input::get_axis("move_sideways"); 29 | transform.translate(camera_mov.camera_side * camera_speed * sideways); 30 | float vertical = input::get_axis("move_vertical"); 31 | transform.translate(Vec3{0.0f, 1.0f, 0.0f} * camera_speed * vertical); 32 | 33 | float scroll = input::get_axis("scroll"); 34 | transform.translate(camera_front * scroll); 35 | } 36 | } // namespace anton_engine 37 | -------------------------------------------------------------------------------- /engine/private/scripts/debug_hotkeys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace anton_engine { 16 | template 17 | void reload_shader(Shader& shader_to_reload, T&&... path) 18 | { 19 | try { 20 | Shader shader = 21 | create_shader(assets::load_shader_stage(ANTON_FWD(path))...); 22 | swap(shader_to_reload, shader); 23 | } catch(Program_Linking_Failed const& e) { 24 | ANTON_LOG_ERROR( 25 | anton::String(u8"Failed to reload shaders due to linking error: ") + 26 | e.get_message()); 27 | } catch(Shader_Compilation_Failed const& e) { 28 | ANTON_LOG_ERROR( 29 | anton::String(u8"Failed to reload shaders due to compilation error: ") + 30 | e.get_message()); 31 | } catch(Exception const& e) { 32 | ANTON_LOG_ERROR( 33 | anton::String(u8"Failed to reload shaders due to unknown error: ") + 34 | e.get_message()); // 35 | } 36 | } 37 | 38 | static char const* current_fxaa = "postprocessing/fxaa.frag"; 39 | static char const* next_fxaa = "postprocessing/nv_fxaa_port.frag"; 40 | 41 | static void swap_fxaa_shader() 42 | { 43 | anton::swap(current_fxaa, next_fxaa); 44 | } 45 | 46 | void Debug_Hotkeys::update(Debug_Hotkeys& debug_hotkeys) 47 | { 48 | auto reload = input::get_action("reload_shaders"); 49 | if(reload.released) { 50 | // TODO reloading shaders 51 | //Engine::get_shader_manager().reload_shaders(); 52 | } 53 | 54 | auto swap_fxaa = input::get_action("swap_fxaa_shaders"); 55 | if(swap_fxaa.released) { 56 | swap_fxaa_shader(); 57 | } 58 | 59 | #if !ANTON_WITH_EDITOR 60 | auto capture_mouse = input::get_action("capture_mouse"); 61 | if(capture_mouse.released) { 62 | // if (debug_hotkeys.cursor_captured) { 63 | // debug_hotkeys.cursor_captured = false; 64 | // Engine::get_window().unlock_cursor(); 65 | // } else { 66 | // debug_hotkeys.cursor_captured = true; 67 | // Engine::get_window().lock_cursor(); 68 | // } 69 | // Editor::set_mouse_captured(debug_hotkeys.cursor_captured); 70 | } 71 | #endif // !ANTON_WITH_EDITOR 72 | } 73 | } // namespace anton_engine 74 | -------------------------------------------------------------------------------- /engine/private/shaders/shader_exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /engine/private/shaders/shader_stage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | static void compile_shader(u32 shader, 10 | anton::String_View name = "Unnamed Shader") 11 | { 12 | glCompileShader(shader); 13 | GLint compilation_status; 14 | glGetShaderiv(shader, GL_COMPILE_STATUS, &compilation_status); 15 | if(compilation_status == GL_FALSE) { 16 | GLint log_length; 17 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); 18 | anton::String log{anton::reserve, log_length + name.size_bytes() + 29}; 19 | log.append(u8"Shader compilation failed ("); 20 | log.append(name); 21 | log.append(")\n"); 22 | glGetShaderInfoLog(shader, log_length, &log_length, 23 | log.data() + log.size_bytes()); 24 | throw Shader_Compilation_Failed(log); 25 | } 26 | } 27 | 28 | static void set_shader_source(u32 shader, anton::String_View source) 29 | { 30 | char const* src = source.data(); 31 | glShaderSource(shader, 1, &src, nullptr); 32 | } 33 | 34 | Shader_Stage::Shader_Stage(anton::String_View n, 35 | opengl::Shader_Stage_Type type, 36 | anton::String_View source) 37 | : type(type), shader(0) 38 | { 39 | shader = glCreateShader(utils::enum_to_value(type)); 40 | if(shader == 0) { 41 | throw Shader_Not_Created(""); 42 | } 43 | set_shader_source(shader, source); 44 | compile_shader(shader, n); 45 | } 46 | 47 | Shader_Stage::Shader_Stage(Shader_Stage&& shader) noexcept 48 | : type(shader.type), shader(shader.shader) 49 | { 50 | shader.shader = 0; 51 | } 52 | 53 | Shader_Stage& Shader_Stage::operator=(Shader_Stage&& s) noexcept 54 | { 55 | anton::swap(shader, s.shader); 56 | return *this; 57 | } 58 | 59 | Shader_Stage::~Shader_Stage() 60 | { 61 | if(shader != 0) { 62 | glDeleteShader(shader); 63 | } 64 | } 65 | } // namespace anton_engine 66 | -------------------------------------------------------------------------------- /engine/private/windowing/window.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine::windowing { 8 | class Window; 9 | class Display; 10 | class OpenGL_Context; 11 | class Cursor; 12 | 13 | enum class Standard_Cursor { 14 | arrow, 15 | resize_right, 16 | resize_left, 17 | resize_top, 18 | resize_bottom, 19 | resize_top_left, 20 | resize_top_right, 21 | resize_bottom_left, 22 | resize_bottom_right, 23 | }; 24 | 25 | // Returns true if windowing has been successfully initialized. 26 | bool init(); 27 | void terminate(); 28 | void poll_events(); 29 | 30 | Display* get_primary_display(); 31 | void fullscreen_window(Window* window, Display* display); 32 | 33 | Window* create_window(f32 width, f32 height, bool decorated); 34 | void destroy_window(Window*); 35 | 36 | void clip_cursor(Window*, Rect const*); 37 | void lock_cursor(Window*); 38 | void unlock_cursor(Window*); 39 | void set_cursor(Window* window, Cursor* cursor); 40 | Cursor* create_standard_cursor(Standard_Cursor cursor); 41 | void destroy_cursor(Cursor* cursor); 42 | 43 | using window_resize_function = void (*)(Window*, f32 width, f32 height, 44 | void* user_data); 45 | using window_activate_function = void (*)(Window*, bool activated, 46 | void* user_data); 47 | using cursor_pos_function = void (*)(Window*, f32 x, f32 y, void* user_data); 48 | // TODO: enum for action? 49 | // TODO: add mods? 50 | using mouse_button_function = void (*)(Window*, Key, i32 action, 51 | void* user_data); 52 | using scroll_function = void (*)(Window*, f32 x_offset, f32 y_offset, 53 | void* user_data); 54 | using key_function = void (*)(Window*, Key key, i32 action, void* user_data); 55 | using joystick_function = void (*)(i32 joystick, i32 action, void* user_data); 56 | 57 | void set_window_resize_callback(Window*, window_resize_function, 58 | void* user_data = nullptr); 59 | void set_window_activate_callback(Window*, window_activate_function, 60 | void* user_data = nullptr); 61 | void set_cursor_pos_callback(Window*, cursor_pos_function, 62 | void* user_data = nullptr); 63 | void set_mouse_button_callback(Window*, mouse_button_function, 64 | void* user_data = nullptr); 65 | void set_scroll_callback(Window*, scroll_function, void* user_data = nullptr); 66 | void set_key_callback(Window*, key_function, void* user_data = nullptr); 67 | void set_joystick_callback(joystick_function, void* user_data = nullptr); 68 | 69 | // Returns whether the specified key has been pressed. 70 | bool get_key(Key); 71 | // Retrieves cursor position. 72 | Vec2 get_cursor_pos(); 73 | 74 | bool close_requested(Window*); 75 | void resize(Window*, f32 width, f32 height); 76 | Vec2 get_window_size(Window*); 77 | Vec2 get_window_pos(Window*); 78 | void set_window_pos(Window*, Vec2); 79 | void set_size(Window* window, Vec2 size); 80 | bool is_active(Window* window); 81 | 82 | enum class OpenGL_Profile { 83 | core, 84 | compatibility, 85 | }; 86 | 87 | OpenGL_Context* create_context(i32 major, i32 minor, OpenGL_Profile); 88 | void destroy_context(OpenGL_Context*); 89 | void make_context_current(OpenGL_Context*, Window*); 90 | void swap_buffers(Window*); 91 | void enable_vsync(bool); 92 | } // namespace anton_engine::windowing 93 | -------------------------------------------------------------------------------- /engine/public/core/class_macros.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // The following macros are used by codegen 4 | 5 | #define COMPONENT 6 | -------------------------------------------------------------------------------- /engine/public/core/color.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Color { 9 | public: 10 | static Color const white; 11 | static Color const black; 12 | static Color const red; 13 | static Color const green; 14 | static Color const blue; 15 | 16 | f32 r = 0; 17 | f32 g = 0; 18 | f32 b = 0; 19 | f32 a = 1.0f; 20 | 21 | Color() = default; 22 | Color(f32 red, f32 green, f32 blue, f32 alpha = 1.0f) 23 | : r(red), g(green), b(blue), a(alpha) 24 | { 25 | } 26 | 27 | // Componentwise multiply 28 | void operator*=(Color const&); 29 | }; 30 | 31 | // Componentwise multiply 32 | Color operator*(Color const&, Color const&); 33 | 34 | void swap(Color&, Color&); 35 | } // namespace anton_engine 36 | 37 | namespace anton_engine { 38 | inline Color const Color::white = Color(1.0f, 1.0f, 1.0f); 39 | inline Color const Color::black = Color(0.0f, 0.0f, 0.0f); 40 | inline Color const Color::red = Color(1.0f, 0.0f, 0.0f); 41 | inline Color const Color::green = Color(0.0f, 1.0f, 0.0f); 42 | inline Color const Color::blue = Color(0.0f, 0.0f, 1.0f); 43 | 44 | inline void Color::operator*=(Color const& c) 45 | { 46 | r *= c.r; 47 | g *= c.g; 48 | b *= c.b; 49 | } 50 | 51 | inline Color operator*(Color const& c1, Color const& c2) 52 | { 53 | Color c(c1); 54 | c *= c2; 55 | return c; 56 | } 57 | 58 | inline void swap(Color& a, Color& b) 59 | { 60 | anton::swap(a.r, b.r); 61 | anton::swap(a.g, b.g); 62 | anton::swap(a.b, b.b); 63 | anton::swap(a.a, b.a); 64 | } 65 | } // namespace anton_engine 66 | -------------------------------------------------------------------------------- /engine/public/core/diagnostic_macros.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // TODO: Add GCC support 4 | #if ANTON_COMPILER_CLANG 5 | #define ANTON_DISABLE_WARNINGS() \ 6 | _Pragma("clang diagnostic push"); \ 7 | _Pragma("clang diagnostic ignored \"-Weverything\""); 8 | #define ANTON_RESTORE_WARNINGS() _Pragma("clang diagnostic pop"); 9 | 10 | #define ANTON_WARNING_PUSH() _Pragma("clang diagnostic push"); 11 | #define ANTON_WARNING_POP() _Pragma("clang diagnostic pop"); 12 | #define ANTON_WARNING_IGNORE(WARNING) _Pragma(WARNING); 13 | 14 | #define ANTON_WARNING_UNUSED_CONST_VARIABLE \ 15 | "clang diagnostic ignored \"-Wunused-const-variable\"" 16 | #elif ANTON_COMPILER_MSVC 17 | #define ANTON_DISABLE_WARNINGS() __pragma(warning(push, 0)); 18 | #define ANTON_RESTORE_WARNINGS() __pragma(warning(pop)); 19 | 20 | #define ANTON_WARNING_PUSH() 21 | #define ANTON_WARNING_POP() 22 | #define ANTON_WARNING_IGNORE(WARNING) 23 | 24 | #define ANTON_WARNING_UNUSED_CONST_VARIABLE 25 | #else 26 | #define ANTON_DISABLE_WARNINGS() 27 | #define ANTON_RESTORE_WARNINGS() 28 | #define ANTON_WARNING_PUSH() 29 | #define ANTON_WARNING_POP() 30 | #define ANTON_WARNING_IGNORE(WARNING) 31 | 32 | #define ANTON_WARNING_UNUSED_CONST_VARIABLE 33 | #endif 34 | 35 | // Note: Clang 8 does not support __declspec(allocator) 36 | #if defined(_MSC_VER) && ANTON_COMPILER_CLANG 37 | // Makes the memory allocations visible via Event Tracing for Windows (ETW), 38 | // which allows Visual Studio's native memory profiler to track memory allocations. 39 | #define ANTON_DECLSPEC_ALLOCATOR __declspec(allocator) 40 | #else 41 | #define ANTON_DECLSPEC_ALLOCATOR 42 | #endif 43 | -------------------------------------------------------------------------------- /engine/public/core/exception.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | class Exception { 8 | public: 9 | Exception(anton::String_View message): _message(message) {} 10 | 11 | anton::String_View get_message() const 12 | { 13 | return _message; 14 | } 15 | 16 | private: 17 | anton::String _message; 18 | }; 19 | 20 | class Invalid_Argument_Exception: public Exception { 21 | public: 22 | using Exception::Exception; 23 | }; 24 | } // namespace anton_engine 25 | -------------------------------------------------------------------------------- /engine/public/core/handle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | template 7 | class Handle { 8 | public: 9 | u64 value = static_cast(-1); 10 | }; 11 | 12 | template 13 | [[nodiscard]] constexpr bool operator==(Handle lhs, Handle rhs) 14 | { 15 | return lhs.value == rhs.value; 16 | } 17 | 18 | template 19 | [[nodiscard]] constexpr bool operator!=(Handle lhs, Handle rhs) 20 | { 21 | return lhs.value != rhs.value; 22 | } 23 | 24 | template 25 | [[nodiscard]] constexpr bool operator<(Handle lhs, Handle rhs) 26 | { 27 | return lhs.value < rhs.value; 28 | } 29 | 30 | template 31 | [[nodiscard]] constexpr bool operator>(Handle lhs, Handle rhs) 32 | { 33 | return lhs.value > rhs.value; 34 | } 35 | 36 | template 37 | [[nodiscard]] constexpr bool operator<=(Handle lhs, Handle rhs) 38 | { 39 | return lhs.value <= rhs.value; 40 | } 41 | 42 | template 43 | [[nodiscard]] constexpr bool operator>=(Handle lhs, Handle rhs) 44 | { 45 | return lhs.value >= rhs.value; 46 | } 47 | } // namespace anton_engine 48 | -------------------------------------------------------------------------------- /engine/public/core/integer_sequence_generator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | class Integer_Sequence_Generator { 7 | public: 8 | Integer_Sequence_Generator(u64 start_number = 0): _next(start_number) {} 9 | 10 | u64 next() 11 | { 12 | return _next++; 13 | } 14 | 15 | private: 16 | u64 _next; 17 | }; 18 | } // namespace anton_engine 19 | -------------------------------------------------------------------------------- /engine/public/core/logging.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | enum class Log_Message_Severity { 7 | info, 8 | warning, 9 | error, 10 | fatal_error, 11 | }; 12 | 13 | void log_message(Log_Message_Severity, anton::String_View message); 14 | 15 | #define ANTON_LOG_INFO(message) \ 16 | ::anton_engine::log_message(::anton_engine::Log_Message_Severity::info, \ 17 | message); 18 | #define ANTON_LOG_WARNING(message) \ 19 | ::anton_engine::log_message(::anton_engine::Log_Message_Severity::warning, \ 20 | message); 21 | #define ANTON_LOG_ERROR(message) \ 22 | ::anton_engine::log_message(::anton_engine::Log_Message_Severity::error, \ 23 | message); 24 | } // namespace anton_engine 25 | -------------------------------------------------------------------------------- /engine/public/core/memory/stack_allocate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | template 8 | class Stack_Allocate { 9 | public: 10 | T& reference() 11 | { 12 | return *pointer(); 13 | } 14 | 15 | T* pointer() 16 | { 17 | return reinterpret_cast(anton::launder(&buffer)); 18 | } 19 | 20 | anton::Aligned_Buffer buffer; 21 | }; 22 | } // namespace anton_engine 23 | -------------------------------------------------------------------------------- /engine/public/core/paths.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::paths { 6 | anton::String_View executable_name(); 7 | anton::String_View executable_directory(); 8 | 9 | anton::String_View assets_directory(); 10 | anton::String_View shaders_directory(); 11 | 12 | // TODO: Move to editor paths 13 | #if ANTON_WITH_EDITOR 14 | anton::String_View project_directory(); 15 | #endif // ANTON_WITH_EDITOR 16 | } // namespace anton_engine::paths 17 | -------------------------------------------------------------------------------- /engine/public/core/random.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | i64 random_i64(i64 min, i64 max); 7 | f32 random_f32(f32 min, f32 max); 8 | f64 random_f64(f64 min, f64 max); 9 | 10 | void seed_default_random_engine(u64); 11 | } // namespace anton_engine 12 | -------------------------------------------------------------------------------- /engine/public/core/serialization/archives/binary.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine::serialization { 7 | class Binary_Input_Archive { 8 | public: 9 | explicit Binary_Input_Archive(anton::Input_Stream& strm): file(strm) {} 10 | 11 | template 12 | void read(T& v) 13 | { 14 | constexpr usize data_size = sizeof(T); 15 | void* out = reinterpret_cast(&v); 16 | read_binary(out, data_size); 17 | } 18 | 19 | void read_binary(void*, i64 bytes); 20 | 21 | private: 22 | anton::Input_Stream& file; 23 | }; 24 | 25 | class Binary_Output_Archive { 26 | public: 27 | explicit Binary_Output_Archive(anton::Output_Stream& strm): file(strm) {} 28 | 29 | template 30 | void write(T const& v) 31 | { 32 | constexpr usize data_size = sizeof(T); 33 | void const* data = reinterpret_cast(&v); 34 | write_binary(data, data_size); 35 | } 36 | 37 | void write_binary(void const*, i64 bytes); 38 | 39 | private: 40 | anton::Output_Stream& file; 41 | }; 42 | } // namespace anton_engine::serialization 43 | -------------------------------------------------------------------------------- /engine/public/core/serialization/serialization.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | template 8 | struct use_default_serialize: anton::False_Type {}; 9 | 10 | template 11 | anton::enable_if::value, void> 12 | serialize(serialization::Binary_Output_Archive& out, T const& obj) 13 | { 14 | out.write(obj); 15 | } 16 | 17 | template 18 | anton::enable_if::value, void> 19 | deserialize(serialization::Binary_Input_Archive& in, T& obj) 20 | { 21 | in.read(obj); 22 | } 23 | } // namespace anton_engine 24 | 25 | #define ANTON_DEFAULT_SERIALIZABLE(type) \ 26 | namespace anton_engine { \ 27 | template<> \ 28 | struct use_default_serialize: anton::True_Type {}; \ 29 | } 30 | -------------------------------------------------------------------------------- /engine/public/core/serialization/types/array.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | template 10 | void serialize(serialization::Binary_Output_Archive& out, 11 | anton::Array const& vec) 12 | { 13 | out.write(vec.capacity()); 14 | out.write(vec.size()); 15 | for(T const& elem: vec) { 16 | serialize(out, elem); 17 | } 18 | } 19 | 20 | template 21 | void deserialize(serialization::Binary_Input_Archive& in, 22 | anton::Array& vec) 23 | { 24 | using size_type = typename anton::Array::size_type; 25 | size_type capacity = 0; 26 | size_type size = 0; 27 | in.read(capacity); 28 | in.read(size); 29 | vec.clear(); 30 | vec.set_capacity(capacity); 31 | if constexpr(anton::is_default_constructible) { 32 | vec.resize(size); 33 | try { 34 | for(T& elem: vec) { 35 | deserialize(in, elem); 36 | } 37 | } catch(...) { 38 | // TODO: Move stream backwards to maintain weak guarantee 39 | anton::destruct_n(vec.data(), size); 40 | throw; 41 | } 42 | } else { 43 | size_type n = size; 44 | try { 45 | for(; n > 0; --n) { 46 | Stack_Allocate elem; 47 | vec.push_back(ANTON_MOV(elem.reference())); 48 | deserialize(in, vec.back()); 49 | } 50 | vec._size = size; 51 | } catch(...) { 52 | // TODO: Move stream backwards to maintain weak guarantee 53 | anton::destruct_n(vec.data(), size - n); 54 | throw; 55 | } 56 | } 57 | } 58 | } // namespace anton_engine 59 | -------------------------------------------------------------------------------- /engine/public/core/serialization/types/string.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | void serialize(serialization::Binary_Output_Archive& out, 10 | anton::String const& str) 11 | { 12 | out.write(str.capacity()); 13 | out.write(str.size_bytes()); 14 | out.write_binary(str.data(), str.size_bytes()); 15 | } 16 | 17 | void deserialize(serialization::Binary_Input_Archive& in, anton::String& str) 18 | { 19 | anton::String::size_type capacity; 20 | anton::String::size_type size; 21 | in.read(capacity); 22 | in.read(size); 23 | str.clear(); 24 | str.ensure_capacity_exact(capacity); 25 | str.force_size(size); 26 | in.read_binary(str.data(), size); 27 | } 28 | } // namespace anton_engine 29 | -------------------------------------------------------------------------------- /engine/public/core/threads.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::threads { 6 | struct Timespec { 7 | i64 seconds; 8 | i64 nanoseconds; 9 | }; 10 | 11 | void sleep(Timespec const& duration); 12 | } // namespace anton_engine::threads 13 | -------------------------------------------------------------------------------- /engine/public/core/types.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton::math { 6 | struct Vec2; 7 | struct Vec3; 8 | struct Vec4; 9 | struct Mat2; 10 | struct Mat3; 11 | struct Mat4; 12 | struct Quat; 13 | } // namespace anton::math 14 | 15 | namespace anton_engine { 16 | using i8 = anton::i8; 17 | using i16 = anton::i16; 18 | using i32 = anton::i32; 19 | using i64 = anton::i64; 20 | 21 | using u8 = anton::u8; 22 | using u16 = anton::u16; 23 | using u32 = anton::u32; 24 | using u64 = anton::u64; 25 | 26 | using f32 = anton::f32; 27 | using f64 = anton::f64; 28 | 29 | using isize = anton::isize; 30 | using usize = anton::usize; 31 | 32 | using char8 = anton::char8; 33 | using char16 = anton::char16; 34 | using char32 = anton::char32; 35 | 36 | using nullptr_t = anton::nullptr_t; 37 | 38 | using anton::math::Mat2; 39 | using anton::math::Mat3; 40 | using anton::math::Mat4; 41 | using anton::math::Quat; 42 | using anton::math::Vec2; 43 | using anton::math::Vec3; 44 | using anton::math::Vec4; 45 | 46 | namespace math { 47 | using namespace anton::math; 48 | } 49 | 50 | template 51 | struct Rect { 52 | T left; 53 | T top; 54 | T right; 55 | T bottom; 56 | }; 57 | } // namespace anton_engine 58 | -------------------------------------------------------------------------------- /engine/public/core/utils/enum.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine::utils { 6 | template 7 | constexpr anton::underlying_type enum_to_value(T v) 8 | { 9 | return static_cast>(v); 10 | } 11 | 12 | template 13 | struct enable_enum_add_operator {}; 14 | 15 | template 16 | struct enable_enum_bitwise_and {}; 17 | 18 | template 19 | struct enable_enum_bitwise_or {}; 20 | } // namespace anton_engine::utils 21 | 22 | template::value> 24 | constexpr T operator+(T a, anton::underlying_type b) 25 | { 26 | return static_cast(anton_engine::utils::enum_to_value(a) + b); 27 | } 28 | 29 | template::value> 31 | constexpr T operator+(anton::underlying_type a, T b) 32 | { 33 | return static_cast(a + anton_engine::utils::enum_to_value(b)); 34 | } 35 | 36 | template::value> 38 | constexpr T operator&(T a, T b) 39 | { 40 | return static_cast(anton_engine::utils::enum_to_value(a) & 41 | anton_engine::utils::enum_to_value(b)); 42 | } 43 | 44 | template::value> 46 | constexpr T operator|(T const a, T const b) 47 | { 48 | return static_cast(anton_engine::utils::enum_to_value(a) | 49 | anton_engine::utils::enum_to_value(b)); 50 | } 51 | -------------------------------------------------------------------------------- /engine/public/core/utils/filesystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine::utils { 8 | // File utility functions 9 | 10 | anton::Array read_file_binary(anton::String_View path); 11 | } // namespace anton_engine::utils 12 | -------------------------------------------------------------------------------- /engine/public/engine.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace anton_engine { 4 | class Framebuffer; 5 | class ECS; 6 | namespace rendering { 7 | class Renderer; 8 | } 9 | 10 | class Shader; 11 | class Mesh; 12 | class Material; 13 | template 14 | class Resource_Manager; 15 | 16 | class Engine { 17 | public: 18 | static rendering::Renderer& get_renderer(); 19 | static ECS& get_ecs(); 20 | static Resource_Manager& get_mesh_manager(); 21 | static Resource_Manager& get_shader_manager(); 22 | static Resource_Manager& get_material_manager(); 23 | }; 24 | } // namespace anton_engine 25 | -------------------------------------------------------------------------------- /engine/public/engine/assets.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | class Mesh; 11 | 12 | namespace assets { 13 | // Reads file as a string of chars without interpreting it 14 | anton::String read_file_raw_string(anton::String_View filename); 15 | 16 | opengl::Shader_Stage_Type 17 | shader_stage_type_from_filename(anton::String_View filename); 18 | 19 | Shader_Stage load_shader_stage(anton::String_View path); 20 | 21 | // Loads texture pixels 22 | Texture_Format load_texture_no_mipmaps(anton::String_View filename, 23 | u64 texture_id, 24 | anton::Array& pixels); 25 | 26 | Mesh load_mesh(anton::String_View filename, u64 guid); 27 | } // namespace assets 28 | } // namespace anton_engine 29 | -------------------------------------------------------------------------------- /engine/public/engine/components/camera.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace anton_engine { 13 | class COMPONENT Camera { 14 | public: 15 | // Size of the camera in ortographic projection 16 | // float size = 5; 17 | // Field of view in perspective projection 18 | f32 fov = 70; 19 | f32 near_plane = 0.3f; 20 | f32 far_plane = 1000.0f; 21 | bool active = true; // Temporarily make active by default 22 | }; 23 | 24 | inline Vec3 get_camera_top(Transform& transform) 25 | { 26 | // TODO: Return global instead of local 27 | Vec4 top = math::rotate(transform.local_rotation) * Vec4(0, 1, 0, 0); 28 | return {top.x, top.y, top.z}; 29 | } 30 | 31 | inline Vec3 get_camera_front(Transform& transform) 32 | { 33 | // TODO: Return global instead of local 34 | Vec4 front = math::rotate(transform.local_rotation) * Vec4(0, 0, -1, 0); 35 | return {front.x, front.y, front.z}; 36 | } 37 | 38 | inline Mat4 get_camera_view_matrix(Transform& transform) 39 | { 40 | Mat4 const camera_matrix = to_matrix(transform); 41 | return math::inverse(camera_matrix); 42 | } 43 | 44 | inline Mat4 get_camera_projection_matrix(Camera& camera, i32 viewport_width, 45 | i32 viewport_height) 46 | { 47 | float aspect_ratio = 48 | static_cast(viewport_width) / static_cast(viewport_height); 49 | return math::perspective_rh(math::radians(camera.fov), aspect_ratio, 50 | camera.near_plane, camera.far_plane); 51 | 52 | // Ortographic camera stuff 53 | // return math::orthographic(-size * aspect_ratio, size * aspect_ratio, -size, size, near_plane, far_plane); 54 | } 55 | 56 | inline Mat4 get_camera_projection_matrix(Camera const camera, 57 | Vec2 const viewport_size) 58 | { 59 | f32 const aspect_ratio = viewport_size.x / viewport_size.y; 60 | return math::perspective_rh(math::radians(camera.fov), aspect_ratio, 61 | camera.near_plane, camera.far_plane); 62 | 63 | // Ortographic camera stuff 64 | // return math::orthographic(-size * aspect_ratio, size * aspect_ratio, -size, size, near_plane, far_plane); 65 | } 66 | 67 | // inline Vec3 screen_to_world_point(Mat4 const inv_view, Mat4 const inv_projection, i32 const screen_width, i32 const screen_height, 68 | // Vec2 const point) { 69 | // // Transform screen point to normalized -1..1 coordinates 70 | // float const normalized_x = 2.0f * point.x / static_cast(screen_width) - 1.0f; 71 | // float const normalized_y = 2.0f * point.y / static_cast(screen_height) - 1.0f; 72 | 73 | // Vec4 const ray_start = Vec4(normalized_x, normalized_y, -1.0f, 1.0f); 74 | // Vec4 const ray_start_hg = ray_start * inv_projection; 75 | // Vec3 ray_start_homogenized = Vec3(ray_start_hg); 76 | 77 | // if (ray_start_hg.w != 0.0f) { 78 | // ray_start_homogenized /= ray_start_hg.w; 79 | // } 80 | 81 | // Vec3 ray_start_world_space = Vec3(Vec4(ray_start_homogenized, 1.0f) * inv_view); 82 | // return ray_start_world_space; 83 | // } 84 | } // namespace anton_engine 85 | 86 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Camera) 87 | -------------------------------------------------------------------------------- /engine/public/engine/components/directional_light_component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | // By default points down along y axis. 10 | // 11 | class COMPONENT Directional_Light_Component { 12 | public: 13 | Vec3 direction = Vec3{0.0f, -1.0f, 0.0f}; 14 | Color color = Color::white; 15 | f32 intensity = 1.0f; 16 | bool dynamic = false; 17 | }; 18 | } // namespace anton_engine 19 | 20 | ANTON_DEFAULT_SERIALIZABLE(::anton_engine::Directional_Light_Component) 21 | -------------------------------------------------------------------------------- /engine/public/engine/components/entity_name.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | class COMPONENT Entity_Name { 11 | public: 12 | anton::String name; 13 | }; 14 | 15 | inline void serialize(serialization::Binary_Output_Archive& out, 16 | Entity_Name const& name) 17 | { 18 | serialize(out, name.name); 19 | } 20 | 21 | inline void deserialize(serialization::Binary_Input_Archive& in, 22 | Entity_Name& name) 23 | { 24 | deserialize(in, name.name); 25 | } 26 | } // namespace anton_engine 27 | -------------------------------------------------------------------------------- /engine/public/engine/components/hierarchy.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | class COMPONENT Hierarchy { 10 | public: 11 | Entity parent; 12 | // TODO: Right now supports only 16 children. 13 | anton::Fixed_Array children; 14 | }; 15 | } // namespace anton_engine 16 | 17 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Hierarchy) 18 | -------------------------------------------------------------------------------- /engine/public/engine/components/line_component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | class Shader; 10 | class Mesh; 11 | class Material; 12 | 13 | class COMPONENT Line_Component { 14 | public: 15 | Color color = Color::white; 16 | float thickness = 1; 17 | 18 | Handle mesh_handle; 19 | Handle shader_handle; 20 | Handle material_handle; 21 | }; 22 | } // namespace anton_engine 23 | 24 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Line_Component) 25 | -------------------------------------------------------------------------------- /engine/public/engine/components/ortographic_camera.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/engine/public/engine/components/ortographic_camera.hpp -------------------------------------------------------------------------------- /engine/public/engine/components/point_light_component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class COMPONENT Point_Light_Component { 9 | public: 10 | Color color = Color::white; 11 | f32 intensity = 1.0f; 12 | bool dynamic = false; 13 | }; 14 | } // namespace anton_engine 15 | 16 | ANTON_DEFAULT_SERIALIZABLE(::anton_engine::Point_Light_Component) 17 | -------------------------------------------------------------------------------- /engine/public/engine/components/spot_light_component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | // By default points down along y axis. 10 | // 11 | class COMPONENT Spot_Light_Component { 12 | public: 13 | Vec3 direction = Vec3{0.0f, -1.0f, 0.0f}; 14 | Color color = Color::white; 15 | f32 cutoff_angle = 25.0f; 16 | f32 blend_angle = 20.0f; 17 | f32 intensity = 1.0f; 18 | bool dynamic = false; 19 | }; 20 | } // namespace anton_engine 21 | 22 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Spot_Light_Component) 23 | -------------------------------------------------------------------------------- /engine/public/engine/components/static_mesh_component.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Mesh; 9 | class Shader; 10 | class Material; 11 | 12 | class COMPONENT Static_Mesh_Component { 13 | public: 14 | Handle mesh_handle; 15 | Handle shader_handle; 16 | Handle material_handle; 17 | }; 18 | } // namespace anton_engine 19 | 20 | ANTON_DEFAULT_SERIALIZABLE(::anton_engine::Static_Mesh_Component) 21 | -------------------------------------------------------------------------------- /engine/public/engine/components/transform.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace anton_engine { 11 | class COMPONENT Transform { 12 | public: 13 | Quat local_rotation; 14 | Vec3 local_position; 15 | Vec3 local_scale = Vec3{1.0f, 1.0f, 1.0f}; 16 | 17 | void translate(Vec3 const& translation_vec) 18 | { 19 | local_position += translation_vec; 20 | } 21 | 22 | void scale(Vec3 const& scale_vec) 23 | { 24 | local_scale *= scale_vec; 25 | } 26 | 27 | // axis to rotate about 28 | // angle in radians 29 | void rotate(Vec3 axis, float angle) 30 | { 31 | float half_angle_sin = math::sin(angle / 2); 32 | Quat q(axis.x * half_angle_sin, axis.y * half_angle_sin, 33 | axis.z * half_angle_sin, math::cos(angle / 2)); 34 | local_rotation = q * local_rotation; 35 | } 36 | 37 | Mat4 to_matrix() const 38 | { 39 | Mat4 mat = math::scale(local_scale) * math::rotate(local_rotation) * 40 | math::translate(local_position); 41 | return mat; 42 | } 43 | }; 44 | 45 | inline Mat4 to_matrix(Transform const t) 46 | { 47 | Mat4 mat = math::scale(t.local_scale) * math::rotate(t.local_rotation) * 48 | math::translate(t.local_position); 49 | return mat; 50 | } 51 | } // namespace anton_engine 52 | 53 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Transform) 54 | -------------------------------------------------------------------------------- /engine/public/engine/ecs/component_container_iterator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | template 9 | class Component_Container; 10 | 11 | // TODO: Visualiser 12 | template 13 | class Component_Container_Iterator { 14 | public: 15 | using value_type = Component; 16 | using reference = Component&; 17 | using pointer = Component*; 18 | using difference_type = isize; 19 | using iteragor_category = anton::Contiguous_Iterator_Tag; 20 | 21 | Component_Container_Iterator() = delete; 22 | Component_Container_Iterator(Component_Container_Iterator const&) = default; 23 | Component_Container_Iterator(Component_Container_Iterator&&) noexcept = 24 | default; 25 | ~Component_Container_Iterator() = default; 26 | Component_Container_Iterator& 27 | operator=(Component_Container_Iterator const&) = default; 28 | Component_Container_Iterator& 29 | operator=(Component_Container_Iterator&&) noexcept = default; 30 | 31 | Component_Container_Iterator& operator++() 32 | { 33 | ++index; 34 | return *this; 35 | } 36 | 37 | [[nodiscard]] Component_Container_Iterator operator++(int) 38 | { 39 | Component_Container_Iterator copy(*this); 40 | ++index; 41 | return copy; 42 | } 43 | 44 | Component_Container_Iterator& operator--() 45 | { 46 | --index; 47 | return *this; 48 | } 49 | 50 | [[nodiscard]] Component_Container_Iterator operator--(int) 51 | { 52 | Component_Container_Iterator copy(*this); 53 | --index; 54 | return copy; 55 | } 56 | 57 | Component_Container_Iterator& operator+=(difference_type n) 58 | { 59 | index += n; 60 | return *this; 61 | } 62 | 63 | Component_Container_Iterator& operator-=(difference_type n) 64 | { 65 | index -= n; 66 | return *this; 67 | } 68 | 69 | [[nodiscard]] Component* operator->() 70 | { 71 | if constexpr(anton::is_empty) { 72 | return data; 73 | } else { 74 | return data + index; 75 | } 76 | } 77 | 78 | [[nodiscard]] Component const* operator->() const 79 | { 80 | if constexpr(anton::is_empty) { 81 | return data; 82 | } else { 83 | return data + index; 84 | } 85 | } 86 | 87 | [[nodiscard]] Component& operator*() 88 | { 89 | if constexpr(anton::is_empty) { 90 | return *data; 91 | } else { 92 | return *(data + index); 93 | } 94 | } 95 | 96 | [[nodiscard]] Component const& operator*() const 97 | { 98 | if constexpr(anton::is_empty) { 99 | return *data; 100 | } else { 101 | return *(data + index); 102 | } 103 | } 104 | 105 | [[nodiscard]] bool operator==(Component_Container_Iterator const& rhs) 106 | { 107 | return index == rhs.index; 108 | } 109 | 110 | [[nodiscard]] bool operator<(Component_Container_Iterator const& rhs) 111 | { 112 | return index < rhs.index; 113 | } 114 | 115 | private: 116 | Component* data; 117 | difference_type index; 118 | 119 | Component_Container_Iterator(Component* p, difference_type i) 120 | : data(p), index(i) 121 | { 122 | } 123 | 124 | friend class Component_Container; 125 | }; 126 | 127 | template 128 | [[nodiscard]] inline Component_Container_Iterator 129 | operator+(Component_Container_Iterator lhs, 130 | typename Component_Container_Iterator::difference_type n) 131 | { 132 | lhs += n; 133 | return lhs; 134 | } 135 | 136 | template 137 | [[nodiscard]] inline Component_Container_Iterator 138 | operator+(typename Component_Container_Iterator::difference_type n, 139 | Component_Container_Iterator rhs) 140 | { 141 | rhs += n; 142 | return rhs; 143 | } 144 | 145 | template 146 | [[nodiscard]] inline Component_Container_Iterator 147 | operator-(Component_Container_Iterator lhs, 148 | typename Component_Container_Iterator::difference_type n) 149 | { 150 | lhs -= n; 151 | return lhs; 152 | } 153 | 154 | template 155 | [[nodiscard]] inline bool 156 | operator!=(Component_Container_Iterator const& lhs, 157 | Component_Container_Iterator const& rhs) 158 | { 159 | return !(lhs == rhs); 160 | } 161 | 162 | template 163 | [[nodiscard]] inline bool 164 | operator>(Component_Container_Iterator const& lhs, 165 | Component_Container_Iterator const& rhs) 166 | { 167 | return rhs < lhs; 168 | } 169 | 170 | template 171 | [[nodiscard]] inline bool 172 | operator<=(Component_Container_Iterator const& lhs, 173 | Component_Container_Iterator const& rhs) 174 | { 175 | return !(lhs > rhs); 176 | } 177 | 178 | template 179 | [[nodiscard]] inline bool 180 | operator>=(Component_Container_Iterator const& lhs, 181 | Component_Container_Iterator const& rhs) 182 | { 183 | return !(lhs < rhs); 184 | } 185 | } // namespace anton_engine 186 | -------------------------------------------------------------------------------- /engine/public/engine/ecs/component_serialization.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Component_Container_Base; 9 | 10 | using serialize_func = void (*)(serialization::Binary_Output_Archive&, 11 | Component_Container_Base const*); 12 | using deserialize_func = void (*)(serialization::Binary_Input_Archive&, 13 | Component_Container_Base*&); 14 | 15 | struct Component_Serialization_Funcs { 16 | u64 identifier; 17 | serialize_func serialize; 18 | deserialize_func deserialize; 19 | }; 20 | 21 | using get_component_serialization_funcs_t = 22 | anton::Array& (*)(); 23 | 24 | ENGINE_API extern get_component_serialization_funcs_t 25 | get_component_serialization_funcs; 26 | } // namespace anton_engine 27 | -------------------------------------------------------------------------------- /engine/public/engine/ecs/entity.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Entity { 9 | public: 10 | u64 id; 11 | }; 12 | 13 | constexpr Entity null_entity{static_cast(-1)}; 14 | 15 | [[nodiscard]] constexpr u64 entity_index(Entity const entity) 16 | { 17 | return entity.id & 0xFFFFFFFF; 18 | } 19 | 20 | [[nodiscard]] constexpr u64 entity_generation(Entity const entity) 21 | { 22 | return (entity.id >> 32) & 0xFFFFFFFF; 23 | } 24 | 25 | [[nodiscard]] constexpr bool operator==(Entity const& lhs, Entity const& rhs) 26 | { 27 | return lhs.id == rhs.id; 28 | } 29 | 30 | [[nodiscard]] constexpr bool operator!=(Entity const& lhs, Entity const& rhs) 31 | { 32 | return lhs.id != rhs.id; 33 | } 34 | 35 | constexpr void swap(Entity& e1, Entity& e2) 36 | { 37 | anton::swap(e1.id, e2.id); 38 | } 39 | } // namespace anton_engine 40 | 41 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Entity) 42 | -------------------------------------------------------------------------------- /engine/public/engine/ecs/jobs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | class Job { 7 | public: 8 | virtual ~Job() {} 9 | 10 | virtual void execute() = 0; 11 | }; 12 | 13 | i64 schedule_job(Job*); 14 | } // namespace anton_engine 15 | -------------------------------------------------------------------------------- /engine/public/engine/ecs/system.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace anton_engine { 4 | class System { 5 | public: 6 | virtual ~System() {} 7 | 8 | virtual void start() {} 9 | virtual void update() = 0; 10 | }; 11 | } // namespace anton_engine 12 | -------------------------------------------------------------------------------- /engine/public/engine/input.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine::input { 8 | struct Key_State { 9 | f64 last_up_down_transition_time = 0.0; 10 | f32 raw_value = 0.0f; 11 | f32 value = 0.0f; 12 | bool down = false; 13 | // Has been pressed or released? 14 | bool up_down_transitioned = false; 15 | }; 16 | 17 | struct Any_Key_State { 18 | // Last time any key was pressed or released 19 | f64 last_up_down_transition_time = 0.0; 20 | // Has any key been pressed? 21 | bool pressed = false; 22 | // Has any key been released? 23 | bool released = false; 24 | // Is any key being held down? 25 | bool down = false; 26 | }; 27 | 28 | struct Action_State { 29 | bool down = false; 30 | bool pressed = false; 31 | bool released = false; 32 | }; 33 | 34 | // raw_value_scale - Scale by which to multiply raw value obtained from input devices. 35 | // accumulation_speed - How fast to accumulate axis value in units/s. 36 | // snap - If raw value changes sign, should we reset to 0 or continue from current value? 37 | void add_axis(anton::String_View name, Key, f32 raw_value_scale, 38 | f32 accumulation_speed, bool snap); 39 | void add_action(anton::String_View name, Key); 40 | 41 | [[nodiscard]] f32 get_axis(anton::String_View axis); 42 | [[nodiscard]] f32 get_axis_raw(anton::String_View axis); 43 | [[nodiscard]] Action_State get_action(anton::String_View action); 44 | [[nodiscard]] Key_State get_key_state(Key); 45 | // [[nodiscard]] Any_Key_State get_any_key_state(); 46 | } // namespace anton_engine::input 47 | -------------------------------------------------------------------------------- /engine/public/engine/key.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | enum class Key { 7 | none, 8 | any_key, 9 | 10 | mouse_x, 11 | mouse_y, 12 | mouse_scroll, 13 | mouse_horiz_scroll, 14 | left_mouse_button, 15 | right_mouse_button, 16 | middle_mouse_button, 17 | thumb_mouse_button_1, 18 | thumb_mouse_button_2, 19 | mouse_button_6, 20 | mouse_button_7, 21 | mouse_button_8, 22 | 23 | escape, 24 | enter, 25 | tab, 26 | caps_lock, 27 | spacebar, 28 | backspace, 29 | left_alt, 30 | right_alt, 31 | left_shift, 32 | right_shift, 33 | left_control, 34 | right_control, 35 | 36 | numpad_0, 37 | numpad_1, 38 | numpad_2, 39 | numpad_3, 40 | numpad_4, 41 | numpad_5, 42 | numpad_6, 43 | numpad_7, 44 | numpad_8, 45 | numpad_9, 46 | numpad_add, 47 | numpad_subtract, 48 | numpad_divide, 49 | numpad_multiply, 50 | numpad_decimal, 51 | numpad_enter, 52 | numlock, 53 | 54 | left, 55 | right, 56 | up, 57 | down, 58 | 59 | insert, 60 | home, 61 | page_up, 62 | page_down, 63 | end, 64 | del, 65 | 66 | zero, 67 | one, 68 | two, 69 | three, 70 | four, 71 | five, 72 | six, 73 | seven, 74 | eight, 75 | nine, 76 | 77 | a, 78 | b, 79 | c, 80 | d, 81 | e, 82 | f, 83 | g, 84 | h, 85 | i, 86 | j, 87 | k, 88 | l, 89 | m, 90 | n, 91 | o, 92 | p, 93 | q, 94 | r, 95 | s, 96 | t, 97 | u, 98 | v, 99 | w, 100 | x, 101 | y, 102 | z, 103 | 104 | slash, 105 | comma, 106 | dot, 107 | semicolon, 108 | left_bracket, 109 | right_bracket, 110 | minus, 111 | equals, 112 | apostrophe, 113 | tick, 114 | backward_slash, 115 | 116 | f1, 117 | f2, 118 | f3, 119 | f4, 120 | f5, 121 | f6, 122 | f7, 123 | f8, 124 | f9, 125 | f10, 126 | f11, 127 | f12, 128 | 129 | pause, 130 | 131 | gamepad_left_stick_x_axis, 132 | gamepad_left_stick_y_axis, 133 | gamepad_right_stick_x_axis, 134 | gamepad_right_stick_y_axis, 135 | gamepad_left_trigger, 136 | gamepad_right_trigger, 137 | 138 | gamepad_button_0, 139 | gamepad_button_1, 140 | gamepad_button_2, 141 | gamepad_button_3, 142 | gamepad_button_4, 143 | gamepad_button_5, 144 | gamepad_button_6, 145 | gamepad_button_7, 146 | gamepad_button_8, 147 | gamepad_button_9, 148 | gamepad_button_10, 149 | gamepad_button_11, 150 | gamepad_button_12, 151 | gamepad_button_13, 152 | gamepad_button_14, 153 | gamepad_button_15, 154 | gamepad_button_16, 155 | gamepad_button_17, 156 | gamepad_button_18, 157 | gamepad_button_19, 158 | }; 159 | 160 | [[nodiscard]] inline bool is_mouse_axis(Key const k) 161 | { 162 | return k == Key::mouse_x | k == Key::mouse_y | k == Key::mouse_scroll; 163 | } 164 | 165 | [[nodiscard]] inline bool is_gamepad_axis(Key const k) 166 | { 167 | return k == Key::gamepad_right_stick_x_axis | 168 | k == Key::gamepad_right_stick_y_axis | 169 | k == Key::gamepad_left_stick_x_axis | 170 | k == Key::gamepad_left_stick_y_axis | 171 | k == Key::gamepad_left_trigger | k == Key::gamepad_right_trigger; 172 | } 173 | 174 | [[nodiscard]] inline bool is_gamepad_stick(Key const k) 175 | { 176 | return k == Key::gamepad_right_stick_x_axis | 177 | k == Key::gamepad_right_stick_y_axis | 178 | k == Key::gamepad_left_stick_x_axis | 179 | k == Key::gamepad_left_stick_y_axis; 180 | } 181 | 182 | anton::String_View key_to_string(Key); 183 | Key key_from_string(anton::String_View); 184 | } // namespace anton_engine 185 | -------------------------------------------------------------------------------- /engine/public/engine/material.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | // std140 requires a member structure be aligned to a multiple of vec4's alignment (16 in our case). 7 | // Textures are stored as array textures on gpu. index is rendering specific internal index that will be mapped 8 | // to gl texture handle when the texture is bound. layer is the array texture layer. 9 | class alignas(16) Texture { 10 | public: 11 | static Texture const default_black; 12 | static Texture const default_black_transparent; 13 | static Texture const default_normal_map; 14 | 15 | u32 index = 0; 16 | float layer = 0; 17 | }; 18 | 19 | inline Texture const Texture::default_black{0, 0.0f}; 20 | inline Texture const Texture::default_black_transparent{0, 1.0f}; 21 | inline Texture const Texture::default_normal_map{0, 2.0f}; 22 | 23 | class Material { 24 | public: 25 | Texture diffuse_texture; 26 | Texture specular_texture; 27 | Texture normal_map; 28 | float shininess = 32.0f; // TODO: Remove 29 | }; 30 | } // namespace anton_engine 31 | -------------------------------------------------------------------------------- /engine/public/engine/mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | struct Vertex { 11 | Vec3 position; 12 | Vec3 normal; 13 | Vec3 tangent; 14 | Vec3 bitangent; 15 | Vec2 uv_coordinates; 16 | 17 | Vertex() = default; 18 | Vertex(Vec3 const pos, Vec3 const normal, Vec3 const tangent, 19 | Vec3 const bitangent, Vec2 const uv) 20 | : position(ANTON_MOV(pos)), normal(ANTON_MOV(normal)), 21 | tangent(ANTON_MOV(tangent)), bitangent(ANTON_MOV(bitangent)), 22 | uv_coordinates(ANTON_MOV(uv)) 23 | { 24 | } 25 | }; 26 | 27 | class Mesh { 28 | public: 29 | Mesh(anton::Array const& vertices, anton::Array const& indices) 30 | : vertices(vertices), indices(indices) 31 | { 32 | } 33 | Mesh(anton::Array&& vertices, anton::Array&& indices) 34 | : vertices(ANTON_MOV(vertices)), indices(ANTON_MOV(indices)) 35 | { 36 | } 37 | 38 | anton::Array vertices; 39 | anton::Array indices; 40 | }; 41 | 42 | Mesh generate_plane(); 43 | Mesh generate_cube(); 44 | } // namespace anton_engine 45 | -------------------------------------------------------------------------------- /engine/public/engine/resource_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | template 10 | class Resource_Manager { 11 | public: 12 | using iterator = typename anton::Array::iterator; 13 | 14 | iterator begin(); 15 | iterator end(); 16 | 17 | Handle add(T&&); 18 | T& get(Handle); 19 | T const& get(Handle) const; 20 | void remove(Handle); 21 | 22 | private: 23 | anton::Array resources; 24 | anton::Array identifiers; 25 | }; 26 | } // namespace anton_engine 27 | 28 | namespace anton_engine { 29 | template 30 | typename Resource_Manager::iterator Resource_Manager::begin() 31 | { 32 | return resources.begin(); 33 | } 34 | 35 | template 36 | typename Resource_Manager::iterator Resource_Manager::end() 37 | { 38 | return resources.end(); 39 | } 40 | 41 | template 42 | Handle Resource_Manager::add(T&& resource) 43 | { 44 | static Integer_Sequence_Generator id_generator; 45 | resources.emplace_back(ANTON_FWD(resource)); 46 | u64 resource_id = id_generator.next(); 47 | identifiers.push_back(resource_id); 48 | return {resource_id}; 49 | } 50 | 51 | template 52 | T& Resource_Manager::get(Handle handle) 53 | { 54 | for(typename anton::Array::size_type i = 0; i < identifiers.size(); 55 | ++i) { 56 | if(identifiers[i] == handle.value) { 57 | return resources[i]; 58 | } 59 | } 60 | 61 | throw Exception(u8"Could not find resource with given handle"); 62 | } 63 | 64 | template 65 | T const& Resource_Manager::get(Handle handle) const 66 | { 67 | for(typename anton::Array::size_type i = 0; i < identifiers.size(); 68 | ++i) { 69 | if(identifiers[i] == handle.value) { 70 | return resources[i]; 71 | } 72 | } 73 | 74 | throw Exception(u8"Could not find resource with given handle"); 75 | } 76 | 77 | template 78 | void Resource_Manager::remove(Handle handle) 79 | { 80 | for(typename anton::Array::size_type i = 0; i < identifiers.size(); 81 | ++i) { 82 | if(identifiers[i] == handle.value) { 83 | identifiers.erase_unsorted_unchecked(i); 84 | resources.erase_unsorted_unchecked(i); 85 | return; 86 | } 87 | } 88 | } 89 | } // namespace anton_engine 90 | -------------------------------------------------------------------------------- /engine/public/engine/time.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | struct System_Time { 7 | u16 year; 8 | // 1 through 12 9 | u16 month; 10 | // 1 through 31 11 | u16 day; 12 | // 0 (Sunday) through 6 (Saturday) 13 | u16 day_of_week; 14 | // 0 through 23 15 | u16 hour; 16 | // 0 through 59 17 | u16 minutes; 18 | // 0 through 59 19 | u16 seconds; 20 | // 0 through 999 21 | u16 milliseconds; 22 | }; 23 | 24 | System_Time get_utc_system_time(); 25 | System_Time get_local_system_time(); 26 | 27 | // Returns time in seconds 28 | double get_time(); 29 | double get_frame_start_time(); 30 | 31 | // The time it took to complete the previous frame 32 | double get_delta_time(); 33 | 34 | // Time scale independent time it took to complete the previous frame 35 | double get_unscaled_delta_time(); 36 | 37 | // Time since the start of the game at the beginning of the frame 38 | double get_frame_time(); 39 | 40 | // Time scale independent time since the start of the game at the beginning of the frame 41 | double get_unscaled_frame_time(); 42 | 43 | // The number of frames since the start of the game 44 | u64 get_frame_count(); 45 | } // namespace anton_engine 46 | -------------------------------------------------------------------------------- /engine/public/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace anton_engine { 10 | #if ANTON_WITH_EDITOR 11 | int editor_main(int argc, char** argv); 12 | #else 13 | int engine_main(int argc, char** argv); 14 | #endif // !ANTON_WITH_EDITOR 15 | } // namespace anton_engine 16 | 17 | int main(int argc, char** argv) 18 | { 19 | using namespace anton_engine; 20 | 21 | try { 22 | #if ANTON_WITH_EDITOR 23 | editor_main(argc, argv); 24 | #else 25 | engine_main(argc, argv); 26 | #endif // !ANTON_WITH_EDITOR 27 | } catch(Exception const& e) { 28 | FILE* file = fopen("crash_log.txt", "w"); 29 | fputs("anton_engine crashed with message:", file); 30 | anton::String_View const msg = e.get_message(); 31 | fputs(msg.data(), file); 32 | fclose(file); 33 | } catch(...) { 34 | FILE* file = fopen("crash_log.txt", "w"); 35 | fputs("anton_engine crashed with message:", file); 36 | fputs("unknown error", file); 37 | fclose(file); 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /engine/public/module_loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #ifdef _MSC_VER 7 | #define WIN32_LEAN_AND_MEAN 8 | #include 9 | #else 10 | #include 11 | #endif // _MSC_VER 12 | 13 | namespace anton_engine { 14 | Module load_module(anton::String_View module_name) 15 | { 16 | Module module; 17 | #ifdef _MSC_VER 18 | module.handle = LoadLibraryA(module_name.data()); 19 | #else 20 | module.handle = dlopen(module_name.data(), RTLD_LAZY); 21 | #endif 22 | if(!module.handle) { 23 | throw Exception(anton::String("Could not load module ") + module_name); 24 | } 25 | return module; 26 | } 27 | 28 | void* get_function_from_module(Module module, anton::String_View name) 29 | { 30 | #ifdef _MSC_VER 31 | // Since GetProcAddress returns a function pointer we reinterpret_cast to void* to silence -Wmicrosoft-cast. 32 | void* func_ptr = reinterpret_cast( 33 | GetProcAddress(static_cast(module.handle), name.data())); 34 | #else 35 | void* func_ptr = dlsym(module.handle, name.data()); 36 | #endif 37 | 38 | if(!func_ptr) { 39 | throw Exception(anton::String("Could not load function ") + name); 40 | } 41 | return func_ptr; 42 | } 43 | 44 | void unload_module(Module module) 45 | { 46 | #ifdef _MSC_VER 47 | if(!FreeLibrary(static_cast(module.handle))) { 48 | throw Exception("Could not unload module"); 49 | } 50 | #else 51 | if(dlclose(module.handle)) { 52 | throw Exception("Could not unload module"); 53 | } 54 | #endif 55 | } 56 | } // namespace anton_engine 57 | -------------------------------------------------------------------------------- /engine/public/module_loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _MSC_VER 4 | #pragma once 5 | #endif // _MSC_VER 6 | 7 | #include 8 | 9 | namespace anton_engine { 10 | class Module { 11 | public: 12 | void* handle; 13 | }; 14 | 15 | Module load_module(anton::String_View module_name); 16 | void unload_module(Module module); 17 | void* get_function_from_module(Module module, anton::String_View name); 18 | 19 | template 20 | T get_function_from_module(Module module, anton::String_View name) 21 | { 22 | return reinterpret_cast(get_function_from_module(module, name)); 23 | } 24 | } // namespace anton_engine 25 | -------------------------------------------------------------------------------- /engine/public/physics/intersection_tests.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace anton_engine { 12 | class Mesh; 13 | 14 | class Linecast_Hit { 15 | public: 16 | Vec3 hit_point; 17 | float distance = 0; 18 | }; 19 | 20 | anton::Optional intersect_ray_triangle(Ray, Vec3, Vec3, Vec3); 21 | anton::Optional intersect_ray_quad(Ray, Vec3, Vec3, Vec3, Vec3); 22 | anton::Optional intersect_ray_plane(Ray, Vec3 plane_normal, 23 | float plane_distance); 24 | anton::Optional intersect_ray_cone(Ray, Vec3 vertex, 25 | Vec3 direction, 26 | float angle_cos, 27 | float height); 28 | anton::Optional 29 | intersect_ray_cylinder(Ray, Vec3 vertex1, Vec3 vertex2, float radius); 30 | bool test_ray_mesh(Ray, Mesh const&); 31 | anton::Optional intersect_ray_mesh(Ray, Mesh const&, 32 | Mat4 model_transform); 33 | anton::Optional intersect_line_plane(Line, Vec3 plane_normal, 34 | float plane_distance); 35 | } // namespace anton_engine 36 | -------------------------------------------------------------------------------- /engine/public/physics/intersections_common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | class Raycast_Hit { 8 | public: 9 | Vec3 hit_point; 10 | Vec3 barycentric_coordinates; 11 | f32 distance = 0; 12 | }; 13 | } // namespace anton_engine 14 | -------------------------------------------------------------------------------- /engine/public/physics/line.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Line { 9 | public: 10 | Vec3 origin; 11 | Vec3 direction; 12 | }; 13 | 14 | // x is coefficient of the first line, y of the second one 15 | Vec2 closest_points_on_lines(Line, Line); 16 | } // namespace anton_engine 17 | -------------------------------------------------------------------------------- /engine/public/physics/obb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | class OBB { 11 | public: 12 | Vec3 center; 13 | Vec3 local_x; 14 | Vec3 local_y; 15 | Vec3 local_z; 16 | Vec3 halfwidths; 17 | }; 18 | 19 | [[nodiscard]] bool test_ray_obb(Ray, OBB); 20 | [[nodiscard]] anton::Optional intersect_ray_obb(Ray, OBB); 21 | } // namespace anton_engine 22 | -------------------------------------------------------------------------------- /engine/public/physics/ray.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine { 9 | class Ray { 10 | public: 11 | Vec3 origin; 12 | Vec3 direction; 13 | }; 14 | 15 | Ray screen_to_ray(Mat4 inv_view, Mat4 inv_projection, i32 screen_width, 16 | i32 screen_height, Vec2 point); 17 | Ray screen_to_ray(Mat4 inv_view_projection, i32 screen_width, 18 | i32 screen_height, Vec2 point); 19 | } // namespace anton_engine 20 | -------------------------------------------------------------------------------- /engine/public/rendering/fonts.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace anton_engine::rendering { 9 | class Font_Face; 10 | 11 | class Font_Render_Info { 12 | public: 13 | u32 points; 14 | u32 h_dpi; 15 | u32 v_dpi; 16 | }; 17 | 18 | // All metrics are expressed in font units. 19 | // 20 | class Face_Metrics { 21 | public: 22 | anton::String_View family_name; 23 | anton::String_View style_name; 24 | // The typographic ascender of the face. 25 | i32 ascender; 26 | // The typographic descender of the face (negative if below baseline). 27 | i32 descender; 28 | // Distance between 2 consecutive baselines. 29 | i32 line_height; 30 | i32 glyph_x_max; 31 | i32 glyph_x_min; 32 | i32 glyph_y_max; 33 | i32 glyph_y_min; 34 | i32 max_advance; 35 | // font units per em 36 | i32 units_per_em; 37 | }; 38 | 39 | // All metrics are expressed in 26.6 pixel format (1/64 of a pixel precision). 40 | // 41 | // Despite FreeType's documentation saying horizontal bearing is always positive for horizontal 42 | // layout, in practice it may be negative (e.g. letter 'j' in Comic Sans). 43 | // 44 | class Glyph_Metrics { 45 | public: 46 | // Width of the glyph. 47 | i32 width; 48 | // Height of the glyph. 49 | i32 height; 50 | // Horizontal offset from the pen position. 51 | i32 bearing_x; 52 | // Height above the baseline. 53 | i32 bearing_y; 54 | i32 advance; 55 | }; 56 | 57 | class Glyph { 58 | public: 59 | Glyph_Metrics metrics; 60 | // Handle a texture. 61 | u64 texture; 62 | // uv coordinates of the glyph in the texture. 63 | Rect uv; 64 | }; 65 | 66 | bool init_font_rendering(); 67 | void terminate_font_rendering(); 68 | 69 | // Returns: 70 | // Strongly typed handle that uniquely identifies the face or nullptr if failed to load the face. 71 | // 72 | Font_Face* load_face_from_file(anton::String_View path, u32 face_index); 73 | 74 | // Returns: 75 | // Strongly typed handle that uniquely identifies the face or nullptr if failed to load the face. 76 | // 77 | Font_Face* load_face(anton::Slice file_data, u32 face_index); 78 | void unload_face(Font_Face* face); 79 | 80 | // points_to_pixels 81 | // points - points in 26.6 format (1/64 of a point precision). 82 | // 83 | // Returns: 84 | // Equialent size in pixels in 26.6 format (1/64 of a pixel precision). 85 | // 86 | i64 points_to_pixels(i64 points, i64 dpi); 87 | 88 | Face_Metrics get_face_metrics(Font_Face* face); 89 | // Face_Metrics get_face_metrics_as_pixels(Font_Face* face, Font_Render_Info); 90 | 91 | // compute_text_width 92 | // Computes the width of the bounding box for text required to render it without clipping. 93 | // text is required to be drawn on a single line. Newline characters are ignored. 94 | // 95 | // Returns: 96 | // Width of text drawn on a single line with specified face and info in 26.6 pixel format (1/64 of a pixel precision). 97 | // 98 | i64 compute_text_width(Font_Face* face, Font_Render_Info info, 99 | anton::String_View text); 100 | 101 | anton::Array render_text(Font_Face* face, Font_Render_Info info, 102 | anton::String_View text); 103 | } // namespace anton_engine::rendering 104 | -------------------------------------------------------------------------------- /engine/public/rendering/framebuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace anton_engine { 12 | class Framebuffer { 13 | public: 14 | static constexpr u64 max_color_attachments = opengl::min_color_attachments; 15 | 16 | using Internal_Format = opengl::Sized_Internal_Format; 17 | 18 | enum class Bind_Mode { 19 | read = GL_READ_FRAMEBUFFER, 20 | draw = GL_DRAW_FRAMEBUFFER, 21 | read_draw = GL_FRAMEBUFFER, 22 | }; 23 | 24 | static constexpr Bind_Mode read = Bind_Mode::read; 25 | static constexpr Bind_Mode draw = Bind_Mode::draw; 26 | static constexpr Bind_Mode read_draw = Bind_Mode::read_draw; 27 | 28 | enum class Buffer_Type { 29 | renderbuffer, 30 | texture, 31 | }; 32 | 33 | struct Color_Buffer_Info { 34 | Internal_Format internal_format = Internal_Format::rgb8; 35 | Buffer_Type buffer_type = Buffer_Type::texture; 36 | }; 37 | 38 | struct Depth_Buffer_Info { 39 | Internal_Format internal_format = Internal_Format::depth_component24; 40 | Buffer_Type buffer_type = Buffer_Type::renderbuffer; 41 | bool enabled = false; 42 | }; 43 | 44 | struct Stencil_Buffer_Info { 45 | Internal_Format internal_format = Internal_Format::stencil_index8; 46 | Buffer_Type buffer_type = Buffer_Type::renderbuffer; 47 | bool enabled = false; 48 | }; 49 | 50 | struct Construct_Info { 51 | anton::Fixed_Array 52 | color_buffers; 53 | Depth_Buffer_Info depth_buffer; 54 | Stencil_Buffer_Info stencil_buffer; 55 | i32 width = 0; 56 | i32 height = 0; 57 | i32 samples = 0; 58 | bool multisampled = false; 59 | }; 60 | 61 | Framebuffer(Construct_Info const&); 62 | Framebuffer(Framebuffer&&) noexcept; 63 | Framebuffer& operator=(Framebuffer&&) noexcept; 64 | ~Framebuffer(); 65 | 66 | Framebuffer() = delete; 67 | Framebuffer(Framebuffer const&) = delete; 68 | Framebuffer& operator=(Framebuffer const&) = delete; 69 | 70 | void resize(i32 width, i32 height); 71 | Vec2 size() const; 72 | u32 get_color_texture(i32 index) const; 73 | anton::Slice get_color_textures() const; 74 | u32 get_depth_texture() const; 75 | 76 | u32 get_framebuffer_gl_handle() const; 77 | Construct_Info get_construct_info() const; 78 | 79 | private: 80 | void create_framebuffer(); 81 | void delete_framebuffer(); 82 | 83 | Construct_Info info; 84 | anton::Fixed_Array color_buffers; 85 | i32 active_color_buffers = 0; 86 | u32 framebuffer = 0; 87 | u32 depth_buffer = 0; 88 | u32 stencil_buffer = 0; 89 | }; 90 | 91 | void bind_framebuffer(Framebuffer const&, 92 | Framebuffer::Bind_Mode = Framebuffer::read_draw); 93 | void bind_framebuffer(Framebuffer const*, 94 | Framebuffer::Bind_Mode = Framebuffer::read_draw); 95 | void blit_framebuffer(Framebuffer& dest, Framebuffer const& source, 96 | opengl::Buffer_Mask); 97 | void blit_framebuffer(Framebuffer* dest, Framebuffer const* source, 98 | opengl::Buffer_Mask); 99 | 100 | } // namespace anton_engine 101 | 102 | #include 103 | -------------------------------------------------------------------------------- /engine/public/rendering/glad.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | ANTON_DISABLE_WARNINGS() 5 | #include 6 | ANTON_RESTORE_WARNINGS() 7 | -------------------------------------------------------------------------------- /engine/public/rendering/renderer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace anton_engine { 16 | class Camera; 17 | class Line_Component; 18 | class Static_Mesh_Component; 19 | class Transform; 20 | class Mesh; 21 | class Framebuffer; 22 | } // namespace anton_engine 23 | 24 | namespace anton_engine::rendering { 25 | struct Draw_Elements_Command { 26 | u32 count; 27 | u32 instance_count; 28 | u32 first_index; 29 | u32 base_vertex; 30 | u32 base_instance; 31 | }; 32 | 33 | struct Draw_Persistent_Geometry_Command { 34 | u32 handle; 35 | u32 instance_count; 36 | u32 base_instance; 37 | }; 38 | 39 | template 40 | struct Buffer { 41 | T* buffer; 42 | T* head; 43 | i64 size; 44 | }; 45 | 46 | void setup_rendering(); 47 | void bind_persistent_geometry_buffers(); 48 | void bind_transient_geometry_buffers(); 49 | void bind_mesh_vao(); 50 | void bind_buffers(); 51 | void update_dynamic_lights(); 52 | 53 | // Write geometry to gpu buffers. The geometry will eventually be overwritten. 54 | [[nodiscard]] Draw_Elements_Command write_geometry(anton::Slice, 55 | anton::Slice); 56 | 57 | // Write matrices and materials to gpu buffers. Data will eventually be overwritten. 58 | // Returns draw_id offset to be used as base_instance in draw commands. 59 | [[nodiscard]] u32 write_matrices_and_materials(anton::Slice, 60 | anton::Slice); 61 | 62 | // Write geometry that will persist across multiple frames. Geometry will not be overwritten. 63 | // Returns: Handle to the persistent geometry. 64 | [[nodiscard]] u64 write_persistent_geometry(anton::Slice, 65 | anton::Slice); 66 | 67 | // Loads base texture and generates mipmaps (since we don't have pregenerated mipmaps yet). 68 | // pixels is a pointer to an array of pointers to the pixel data. 69 | // handles (out) array of handles to the textures. Must be at least texture_count big. 70 | // handle 71 | void load_textures_generate_mipmaps(Texture_Format, i32 texture_count, 72 | void const* const* pixels, 73 | Texture* handles); 74 | 75 | // handle 76 | // The handle is translated to gl texture handle and then bound. 77 | // Since textures are stored as array textures, textures with same index do not have to 78 | // be bound multiple times. 79 | void bind_texture(u32 unit, Texture handle); 80 | 81 | // TODO: Texture unloading. 82 | // void unload_texture(u64 handle); 83 | // void unload_textures(i32 handle_count, u64 const* handles); 84 | 85 | void add_draw_command(Draw_Elements_Command); 86 | void add_draw_command(Draw_Persistent_Geometry_Command); 87 | void commit_draw(); 88 | 89 | // objects - snapshot of ecs containing Static_Mesh_Components and Transforms 90 | void render_scene(ECS objects, Transform camera_transform, Mat4 view, 91 | Mat4 projection); 92 | 93 | // Render a quad taking up the whole viewport 94 | // Intended for rendering textures to the screen or applying postprocessing effects 95 | // Rebinds element buffer and vertex buffer with binding index 0 96 | void render_texture_quad(); 97 | 98 | // Ugly thing 99 | class Renderer { 100 | public: 101 | Renderer(i32 width, i32 height); 102 | ~Renderer(); 103 | 104 | void resize(i32 width, i32 height); 105 | void render_frame(Mat4 view_mat, Mat4 proj_mat, Transform camera_transform, 106 | Vec2 viewport_size); 107 | void swap_postprocess_buffers(); 108 | 109 | private: 110 | void build_framebuffers(i32 width, i32 height); 111 | void delete_framebuffers(); 112 | 113 | public: 114 | Framebuffer* framebuffer; 115 | Framebuffer* postprocess_front_buffer; 116 | Framebuffer* postprocess_back_buffer; 117 | }; 118 | } // namespace anton_engine::rendering 119 | -------------------------------------------------------------------------------- /engine/public/scripts/camera_movement.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace anton_engine { 10 | class COMPONENT Camera_Movement { 11 | public: 12 | static void update(Camera_Movement&, Camera&, Transform&); 13 | 14 | Vec3 camera_side = Vec3{1.0f, 0.0f, 0.0f}; 15 | }; 16 | } // namespace anton_engine 17 | 18 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Camera_Movement) 19 | -------------------------------------------------------------------------------- /engine/public/scripts/debug_hotkeys.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace anton_engine { 7 | class COMPONENT Debug_Hotkeys { 8 | public: 9 | bool cursor_captured = false; 10 | 11 | static void update(Debug_Hotkeys&); 12 | }; 13 | } // namespace anton_engine 14 | 15 | ANTON_DEFAULT_SERIALIZABLE(anton_engine::Debug_Hotkeys) 16 | -------------------------------------------------------------------------------- /engine/public/shaders/builtin_shaders.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | enum class Builtin_Shader { 7 | uniform_color_3d = 0, 8 | uniform_color_line_3d, 9 | deferred_shading, 10 | skybox, 11 | gamma_correction, 12 | passthrough, 13 | }; 14 | 15 | // TODO: Should be private (most likely) 16 | void load_builtin_shaders(); 17 | void unload_builtin_shaders(); 18 | // TODO: Dev build only(?) 19 | void reload_builtin_shaders(); 20 | 21 | Shader& get_builtin_shader(Builtin_Shader); 22 | } // namespace anton_engine 23 | -------------------------------------------------------------------------------- /engine/public/shaders/shader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace anton_engine { 15 | class Shader { 16 | public: 17 | Shader(bool create = true); 18 | Shader(Shader const&) = delete; 19 | Shader& operator=(Shader const&) = delete; 20 | Shader(Shader&&) noexcept; 21 | Shader& operator=(Shader&&) noexcept; 22 | ~Shader(); 23 | 24 | void attach(Shader_Stage const& shader); 25 | void link(); 26 | void use(); 27 | void detach(Shader_Stage const&); 28 | 29 | void set_int(anton::String_View, i32); 30 | void set_uint(anton::String_View, u32); 31 | void set_float(anton::String_View, f32); 32 | void set_vec2(anton::String_View, Vec2); 33 | void set_vec3(anton::String_View, Vec3); 34 | void set_vec3(anton::String_View, Color); 35 | void set_vec4(anton::String_View, Color); 36 | void set_mat4(anton::String_View, Mat4 const&); 37 | 38 | u32 get_shader_native_handle() const 39 | { 40 | return program; 41 | } 42 | 43 | friend void swap(Shader&, Shader&); 44 | friend void delete_shader(Shader&); 45 | 46 | private: 47 | anton::Flat_Hash_Map uniform_cache; 48 | u32 program = 0; 49 | }; 50 | 51 | template 52 | auto create_shader(Ts const&... shaders) 53 | { 54 | static_assert((... && anton::is_same>), 55 | "Passed arguments are not of Shader_Stage type"); 56 | Shader shader; 57 | (shader.attach(shaders), ...); 58 | shader.link(); 59 | (shader.detach(shaders), ...); 60 | return shader; 61 | } 62 | } // namespace anton_engine 63 | -------------------------------------------------------------------------------- /engine/public/shaders/shader_exceptions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | class Shader_Not_Created: public Exception { 7 | public: 8 | using Exception::Exception; 9 | }; 10 | 11 | class Shader_Compilation_Failed: public Exception { 12 | public: 13 | using Exception::Exception; 14 | }; 15 | 16 | class Program_Not_Created: public Exception { 17 | public: 18 | using Exception::Exception; 19 | }; 20 | 21 | class Program_Linking_Failed: public Exception { 22 | public: 23 | using Exception::Exception; 24 | }; 25 | } // namespace anton_engine 26 | -------------------------------------------------------------------------------- /engine/public/shaders/shader_stage.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class Shader; 9 | 10 | class Shader_Stage { 11 | public: 12 | Shader_Stage() = delete; 13 | Shader_Stage(Shader_Stage const&) = delete; 14 | Shader_Stage& operator=(Shader_Stage const&) = delete; 15 | 16 | Shader_Stage(anton::String_View name, opengl::Shader_Stage_Type type, 17 | anton::String_View source); 18 | Shader_Stage(Shader_Stage&& shader) noexcept; 19 | Shader_Stage& operator=(Shader_Stage&& shader) noexcept; 20 | ~Shader_Stage(); 21 | 22 | private: 23 | friend class Shader; 24 | 25 | opengl::Shader_Stage_Type type; 26 | u32 shader; 27 | }; 28 | } // namespace anton_engine 29 | -------------------------------------------------------------------------------- /gifs/engine_dock_multiviewport.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/engine_dock_multiviewport.gif -------------------------------------------------------------------------------- /gifs/engine_multiviewport.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/engine_multiviewport.gif -------------------------------------------------------------------------------- /gifs/layout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/layout.gif -------------------------------------------------------------------------------- /gifs/multiviewport.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/multiviewport.gif -------------------------------------------------------------------------------- /gifs/new_drag_preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/new_drag_preview.gif -------------------------------------------------------------------------------- /gifs/window_better_tabs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/window_better_tabs.gif -------------------------------------------------------------------------------- /gifs/window_docking.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kociap/GameEngine/2ab711f19205eb8c3ca1309aa86be0873b545cb0/gifs/window_docking.gif -------------------------------------------------------------------------------- /shaders/basicfrag.2.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in Frag_Data { 4 | mat3 tbn; 5 | vec3 fragment_position; 6 | vec3 normal; 7 | vec2 tex_coords; 8 | } fs_in; 9 | 10 | struct Material { 11 | sampler2D texture_diffuse; 12 | sampler2D texture_specular; 13 | sampler2D normal_map; 14 | float shininess; 15 | bool normal_map_attached; 16 | }; 17 | 18 | uniform Material material; 19 | 20 | layout(location = 0) out vec3 gbuf_position; 21 | layout(location = 1) out vec3 gbuf_normal; 22 | layout(location = 2) out vec4 gbuf_albedo_spec; 23 | 24 | vec3 get_surface_normal(sampler2D normal_map, vec2 tex_pos); 25 | vec3 color_to_normal(vec3 c); 26 | 27 | void main() { 28 | // vec3 surface_normal = material.normal_map_attached ? get_surface_normal(material.normal_map, fs_in.tex_coords) : fs_in.normal; 29 | vec3 surface_normal = fs_in.normal; 30 | vec4 tex_color = texture(material.texture_diffuse, fs_in.tex_coords); 31 | vec4 specular_tex_color = texture(material.texture_specular, fs_in.tex_coords); 32 | 33 | gbuf_position = fs_in.fragment_position; 34 | gbuf_normal = surface_normal; 35 | gbuf_albedo_spec = vec4(0.7, 0.7, 0.7, 0.5); 36 | } 37 | 38 | vec3 color_to_normal(vec3 c) { 39 | return c * 2.0 - 1.0; 40 | } 41 | 42 | vec3 get_surface_normal(sampler2D normal_map, vec2 tex_pos) { 43 | vec3 tex_normal = textureLod(normal_map, tex_pos, 0.0).rgb; 44 | vec3 normal = color_to_normal(tex_normal); 45 | return normalize(fs_in.tbn * normal); 46 | } -------------------------------------------------------------------------------- /shaders/basicfrag.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in Frag_Data { 4 | mat3 tbn; 5 | vec3 normal; 6 | vec2 tex_coords; 7 | flat uint draw_id; 8 | } fs_in; 9 | 10 | struct Texture { 11 | uint index; 12 | float layer; 13 | }; 14 | 15 | struct Material { 16 | Texture diffuse; 17 | Texture specular; 18 | Texture normal_map; 19 | float shininess; 20 | }; 21 | 22 | layout(std140, binding = 2) readonly buffer Materials { 23 | Material materials[]; 24 | }; 25 | 26 | layout(binding = 0) uniform sampler2DArray array_textures[16]; 27 | 28 | layout(location = 0) out vec3 gbuf_normal; 29 | layout(location = 1) out vec4 gbuf_albedo_spec; 30 | 31 | vec3 get_surface_normal(sampler2DArray normal_map, vec3 tex_pos); 32 | vec3 color_to_normal(vec3 c); 33 | 34 | void main() { 35 | Material material = materials[fs_in.draw_id]; 36 | vec3 surface_normal = get_surface_normal(array_textures[material.normal_map.index], vec3(fs_in.tex_coords, material.normal_map.layer)); 37 | // vec3 surface_normal = fs_in.normal; 38 | vec4 tex_color = texture(array_textures[material.diffuse.index], vec3(fs_in.tex_coords, material.diffuse.layer)); 39 | vec4 specular_tex_color = texture(array_textures[material.specular.index], vec3(fs_in.tex_coords, material.specular.layer)); 40 | 41 | gbuf_normal = surface_normal; 42 | gbuf_albedo_spec = vec4(tex_color.rgb, specular_tex_color.r); 43 | } 44 | 45 | vec3 color_to_normal(vec3 c) { 46 | return c * 2.0 - 1.0; 47 | } 48 | 49 | vec3 get_surface_normal(sampler2DArray normal_map, vec3 tex_pos) { 50 | vec3 tex_normal = textureLod(normal_map, tex_pos, 0.0).rgb; 51 | vec3 normal = color_to_normal(tex_normal); 52 | return normalize(fs_in.tbn * normal); 53 | } 54 | -------------------------------------------------------------------------------- /shaders/basicvertex.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 in_normal; 5 | layout(location = 2) in vec3 in_tangent; 6 | layout(location = 3) in vec3 in_bitangent; 7 | layout(location = 4) in vec2 tex_coordinates; 8 | layout(location = 5) in uint draw_id; 9 | 10 | uniform mat4 projection; 11 | uniform mat4 view; 12 | 13 | layout (std140, binding = 1) readonly buffer Matrices { 14 | mat4 model_matrices[]; 15 | }; 16 | 17 | out Frag_Data { 18 | mat3 tbn; 19 | vec3 normal; 20 | vec2 tex_coords; 21 | uint draw_id; 22 | } vs_out; 23 | 24 | void main() { 25 | const mat4 model = model_matrices[draw_id]; 26 | const mat3 model_reduced = transpose(inverse(mat3(model))); 27 | const vec3 normal = normalize(model_reduced * in_normal); 28 | const vec3 tangent = normalize(model_reduced * in_tangent); 29 | const vec3 bitangent = normalize(model_reduced * in_bitangent); 30 | 31 | gl_Position = projection * view * model * vec4(pos, 1.0); 32 | vs_out.normal = normal; 33 | vs_out.tex_coords = tex_coordinates; 34 | vs_out.tbn = mat3(tangent, bitangent, normal); 35 | vs_out.draw_id = draw_id; 36 | } 37 | -------------------------------------------------------------------------------- /shaders/deferred_shading.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | struct Point_Light { 4 | vec3 position; 5 | vec4 color; 6 | float intensity; 7 | float attentuation_constant; 8 | float attentuation_linear; 9 | float attentuation_quadratic; 10 | float diffuse_strength; 11 | float specular_strength; 12 | }; 13 | 14 | struct Directional_Light { 15 | vec4 color; 16 | vec3 direction; 17 | float intensity; 18 | float diffuse_strength; 19 | float specular_strength; 20 | }; 21 | 22 | // Move to SSBO (somehow and someday) 23 | layout(std140, binding = 0) uniform Lighting_Data { 24 | vec4 ambient_color; 25 | float ambient_strength; 26 | float todo_remove_shininess; 27 | int point_lights_count; 28 | int directional_lights_count; 29 | Point_Light[16] point_lights; 30 | Directional_Light[16] directional_lights; 31 | }; 32 | 33 | struct Camera { 34 | vec3 position; 35 | }; 36 | 37 | uniform Camera camera; 38 | uniform mat4 inv_view_mat; 39 | uniform mat4 inv_proj_mat; 40 | uniform vec2 viewport_size; 41 | 42 | layout(binding = 0) uniform sampler2D gbuffer_depth; 43 | layout(binding = 1) uniform sampler2D gbuffer_normal; 44 | layout(binding = 2) uniform sampler2D gbuffer_albedo_spec; 45 | 46 | in vec2 tex_coords; 47 | out vec4 frag_color; 48 | 49 | vec3 unproject_point(vec3 coords) { 50 | vec4 normalized = vec4(coords * 2.0 - 1.0, 1.0); 51 | vec4 homogenized = inv_proj_mat * normalized; 52 | if(homogenized.w != 0.0) { 53 | homogenized /= homogenized.w; 54 | } 55 | return (inv_view_mat * homogenized).xyz; 56 | } 57 | 58 | vec3 compute_point_lighting(Point_Light light, vec3 surface_position, vec3 surface_normal, vec3 view_vec, vec3 albedo_color, float specular_factor); 59 | vec3 compute_directional_lighting(Directional_Light light, vec3 surface_normal, vec3 view_vec, vec3 albedo_color, float specular_factor); 60 | 61 | void main() { 62 | vec4 fragment_depth = texture(gbuffer_depth, tex_coords); 63 | // Pass depth through 64 | gl_FragDepth = fragment_depth.r; 65 | 66 | vec4 albedo_spec = texture(gbuffer_albedo_spec, tex_coords); 67 | if(albedo_spec == vec4(0.0)) { 68 | // Light doesn't bounce off pure black surfaces, so we can exit early. 69 | frag_color = vec4(0.0, 0.0, 0.0, 1.0); 70 | return; 71 | } 72 | 73 | vec3 albedo = albedo_spec.rgb; 74 | float specular = albedo_spec.a; 75 | vec3 point_ndc = vec3(tex_coords, fragment_depth.r); 76 | vec3 surface_position = unproject_point(point_ndc); 77 | vec3 surface_normal = texture(gbuffer_normal, tex_coords).rgb; 78 | 79 | vec3 view_vec = normalize(camera.position - surface_position); 80 | vec3 ambient = albedo * vec3(ambient_color) * ambient_strength; 81 | 82 | vec3 light_color = vec3(0); 83 | for(int i = 0; i < point_lights_count; ++i) { 84 | light_color += compute_point_lighting(point_lights[i], surface_position, surface_normal, view_vec, albedo, specular); 85 | } 86 | 87 | for(int i = 0; i < directional_lights_count; ++i) { 88 | light_color += compute_directional_lighting(directional_lights[i], surface_normal, view_vec, albedo, specular); 89 | } 90 | 91 | frag_color = vec4(ambient + light_color, 1.0); 92 | } 93 | 94 | vec3 compute_point_lighting(Point_Light light, vec3 surface_position, vec3 surface_normal, vec3 view_vec, vec3 albedo_color, float specular_factor) { 95 | vec3 light_vec = normalize(light.position - surface_position); 96 | vec3 half_vec = normalize(view_vec + light_vec); 97 | float source_frag_dist = length(light.position - surface_position); 98 | vec3 diffuse = albedo_color * max(dot(surface_normal, light_vec), 0.0); 99 | vec3 specular = vec3(specular_factor * pow(max(dot(surface_normal, half_vec), 0.0), todo_remove_shininess)); 100 | 101 | float attentuation = light.intensity / (light.attentuation_constant + source_frag_dist * light.attentuation_linear + 102 | source_frag_dist * source_frag_dist * light.attentuation_quadratic); 103 | 104 | diffuse *= light.diffuse_strength; 105 | specular *= light.specular_strength; 106 | return attentuation * vec3(light.color) * (diffuse + specular); 107 | } 108 | 109 | vec3 compute_directional_lighting(Directional_Light light, vec3 surface_normal, vec3 view_vec, vec3 albedo_color, float specular_factor) { 110 | vec3 half_vec = normalize(view_vec - light.direction); 111 | vec3 diffuse = albedo_color * max(0.0, dot(surface_normal, -light.direction)); 112 | vec3 specular = vec3(specular_factor * pow(max(0.0, dot(surface_normal, half_vec)), todo_remove_shininess)); 113 | diffuse *= light.diffuse_strength; 114 | specular *= light.specular_strength; 115 | return light.intensity * vec3(light.color) * (diffuse + specular); 116 | } -------------------------------------------------------------------------------- /shaders/editor/gizmo_billboard.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec4 color; 4 | out vec4 frag_color; 5 | 6 | void main() { 7 | frag_color = color; 8 | } -------------------------------------------------------------------------------- /shaders/editor/gizmo_billboard.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 in_position; 4 | layout(location = 1) in mat4 mv_matrix; 5 | layout(location = 5) in vec4 in_color; 6 | 7 | uniform mat4 projection; 8 | 9 | out vec4 color; 10 | 11 | void main() { 12 | color = in_color; 13 | gl_Position = projection * mv_matrix * vec4(in_position, 1.0); 14 | } -------------------------------------------------------------------------------- /shaders/editor/gizmo_line.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec4 color; 4 | out vec4 frag_color; 5 | 6 | void main() { 7 | frag_color = color; 8 | } -------------------------------------------------------------------------------- /shaders/editor/gizmo_line.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 in_position; 4 | layout(location = 1) in vec4 in_color; 5 | 6 | uniform mat4 projection; 7 | uniform mat4 view; 8 | 9 | out vec4 color; 10 | 11 | void main() { 12 | color = in_color; 13 | gl_Position = projection * view * vec4(in_position, 1.0); 14 | } -------------------------------------------------------------------------------- /shaders/editor/grid.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec3 world_pos; 4 | out vec4 frag_color; 5 | 6 | uniform vec3 camera_pos; 7 | uniform vec2 rcp_res; 8 | 9 | uniform vec4 axis_x_color; 10 | uniform vec4 axis_z_color; 11 | uniform vec4 axis_y_color; 12 | uniform uint grid_flags; 13 | #define GRID_AXIS_X 1 14 | #define GRID_AXIS_Y 2 15 | #define GRID_AXIS_Z 4 16 | #define GRID_ENABLED 32 17 | 18 | float log10(float v) { 19 | return log(v) / log(10.0); 20 | } 21 | 22 | float grid_factor(vec2 pos, float grid_size, vec2 grid_fwidth) { 23 | float half_size = grid_size * 0.5; 24 | vec2 grid = abs(mod(pos + half_size, grid_size) - half_size); 25 | grid /= grid_fwidth; 26 | float merged_grid = min(grid.x, grid.y); 27 | return 1.0 - smoothstep(0.0, 1.0, merged_grid); 28 | } 29 | 30 | void main() { 31 | vec4 grid_color = vec4(0.2, 0.2, 0.2, 0.5); 32 | float grid_fade_length = 100.0; 33 | float grid_fade_distance = 100.0; 34 | 35 | float line_width = 4.0; 36 | float line_width_adjusted = line_width * rcp_res.y / gl_FragCoord.w; 37 | float line_half_width = line_width_adjusted / 2.0; 38 | vec2 plane_coord = vec2(world_pos.x, world_pos.z); 39 | 40 | // Fade 41 | 42 | vec3 view_vec = camera_pos - world_pos; 43 | float view_dist = length(view_vec); 44 | vec3 view_vec_normalized = view_vec / view_dist; 45 | float fade = 1 - abs(view_vec_normalized.y); 46 | fade *= fade; 47 | fade = 1 - fade; 48 | fade *= 1.0 - smoothstep(0.0, grid_fade_length, view_dist - grid_fade_distance); 49 | 50 | vec2 grid_fwidth = fwidth(world_pos).xz; 51 | 52 | // Grid 53 | 54 | if((grid_flags & GRID_ENABLED) != 0) { 55 | float camera_height = max(abs(camera_pos.y), 10.0); 56 | float distance_linear = log10(camera_height); 57 | float distance_magnitude = floor(distance_linear); 58 | float distance_diff = distance_magnitude - (distance_linear - 1.0); 59 | 60 | float scale_a = pow(10.0, distance_magnitude - 1); 61 | float scale_b = scale_a * 10.0; 62 | float grid_a = grid_factor(plane_coord, scale_a, grid_fwidth); 63 | float grid_b = grid_factor(plane_coord, scale_b, grid_fwidth); 64 | 65 | frag_color = grid_color; 66 | frag_color.a *= grid_a * max(0.0, min(1.0, distance_diff * 2.0 - 1.0)); 67 | frag_color = mix(frag_color, grid_color, grid_b); 68 | } else { 69 | frag_color = vec4(0.0); 70 | } 71 | 72 | // Axes 73 | 74 | if((grid_flags & GRID_AXIS_X) != 0) { 75 | float alpha = 1.0 - smoothstep(0.0, 1.0, abs(plane_coord.y) / grid_fwidth.y); 76 | frag_color = axis_x_color * alpha + frag_color * (1.0 - alpha); 77 | } 78 | 79 | if((grid_flags & GRID_AXIS_Z) != 0) { 80 | float alpha = 1.0 - smoothstep(0.0, 1.0, abs(plane_coord.x) / grid_fwidth.x); 81 | frag_color = axis_z_color * alpha + frag_color * (1.0 - alpha); 82 | } 83 | 84 | frag_color.a *= fade; 85 | } 86 | -------------------------------------------------------------------------------- /shaders/editor/grid.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 in_position; 4 | 5 | uniform mat4 model_mat; 6 | uniform mat4 vp_mat; 7 | 8 | out vec3 world_pos; 9 | 10 | void main() { 11 | vec4 wp = model_mat * vec4(in_position, 1.0); 12 | world_pos = vec3(wp); 13 | gl_Position = vp_mat * wp; 14 | } 15 | -------------------------------------------------------------------------------- /shaders/editor/imgui.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec4 color; 4 | 5 | uniform bool texture_bound; 6 | layout(binding = 0) uniform sampler2D tex; 7 | 8 | in Frag_Data { 9 | vec4 color; 10 | vec2 uv; 11 | } fs_in; 12 | 13 | out vec4 frag_color; 14 | 15 | void main() { 16 | if(texture_bound) { 17 | frag_color = texture(tex, fs_in.uv); 18 | } else { 19 | frag_color = fs_in.color; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /shaders/editor/imgui.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec2 in_pos; 4 | layout(location = 1) in vec2 in_uv; 5 | layout(location = 2) in vec4 in_color; 6 | 7 | uniform mat4 proj_mat; 8 | 9 | out Frag_Data { 10 | vec4 color; 11 | vec2 uv; 12 | } vs_out; 13 | 14 | out vec4 color; 15 | 16 | void main() { 17 | vs_out.color = in_color; 18 | vs_out.uv = in_uv; 19 | gl_Position = proj_mat * vec4(in_pos, 0, 1); 20 | } 21 | -------------------------------------------------------------------------------- /shaders/editor/outline_mix.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec2 tex_coords; 4 | in vec2 screen_size_rcp; 5 | 6 | layout(binding = 0) uniform sampler2D scene_texture; 7 | layout(binding = 1) uniform sampler2D outline_texture; 8 | 9 | out vec4 frag_color; 10 | 11 | // #define INSET_OUTLINE 12 | 13 | vec4 texture_offset(sampler2D tex, vec2 coords, vec2 offset) { 14 | return texture(tex, coords + offset * screen_size_rcp); 15 | } 16 | 17 | void main() { 18 | vec4 current_frag_color = texture(outline_texture, tex_coords); 19 | vec4 around_color_average = texture_offset(outline_texture, tex_coords, vec2(1, 0)) + 20 | texture_offset(outline_texture, tex_coords, vec2(1, 1)) + 21 | texture_offset(outline_texture, tex_coords, vec2(0, 1)) + 22 | texture_offset(outline_texture, tex_coords, vec2(-1, 1)) + 23 | texture_offset(outline_texture, tex_coords, vec2(-1, 0)) + 24 | texture_offset(outline_texture, tex_coords, vec2(-1, -1)) + 25 | texture_offset(outline_texture, tex_coords, vec2(0, -1)) + 26 | texture_offset(outline_texture, tex_coords, vec2(1, -1)); 27 | around_color_average /= 8.0; 28 | #ifdef INSET_OUTLINE 29 | bool edge_detected = current_frag_color.a > 0 && around_color_average.a < 1; 30 | #else 31 | bool edge_detected = current_frag_color.a == 0 && around_color_average.a != 0; 32 | #endif 33 | if(edge_detected) { 34 | around_color_average /= around_color_average.a; 35 | frag_color = vec4(around_color_average.rgb, 1.0); 36 | } else { 37 | frag_color = texture(scene_texture, tex_coords); 38 | } 39 | } -------------------------------------------------------------------------------- /shaders/normals.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | out vec4 frag_color; 4 | 5 | void main() { 6 | frag_color = vec4(1.0, 1.0, 0.0, 1.0); 7 | } -------------------------------------------------------------------------------- /shaders/normals.geom: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | layout(triangles) in; 3 | layout(line_strip, max_vertices = 6) out; 4 | 5 | in Vert_data { 6 | vec3 normal; 7 | } 8 | vert_data[]; 9 | 10 | uniform float normal_magnitude; 11 | 12 | void generate_line(int index) { 13 | gl_Position = gl_in[index].gl_Position; 14 | EmitVertex(); 15 | gl_Position = gl_in[index].gl_Position + vec4(vert_data[index].normal, 0.0) * normal_magnitude; 16 | EmitVertex(); 17 | EndPrimitive(); 18 | } 19 | 20 | void main() { 21 | generate_line(0); 22 | generate_line(1); 23 | generate_line(2); 24 | } -------------------------------------------------------------------------------- /shaders/normals.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 position; 4 | layout(location = 1) in vec3 normal; 5 | layout(location = 2) in vec2 texture_coordinates; 6 | 7 | out Vert_data { 8 | vec3 normal; 9 | } 10 | vs_out; 11 | 12 | uniform mat4 projection; 13 | uniform mat4 view; 14 | uniform mat4 model; 15 | 16 | void main() { 17 | gl_Position = projection * view * model * vec4(position, 1.0); 18 | vs_out.normal = normalize(vec3(projection * transpose(inverse(view * model)) * vec4(normal, 0.0))); 19 | } -------------------------------------------------------------------------------- /shaders/postprocessing/blur.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec2 texture_coordinates; 4 | 5 | uniform sampler2D scene_texture; 6 | 7 | out vec4 frag_color; 8 | 9 | void main() { 10 | const float offset = 1.0 / 300.0; 11 | 12 | // clang-format off 13 | float kernel[9] = float[]( 14 | 2.0 / 28, 4.0 / 28, 2.0 / 28, 15 | 4.0 / 28, 4.0 / 28, 4.0 / 28, 16 | 2.0 / 28, 4.0 / 28, 2.0 / 28 17 | ); 18 | 19 | vec2 offsets[9] = vec2[]( 20 | vec2(-offset, offset), vec2(0.0, offset), vec2(offset, offset), 21 | vec2(-offset, 0.0), vec2(0.0, 0.0), vec2(offset, 0.0), 22 | vec2(-offset, -offset), vec2(0.0, -offset), vec2(offset, -offset) 23 | ); 24 | // clang-format on 25 | 26 | vec3 color = vec3(0.0); 27 | for (int i = 0; i < 9; ++i) { 28 | color += vec3(texture(scene_texture, texture_coordinates + offsets[i])) * kernel[i]; 29 | } 30 | 31 | frag_color = vec4(color, 1.0); 32 | } -------------------------------------------------------------------------------- /shaders/postprocessing/gamma_correction.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec2 tex_coords; 4 | out vec4 frag_color; 5 | 6 | layout(binding = 0) uniform sampler2D scene_texture; 7 | uniform float gamma; 8 | 9 | void main() { 10 | frag_color.rgb = pow(texture(scene_texture, tex_coords).rgb, vec3(gamma)); 11 | frag_color.a = 1.0; 12 | } 13 | -------------------------------------------------------------------------------- /shaders/postprocessing/postprocess_vertex.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 position; 4 | layout(location = 4) in vec2 tex_coordinates; 5 | 6 | out vec2 tex_coords; 7 | out vec2 screen_size_rcp; 8 | 9 | uniform sampler2D scene_texture; 10 | 11 | void main() { 12 | vec2 tex_size = textureSize(scene_texture, 0).xy; 13 | screen_size_rcp = 1 / tex_size; 14 | tex_coords = tex_coordinates; 15 | gl_Position = vec4(position, 1.0); 16 | } -------------------------------------------------------------------------------- /shaders/quad.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec2 tex_coords; 4 | 5 | layout(binding = 0) uniform sampler2D scene_texture; 6 | 7 | out vec4 frag_color; 8 | 9 | void main() { 10 | frag_color = texture(scene_texture, tex_coords); 11 | } -------------------------------------------------------------------------------- /shaders/quad.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 in_normal; 5 | layout(location = 4) in vec2 tex_coordinates; 6 | 7 | out vec2 tex_coords; 8 | 9 | void main() { 10 | gl_Position = vec4(pos, 1.0); 11 | tex_coords = tex_coordinates; 12 | } 13 | -------------------------------------------------------------------------------- /shaders/shadow_map.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | void main() {} 4 | -------------------------------------------------------------------------------- /shaders/shadow_map.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 in_normal; 5 | layout(location = 2) in vec2 tex_coordinates; 6 | layout(location = 3) in mat4 instance_model; 7 | 8 | uniform mat4 projection; 9 | uniform mat4 view; 10 | 11 | out Frag_data { 12 | vec2 texture_coordinates; 13 | } 14 | fragment_data; 15 | 16 | void main() { 17 | gl_Position = projection * view * instance_model * vec4(pos, 1.0); 18 | fragment_data.texture_coordinates = tex_coordinates; 19 | } 20 | -------------------------------------------------------------------------------- /shaders/skybox.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in vec3 texture_coordinates; 4 | 5 | layout(binding = 0) uniform samplerCube skybox; 6 | 7 | out vec4 frag_color; 8 | 9 | void main() { 10 | frag_color = texture(skybox, texture_coordinates); 11 | } -------------------------------------------------------------------------------- /shaders/skybox.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | 5 | uniform mat4 vp_mat; 6 | 7 | out vec3 texture_coordinates; 8 | 9 | void main() { 10 | gl_Position = (vp_mat * vec4(pos, 1.0)).xyww; 11 | texture_coordinates = pos; 12 | } 13 | -------------------------------------------------------------------------------- /shaders/tangents.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in Frag_Data { 4 | vec3 color; 5 | } frag_data; 6 | 7 | out vec4 frag_color; 8 | 9 | void main() { 10 | frag_color = vec4(frag_data.color, 1.0); 11 | } -------------------------------------------------------------------------------- /shaders/tangents.geom: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | layout(triangles) in; 3 | layout(line_strip, max_vertices = 256) out; 4 | 5 | in VS_Data { 6 | mat3 tbn; 7 | vec3 normal_clip; 8 | vec3 tangent_clip; 9 | vec3 bitangent_clip; 10 | vec3 normal; 11 | vec3 tangent; 12 | vec3 bitangent; 13 | vec2 tex_coords; 14 | } vs_data[]; 15 | 16 | out Frag_Data { 17 | vec3 color; 18 | } frag_data; 19 | 20 | struct Material { 21 | sampler2D texture_diffuse; 22 | sampler2D texture_specular; 23 | sampler2D normal_map; 24 | float shininess; 25 | bool normal_map_attached; 26 | }; 27 | 28 | uniform Material material; 29 | uniform mat4 projection; 30 | uniform mat4 view; 31 | uniform mat4 model; 32 | uniform float line_length = 0.5; 33 | 34 | void emit_line(vec4 pos, vec4 direction, float dir_length, vec3 color) { 35 | gl_Position = pos; 36 | frag_data.color = color; 37 | EmitVertex(); 38 | gl_Position = pos + direction * dir_length; 39 | frag_data.color = color; 40 | EmitVertex(); 41 | EndPrimitive(); 42 | } 43 | 44 | void emit_vert(vec4 pos, vec3 color) { 45 | gl_Position = pos; 46 | gl_PointSize = 15; 47 | frag_data.color = color; 48 | EmitVertex(); 49 | } 50 | 51 | vec3 color_to_normal(vec3 c) { 52 | return c * 2.0 - 1.0; 53 | } 54 | 55 | const int normal_samples = 1; 56 | const int normal_increment = 1; 57 | 58 | void main() { 59 | vec3 normal = normalize(vs_data[0].normal_clip + vs_data[1].normal_clip + vs_data[2].normal_clip); 60 | vec3 tangent = normalize(vs_data[0].tangent_clip + vs_data[1].tangent_clip + vs_data[2].tangent_clip); 61 | vec3 bitangent = normalize(vs_data[0].bitangent_clip + vs_data[1].bitangent_clip + vs_data[2].bitangent_clip); 62 | vec4 mesh_offset = vec4(vs_data[0].normal_clip * 0.05, 0.0); 63 | for(int i = 1; i <= normal_samples * normal_increment; i += normal_increment) { 64 | for(int j = 1; j <= normal_samples * normal_increment; j += normal_increment) { 65 | for(int k = 1; k <= normal_samples * normal_increment; k += normal_increment) { 66 | vec4 triangle_center = (i * gl_in[0].gl_Position + j * gl_in[1].gl_Position + k * gl_in[2].gl_Position) / (i + j + k); 67 | vec2 tex_coords = (i * vs_data[0].tex_coords + j * vs_data[1].tex_coords + k * vs_data[2].tex_coords) / (i + j + k); 68 | 69 | vec3 tex_normal_sampled = texture(material.normal_map, tex_coords).rgb; 70 | vec3 tex_normal = color_to_normal(tex_normal_sampled); 71 | 72 | // vec4 tbned_normal = vec4(normalize(vs_data[0].tbn * tex_normal + vs_data[1].tbn * tex_normal + vs_data[2].tbn * tex_normal), 0.0); 73 | vec4 tbned_normal = vec4(normalize(vs_data[0].tbn * tex_normal), 0.0); 74 | vec3 color = vec3(abs(tbned_normal.x), abs(tbned_normal.y), abs(tbned_normal.z)); 75 | // color = tex_normal; 76 | 77 | emit_line(triangle_center + mesh_offset, normalize(projection * view * tbned_normal), line_length, color); 78 | } 79 | } 80 | } 81 | // emit_line(triangle_center + mesh_offset, vec4(normal, 0.0), line_length, vec3(0, 0.35, 1)); 82 | // emit_line(triangle_center + mesh_offset, vec4(tangent, 0.0), line_length, vec3(1, 0, 0)); 83 | // emit_line(triangle_center + mesh_offset, vec4(bitangent, 0.0), line_length, vec3(0, 1, 0)); 84 | } -------------------------------------------------------------------------------- /shaders/tangents.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 in_normal; 5 | layout(location = 2) in vec3 in_tangent; 6 | layout(location = 3) in vec3 in_bitangent; 7 | layout(location = 4) in vec2 tex_coordinates; 8 | 9 | uniform mat4 projection; 10 | uniform mat4 view; 11 | uniform mat4 model; 12 | 13 | out VS_Data { 14 | mat3 tbn; 15 | vec3 normal_clip; 16 | vec3 tangent_clip; 17 | vec3 bitangent_clip; 18 | vec3 normal; 19 | vec3 tangent; 20 | vec3 bitangent; 21 | vec2 tex_coords; 22 | } vs_data; 23 | 24 | void main() { 25 | mat4 vp_mat = projection * view; 26 | mat4 mvp_mat = vp_mat * model; 27 | mat3 model_reduced = mat3(model); 28 | mat3 model_normal_mat = transpose(inverse(model_reduced)); 29 | vec3 normal = normalize(model_normal_mat * in_normal); 30 | vec3 tangent = normalize(model_reduced * in_tangent); 31 | vec3 bitangent = normalize(model_reduced * in_bitangent); 32 | mat3 tbn = mat3(tangent, bitangent, normal); 33 | 34 | gl_Position = mvp_mat * vec4(pos, 1.0); 35 | vs_data.normal = in_normal; 36 | vs_data.tangent = in_tangent; 37 | vs_data.bitangent = in_bitangent; 38 | vs_data.normal_clip = normalize(vec3(vp_mat * vec4(normal, 0.0))); 39 | vs_data.tangent_clip = normalize(vec3(vp_mat * vec4(tangent, 0.0))); 40 | vs_data.bitangent_clip = normalize(vec3(vp_mat * vec4(bitangent, 0.0))); 41 | // vs_data.bitangent_clip = normalize(vec3(vp_mat * vec4(cross(normal, tangent), 0.0))); 42 | vs_data.tbn = tbn; 43 | vs_data.tex_coords = tex_coordinates; 44 | } 45 | -------------------------------------------------------------------------------- /shaders/uniform_color.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | uniform vec4 color; 4 | 5 | out vec4 frag_color; 6 | 7 | void main() { 8 | frag_color = color; 9 | } 10 | -------------------------------------------------------------------------------- /shaders/uniform_color.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | 5 | uniform mat4 mvp_mat; 6 | 7 | void main() { 8 | gl_Position = mvp_mat * vec4(pos, 1.0); 9 | } 10 | -------------------------------------------------------------------------------- /shaders/uniform_color_line.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 rotation_axis; 5 | layout(location = 2) in float scale_factor; 6 | 7 | uniform mat4 model_mat; 8 | uniform mat4 vp_mat; 9 | uniform vec3 camera_pos; 10 | uniform float line_width; 11 | 12 | void main() { 13 | mat3 model_inv = inverse(transpose(mat3(model_mat))); 14 | vec3 axis_world = normalize(model_inv * rotation_axis); 15 | vec3 pos_world = vec3(model_mat * vec4(pos, 1)); 16 | vec3 projected_camera = camera_pos - axis_world * dot(axis_world, camera_pos - pos_world); 17 | 18 | vec3 view_vec_projected = projected_camera - pos_world; 19 | float len = length(view_vec_projected); 20 | if(len > 0.00001) { 21 | vec3 normalized_view = view_vec_projected / len; 22 | float expand_dir = (gl_VertexID & 1) == 1 ? -1 : 1; 23 | gl_Position = vp_mat * vec4(pos_world + scale_factor * line_width * expand_dir * cross(normalized_view, axis_world), 1); 24 | } else { 25 | gl_Position = vp_mat * vec4(pos_world, 1); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /shaders/unlit_default.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | in Frag_Data { 4 | vec3 fragment_position; 5 | vec3 normal; 6 | vec2 texture_coordinates; 7 | } 8 | fragment_data; 9 | 10 | struct Material { 11 | sampler2D texture_diffuse0; 12 | sampler2D texture_diffuse1; 13 | sampler2D texture_diffuse2; 14 | sampler2D texture_diffuse3; 15 | sampler2D texture_specular0; 16 | sampler2D texture_specular1; 17 | sampler2D texture_specular2; 18 | sampler2D texture_specular3; 19 | }; 20 | 21 | struct Camera { 22 | vec3 position; 23 | }; 24 | 25 | uniform Material material; 26 | uniform Camera camera; 27 | 28 | out vec4 frag_color; 29 | 30 | void main() { 31 | frag_color = texture(material.texture_diffuse0, fragment_data.texture_coordinates); 32 | } 33 | -------------------------------------------------------------------------------- /shaders/unlit_default.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 pos; 4 | layout(location = 1) in vec3 in_normal; 5 | layout(location = 4) in vec2 tex_coordinates; 6 | 7 | uniform mat4 projection; 8 | uniform mat4 view; 9 | uniform mat4 model; 10 | 11 | out Frag_Data { 12 | vec3 fragment_position; 13 | vec3 normal; 14 | vec2 texture_coordinates; 15 | } 16 | fragment_data; 17 | 18 | void main() { 19 | gl_Position = projection * view * model * vec4(pos, 1.0); 20 | fragment_data.fragment_position = vec3(model * vec4(pos, 1.0)); 21 | fragment_data.normal = normalize(vec3(transpose(inverse(model)) * vec4(in_normal, 0.0))); 22 | fragment_data.texture_coordinates = tex_coordinates; 23 | } 24 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(Codegen CXX) 4 | 5 | add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/codegen/component_serialization_generator.cpp") 6 | set_target_properties(${PROJECT_NAME} 7 | PROPERTIES 8 | FOLDER ${ENGINE_TOOLS_FOLDER} 9 | ) 10 | 11 | target_compile_options(Codegen PRIVATE ${ANTON_COMPILE_FLAGS}) 12 | 13 | add_subdirectory(codegen/private) 14 | add_subdirectory(codegen/public) 15 | 16 | target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../source/public") 17 | target_sources(${PROJECT_NAME} 18 | PRIVATE ${SOURCE_FILES} 19 | PRIVATE ${HEADER_FILES} 20 | ) 21 | 22 | target_link_libraries(Codegen 23 | anton_engine 24 | ) 25 | 26 | target_compile_definitions(Codegen 27 | PRIVATE 28 | ENGINE_API=${ENGINE_DLL_IMPORT} 29 | ANTON_WITH_EDITOR=${ENGINE_WITH_EDITOR} 30 | # Use unicode instead of multibyte charset (VS) 31 | UNICODE 32 | _UNICODE 33 | ) 34 | 35 | if(ENGINE_COMPILER_CLANG) 36 | target_compile_definitions(Codegen PRIVATE ANTON_COMPILER_CLANG) 37 | endif() 38 | 39 | if(ENGINE_COMPILER_GCC) 40 | target_compile_definitions(Codegen PRIVATE ANTON_COMPILER_GCC) 41 | endif() 42 | 43 | if(ENGINE_COMPILER_MSVC) 44 | target_compile_definitions(Codegen PRIVATE ANTON_COMPILER_MSVC) 45 | endif() 46 | 47 | if(ENGINE_COMPILER_UNKNOWN) 48 | target_compile_definitions(Codegen PRIVATE ANTON_COMPILER_UNKNOWN) 49 | endif() 50 | 51 | set_target_properties(Codegen 52 | PROPERTIES 53 | RUNTIME_OUTPUT_DIRECTORY "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 54 | RUNTIME_OUTPUT_DIRECTORY_DEBUG "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 55 | RUNTIME_OUTPUT_DIRECTORY_RELEASE "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 56 | ARCHIVE_OUTPUT_DIRECTORY "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 57 | ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 58 | ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 59 | LIBRARY_OUTPUT_DIRECTORY "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 60 | LIBRARY_OUTPUT_DIRECTORY_DEBUG "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 61 | LIBRARY_OUTPUT_DIRECTORY_RELEASE "${ENGINE_BINARY_OUTPUT_DIRECTORY}" 62 | ) 63 | -------------------------------------------------------------------------------- /tools/codegen/component_serialization_generator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std::string_view_literals; 10 | 11 | namespace anton_engine { 12 | struct Component { 13 | std::string include_directory; 14 | std::string name; 15 | }; 16 | 17 | static std::string_view extract_include_directory(std::string_view path) 18 | { 19 | // TODO extend to allow user-defined components in project directory 20 | if(auto pos = path.find("public/"); pos != std::string_view::npos) { 21 | path.remove_prefix(pos + "public/"sv.size()); 22 | } else if(auto pos = path.find("private/"); pos != std::string_view::npos) { 23 | path.remove_prefix(pos + "private/"sv.size()); 24 | } else if(auto pos = path.find("scripts/"); 25 | pos != 26 | std::string_view:: 27 | npos) { // TODO remove this branch, temporary script location 28 | path.remove_prefix(pos + "scripts/"sv.size()); 29 | } 30 | return path; 31 | } 32 | 33 | static void serach_for_components(std::string_view directory, 34 | anton::Array& out) 35 | { 36 | std::filesystem::recursive_directory_iterator dir_iterator(directory); 37 | std::filesystem::path header_extension(".hpp"); 38 | for(auto entry: dir_iterator) { 39 | if(auto current_path = entry.path(); 40 | entry.is_regular_file() && 41 | current_path.extension() == header_extension) { 42 | File header(current_path); 43 | auto classes_found = parse_component_header(header); 44 | for(auto& name: classes_found) { 45 | std::string str = 46 | current_path 47 | .generic_string(); // Because windows uses retarded wstring and \ as the directory separator 48 | std::string_view include_dir = extract_include_directory(str); 49 | out.push_back( 50 | Component{std::string(include_dir.data(), include_dir.size()), 51 | ANTON_MOV(name)}); 52 | } 53 | } 54 | } 55 | } 56 | 57 | struct Indent { 58 | u32 indent_level; 59 | }; 60 | 61 | std::ostream& operator<<(std::ostream& out, Indent i) 62 | { 63 | while(i.indent_level > 0) { 64 | out << u8" "; 65 | i.indent_level -= 1; 66 | } 67 | return out; 68 | } 69 | 70 | Indent indent(u32 indent_level) 71 | { 72 | return {indent_level}; 73 | } 74 | } // namespace anton_engine 75 | 76 | // argv[1] is the path to the output file 77 | // argv[2], argv[3]... are the search locations 78 | int main(int argc, char** argv) 79 | { 80 | using namespace anton_engine; 81 | 82 | if(argc < 3) { 83 | throw std::runtime_error("Too few parameters"); 84 | } 85 | 86 | std::ios_base::sync_with_stdio(false); 87 | 88 | std::string_view output_file(argv[1]); 89 | 90 | anton::Array components; 91 | for(i32 i = 2; i < argc; ++i) { 92 | std::string_view components_search_directory(argv[i]); 93 | serach_for_components(components_search_directory, components); 94 | } 95 | 96 | std::ofstream generated_file(output_file.data()); 97 | generated_file << "#include \n#include " 98 | "\n\n"; 99 | for(auto& [include_directory, name]: components) { 100 | generated_file << "#include <" << include_directory << ">\n"; 101 | } 102 | generated_file << '\n' 103 | << "namespace anton_engine {\n" 104 | << indent(1) 105 | << "anton::Array& " 106 | "get_component_serialization_functions() {\n" 107 | << indent(2) 108 | << "static anton::Array " 109 | "serialization_funcs{anton::variadic_construct,\n"; 110 | i32 component_index = 1; 111 | for(auto& [include_directory, name]: components) { 112 | generated_file << indent(3) 113 | << "Component_Serialization_Funcs{Type_Family::family_id<" 114 | << name << ">(), &Component_Container<" << name 115 | << ">::serialize, &Component_Container<" << name 116 | << ">::deserialize}"; 117 | if(component_index < components.size()) { 118 | generated_file << ",\n"; 119 | } else { 120 | generated_file << "};\n"; 121 | } 122 | ++component_index; 123 | } 124 | generated_file << indent(2) << "return serialization_funcs;\n" 125 | << indent(1) << "}\n" 126 | << "} // namespace anton_engine\n"; 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /tools/codegen/private/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_FILES ${SOURCE_FILES} 2 | "${CMAKE_CURRENT_SOURCE_DIR}/component_header_parser.cpp" 3 | "${CMAKE_CURRENT_SOURCE_DIR}/file.cpp" 4 | PARENT_SCOPE 5 | ) -------------------------------------------------------------------------------- /tools/codegen/private/component_header_parser.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // identifier -> identifier identifier_allowed_character | non_number 6 | // opt_attributes -> opt_attributes identifier | identifier 7 | // class_declaration -> class opt_attributes identifier : access_specifier identifier { class_body }; 8 | namespace anton_engine { 9 | static bool is_whitespace(char c) 10 | { 11 | return c == '\n' || c == '\t' || c == ' '; 12 | } 13 | 14 | static bool is_digit(char c) 15 | { 16 | return c >= 48 && c < 58; 17 | } 18 | 19 | static bool is_alpha(char c) 20 | { 21 | return (c >= 97 && c < 123) || (c >= 65 && c < 91); 22 | } 23 | 24 | static bool is_allowed_identifier_character(char c) 25 | { 26 | return c == '_' || is_digit(c) || is_alpha(c); 27 | } 28 | 29 | enum class Token { 30 | keyword_class, 31 | identifier, 32 | opening_brace, 33 | macro_component, 34 | }; 35 | 36 | struct Word { 37 | std::string string; 38 | Token token; 39 | }; 40 | 41 | class Lexer { 42 | public: 43 | std::unordered_map tokens; 44 | 45 | Lexer(); 46 | 47 | anton::Array parse(File&); 48 | 49 | private: 50 | std::tuple scan(File::iterator begin, 51 | File::iterator end); 52 | }; 53 | 54 | Lexer::Lexer() 55 | : tokens{{"class", Token::keyword_class}, 56 | {"{", Token::opening_brace}, 57 | {"COMPONENT", Token::macro_component}} 58 | { 59 | } 60 | 61 | anton::Array Lexer::parse(File& file) 62 | { 63 | anton::Array tokens_vec; 64 | for(File::iterator current = file.begin(), end = file.end(); 65 | current != end;) { 66 | auto [new_iter, token_type, string] = scan(current, end); 67 | current = new_iter; 68 | tokens_vec.emplace_back(string, token_type); 69 | } 70 | return tokens_vec; 71 | } 72 | 73 | std::tuple 74 | Lexer::scan(File::iterator begin, File::iterator const end) 75 | { 76 | char current = *begin; 77 | while(begin != end && is_whitespace(current)) { 78 | current = *(++begin); 79 | } 80 | 81 | File::iterator copy = begin + 1; 82 | if(begin != end && is_allowed_identifier_character(*begin)) { 83 | while(copy != end && is_allowed_identifier_character(*copy)) { 84 | ++copy; 85 | } 86 | } 87 | 88 | std::string identifier(begin, copy); 89 | auto tokens_iter = tokens.find(identifier); 90 | if(tokens_iter != tokens.end()) { 91 | return {copy, tokens_iter->second, tokens_iter->first}; 92 | } else { 93 | tokens.emplace(identifier, Token::identifier); 94 | return {copy, Token::identifier, identifier}; 95 | } 96 | } 97 | 98 | anton::Array parse_component_header(File& file) 99 | { 100 | anton::Array class_names; 101 | Lexer lexer; 102 | auto tokens = lexer.parse(file); 103 | for(i64 i = 0; i + 2 < tokens.size(); ++i) { 104 | if(tokens[i].token == Token::keyword_class) { 105 | if(tokens[i + 1].token == Token::macro_component && 106 | tokens[i + 2].token == Token::identifier) { 107 | class_names.push_back(tokens[i + 2].string); 108 | } 109 | i += 2; 110 | } 111 | } 112 | return class_names; 113 | } 114 | } // namespace anton_engine 115 | -------------------------------------------------------------------------------- /tools/codegen/private/file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace anton_engine { 6 | File::File() {} 7 | 8 | File::File(std::string_view filename) 9 | { 10 | read_file(filename); 11 | } 12 | 13 | File::File(std::filesystem::path filename) 14 | { 15 | read_file(filename); 16 | } 17 | 18 | void File::read_file(std::string_view filename) 19 | { 20 | std::ifstream f(filename.data()); 21 | f.seekg(std::ios::end); 22 | u64 file_size = f.tellg(); 23 | f.seekg(std::ios::beg); 24 | contents.resize(file_size); 25 | f.read(contents.data(), file_size); 26 | } 27 | 28 | void File::read_file(std::filesystem::path filename) 29 | { 30 | std::ifstream f(filename); 31 | f.seekg(0, std::ios::end); 32 | u64 file_size = f.tellg(); 33 | f.seekg(0, std::ios::beg); 34 | contents.resize(file_size); 35 | f.read(contents.data(), file_size); 36 | } 37 | 38 | void File::write_file(std::string_view filename) 39 | { 40 | std::ofstream f(filename.data()); 41 | f.write(contents.data(), contents.size()); 42 | } 43 | 44 | File::iterator File::begin() 45 | { 46 | return contents.begin(); 47 | } 48 | 49 | File::iterator File::end() 50 | { 51 | return contents.end(); 52 | } 53 | } // namespace anton_engine 54 | -------------------------------------------------------------------------------- /tools/codegen/public/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(HEADER_FILES ${HEADER_FILES} 2 | "${CMAKE_CURRENT_SOURCE_DIR}/component_header_parser.hpp" 3 | "${CMAKE_CURRENT_SOURCE_DIR}/file.hpp" 4 | PARENT_SCOPE 5 | ) 6 | 7 | target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") -------------------------------------------------------------------------------- /tools/codegen/public/component_header_parser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | anton::Array parse_component_header(File& file); 9 | } 10 | -------------------------------------------------------------------------------- /tools/codegen/public/file.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace anton_engine { 8 | class File { 9 | public: 10 | using iterator = anton::Array::iterator; 11 | 12 | File(); 13 | File(std::string_view filename); 14 | File(std::filesystem::path filename); 15 | 16 | void read_file(std::string_view filename); 17 | void read_file(std::filesystem::path filename); 18 | void write_file(std::string_view filename); 19 | 20 | iterator begin(); 21 | iterator end(); 22 | 23 | private: 24 | anton::Array contents; 25 | }; 26 | } // namespace anton_engine 27 | --------------------------------------------------------------------------------