From 2293033596e5fb7efa26a6696dfb3d684eefee82 Mon Sep 17 00:00:00 2001 From: WillisMedwell Date: Tue, 23 Jan 2024 16:41:49 +1100 Subject: [PATCH] Added Models::Static and its decoding --- code/.clang-tidy | 2 +- code/CmakePresets.json | 80 +++++++++ code/Demos/CMakeLists.txt | 11 +- code/Demos/src/Main.cpp | 38 ++-- code/Engine/CMakeLists.txt | 16 +- code/Engine/include/AppAnalyitics.hpp | 4 - code/Engine/include/AppAnalytics.hpp | 90 ++++++++++ code/Engine/include/Models/Animated.hpp | 1 + code/Engine/include/Models/Dynamic.hpp | 1 + code/Engine/include/Models/Models.hpp | 4 +- code/Engine/include/Models/Staging.hpp | 33 ---- code/Engine/include/Models/Static.hpp | 32 ++-- code/Engine/include/Models/Types.hpp | 25 +++ code/Engine/src/Models/Staging.cpp | 145 --------------- code/Engine/src/Models/Static.cpp | 224 ++++++++++++++++++++++++ code/Test/CMakeLists.txt | 9 +- code/Test/src/Integration/BasicApps.cpp | 1 + code/build-web.bat | 7 +- code/vcpkg.json | 9 +- 19 files changed, 485 insertions(+), 247 deletions(-) create mode 100644 code/CmakePresets.json delete mode 100644 code/Engine/include/AppAnalyitics.hpp create mode 100644 code/Engine/include/AppAnalytics.hpp create mode 100644 code/Engine/include/Models/Animated.hpp create mode 100644 code/Engine/include/Models/Dynamic.hpp delete mode 100644 code/Engine/include/Models/Staging.hpp create mode 100644 code/Engine/include/Models/Types.hpp delete mode 100644 code/Engine/src/Models/Staging.cpp create mode 100644 code/Engine/src/Models/Static.cpp diff --git a/code/.clang-tidy b/code/.clang-tidy index 4b3f774..a466cd5 100644 --- a/code/.clang-tidy +++ b/code/.clang-tidy @@ -9,7 +9,7 @@ Checks: > Checks: '-*,readability-identifier-naming' CheckOptions: - { key: readability-identifier-naming.VariableCase, value: lower_case } - - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.FunctionCase, value: lower_case } - { key: readability-identifier-naming.StructCase, value: CamelCase } - { key: readability-identifier-naming.ClassCase, value: CamelCase } - { key: readability-identifier-naming.MethodCase, value: lower_case } diff --git a/code/CmakePresets.json b/code/CmakePresets.json new file mode 100644 index 0000000..ccff7f6 --- /dev/null +++ b/code/CmakePresets.json @@ -0,0 +1,80 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 11, + "patch": 0 + }, + "configurePresets": [ + { + "name": "gcc-ninja-release", + "description": "Build with GCC and Ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/gcc-ninja-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + }, + "environment": { + "CC": "gcc", + "CXX": "g++" + } + }, + { + "name": "clang-ninja-release", + "description": "Build with Clang and Ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/clang-ninja-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + }, + "environment": { + "CC": "clang", + "CXX": "clang++" + } + }, + { + "name": "emscripten-ninja-release", + "description": "Build with Emscripten SDK", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/emscripten-ninja-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + }, + "environment": { + "CC": "emcc", + "CXX": "em++" + } + }, + { + "name": "emscripten-ninja-debug", + "description": "Build with Emscripten SDK", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/emscripten-ninja-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + }, + "environment": { + "CC": "emcc", + "CXX": "em++" + } + } + ], + "buildPresets": [ + { + "name": "gcc-ninja-release", + "configurePreset": "gcc-ninja-release" + }, + { + "name": "clang-ninja-release", + "configurePreset": "clang-ninja" + }, + { + "name": "emscripten-ninja-release", + "configurePreset": "emscripten-ninja" + }, + { + "name": "emscripten-ninja-debug", + "configurePreset": "emscripten-ninja" + } + ] +} \ No newline at end of file diff --git a/code/Demos/CMakeLists.txt b/code/Demos/CMakeLists.txt index a16bce1..f0e5e84 100644 --- a/code/Demos/CMakeLists.txt +++ b/code/Demos/CMakeLists.txt @@ -8,15 +8,8 @@ file(COPY ${CMAKE_SOURCE_DIR}/.clang-tidy DESTINATION ${CMAKE_CURRENT_BINARY_DIR add_executable(Demos ${DEMOS_SOURCES} ${DEMOS_HEADERS}) -if(DEFINED EMSCRIPTEN) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument") - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g -s DEMANGLE_SUPPORT=1 -s FORCE_FILESYSTEM=1 -s ASSERTIONS=1 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=2 -s NO_DISABLE_EXCEPTION_CATCHING") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -Os") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_WEBGL2=1 -s MAX_WEBGL_VERSION=3 -s USE_GLFW=3 -s FULL_ES3=1 -s FULL_ES2=1") +if(DEFINED EMSCRIPTEN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='_main' -s EXPORT_NAME=\"'WasmModuleDemos'\"") - # Move index.html. file(COPY ${CMAKE_SOURCE_DIR}/index.html DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) @@ -30,8 +23,10 @@ if(DEFINED EMSCRIPTEN) endforeach() message(STATUS "PRELOAD FILES: \"${PRELOAD_FILES}\"") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PRELOAD_FILES}") + target_compile_options(Demos PRIVATE -msimd128 -mrelaxed-simd -msse -msse2 -mavx) else() file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + target_compile_options(Demos PRIVATE -march=native) endif() target_link_libraries(Demos PUBLIC Engine) diff --git a/code/Demos/src/Main.cpp b/code/Demos/src/Main.cpp index 5eff8f7..1cd9308 100644 --- a/code/Demos/src/Main.cpp +++ b/code/Demos/src/Main.cpp @@ -1,6 +1,6 @@ #include "App.hpp" #include "Config.hpp" -#include "Models/Staging.hpp" +#include "Models/Models.hpp" #include #include @@ -9,24 +9,24 @@ #include -auto print_then_quit = [](auto& error) { - std::cerr - << error.what() - << std::endl; - exit(1); -}; - -auto print_num_faces = [](Models::Staging::Model& model) { - std::println("Triangle Count: {}", model.index_data.size() / 3); -}; - -void timeLoadModel(const std::string& file_path) { - auto start = std::chrono::high_resolution_clock::now(); - Models::Staging::loadModel(file_path).on_error(print_then_quit).on_value(print_num_faces); - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration duration = end - start; - std::cout << "Loading " << file_path << " took " << duration.count() << " milliseconds." << std::endl; -} +// auto print_then_quit = [](auto& error) { +// std::cerr +// << error.what() +// << std::endl; +// exit(1); +// }; + +// auto print_num_faces = [](Model::Staging::Model& model) { +// std::println("Triangle Count: {}", model.index_data.size() / 3); +// }; + +// void timeLoadModel(const std::string& file_path) { +// auto start = std::chrono::high_resolution_clock::now(); +// Models::Staging::loadModel(file_path).on_error(print_then_quit).on_value(print_num_faces); +// auto end = std::chrono::high_resolution_clock::now(); +// std::chrono::duration duration = end - start; +// std::cout << "Loading " << file_path << " took " << duration.count() << " milliseconds." << std::endl; +// } struct Data { Cameras::StationaryPerspective camera { diff --git a/code/Engine/CMakeLists.txt b/code/Engine/CMakeLists.txt index 84193a1..fb1e720 100644 --- a/code/Engine/CMakeLists.txt +++ b/code/Engine/CMakeLists.txt @@ -27,22 +27,28 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(Utily) +if(NOT MSVC) + target_compile_options(Engine PRIVATE -fexperimental-library -Wall -Wextra -Wpedantic) +endif() + if(DEFINED EMSCRIPTEN) target_link_libraries(Engine PUBLIC glm::glm assimp::assimp EnTT::EnTT Utily::Utily lodepng ${BULLET_LIBRARIES} ) target_include_directories(Engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${Stb_INCLUDE_DIR}) + target_compile_options(Engine PUBLIC + "$<$:-O0;-g;-sDEMANGLE_SUPPORT=1;-sFORCE_FILESYSTEM=1;-sASSERTIONS=1;-sSAFE_HEAP=1;-sSTACK_OVERFLOW_CHECK=2;-sNO_DISABLE_EXCEPTION_CATCHING;-Wno-unused-command-line-argument>" + "$<$:-Oz;-sGL_FFP_ONLY;-msimd128;-Wno-unused-command-line-argument>" + ) + target_link_options(Engine PUBLIC -sUSE_WEBGL2=1 -sUSE_GLFW=3 -sFULL_ES3=1 -sFULL_ES2=1 -Wno-unused-command-line-argument) else() find_package(OpenGL REQUIRED) + find_package(OpenAL CONFIG REQUIRED) find_package(GLFW3 CONFIG REQUIRED) find_package(GLEW REQUIRED) target_link_libraries(Engine PUBLIC glm::glm assimp::assimp EnTT::EnTT Utily::Utily lodepng ${BULLET_LIBRARIES} - OpenGL::GL GLEW::GLEW glfw + OpenGL::GL OpenAL::OpenAL GLEW::GLEW glfw ) target_include_directories(Engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${OPENGL_INCLUDE_DIR} ${Stb_INCLUDE_DIR}) endif() - -if(NOT MSVC) - target_compile_options(Engine PRIVATE -fexperimental-library -Wall -Wextra -Wpedantic) -endif() \ No newline at end of file diff --git a/code/Engine/include/AppAnalyitics.hpp b/code/Engine/include/AppAnalyitics.hpp deleted file mode 100644 index 6c11185..0000000 --- a/code/Engine/include/AppAnalyitics.hpp +++ /dev/null @@ -1,4 +0,0 @@ - -class AppAnalytics { - -}; \ No newline at end of file diff --git a/code/Engine/include/AppAnalytics.hpp b/code/Engine/include/AppAnalytics.hpp new file mode 100644 index 0000000..5efa2b1 --- /dev/null +++ b/code/Engine/include/AppAnalytics.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include + +#include + +#include "Config.hpp" + +class AppAnalytics +{ +public: + std::string gpu_info; + + auto get_gpu_info() { + std::ostringstream info_stream; + + // Basic GPU Information + const GLubyte* vendor = glGetString(GL_VENDOR); + const GLubyte* renderer = glGetString(GL_RENDERER); + const GLubyte* version = glGetString(GL_VERSION); + info_stream << "Vendor: " << vendor << "\n" + << "Renderer: " << renderer << "\n" + << "OpenGL Version: " << version << "\n"; + + // Additional GPU Capabilities + GLint value; + + // Max Texture Size + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); + info_stream << "Max Texture Size: " << value << "\n"; + + // Max Number of Texture Image Units + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &value); + info_stream << "Max Texture Image Units: " << value << "\n"; + + // Max Cube Map Texture Size + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &value); + info_stream << "Max Cube Map Texture Size: " << value << "\n"; + + // Max Renderbuffer Size + glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &value); + info_stream << "Max Renderbuffer Size: " << value << "\n"; + + // Max Viewport Dimensions + GLint maxViewportDims[2]; + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDims); + info_stream << "Max Viewport Dimensions: " << maxViewportDims[0] << " x " << maxViewportDims[1] << "\n"; + + // Max Anisotropy + GLfloat maxAniso = 0.0f; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + info_stream << "Max Texture Anisotropy: " << maxAniso << "\n"; + + // Max Samples in Multisample + glGetIntegerv(GL_MAX_SAMPLES, &value); + info_stream << "Max Samples in Multisample: " << value << "\n"; + + // Max Color Attachments + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &value); + info_stream << "Max Color Attachments: " << value << "\n"; + + // Max Draw Buffers + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &value); + info_stream << "Max Draw Buffers: " << value << "\n"; + + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value); + info_stream << "Max Vertex Attributes: " << value << "\n"; + + glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &value); + info_stream << "Max Vertex Uniform Components: " << value << "\n"; + + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &value); + info_stream << "Max Fragment Uniform Components: " << value << "\n"; + + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &value); + info_stream << "Max Vertex Texture Image Units: " << value << "\n"; + + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &value); + info_stream << "Max Combined Texture Image Units: " << value << "\n"; + + // Fragment Processing + glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &value); + info_stream << "Max Fragment Input Components: " << value << "\n"; + + glGetIntegerv(GL_MAX_TEXTURE_LOD_BIAS, &value); + info_stream << "Max Texture LOD Bias: " << value << "\n"; + + gpu_info = info_stream.str(); + } +}; \ No newline at end of file diff --git a/code/Engine/include/Models/Animated.hpp b/code/Engine/include/Models/Animated.hpp new file mode 100644 index 0000000..7b9637e --- /dev/null +++ b/code/Engine/include/Models/Animated.hpp @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/code/Engine/include/Models/Dynamic.hpp b/code/Engine/include/Models/Dynamic.hpp new file mode 100644 index 0000000..7b9637e --- /dev/null +++ b/code/Engine/include/Models/Dynamic.hpp @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/code/Engine/include/Models/Models.hpp b/code/Engine/include/Models/Models.hpp index c5e6be8..693e36b 100644 --- a/code/Engine/include/Models/Models.hpp +++ b/code/Engine/include/Models/Models.hpp @@ -1,4 +1,6 @@ #pragma once -#include "Models/Staging.hpp" +#include "Models/Types.hpp" #include "Models/Static.hpp" +#include "Models/Animated.hpp" +#include "Models/Dynamic.hpp" diff --git a/code/Engine/include/Models/Staging.hpp b/code/Engine/include/Models/Staging.hpp deleted file mode 100644 index 0c56a8a..0000000 --- a/code/Engine/include/Models/Staging.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include - -namespace Models::Staging { - struct Vertex { - glm::vec3 position; - glm::vec3 normal; - glm::vec2 uv_coord; - }; - - struct Action { - std::string name; - }; - - struct Model { - std::string name; - std::vector vertex_data; - std::vector index_data; - - bool has_animations = false; - }; - - [[nodiscard]] auto loadModel(const std::filesystem::path& path) -> Utily::Result; -} // Models::Staging diff --git a/code/Engine/include/Models/Static.hpp b/code/Engine/include/Models/Static.hpp index d8d6a33..1afbb17 100644 --- a/code/Engine/include/Models/Static.hpp +++ b/code/Engine/include/Models/Static.hpp @@ -1,25 +1,19 @@ #pragma once -#include -#include -#include +#include "Models/Types.hpp" +#include "Utily/Utily.hpp" -#include -#include +namespace Models { -namespace Models::Static { - struct Vertex { - glm::vec3 position; - glm::vec3 normal; - glm::vec2 uv_coord; + struct Static { + std::array axis_align_bounding_box; + std::unique_ptr data; + std::span vertices; + std::span indices; }; - static_assert(sizeof(Models::Static::Vertex) == sizeof(std::array)); - - struct Model { - std::string name; - std::vector vertex_data; - std::vector index_data; - }; - -} // namespace Models::Static + auto decode_as_static_model( + std::span file_data, + Utily::StaticVector file_extension) + -> Utily::Result; +} \ No newline at end of file diff --git a/code/Engine/include/Models/Types.hpp b/code/Engine/include/Models/Types.hpp new file mode 100644 index 0000000..ebcc217 --- /dev/null +++ b/code/Engine/include/Models/Types.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include + +namespace Models { + using Vec2 = glm::vec2; + using Vec3 = glm::vec3; + using Quat = glm::quat; + using Mat4 = glm::mat4x4; + + struct Vertex { + Vec3 position; + Vec3 normal; + Vec2 uv_coord; + }; + + using Index = uint32_t; + + static_assert(sizeof(Vertex) == sizeof(std::array), "Unsupported alignment"); + static_assert(sizeof(Vertex) * 7 == sizeof(std::array), "Unsupported packing"); + +} \ No newline at end of file diff --git a/code/Engine/src/Models/Staging.cpp b/code/Engine/src/Models/Staging.cpp deleted file mode 100644 index 324bf14..0000000 --- a/code/Engine/src/Models/Staging.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "Models/Staging.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace std::literals; - -auto isModelFormatSupported(const std::string_view& extension) -> bool { - static constexpr auto supported_model_extensions = std::to_array({ ".fbx"sv }); //,".gltf"sv }); - - auto is_same_extension = [&](const auto& ext) { - return extension == ext; - }; - - return std::ranges::any_of(supported_model_extensions, is_same_extension); -} - -auto readRawFile(const std::filesystem::path& path) -> Utily::Result, Utily::Error> { - if (!std::filesystem::exists(path)) { - return Utily::Error("The file does not exist"); - } - - std::ifstream infile(path, std::ios::binary); - - if (!infile.is_open()) { - return Utily::Error("The file is in use"); - } - - std::vector raw_contents; - - infile.seekg(0, std::ios::end); - raw_contents.resize(infile.tellg()); - infile.seekg(0, std::ios::beg); - infile.read(raw_contents.data(), raw_contents.size()); - - if (!infile.good()) { - return Utily::Error("Error reading the file"); - } - - return raw_contents; -} - -auto importAnimationData(Models::Staging::Model* model_ptr, std::span assimp_animations) noexcept { - Models::Staging::Model& model = *model_ptr; - - for (const auto& assimp_animation : assimp_animations) { - - const auto assimp_channels = std::span { assimp_animation->mChannels, assimp_animation->mNumChannels }; - const auto assimp_mesh_channels = std::span { assimp_animation->mMeshChannels, assimp_animation->mNumMeshChannels }; - const auto assimp_mesh_morph_channels = std::span { assimp_animation->mMorphMeshChannels, assimp_animation->mNumMorphMeshChannels }; - } -} - -auto importMeshData(Models::Staging::Model* model_ptr, std::span assimp_meshes) noexcept { - Models::Staging::Model& model = *model_ptr; - - for (const auto& assimp_mesh : assimp_meshes) { - const auto assimp_vertices = std::span { assimp_mesh->mVertices, assimp_mesh->mNumVertices }; - const auto assimp_uv_coords = std::span { assimp_mesh->mTextureCoords[0], assimp_mesh->mNumVertices }; - const auto assimp_normals = std::span { assimp_mesh->mNormals, assimp_mesh->mNumVertices }; - - for (const auto& [v, n, uv] : std::views::zip(assimp_vertices, assimp_normals, assimp_uv_coords)) { - model.vertex_data.emplace_back( - Models::Staging::Vertex { - .position = { v.x, v.y, v.z }, - .normal = { n.x, n.y, n.z }, - .uv_coord = { uv.x, uv.y } }); - } - - const auto assimp_faces = std::span { assimp_mesh->mFaces, assimp_mesh->mNumFaces }; - - for (const auto& assimp_face : assimp_faces) { - for (const auto& index : std::span { assimp_face.mIndices, assimp_face.mNumIndices }) { - model.index_data.emplace_back(index); - } - } - } -} - -namespace Models::Staging { - auto loadModel(const std::filesystem::path& path) -> Utily::Result { - const auto ext = path.extension().string(); - - if (!isModelFormatSupported(ext)) { - return Utily::Error { - std::format( - "Not going to load model \"{}\", the format is not supported.", - path.string()) - }; - } - - auto maybe_file_contents = readRawFile(path); - - if (maybe_file_contents.has_error()) { - return Utily::Error { - std::format( - "Failed to load model \"{}\". The error was \"{}\".", - path.string(), - maybe_file_contents.error().what()) - }; - } - const auto& file_contents = maybe_file_contents.value(); - - Assimp::Importer importer {}; - - const aiScene* assimp_scene = importer.ReadFileFromMemory( - file_contents.data(), - file_contents.size(), - aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, - ext.c_str()); - - if (assimp_scene == nullptr) { - return Utily::Error { - std::format( - "Failed to load model \"{}\". The error was: \"{}\"", - path.string(), - importer.GetErrorString()) - }; - } - - Staging::Model model; - - auto assimp_meshes = std::span { assimp_scene->mMeshes, assimp_scene->mNumMeshes }; - auto assimp_animations = std::span { assimp_scene->mAnimations, assimp_scene->mNumAnimations }; - - importMeshData(&model, assimp_meshes); - importAnimationData(&model, assimp_animations); - - model.has_animations = false; - - return model; - } -} diff --git a/code/Engine/src/Models/Static.cpp b/code/Engine/src/Models/Static.cpp new file mode 100644 index 0000000..42de3dc --- /dev/null +++ b/code/Engine/src/Models/Static.cpp @@ -0,0 +1,224 @@ +#include "Models/Static.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Models { + auto decode_as_static_model(std::span file_data, Utily::StaticVector file_extension) + -> Utily::Result { + constexpr auto assimp_process_flags = + aiProcess_CalcTangentSpace + | aiProcess_Triangulate + | aiProcess_JoinIdenticalVertices + | aiProcess_SortByPType + | aiProcess_OptimizeGraph + | aiProcess_OptimizeMeshes + | aiProcess_GenNormals + | aiProcess_GenBoundingBoxes; + + Assimp::Importer importer {}; + + file_extension.emplace_back('\0'); // make null terminated. + + const aiScene* assimp_scene = importer.ReadFileFromMemory( + file_data.data(), + file_data.size(), + assimp_process_flags, + &(*file_extension.begin())); + + if (assimp_scene == nullptr) { + return Utily::Error { + std::format( + "Failed to load model. The error was: \"{}\"", + importer.GetErrorString()) + }; + } + auto assimp_meshes = std::span { assimp_scene->mMeshes, assimp_scene->mNumMeshes }; + + Static loaded_model; + + if (assimp_meshes.size() > 1) { + return Utily::Error { "There was multiple model mesh data. Use function decode_as_static_models." }; + } else if (assimp_meshes.size() == 0) { + return Utily::Error { "There was no model mesh data" }; + } + + for (const auto& assimp_mesh : assimp_meshes) { + if (!assimp_mesh->HasFaces() || !assimp_mesh->HasNormals() || !assimp_mesh->HasPositions()) { + return Utily::Error("There was either no: faces || normals || positions"); + } + + auto faces = std::span { assimp_mesh->mFaces, assimp_mesh->mNumFaces }; + auto positions = std::span { assimp_mesh->mVertices, assimp_mesh->mNumVertices }; + auto normals = std::span { assimp_mesh->mNormals, assimp_mesh->mNumVertices }; + auto uvs = std::span { assimp_mesh->mTextureCoords[0], assimp_mesh->mNumVertices }; + + auto get_formatted_aabb = [&] { + return std::array { + Vec3 { static_cast(assimp_mesh->mAABB.mMin.x), static_cast(assimp_mesh->mAABB.mMin.y), static_cast(assimp_mesh->mAABB.mMin.z) }, + Vec3 { static_cast(assimp_mesh->mAABB.mMax.x), static_cast(assimp_mesh->mAABB.mMax.y), static_cast(assimp_mesh->mAABB.mMax.z) }, + }; + }; + auto to_vert = [](auto& p, auto& n, auto& u) -> Vertex { + return { + .position = { p.x, p.y, p.z }, + .normal = { n.x, n.y, n.z }, + .uv_coord = { u.x, u.y } + }; + }; + auto to_span = [](const aiFace& face) -> std::span { + return { face.mIndices, face.mNumIndices }; + }; + auto vertices_view = std::views::zip_transform(to_vert, positions, normals, uvs); + auto indices_view = faces | std::views::transform(to_span) | std::views::join; + + auto [ptr, vert, ind] = Utily::InlineArrays::alloc_copy(vertices_view, std::move(indices_view)); + loaded_model.axis_align_bounding_box = get_formatted_aabb(); + loaded_model.data = std::move(ptr); + loaded_model.vertices = vert; + loaded_model.indices = ind; + } + return loaded_model; + } +} + +// using namespace std::literals; + +// auto isModelFormatSupported(const std::string_view& extension) -> bool { +// static constexpr auto supported_model_extensions = std::to_array({ ".fbx"sv }); //,".gltf"sv }); + +// auto is_same_extension = [&](const auto& ext) { +// return extension == ext; +// }; + +// return std::ranges::any_of(supported_model_extensions, is_same_extension); +// } + +// auto readRawFile(const std::filesystem::path& path) -> Utily::Result, Utily::Error> { +// if (!std::filesystem::exists(path)) { +// return Utily::Error("The file does not exist"); +// } + +// std::ifstream infile(path, std::ios::binary); + +// if (!infile.is_open()) { +// return Utily::Error("The file is in use"); +// } + +// std::vector raw_contents; + +// infile.seekg(0, std::ios::end); +// raw_contents.resize(infile.tellg()); +// infile.seekg(0, std::ios::beg); +// infile.read(raw_contents.data(), raw_contents.size()); + +// if (!infile.good()) { +// return Utily::Error("Error reading the file"); +// } + +// return raw_contents; +// } + +// auto importAnimationData(Models::Staging::Model* model_ptr, std::span assimp_animations) noexcept { +// Models::Staging::Model& model = *model_ptr; + +// for (const auto& assimp_animation : assimp_animations) { + +// const auto assimp_channels = std::span { assimp_animation->mChannels, assimp_animation->mNumChannels }; +// const auto assimp_mesh_channels = std::span { assimp_animation->mMeshChannels, assimp_animation->mNumMeshChannels }; +// const auto assimp_mesh_morph_channels = std::span { assimp_animation->mMorphMeshChannels, assimp_animation->mNumMorphMeshChannels }; +// } +// } + +// auto importMeshData(Models::Staging::Model* model_ptr, std::span assimp_meshes) noexcept { +// Models::Staging::Model& model = *model_ptr; + +// for (const auto& assimp_mesh : assimp_meshes) { +// const auto assimp_vertices = std::span { assimp_mesh->mVertices, assimp_mesh->mNumVertices }; +// const auto assimp_uv_coords = std::span { assimp_mesh->mTextureCoords[0], assimp_mesh->mNumVertices }; +// const auto assimp_normals = std::span { assimp_mesh->mNormals, assimp_mesh->mNumVertices }; + +// for (const auto& [v, n, uv] : std::views::zip(assimp_vertices, assimp_normals, assimp_uv_coords)) { +// model.vertex_data.emplace_back( +// Models::Staging::Vertex { +// .position = { v.x, v.y, v.z }, +// .normal = { n.x, n.y, n.z }, +// .uv_coord = { uv.x, uv.y } }); +// } + +// const auto assimp_faces = std::span { assimp_mesh->mFaces, assimp_mesh->mNumFaces }; + +// for (const auto& assimp_face : assimp_faces) { +// for (const auto& index : std::span { assimp_face.mIndices, assimp_face.mNumIndices }) { +// model.index_data.emplace_back(index); +// } +// } +// } +// } + +// namespace Models::Staging { +// auto loadModel(const std::filesystem::path& path) -> Utily::Result { +// const auto ext = path.extension().string(); + +// if (!isModelFormatSupported(ext)) { +// return Utily::Error { +// std::format( +// "Not going to load model \"{}\", the format is not supported.", +// path.string()) +// }; +// } + +// auto maybe_file_contents = readRawFile(path); + +// if (maybe_file_contents.has_error()) { +// return Utily::Error { +// std::format( +// "Failed to load model \"{}\". The error was \"{}\".", +// path.string(), +// maybe_file_contents.error().what()) +// }; +// } +// const auto& file_contents = maybe_file_contents.value(); + +// Assimp::Importer importer {}; + +// const aiScene* assimp_scene = importer.ReadFileFromMemory( +// file_contents.data(), +// file_contents.size(), +// aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType, +// ext.c_str()); + +// if (assimp_scene == nullptr) { +// return Utily::Error { +// std::format( +// "Failed to load model \"{}\". The error was: \"{}\"", +// path.string(), +// importer.GetErrorString()) +// }; +// } + +// Staging::Model model; + +// auto assimp_meshes = std::span { assimp_scene->mMeshes, assimp_scene->mNumMeshes }; +// auto assimp_animations = std::span { assimp_scene->mAnimations, assimp_scene->mNumAnimations }; + +// importMeshData(&model, assimp_meshes); +// importAnimationData(&model, assimp_animations); + +// model.has_animations = false; + +// return model; +// } +// } diff --git a/code/Test/CMakeLists.txt b/code/Test/CMakeLists.txt index 8126f29..4cf13e8 100644 --- a/code/Test/CMakeLists.txt +++ b/code/Test/CMakeLists.txt @@ -10,14 +10,7 @@ add_executable(Test ${TEST_SOURCES} ${TEST_HEADERS}) if(DEFINED EMSCRIPTEN) set(CMAKE_EXECUTABLE_SUFFIX ".html") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument") - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g -s DEMANGLE_SUPPORT=1 -s FORCE_FILESYSTEM=1 -s ASSERTIONS=1 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=2 -s NO_DISABLE_EXCEPTION_CATCHING") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -Os") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_WEBGL2=1 -s USE_GLFW=3 -s FULL_ES3=1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='_main'") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='_main' --closure 1") # Asset embedding. file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/code/Test/src/Integration/BasicApps.cpp b/code/Test/src/Integration/BasicApps.cpp index a5cb5ab..de6c03e 100644 --- a/code/Test/src/Integration/BasicApps.cpp +++ b/code/Test/src/Integration/BasicApps.cpp @@ -5,6 +5,7 @@ using namespace std::literals; +#include "AppAnalytics.hpp" struct OneSecondAppData { std::chrono::steady_clock::time_point start_time; diff --git a/code/build-web.bat b/code/build-web.bat index 338bf28..d0c1ed9 100644 --- a/code/build-web.bat +++ b/code/build-web.bat @@ -1,13 +1,16 @@ set VCPKG_PATH=C:/apps/vcpkg/vcpkg/ set EMSDK=C:/apps/emscripten/emsdk/ set EMSCRIPTEN=C:/apps/emscripten/emsdk/upstream/emscripten/ +set BUILD_TYPE=Debug if not exist "build-web\" ( mkdir build-web ) cd build-web -call emcmake cmake .. -DCMAKE_TOOLCHAIN_FILE=%VCPKG_PATH%/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=wasm32-emscripten -DEMSCRIPTEN=1 -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=%EMSCRIPTEN%cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release -call cmake --build . --config Release +call emcmake cmake .. -DCMAKE_TOOLCHAIN_FILE=%VCPKG_PATH%/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=wasm32-emscripten -DEMSCRIPTEN=1 -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=%EMSCRIPTEN%cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=%BUILD_TYPE% +call cmake --build . --target Engine --config %BUILD_TYPE% +call cmake --build . --target Demos --config %BUILD_TYPE% +call cmake --build . --target Test --config %BUILD_TYPE% cd .. diff --git a/code/vcpkg.json b/code/vcpkg.json index 824ce9b..fcc5398 100644 --- a/code/vcpkg.json +++ b/code/vcpkg.json @@ -8,11 +8,15 @@ "lodepng", "stb", { - "name": "glfw3", + "name": "opengl", "platform": "!emscripten" }, { - "name": "opengl", + "name": "openal-soft", + "platform": "!emscripten" + }, + { + "name": "glfw3", "platform": "!emscripten" }, { @@ -20,4 +24,5 @@ "platform": "!emscripten" } ] + } \ No newline at end of file