diff --git a/.gitignore b/.gitignore index a207396..a6fc926 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ -cmake-wsl-build-debug -cmake-build-debug/ +cmake-build*/ +build*/ + .idea/ -build/ + .ccls-cache/ compile_commands.json .cache/ + temp/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 20325b5..5b75236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,34 @@ cmake_minimum_required (VERSION 3.16) +# +set(HPR_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +set(HPR_EXTERNAL_PATH "${HPR_MODULE_PATH}/external") +set(HPR_TOOLCHAINS_PATH "${HPR_MODULE_PATH}/toolchains") + +set(HPR_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/source") + +# toolchain +#if (MINGW) +# set(CMAKE_TOOLCHAIN_FILE "${HPR_TOOLCHAINS_PATH}/mingw-gcc.cmake") +#else() +# set(CMAKE_TOOLCHAIN_FILE "${HPR_TOOLCHAINS_PATH}/linux-gcc.cmake") +#endif() + # Extract project version from source -file(STRINGS "source/hpr/core/common.hpp" - hpr_version_defines REGEX "#define HPR_VERSION_(MAJOR|MINOR|PATCH) ") +include(${HPR_MODULE_PATH}/hpr-macros.cmake) -foreach(ver ${hpr_version_defines}) - if(ver MATCHES [[#define HPR_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$]]) - set(HPR_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}") - endif() -endforeach() - -if(HPR_VERSION_PATCH MATCHES [[\.([a-zA-Z0-9]+)$]]) - set(hpr_VERSION_TYPE "${CMAKE_MATCH_1}") -endif() - -string(REGEX MATCH "^[0-9]+" HPR_VERSION_PATCH "${HPR_VERSION_PATCH}") -set(HPR_PROJECT_VERSION "${HPR_VERSION_MAJOR}.${HPR_VERSION_MINOR}.${HPR_VERSION_PATCH}") +hpr_parse_version("${HPR_SOURCE_DIR}/hpr/hpr.hpp" "#define HPR_VERSION_(MAJOR|MINOR|PATCH)") # Main project project( hpr - VERSION "${HPR_PROJECT_VERSION}" + VERSION "${HPR_VERSION}" LANGUAGES CXX ) +# Compiler settings +set(CMAKE_CXX_STANDARD 20) + # Detect how project is used if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) @@ -35,133 +40,124 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) message(AUTHOR_WARNING ${lines}) endif() - set(HPR_MASTER_PROJECT ON) - set(CMAKE_CXX_STANDARD 20) - - message(STATUS ${CMAKE_SOURCE_DIR}) + set(HPR_IS_TOP_LEVEL ON) else() - set(HPR_MASTER_PROJECT OFF) + set(HPR_IS_TOP_LEVEL OFF) endif() +# Project options +option(HPR_INSTALL "Install hpr files?" ${HPR_IS_TOP_LEVEL}) +option(HPR_TEST "Build hpr tests?" ${HPR_IS_TOP_LEVEL}) - -# Standard includes +# Installation settings include(GNUInstallDirs) -include(CPack) -# Options -option(HPR_INSTALL "Install hpr files?" ${HPR_MASTER_PROJECT}) -option(HPR_TEST "Build hpr tests?" ${HPR_MASTER_PROJECT}) +set(HPR_INSTALL_INTERFACE "$' not included + +# Package manager +include(${HPR_MODULE_PATH}/tools/CPM.cmake) # Testing if(HPR_TEST) enable_testing() - option(INSTALL_GMOCK "" OFF) - option(INSTALL_GTEST "" OFF) - - include(${CMAKE_SOURCE_DIR}/cmake/external/googletest.cmake) + include("${HPR_EXTERNAL_PATH}/googletest.cmake") include(GoogleTest) endif() -# Modules -option(WITH_CONTAINERS "" ON) -option(WITH_MATH "" ON) -option(WITH_IO "" ON) -option(WITH_MESH "" ON) -option(WITH_CSG "" ON) - option(USE_SYSTEM_OCCT "" ON) -option(WITH_GPU "" ON) -option(WITH_WINDOW_SYSTEM "" ON) +# Uninstall target +if (NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/cmake/templates/cmake_uninstall.cmake.in" cmake_uninstall.cmake + IMMEDIATE @ONLY + ) -set_property(GLOBAL PROPERTY HPR_MODULES "") -macro(add_module MODULE) - set_property(GLOBAL APPEND PROPERTY HPR_MODULES "${MODULE}") -endmacro() + add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_BINARY_DIR}/cmake_uninstall.cmake") +endif() + + +# Modules +option(HPR_WITH_CONTAINERS "" ON) +option(HPR_WITH_MATH "" ON) +option(HPR_WITH_IO "" ON) +option(HPR_WITH_MESH "" ON) +option(HPR_WITH_CSG "" ON) +option(HPR_WITH_GPU "" ON) +option(HPR_WITH_PARALLEL "" ON) + +include_directories(${HPR_SOURCE_DIR}) add_subdirectory(source/hpr) -get_property(hpr_modules GLOBAL PROPERTY HPR_MODULES) -foreach(module ${hpr_modules}) - get_target_property(module_type ${module} TYPE) - if(module_type STREQUAL "INTERFACE_LIBRARY") - list(APPEND HPR_INTERFACE_LIBS "${PROJECT_NAME}::${module}") - else() - list(APPEND HPR_PUBLIC_LIBS "${PROJECT_NAME}::${module}") - endif() - set(hpr_modules_summary "${hpr_modules_summary} ${module}") -endforeach() +hpr_collect_modules() # Main library -add_library(hpr SHARED - source/hpr/hpr.cpp) +add_library(hpr SHARED source/hpr/hpr.cpp) add_library(hpr::hpr ALIAS hpr) target_sources(hpr - INTERFACE - "$" - "$" + INTERFACE "$" "${HPR_INSTALL_INTERFACE}>" ) target_link_libraries(hpr - INTERFACE - ${HPR_INTERFACE_LIBS} - PUBLIC - ${HPR_PUBLIC_LIBS} + INTERFACE ${HPR_INTERFACE_LIBS} + PUBLIC ${HPR_PUBLIC_LIBS} ) -include(CMakePackageConfigHelpers) -configure_package_config_file( - "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION - ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION} -) +# Installation +if (HPR_INSTALL) + include(CMakePackageConfigHelpers) -write_basic_package_version_file( - "${PROJECT_NAME}ConfigVersion.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion -) + configure_package_config_file( + "${HPR_MODULE_PATH}/templates/Config.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + ) -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - DESTINATION - ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION} -) -install( + write_basic_package_version_file( + "${PROJECT_NAME}ConfigVersion.cmake" + VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion + ) + + install(FILES + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} COMPONENT devel + ) + + install( TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel + ) + + install( EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} COMPONENT devel NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) + ) + install( + FILES source/${PROJECT_NAME}/${PROJECT_NAME}.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} COMPONENT devel + ) + + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") + set(CPACK_PACKAGE_VERSION "${HPR_VERSION}") + + include(CPack) + cpack_add_component(devel DISPLAY_NAME "Development") + cpack_add_component(runtime DISPLAY_NAME "Runtime libraries") +endif() # Project summary -set(summary - "Summary:\n" - "Version: ${HPR_PROJECT_VERSION}\n" - "Master: ${HPR_MASTER_PROJECT}\n" - "Modules: ${hpr_modules_summary}" -) -message(STATUS ${summary}) +hpr_print_summary() # Documentation #add_subdirectory(docs) # Additional applications +add_subdirectory(source/creator) add_subdirectory(source/applications) -add_subdirectory(source/creator) \ No newline at end of file diff --git a/README.md b/README.md index e69de29..5c7ec7a 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,36 @@ +# hpr + +## Installation from sources + +### Prerequisites + +- CMake version 3.16 (or newer) + +### Configure + +``` +cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -B cmake-build-debug -S . +``` + +### Build + +``` +cmake --build cmake-build-debug --target hpr +``` + +### Install + +``` +cmake --install cmake-build-debug --component devel +``` + +The following install components are supported: +- `runtime` - runtime package (core shared libraries and `.dll` files on Windows* OS). +- `devel` - development package (header files, CMake integration files, library symbolic links, and `.lib` files on Windows* OS). + +### Pack + +``` +cd cmake-build-debug[.gitignore](.gitignore) +cpack +``` \ No newline at end of file diff --git a/cmake/external/glad.cmake b/cmake/external/glad.cmake index 663275b..785424d 100644 --- a/cmake/external/glad.cmake +++ b/cmake/external/glad.cmake @@ -1,4 +1,3 @@ -include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) CPMAddPackage( NAME glad @@ -6,10 +5,45 @@ CPMAddPackage( #VERSION 2.0.2 VERSION 0.1.36 GIT_PROGRESS TRUE - OPTIONS "GLAD_EXPORT ON" "GLAD_INSTALL ON" + EXCLUDE_FROM_ALL ON + OPTIONS "GLAD_EXPORT OFF" "GLAD_INSTALL OFF" ) -#if(glad_ADDED) -# add_subdirectory("${glad_SOURCE_DIR}/cmake" glad_cmake) -# glad_add_library(glad REPRODUCIBLE API gl:core=3.3) -#endif() \ No newline at end of file +if(glad_ADDED) + set(EXTERNAL_PROJECT_NAME glad) + + include(GNUInstallDirs) + + add_library(glad::glad ALIAS glad) + + install( + TARGETS ${EXTERNAL_PROJECT_NAME} + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT devel + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT devel + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT devel + ) + + install( + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake + NAMESPACE ${EXTERNAL_PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + ) + + install( + DIRECTORY ${glad_BINARY_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT devel + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.hpp" + ) + +endif() \ No newline at end of file diff --git a/cmake/external/glfw.cmake b/cmake/external/glfw.cmake index b8c033f..9b5d6cd 100644 --- a/cmake/external/glfw.cmake +++ b/cmake/external/glfw.cmake @@ -1,8 +1,43 @@ -include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) - -CPMAddPackage( - NAME glfw - GIT_REPOSITORY https://github.com/glfw/glfw.git - GIT_TAG 3.3.7 - EXCLUDE_FROM_ALL ON -) \ No newline at end of file + +CPMAddPackage( + NAME glfw + GIT_REPOSITORY https://github.com/glfw/glfw.git + GIT_TAG 3.3.7 + #EXCLUDE_FROM_ALL ON + OPTIONS "GLFW_INSTALL OFF" "GLFW_BUILD_EXAMPLES OFF" "GLFW_BUILD_TESTS OFF" +) + +if(glad_ADDED) + set(EXTERNAL_PROJECT_NAME glfw) + + include(GNUInstallDirs) + + add_library(glfw::glfw ALIAS glfw) + + install(DIRECTORY "${glfw_SOURCE_DIR}/include/GLFW" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT devel + FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h) + + install(FILES "${glfw_BINARY_DIR}/src/glfw3Config.cmake" + "${glfw_BINARY_DIR}/src/glfw3ConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/glfw3 + COMPONENT devel) + + install(EXPORT glfwTargets FILE glfw3Targets.cmake + EXPORT_LINK_INTERFACE_LIBRARIES + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/glfw3 + COMPONENT devel) + + install(FILES "${glfw_BINARY_DIR}/src/glfw3.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" + COMPONENT devel) + install( + TARGETS ${EXTERNAL_PROJECT_NAME} + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + RUNTIME COMPONENT runtime + LIBRARY COMPONENT devel + ARCHIVE COMPONENT devel + INCLUDES COMPONENT devel + ) + +endif() diff --git a/cmake/external/glm.cmake b/cmake/external/glm.cmake new file mode 100644 index 0000000..0b34c4e --- /dev/null +++ b/cmake/external/glm.cmake @@ -0,0 +1,5 @@ +CPMAddPackage( + NAME glm + GIT_REPOSITORY https://github.com/g-truc/glm.git + GIT_TAG 0.9.9.8 +) \ No newline at end of file diff --git a/cmake/external/googletest.cmake b/cmake/external/googletest.cmake index 29690e7..1f01338 100644 --- a/cmake/external/googletest.cmake +++ b/cmake/external/googletest.cmake @@ -1,7 +1,8 @@ -include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) CPMAddPackage( NAME googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1 + EXCLUDE_FROM_ALL ON + OPTIONS "BUILD_GMOCK OFF" "INSTALL_GTEST OFF" ) diff --git a/cmake/external/imgui.cmake b/cmake/external/imgui.cmake index a27e963..87d8401 100644 --- a/cmake/external/imgui.cmake +++ b/cmake/external/imgui.cmake @@ -1,86 +1,96 @@ -include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) - -# branch: docking -CPMAddPackage( - NAME imgui_external - GIT_REPOSITORY https://github.com/ocornut/imgui.git - GIT_TAG 24dfebf455ac1f7685e1a72272d37b72601fe70c - DOWNLOAD_ONLY YES -) - -if(imgui_external_ADDED) - set(EXTERNAL_PROJECT_NAME imgui) - - set(CMAKE_CXX_STANDARD 17) - - find_package(PkgConfig REQUIRED) - find_package(Freetype REQUIRED) - find_package(OpenGL REQUIRED) - pkg_search_module(GLFW REQUIRED glfw3) - - add_library(${EXTERNAL_PROJECT_NAME} STATIC - ${imgui_external_SOURCE_DIR}/imgui.cpp - ${imgui_external_SOURCE_DIR}/imgui_demo.cpp - ${imgui_external_SOURCE_DIR}/imgui_draw.cpp - ${imgui_external_SOURCE_DIR}/imgui_tables.cpp - ${imgui_external_SOURCE_DIR}/imgui_widgets.cpp - - ${imgui_external_SOURCE_DIR}/backends/imgui_impl_glfw.cpp - ${imgui_external_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp - - ${imgui_external_SOURCE_DIR}/misc/freetype/imgui_freetype.cpp - ${imgui_external_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp - ) - add_library(imgui::imgui ALIAS ${EXTERNAL_PROJECT_NAME}) - - add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD) - - target_include_directories(${EXTERNAL_PROJECT_NAME} - PUBLIC - $ - $ - $ - $ - - ${FREETYPE_INCLUDE_DIRS} - ${GLFW_INCLUDE_DIRS} - ) - - target_link_libraries(${EXTERNAL_PROJECT_NAME} - PUBLIC - Freetype::Freetype - glfw - OpenGL::GL - ) - - set_target_properties(${EXTERNAL_PROJECT_NAME} - PROPERTIES - POSITION_INDEPENDENT_CODE ON - OUTPUT_NAME imgui - EXCLUDE_FROM_ALL ON - ) - - include(GNUInstallDirs) - - install( - TARGETS ${EXTERNAL_PROJECT_NAME} - EXPORT ${EXTERNAL_PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/${EXTERNAL_PROJECT_NAME} - ) - - install( - EXPORT ${EXTERNAL_PROJECT_NAME}Targets - FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake - NAMESPACE ${EXTERNAL_PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} - ) - - install( - DIRECTORY ${imgui_external_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${EXTERNAL_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - ) -endif() + +# branch: docking +CPMAddPackage( + NAME imgui_external + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_TAG 24dfebf455ac1f7685e1a72272d37b72601fe70c + DOWNLOAD_ONLY YES +) + +if(imgui_external_ADDED) + set(EXTERNAL_PROJECT_NAME imgui) + + set(CMAKE_CXX_STANDARD 17) + + find_package(PkgConfig REQUIRED) + find_package(Freetype REQUIRED) + find_package(OpenGL REQUIRED) + find_package(GLFW REQUIRED) + + add_library(${EXTERNAL_PROJECT_NAME} + ${imgui_external_SOURCE_DIR}/imgui.cpp + ${imgui_external_SOURCE_DIR}/imgui_demo.cpp + ${imgui_external_SOURCE_DIR}/imgui_draw.cpp + ${imgui_external_SOURCE_DIR}/imgui_tables.cpp + ${imgui_external_SOURCE_DIR}/imgui_widgets.cpp + + ${imgui_external_SOURCE_DIR}/backends/imgui_impl_glfw.cpp + ${imgui_external_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp + + ${imgui_external_SOURCE_DIR}/misc/freetype/imgui_freetype.cpp + ${imgui_external_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp + ) + add_library(imgui::imgui ALIAS ${EXTERNAL_PROJECT_NAME}) + + add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD) + + target_include_directories(${EXTERNAL_PROJECT_NAME} + PUBLIC + $ + $ + $ + $ + + ${FREETYPE_INCLUDE_DIRS} + ${GLFW_INCLUDE_DIRS} + ) + + target_link_libraries(${EXTERNAL_PROJECT_NAME} + PUBLIC + Freetype::Freetype + glfw + OpenGL::GL + ) + + set_target_properties(${EXTERNAL_PROJECT_NAME} + PROPERTIES + POSITION_INDEPENDENT_CODE ON + OUTPUT_NAME imgui + EXCLUDE_FROM_ALL ON + ) + + if(IMGUI_INSTALL) + include(GNUInstallDirs) + + install( + TARGETS ${EXTERNAL_PROJECT_NAME} + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT devel + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT devel + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT devel + + ) + + install( + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake + NAMESPACE ${EXTERNAL_PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + ) + + install( + DIRECTORY ${imgui_external_SOURCE_DIR}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.hpp" + ) + endif() +endif() diff --git a/cmake/external/implot.cmake b/cmake/external/implot.cmake new file mode 100644 index 0000000..d88212d --- /dev/null +++ b/cmake/external/implot.cmake @@ -0,0 +1,73 @@ + +CPMAddPackage( + NAME implot_external + GIT_REPOSITORY https://github.com/epezent/implot.git + GIT_TAG v0.14 + DOWNLOAD_ONLY YES +) + +if(implot_external_ADDED) + set(EXTERNAL_PROJECT_NAME implot) + + set(CMAKE_CXX_STANDARD 17) + + find_package(PkgConfig REQUIRED) + find_package(Freetype REQUIRED) + find_package(OpenGL REQUIRED) + find_package(GLFW REQUIRED) + + add_library(${EXTERNAL_PROJECT_NAME} + ${implot_external_SOURCE_DIR}/implot.cpp + ${implot_external_SOURCE_DIR}/implot_demo.cpp + ${implot_external_SOURCE_DIR}/implot_items.cpp + ) + add_library(implot::implot ALIAS ${EXTERNAL_PROJECT_NAME}) + + + target_include_directories(${EXTERNAL_PROJECT_NAME} + PUBLIC + $ + ) + + target_link_libraries(${EXTERNAL_PROJECT_NAME} + PUBLIC + imgui::imgui + ) + + set_target_properties(${EXTERNAL_PROJECT_NAME} + PROPERTIES + POSITION_INDEPENDENT_CODE ON + OUTPUT_NAME implot + EXCLUDE_FROM_ALL ON + ) + + if(IMPLOT_INSTALL) + include(GNUInstallDirs) + + install( + TARGETS ${EXTERNAL_PROJECT_NAME} + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel + ) + + install( + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake + NAMESPACE ${EXTERNAL_PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + ) + + install( + DIRECTORY ${implot_external_SOURCE_DIR}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.hpp" + ) + endif() +endif() diff --git a/cmake/external/occt.cmake b/cmake/external/occt.cmake index 61f664e..35319e5 100644 --- a/cmake/external/occt.cmake +++ b/cmake/external/occt.cmake @@ -1,76 +1,67 @@ - -if(USE_SYSTEM_OCCT) - find_package(OpenCASCADE REQUIRED) - - if(OpenCASCADE_FOUND) - message(STATUS "OCCT: Found") - else() - message(FATAL "OCCT: Not Found") - endif() - -else() - include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) - - CPMAddPackage( - NAME occt - GIT_REPOSITORY https://github.com/Open-Cascade-SAS/OCCT.git - GIT_TAG V7_6_2 - DOWNLOAD_ONLY YES - ) - - if(occt_ADDED) - # They are using CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR for the project root, fix it - file(READ ${occt_SOURCE_DIR}/CMakeLists.txt filedata_) - string(FIND "${filedata_}" "CMAKE_SOURCE_DIR" need_patch) - - if(NOT ${need_patch} EQUAL -1) - string(REPLACE "CMAKE_SOURCE_DIR" "OCCT_SOURCE_DIR" filedata_ "${filedata_}") - string(REPLACE "CMAKE_BINARY_DIR" "OCCT_BINARY_DIR" filedata_ "${filedata_}") - string(REPLACE "project (OCCT)" "" filedata_ "${filedata_}") - string(PREPEND filedata_ "project(OCCT)\nset(OCCT_BINARY_DIR $\{_OCCT_BINARY_DIR\})\n") - endif() - file(WRITE ${occt_SOURCE_DIR}/CMakeLists.txt "${filedata_}") - - file(GLOB_RECURSE files_to_patch ${occt_SOURCE_DIR}/adm/cmake "occt_*") - - foreach(file_path ${files_to_patch}) - file(READ ${file_path} filedata_) - string(REPLACE "CMAKE_SOURCE_DIR" "OCCT_SOURCE_DIR" filedata_ "${filedata_}") - string(REPLACE "CMAKE_BINARY_DIR" "OCCT_BINARY_DIR" filedata_ "${filedata_}") - file(WRITE ${file_path} "${filedata_}") - endforeach() - - project(OCCT) - # find better way to pass build directory - set(_OCCT_BINARY_DIR ${occt_BINARY_DIR}) - set(INSTALL_DIR ${occt_BINARY_DIR} CACHE BOOL "" FORCE) - - set(USE_TK OFF CACHE BOOL "" FORCE) - set(USE_FREETYPE OFF CACHE BOOL "" FORCE) - set(USE_TCL OFF CACHE INTERNAL "" FORCE) - - set(BUILD_MODULE_Visualization OFF CACHE BOOL "" FORCE) - set(BUILD_MODULE_ApplicationFramework OFF CACHE BOOL "" FORCE) - set(BUILD_MODULE_Draw OFF CACHE BOOL "" FORCE) - - add_subdirectory(${occt_SOURCE_DIR}) - endif() -endif() - -set(OCCT_LIBRARIES - TKernel - TKService - TKV3d - TKOpenGl - TKBRep - TKBool - TKFillet - TKGeomBase - TKGeomAlgo - TKG3d - TKG2d - TKTopAlgo - TKPrim - TKSTEP - ) -set(OCCT_INCLUDE_DIRS ${OpenCASCADE_INCLUDE_DIR}) + +find_package(OpenCASCADE QUIET) + +if (NOT OpenCASCADE_FOUND) + CPMAddPackage( + NAME OpenCASCADE + GIT_REPOSITORY https://github.com/Open-Cascade-SAS/OCCT.git + GIT_TAG V7_6_2 + DOWNLOAD_ONLY YES + ) + + if(OpenCASCADE_ADDED) + # They are using CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR for the project root, fix it + file(READ ${OpenCASCADE_SOURCE_DIR}/CMakeLists.txt filedata_) + string(FIND "${filedata_}" "CMAKE_SOURCE_DIR" need_patch) + + if(NOT ${need_patch} EQUAL -1) + string(REPLACE "CMAKE_SOURCE_DIR" "OCCT_SOURCE_DIR" filedata_ "${filedata_}") + string(REPLACE "CMAKE_BINARY_DIR" "OCCT_BINARY_DIR" filedata_ "${filedata_}") + string(REPLACE "project (OCCT)" "" filedata_ "${filedata_}") + string(PREPEND filedata_ "project(OCCT)\nset(OCCT_BINARY_DIR $\{_OCCT_BINARY_DIR\})\n") + endif() + file(WRITE ${OpenCASCADE_SOURCE_DIR}/CMakeLists.txt "${filedata_}") + + file(GLOB_RECURSE files_to_patch ${OpenCASCADE_SOURCE_DIR}/adm/cmake "occt_*") + + foreach(file_path ${files_to_patch}) + file(READ ${file_path} filedata_) + string(REPLACE "CMAKE_SOURCE_DIR" "OCCT_SOURCE_DIR" filedata_ "${filedata_}") + string(REPLACE "CMAKE_BINARY_DIR" "OCCT_BINARY_DIR" filedata_ "${filedata_}") + file(WRITE ${file_path} "${filedata_}") + endforeach() + + #project(OCCT) + # find better way to pass build directory + #set(_OCCT_BINARY_DIR ${OpenCASCADE_BINARY_DIR}) + set(INSTALL_DIR ${OpenCASCADE_BINARY_DIR} CACHE BOOL "" FORCE) + + set(USE_TK OFF CACHE BOOL "" FORCE) + set(USE_FREETYPE OFF CACHE BOOL "" FORCE) + set(USE_TCL OFF CACHE INTERNAL "" FORCE) + + set(BUILD_MODULE_Visualization OFF CACHE BOOL "" FORCE) + set(BUILD_MODULE_ApplicationFramework OFF CACHE BOOL "" FORCE) + set(BUILD_MODULE_Draw OFF CACHE BOOL "" FORCE) + + add_subdirectory(${OpenCASCADE_SOURCE_DIR}) + endif() +endif() + +set(OpenCASCADE_LIBS + TKernel + TKService + TKV3d + TKOpenGl + TKBRep + TKBool + TKFillet + TKGeomBase + TKGeomAlgo + TKG3d + TKG2d + TKTopAlgo + TKPrim + TKSTEP +) + diff --git a/cmake/external/onetbb.cmake b/cmake/external/onetbb.cmake new file mode 100644 index 0000000..2853837 --- /dev/null +++ b/cmake/external/onetbb.cmake @@ -0,0 +1,8 @@ + +CPMAddPackage( + NAME onetbb + GIT_REPOSITORY https://github.com/oneapi-src/oneTBB.git + GIT_TAG v2021.8.0 + EXCLUDE_FROM_ALL ON + OPTIONS "TBB_INSTALL ON" "TBB_TEST OFF" "TBB_BENCH OFF" "BUILD_SHARED_LIBS ON" +) diff --git a/cmake/external/openxlsx.cmake b/cmake/external/openxlsx.cmake new file mode 100644 index 0000000..107d45f --- /dev/null +++ b/cmake/external/openxlsx.cmake @@ -0,0 +1,8 @@ + +CPMAddPackage( + NAME OpenXLSX + GIT_REPOSITORY https://github.com/troldal/OpenXLSX.git + GIT_TAG b80da42d1454f361c29117095ebe1989437db390 + #EXCLUDE_FROM_ALL ON +) +set(OPENXLSX_LIBRARY_TYPE "STATIC") diff --git a/cmake/external/stb.cmake b/cmake/external/stb.cmake index cfb5182..5f7c052 100644 --- a/cmake/external/stb.cmake +++ b/cmake/external/stb.cmake @@ -1,49 +1,50 @@ -include(${CMAKE_SOURCE_DIR}/cmake/tools/CPM.cmake) - -CPMAddPackage( - NAME stb_external - GIT_REPOSITORY https://github.com/nothings/stb.git - GIT_TAG af1a5bc352164740c1cc1354942b1c6b72eacb8a - DOWNLOAD_ONLY TRUE -) - -if(stb_external_ADDED) - set(EXTERNAL_PROJECT_NAME stb) - - add_library(${EXTERNAL_PROJECT_NAME} INTERFACE) - add_library(stb::stb ALIAS ${EXTERNAL_PROJECT_NAME}) - - target_include_directories(${EXTERNAL_PROJECT_NAME} - INTERFACE - $ - ) - - set_target_properties(${EXTERNAL_PROJECT_NAME} - PROPERTIES - OUTPUT_NAME stb - ) - - include(GNUInstallDirs) - - install( - TARGETS ${EXTERNAL_PROJECT_NAME} - EXPORT ${EXTERNAL_PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/${EXTERNAL_PROJECT_NAME} - ) - - install( - EXPORT ${EXTERNAL_PROJECT_NAME}Targets - FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake - NAMESPACE ${EXTERNAL_PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} - ) - - install( - DIRECTORY ${stb_external_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${EXTERNAL_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - ) -endif() + +CPMAddPackage( + NAME stb_external + GIT_REPOSITORY https://github.com/nothings/stb.git + GIT_TAG af1a5bc352164740c1cc1354942b1c6b72eacb8a + DOWNLOAD_ONLY TRUE +) + +if(stb_external_ADDED) + set(EXTERNAL_PROJECT_NAME stb) + + add_library(${EXTERNAL_PROJECT_NAME} INTERFACE EXCLUDE_FROM_ALL) + add_library(stb::stb ALIAS ${EXTERNAL_PROJECT_NAME}) + + target_include_directories(${EXTERNAL_PROJECT_NAME} + INTERFACE + $ + ) + + set_target_properties(${EXTERNAL_PROJECT_NAME} + PROPERTIES + OUTPUT_NAME stb + ) + + include(GNUInstallDirs) + + install( + TARGETS ${EXTERNAL_PROJECT_NAME} + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + DESTINATION ${CMAKE_INSTALL_LIBDIR}/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + ) + + install( + EXPORT ${EXTERNAL_PROJECT_NAME}Targets + FILE ${EXTERNAL_PROJECT_NAME}Targets.cmake + NAMESPACE ${EXTERNAL_PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + ) + + install( + DIRECTORY ${stb_external_SOURCE_DIR}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${EXTERNAL_PROJECT_NAME} + COMPONENT devel + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.hpp" + ) +endif() diff --git a/cmake/hpr-macros.cmake b/cmake/hpr-macros.cmake new file mode 100644 index 0000000..f7da928 --- /dev/null +++ b/cmake/hpr-macros.cmake @@ -0,0 +1,137 @@ + +# args: +# provide: HPR_VERSION +macro(hpr_parse_version _file _regex) + file( + STRINGS "${_file}" _version_defines + REGEX "${_regex}" + ) + + set(_regex_match "${_regex} +([^ ]+)$") + foreach(_ver ${_version_defines}) + if(_ver MATCHES ${_regex_match}) + set(_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}") + endif() + endforeach() + + if(_VERSION_PATCH MATCHES [[\.([a-zA-Z0-9]+)$]]) + set(_VERSION_TYPE "${CMAKE_MATCH_1}") + endif() + + string(REGEX MATCH "^[0-9]+" _VERSION_PATCH "${_VERSION_PATCH}") + set(HPR_VERSION "${_VERSION_MAJOR}.${_VERSION_MINOR}.${_VERSION_PATCH}") +endmacro() + +# args: ... +# provide : *_HEADERS *_HEADERS_INTERFACE +macro(hpr_collect_interface _project_name) + file(GLOB ${_project_name}_HEADERS ${ARGN}) + + foreach(_header_path ${${_project_name}_HEADERS}) + list(APPEND ${_project_name}_HEADERS_INTERFACE "$") + endforeach() +endmacro() + +# args: ... +# provide : *_SOURCES +macro(hpr_collect_sources _project_name) + file(GLOB ${_project_name}_SOURCES ${ARGN}) +endmacro() + +# Common installation +# args: +macro(hpr_install _project_name _project_source_dir) + if (HPR_INSTALL) + install( + TARGETS ${_project_name} + EXPORT ${_project_name}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} NAMELINK_SKIP COMPONENT runtime + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hpr COMPONENT devel + ) + + if (BUILD_SHARED_LIBS) + install( + TARGETS ${target} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} NAMELINK_ONLY COMPONENT devel + ) + endif() + + install( + EXPORT ${_project_name}Targets + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/hpr COMPONENT devel + NAMESPACE hpr:: + ) + + install( + DIRECTORY ${_project_source_dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hpr COMPONENT devel + FILES_MATCHING + PATTERN "*.h" + PATTERN "*.hpp" + PATTERN "tests" EXCLUDE + ) + + install( + FILES ../${_project_name}.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hpr COMPONENT devel + ) + endif() +endmacro() + +# Common tests template +# args: +macro(hpr_tests _project_name _tests_dir) + if (HPR_TEST) + file(GLOB tests_cpp "${_tests_dir}/*.cpp") + + add_executable(${_project_name}-tests ${tests_cpp}) + + target_link_libraries( + ${_project_name}-tests + PUBLIC hpr::${_project_name} + PRIVATE GTest::gtest_main + ) + + gtest_add_tests(TARGET ${_project_name}-tests) + endif() +endmacro() + +# Collect modules +# args: - +macro(hpr_collect_modules_) + set_property(GLOBAL PROPERTY _HPR_MODULES "") +endmacro() + +# Add module library +# args: +macro(hpr_add_library _library_name _library_type) + set_property(GLOBAL APPEND PROPERTY _HPR_MODULES "${_library_name}") + add_library(${_library_name} ${_library_type}) + add_library(hpr::${_library_name} ALIAS ${_library_name}) +endmacro() + +# args: - +# provide: HPR_MODULES HPR_INTERFACE_LIBS HPR_PUBLIC_LIBS +macro(hpr_collect_modules) + get_property(_hpr_modules GLOBAL PROPERTY _HPR_MODULES) + + foreach(_module ${_hpr_modules}) + get_target_property(_module_type ${_module} TYPE) + + if(_module_type STREQUAL "INTERFACE_LIBRARY") + list(APPEND HPR_INTERFACE_LIBS "${PROJECT_NAME}::${_module}") + else() + list(APPEND HPR_PUBLIC_LIBS "${PROJECT_NAME}::${_module}") + endif() + + set(HPR_MODULES "${HPR_MODULES} ${_module}") + endforeach() +endmacro() + +# args: - +macro(hpr_print_summary) + set(_summary "hpr-${HPR_VERSION}:${HPR_MODULES}") + message(STATUS ${_summary}) +endmacro() diff --git a/cmake/hprConfig.cmake.in b/cmake/templates/Config.cmake.in similarity index 57% rename from cmake/hprConfig.cmake.in rename to cmake/templates/Config.cmake.in index 91ee8da..63b5fc7 100644 --- a/cmake/hprConfig.cmake.in +++ b/cmake/templates/Config.cmake.in @@ -1,7 +1,7 @@ -@PACKAGE_INIT@ - -include(CMakeFindDependencyMacro) - -include("${CMAKE_CURRENT_LIST_DIR}/hprTargets.cmake") - +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + check_required_components("@PROJECT_NAME@") \ No newline at end of file diff --git a/cmake/templates/cmake_uninstall.cmake.in b/cmake/templates/cmake_uninstall.cmake.in new file mode 100644 index 0000000..4ea57b1 --- /dev/null +++ b/cmake/templates/cmake_uninstall.cmake.in @@ -0,0 +1,29 @@ + +if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +endif() + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") + +foreach (file ${files}) + message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + if (EXISTS "$ENV{DESTDIR}${file}") + exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval) + if (NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + endif() + elseif (IS_SYMLINK "$ENV{DESTDIR}${file}") + EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval) + if (NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"") + endif() + else() + message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + endif() +endforeach() + diff --git a/cmake/toolchains/linux-gcc.cmake b/cmake/toolchains/linux-gcc.cmake new file mode 100644 index 0000000..aec949d --- /dev/null +++ b/cmake/toolchains/linux-gcc.cmake @@ -0,0 +1,10 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_ARCH x86_64) + +set(CMAKE_C_COMPILER /bin/gcc) +set(CMAKE_CXX_COMPILER /bin/g++) +set(CMAKE_MAKE_PROGRAM /bin/ninja) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/toolchains/mingw-gcc.cmake b/cmake/toolchains/mingw-gcc.cmake new file mode 100644 index 0000000..a73d8d1 --- /dev/null +++ b/cmake/toolchains/mingw-gcc.cmake @@ -0,0 +1,12 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_ARCH x86_64) + +set(MINGW_PREFIX /mingw64) + +set(CMAKE_C_COMPILER ${MINGW_PREFIX}/bin/gcc) +set(CMAKE_CXX_COMPILER ${MINGW_PREFIX}/bin/g++) +set(CMAKE_MAKE_PROGRAM ${MINGW_PREFIX}/bin/ninja) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) \ No newline at end of file diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 6fe171c..b9a7477 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,23 +1,23 @@ - -find_package(Doxygen) - -if(NOT ${DOXYGEN_FOUND}) - message(STATUS "Doxygen is not found.") -endif() - -set(doc_api ${CMAKE_CURRENT_BINARY_DIR}/api/Doxyfile) - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/api/Doxyfile.in ${doc_api} @ONLY) - -add_custom_target( - documentation - COMMAND ${DOXYGEN_EXECUTABLE} ${doc_api} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/api - COMMENT "Generating API documentation with Doxygen" - VERBATIM -) - -install( - DIRECTORY ${PROJECT_BINARY_DIR}/docs/api/html - DESTINATION share/doc/${CMAKE_PROJECT_NAME}/api + +find_package(Doxygen) + +if(NOT ${DOXYGEN_FOUND}) + message(STATUS "Doxygen is not found.") +endif() + +set(doc_api ${CMAKE_CURRENT_BINARY_DIR}/api/Doxyfile) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/api/Doxyfile.in ${doc_api} @ONLY) + +add_custom_target( + documentation + COMMAND ${DOXYGEN_EXECUTABLE} ${doc_api} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/api + COMMENT "Generating API documentation with Doxygen" + VERBATIM +) + +install( + DIRECTORY ${PROJECT_BINARY_DIR}/docs/api/html + DESTINATION share/doc/${CMAKE_PROJECT_NAME}/api ) \ No newline at end of file diff --git a/docs/api/Doxyfile.in b/docs/api/Doxyfile.in index 397d3d3..2ea97f2 100644 --- a/docs/api/Doxyfile.in +++ b/docs/api/Doxyfile.in @@ -1,389 +1,389 @@ -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "@CMAKE_PROJECT_NAME@" -PROJECT_NUMBER = @PROJECT_VERSION@ -PROJECT_BRIEF = -PROJECT_LOGO = -OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/api -CREATE_SUBDIRS = NO -ALLOW_UNICODE_NAMES = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = # @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -JAVADOC_BANNER = NO -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -PYTHON_DOCSTRING = YES -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 4 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -OPTIMIZE_OUTPUT_SLICE = NO -EXTENSION_MAPPING = -MARKDOWN_SUPPORT = YES -TOC_INCLUDE_HEADINGS = 5 -AUTOLINK_SUPPORT = YES -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -SIP_SUPPORT = NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -GROUP_NESTED_COMPOUNDS = NO -SUBGROUPING = YES -INLINE_GROUPED_CLASSES = NO -INLINE_SIMPLE_STRUCTS = NO -TYPEDEF_HIDES_STRUCT = NO -LOOKUP_CACHE_SIZE = 0 -NUM_PROC_THREADS = 1 -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = NO -EXTRACT_PRIV_VIRTUAL = NO -EXTRACT_PACKAGE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -RESOLVE_UNNAMED_PARAMS = YES -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO -HIDE_COMPOUND_REFERENCE= NO -SHOW_HEADERFILE = YES -SHOW_INCLUDE_FILES = YES -SHOW_GROUPED_MEMB_INC = NO -FORCE_LOCAL_INCLUDES = NO -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_MEMBERS_CTORS_1ST = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -STRICT_PROTO_MATCHING = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_FILES = YES -SHOW_NAMESPACES = YES -FILE_VERSION_FILTER = -LAYOUT_FILE = -CITE_BIB_FILES = -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_IF_INCOMPLETE_DOC = YES -WARN_NO_PARAMDOC = NO -WARN_AS_ERROR = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = @PROJECT_SOURCE_DIR@/source -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.l \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f18 \ - *.f \ - *.for \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf \ - *.ice \ - *.org -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -FILTER_SOURCE_PATTERNS = -#USE_MDFILE_AS_MAINPAGE = -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -SOURCE_TOOLTIPS = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = -HTML_EXTRA_FILES = -HTML_COLORSTYLE_HUE = 220 -HTML_COLORSTYLE_SAT = 100 -HTML_COLORSTYLE_GAMMA = 80 -HTML_TIMESTAMP = NO -HTML_DYNAMIC_MENUS = YES -HTML_DYNAMIC_SECTIONS = NO -HTML_INDEX_NUM_ENTRIES = 100 -GENERATE_DOCSET = NO -DOCSET_FEEDNAME = "Doxygen generated docs" -DOCSET_FEEDURL = -DOCSET_BUNDLE_ID = org.doxygen.Project -DOCSET_PUBLISHER_ID = org.doxygen.Publisher -DOCSET_PUBLISHER_NAME = Publisher -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -CHM_INDEX_ENCODING = -BINARY_TOC = NO -TOC_EXPAND = NO -GENERATE_QHP = NO -QCH_FILE = -QHP_NAMESPACE = org.doxygen.Project -QHP_VIRTUAL_FOLDER = doc -QHP_CUST_FILTER_NAME = -QHP_CUST_FILTER_ATTRS = -QHP_SECT_FILTER_ATTRS = -QHG_LOCATION = -GENERATE_ECLIPSEHELP = NO -ECLIPSE_DOC_ID = org.doxygen.Project -DISABLE_INDEX = NO -GENERATE_TREEVIEW = YES -FULL_SIDEBAR = NO -ENUM_VALUES_PER_LINE = 4 -TREEVIEW_WIDTH = 250 -EXT_LINKS_IN_WINDOW = NO -OBFUSCATE_EMAILS = YES -HTML_FORMULA_FORMAT = png -FORMULA_FONTSIZE = 10 -FORMULA_TRANSPARENT = YES -FORMULA_MACROFILE = -USE_MATHJAX = NO -MATHJAX_VERSION = MathJax_2 -MATHJAX_FORMAT = HTML-CSS -MATHJAX_RELPATH = -MATHJAX_EXTENSIONS = -MATHJAX_CODEFILE = -SEARCHENGINE = YES -SERVER_BASED_SEARCH = NO -EXTERNAL_SEARCH = NO -SEARCHENGINE_URL = -SEARCHDATA_FILE = searchdata.xml -EXTERNAL_SEARCH_ID = -EXTRA_SEARCH_MAPPINGS = -#--------------------------------------------------------------------------- -# Configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = -MAKEINDEX_CMD_NAME = makeindex -LATEX_MAKEINDEX_CMD = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4 -EXTRA_PACKAGES = -LATEX_HEADER = -LATEX_FOOTER = -LATEX_EXTRA_STYLESHEET = -LATEX_EXTRA_FILES = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -LATEX_BIB_STYLE = plain -LATEX_TIMESTAMP = NO -LATEX_EMOJI_DIRECTORY = -#--------------------------------------------------------------------------- -# Configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# Configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_SUBDIR = -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# Configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_PROGRAMLISTING = YES -XML_NS_MEMB_FILE_SCOPE = NO -#--------------------------------------------------------------------------- -# Configuration options related to the DOCBOOK output -#--------------------------------------------------------------------------- -GENERATE_DOCBOOK = NO -DOCBOOK_OUTPUT = docbook -#--------------------------------------------------------------------------- -# Configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# Configuration options related to Sqlite3 output -#--------------------------------------------------------------------------- -#--------------------------------------------------------------------------- -# Configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration options related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -EXTERNAL_PAGES = YES -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -DIA_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -DOT_NUM_THREADS = 0 -DOT_FONTNAME = Helvetica -DOT_FONTSIZE = 10 -DOT_FONTPATH = -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -UML_LIMIT_NUM_FIELDS = 10 -DOT_UML_DETAILS = NO -DOT_WRAP_THRESHOLD = 17 -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DIR_GRAPH_MAX_DEPTH = 1 -DOT_IMAGE_FORMAT = png -INTERACTIVE_SVG = NO -DOT_PATH = -DOTFILE_DIRS = -MSCFILE_DIRS = -DIAFILE_DIRS = -PLANTUML_JAR_PATH = -PLANTUML_CFG_FILE = -PLANTUML_INCLUDE_PATH = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 0 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "@CMAKE_PROJECT_NAME@" +PROJECT_NUMBER = @PROJECT_VERSION@ +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/api +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = # @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +JAVADOC_BANNER = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +PYTHON_DOCSTRING = YES +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +OPTIMIZE_OUTPUT_SLICE = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +TOC_INCLUDE_HEADINGS = 5 +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +GROUP_NESTED_COMPOUNDS = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +NUM_PROC_THREADS = 1 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_PRIV_VIRTUAL = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +RESOLVE_UNNAMED_PARAMS = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = NO +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_HEADERFILE = YES +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_IF_INCOMPLETE_DOC = YES +WARN_NO_PARAMDOC = NO +WARN_AS_ERROR = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @PROJECT_SOURCE_DIR@/source +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice \ + *.org +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +#USE_MDFILE_AS_MAINPAGE = +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_DYNAMIC_MENUS = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_FEEDURL = +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +FULL_SIDEBAR = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +OBFUSCATE_EMAILS = YES +HTML_FORMULA_FORMAT = png +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +FORMULA_MACROFILE = +USE_MATHJAX = NO +MATHJAX_VERSION = MathJax_2 +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = +MAKEINDEX_CMD_NAME = makeindex +LATEX_MAKEINDEX_CMD = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_BIB_STYLE = plain +LATEX_TIMESTAMP = NO +LATEX_EMOJI_DIRECTORY = +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +XML_NS_MEMB_FILE_SCOPE = NO +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +DOT_UML_DETAILS = NO +DOT_WRAP_THRESHOLD = 17 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DIR_GRAPH_MAX_DEPTH = 1 +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_CFG_FILE = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/source/applications/CMakeLists.txt b/source/applications/CMakeLists.txt index 07465bc..0d81988 100644 --- a/source/applications/CMakeLists.txt +++ b/source/applications/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(periodic) \ No newline at end of file +#add_subdirectory(periodic) +add_subdirectory(fes) \ No newline at end of file diff --git a/source/applications/fes/CMakeLists.txt b/source/applications/fes/CMakeLists.txt new file mode 100644 index 0000000..ffd6f2d --- /dev/null +++ b/source/applications/fes/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required (VERSION 3.16) + +include(${CMAKE_SOURCE_DIR}/cmake/external/imgui.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/external/implot.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/external/openxlsx.cmake) + +project( + fes + VERSION 0.1.0 + LANGUAGES CXX +) + +# Compiler options +set(CMAKE_CXX_STANDARD 20) + +add_executable(${PROJECT_NAME} + fes.cpp + ) + +target_link_libraries(${PROJECT_NAME} + hpr::gpu + imgui::imgui + implot::implot + OpenXLSX::OpenXLSX + ) + +target_link_libraries(${PROJECT_NAME} -static gcc stdc++ winpthread -dynamic) +#message(STATUS "${OpenXLSX_DIR}") +#target_include_directories(${PROJECT_NAME} PUBLIC ${OpenXLSX_DIR}) \ No newline at end of file diff --git a/source/applications/fes/fes.cpp b/source/applications/fes/fes.cpp new file mode 100644 index 0000000..da91e29 --- /dev/null +++ b/source/applications/fes/fes.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + OpenXLSX::XLDocument doc; + doc.open("fes.xlsx"); + auto wb = doc.workbook(); + auto wks = wb.worksheet("Капилляриметрия"); + std::cout << wb.sheetCount() << std::endl; + auto rng = wks.range(OpenXLSX::XLCellReference("B7"), OpenXLSX::XLCellReference("B52")); + //for (auto cell : rng) + // std::cout << cell.value() << std::endl; + //xlnt::workbook wb; + //wb.load("fes.xlsx"); + //auto ws = wb.active_sheet(); + + + //std::clog << wb.sheet_count() << std::endl; + auto window = hpr::gpu::Window{50, 50, 1000, 800, "FES", hpr::gpu::Window::Windowed, nullptr, nullptr}; + + window.keyClickCallback([](hpr::gpu::Window* window, int key, int scancode, int action, int mods) + { + if (key == GLFW_KEY_ESCAPE) + window->state(hpr::gpu::Window::Closed); + }); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImPlot::CreateContext(); + + ImGui_ImplGlfw_InitForOpenGL(window.instance(), true); + ImGui_ImplOpenGL3_Init("#version 430"); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + + while (window.state() != hpr::gpu::Window::Closed) + { + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + static int selected = 0; + + if (ImGui::Begin("Table")) + { + if (ImGui::BeginTable("##table", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_BordersOuterV)) + { + ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 100.0f); + ImGui::TableSetupColumn("Core sample", ImGuiTableColumnFlags_NoHide); + ImGui::TableSetupColumn("Depth", ImGuiTableColumnFlags_NoHide); + ImGui::TableSetupColumn("Lithotype", ImGuiTableColumnFlags_NoHide); + ImGui::TableHeadersRow(); + const int start = 7;//54; + const int end = 11;//113; + int n = start; + + auto sample_range = wks.range(OpenXLSX::XLCellReference("B" + std::to_string(7)), OpenXLSX::XLCellReference("B" + std::to_string(11))); + hpr::darray sample {sample_range.begin(), sample_range.end()}; + //auto depth_range = wks.range(OpenXLSX::XLCellReference("H" + std::to_string(start)), OpenXLSX::XLCellReference("H" + std::to_string(end))); + //hpr::darray depth {sample_range.begin(), sample_range.end()}; + //auto lithotype_range = wks.range(OpenXLSX::XLCellReference("K" + std::to_string(start)), OpenXLSX::XLCellReference("K" + std::to_string(end))); + //hpr::darray lithotype {sample_range.begin(), sample_range.end()}; + + for ( ; n < end; ++n) + { + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextDisabled("#%d", n); + + ImGui::TableNextColumn(); + //float value = static_cast(cell.value()); + if (ImGui::Selectable(sample[n - start].value().get().c_str())) + { + selected = n; + } + + ImGui::TableNextColumn(); + //ImGui::Text(depth[n - start].value().get().c_str()); + ImGui::TableNextColumn(); + //ImGui::Text(lithotype[n - start].value().get().c_str()); + ++n; + } + + ImGui::EndTable(); + } + ImGui::End(); + } + + if (ImGui::Begin("Capillarimetry")) + { + hpr::darray P_c { 0.025, 0.05, 0.1, 0.3, 0.5, 0.7, 1.0}; + hpr::darray data; + + if (ImGui::BeginTabBar("Graphs", ImGuiTabBarFlags_None)) + { + const hpr::darray vars {"K_w", "P_n"}; + std::map> cols { + {"K_w", hpr::darray{"S", "V", "Y", "AB", "AE", "AH", "AK"}}, + {"P_n", hpr::darray{"U", "X", "AA", "AD", "AG", "AJ", "AM"}} + }; + + for (const auto& var : vars) + if (ImGui::BeginTabItem(var.data())) + { + //ImPlot::SetNextAxesToFit(); + if (ImPlot::BeginPlot(var.data(), ImVec2(-1, -1) )) + { + ImPlot::SetupAxes("P_c",var.data()); + + for (const auto& col : cols[var]) + data.push(wks.cell(col + std::to_string(selected)).value().get()); + + ImPlot::PlotLine(var.data(), P_c.data(), data.data(), data.size()); + + ImPlot::EndPlot(); + } + + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + } + + ImGui::End(); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + window.swapBuffers(); + window.pollEvents(); + } + + ImPlot::DestroyContext(); + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + return 0; +} \ No newline at end of file diff --git a/source/applications/fes/fes.xlsx b/source/applications/fes/fes.xlsx new file mode 100644 index 0000000..64c0920 Binary files /dev/null and b/source/applications/fes/fes.xlsx differ diff --git a/source/applications/periodic/CMakeLists.txt b/source/applications/periodic/CMakeLists.txt index 3fca096..7ed44c9 100644 --- a/source/applications/periodic/CMakeLists.txt +++ b/source/applications/periodic/CMakeLists.txt @@ -1,16 +1,16 @@ -cmake_minimum_required(VERSION 3.16) - -project(periodic - VERSION "0.1.0" - LANGUAGES CXX -) - - -add_executable(periodic - periodic.cpp -) - -target_link_libraries(periodic - hpr::csg -) - +cmake_minimum_required(VERSION 3.16) + +project(periodic + VERSION "0.1.0" + LANGUAGES CXX +) + + +add_executable(periodic + periodic.cpp +) + +target_link_libraries(periodic + hpr::csg +) + diff --git a/source/applications/periodic/lattice.hpp b/source/applications/periodic/lattice.hpp index efdeb1d..9db3eb2 100644 --- a/source/applications/periodic/lattice.hpp +++ b/source/applications/periodic/lattice.hpp @@ -1,205 +1,205 @@ -#pragma once - -#include "../../hpr/math.hpp" -#include "../../hpr/csg.hpp" - - -namespace hpr::csg -{ -void prints(scalar point) -{ - std::cout << point << std::endl; -} -class Lattice : public csg::Shape -{ - -public: - - enum class System - { - Triclinic, - Monoclinic, - Orthorhombic, - Tetragonal, - Rhombohedral, - Hexagonal, - Cubic, - Unknown - }; - - enum class Type - { - Primitive, - BaseCentered, - BodyCentered, - FaceCentered, - Unknown - }; - -protected: - - vec3 p_lengths; - vec3 p_angles; - Type p_type; - scalar p_radius; - darray p_controlPoints; - -public: - - Lattice() = delete; - - Lattice(const vec3& lengths, const vec3& angles, scalar radius, Type type) : - csg::Shape {}, - p_lengths {lengths}, - p_angles {angles}, - p_radius {radius}, - p_type {type} - { - generateControlPoints(); - darray spheres; - for (const auto& point : controlPoints()) { - spheres.push(csg::sphere(point, p_radius)); - print(point); - } - - p_shape = csg::Compound(spheres).tshape();//csg::fuse({spheres.front()}, spheres.slice(spheres.begin() + 1, spheres.end())).tshape(); - } - - darray controlPoints() const - { - return p_controlPoints; - } - - vec3 lengths() const - { - return p_lengths; - } - - vec3 angles() const - { - return p_angles; - } - - void generateControlPoints() - { - if (p_type == Type::Unknown) - throw std::runtime_error("Unknown type of lattice"); - p_controlPoints.resize(14); - // - vec3 ox {1, 0, 0}; - vec3 oy {0, 1, 0}; - vec3 oz {0, 0, 1}; - vec3 ox1 = hpr::rotate(ox, oz, radians(-p_angles[2])); - p_controlPoints.push(vec3{0, 0, 0}); - p_controlPoints.push(vec3{0, p_lengths[0], 0}); - vec3 t1 = hpr::translate(p_controlPoints.back(), ox1 * p_lengths[1]); - p_controlPoints.push(t1); - p_controlPoints.push(hpr::translate(p_controlPoints.front(), ox1 * p_lengths[1])); - print(t1); - print(ox1); - scalar c1 = cos(radians(p_angles[2])), c2 = cos(radians(p_angles[1])), c3 = cos(radians(p_angles[0])); - scalar D1 = sqrt(mat3( - 1, cos(radians(p_angles[2])), cos(radians(p_angles[1])), - cos(radians(p_angles[2])), 1, cos(radians(p_angles[0])), - cos(radians(p_angles[1])), cos(radians(p_angles[0])), 1).det()); - scalar volume = 1. / 6. * p_lengths[0] * p_lengths[1] * p_lengths[2] * - D1; - scalar s1 = sqrt(std::pow(p_lengths[0], 2) + std::pow(p_lengths[1], 2) - 2 * - p_lengths[0] * p_lengths[1] * cos(radians(p_angles[2]))); - scalar s2 = sqrt(std::pow(p_lengths[1], 2) + std::pow(p_lengths[2], 2) - 2 * - p_lengths[1] * p_lengths[2] * cos(radians(p_angles[1]))); - scalar s3 = sqrt(std::pow(p_lengths[0], 2) + std::pow(p_lengths[2], 2) - 2 * - p_lengths[0] * p_lengths[2] * cos(radians(p_angles[0]))); - scalar area = 1. / 2. * p_lengths[0] * p_lengths[1] * - sqrt(mat2{1, cos(radians(p_angles[2])), cos(radians(p_angles[2])), 1}.det()); - scalar h1 = 3 * volume / area; - scalar a1 = asin(h1 / p_lengths[2]); - scalar sh1 = sqrt(std::pow(p_lengths[2], 2) - std::pow(h1, 2)); - scalar sh2 = p_lengths[2] * cos(radians(p_angles[0])); - scalar a2 = acos(sh2 / sh1); - - vec3 ox2 = hpr::rotate(ox, oy, a1); - if (!std::isnan(a2)) - ox2 = hpr::rotate(ox2, oz, a2); - print(ox2); - for (auto n = 0; n < 4; ++n) - p_controlPoints.push(hpr::translate(p_controlPoints[n], ox2 * p_lengths[2])); - - /*p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], 0}); - p_controlPoints.push(vec3{p_lengths[0], 0, 0}); - - p_controlPoints.push(vec3{0, 0, p_lengths[2]}); - p_controlPoints.push(vec3{0, p_lengths[1], p_lengths[2]}); - p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], p_lengths[2]}); - p_controlPoints.push(vec3{p_lengths[0], 0, p_lengths[2]}); - - // central points on base faces - if (p_type == Type::BaseCentered || p_type == Type::FaceCentered) - { - for (int n = 0; n < 2; ++n) - { - vec3 center; - for (int k = 0; k < 4; ++k) - center += p_controlPoints[k + 4 * n]; - p_controlPoints.push(center * 0.25); - } - } - - // central point (center of mass) - if (p_type == Type::BodyCentered) - { - vec3 center; - for (const auto& point : p_controlPoints) - center += point; - p_controlPoints.push(center / p_controlPoints.size()); - } - - // central points on side faces - if (p_type == Type::FaceCentered) - { - for (int n = 0; n < 3; ++n) - { - vec3 center; - for (int k = 0; k < 2; ++k) - { - center += p_controlPoints[n + k]; - center += p_controlPoints[n + k + 4]; - } - p_controlPoints.push(center * 0.25); - } - vec3 center; - for (int n = 0; n < 2; ++n) - { - center += p_controlPoints[n * 3]; - center += p_controlPoints[4 + n * 3]; - } - p_controlPoints.push(center * 0.25); - } - - mat4 trans = mat4::identity(); - vec3 ox {1, 0, 0}; - vec3 oy {0, 1, 0}; - vec3 oz {0, 0, 1}; - int n = 0; - for (auto& point : p_controlPoints) - { - if (n == 0 || n == 3) - { - ++n; - continue; - } - trans.row(3, vec4(point, 0)); - trans = hpr::rotate(trans, oz, -radians(90 - p_angles[2])); - if (n >= 4 && n <= 7) - { - trans = hpr::rotate(trans, ox, -radians(90 - p_angles[1])); - trans = hpr::rotate(trans, oy, -radians(90 - p_angles[0])); - } - point = vec3(trans.row(3)[0], trans.row(3)[1], trans.row(3)[2]); - ++n; - }*/ - - } -}; - +#pragma once + +#include "../../hpr/math.hpp" +#include "../../hpr/csg.hpp" + + +namespace hpr::csg +{ +void prints(scalar point) +{ + std::cout << point << std::endl; +} +class Lattice : public csg::Shape +{ + +public: + + enum class System + { + Triclinic, + Monoclinic, + Orthorhombic, + Tetragonal, + Rhombohedral, + Hexagonal, + Cubic, + Unknown + }; + + enum class Type + { + Primitive, + BaseCentered, + BodyCentered, + FaceCentered, + Unknown + }; + +protected: + + vec3 p_lengths; + vec3 p_angles; + Type p_type; + scalar p_radius; + darray p_controlPoints; + +public: + + Lattice() = delete; + + Lattice(const vec3& lengths, const vec3& angles, scalar radius, Type type) : + csg::Shape {}, + p_lengths {lengths}, + p_angles {angles}, + p_radius {radius}, + p_type {type} + { + generateControlPoints(); + darray spheres; + for (const auto& point : controlPoints()) { + spheres.push(csg::sphere(point, p_radius)); + print(point); + } + + p_shape = csg::Compound(spheres).tshape();//csg::fuse({spheres.front()}, spheres.slice(spheres.begin() + 1, spheres.end())).tshape(); + } + + darray controlPoints() const + { + return p_controlPoints; + } + + vec3 lengths() const + { + return p_lengths; + } + + vec3 angles() const + { + return p_angles; + } + + void generateControlPoints() + { + if (p_type == Type::Unknown) + throw std::runtime_error("Unknown type of lattice"); + p_controlPoints.resize(14); + // + vec3 ox {1, 0, 0}; + vec3 oy {0, 1, 0}; + vec3 oz {0, 0, 1}; + vec3 ox1 = hpr::rotate(ox, oz, rad(-p_angles[2])); + p_controlPoints.push(vec3{0, 0, 0}); + p_controlPoints.push(vec3{0, p_lengths[0], 0}); + vec3 t1 = hpr::translate(p_controlPoints.back(), ox1 * p_lengths[1]); + p_controlPoints.push(t1); + p_controlPoints.push(hpr::translate(p_controlPoints.front(), ox1 * p_lengths[1])); + print(t1); + print(ox1); + scalar c1 = cos(rad(p_angles[2])), c2 = cos(rad(p_angles[1])), c3 = cos(rad(p_angles[0])); + scalar D1 = sqrt(det(mat3( + 1, cos(rad(p_angles[2])), cos(rad(p_angles[1])), + cos(rad(p_angles[2])), 1, cos(rad(p_angles[0])), + cos(rad(p_angles[1])), cos(rad(p_angles[0])), 1))); + scalar volume = 1. / 6. * p_lengths[0] * p_lengths[1] * p_lengths[2] * + D1; + scalar s1 = sqrt(pow(p_lengths[0], 2) + pow(p_lengths[1], 2) - 2 * + p_lengths[0] * p_lengths[1] * cos(rad(p_angles[2]))); + scalar s2 = sqrt(pow(p_lengths[1], 2) + pow(p_lengths[2], 2) - 2 * + p_lengths[1] * p_lengths[2] * cos(rad(p_angles[1]))); + scalar s3 = sqrt(pow(p_lengths[0], 2) + pow(p_lengths[2], 2) - 2 * + p_lengths[0] * p_lengths[2] * cos(rad(p_angles[0]))); + scalar area = 1. / 2. * p_lengths[0] * p_lengths[1] * + sqrt(det(mat2{1, cos(rad(p_angles[2])), cos(rad(p_angles[2])), 1})); + scalar h1 = 3 * volume / area; + scalar a1 = asin(h1 / p_lengths[2]); + scalar sh1 = sqrt(pow(p_lengths[2], 2) - pow(h1, 2)); + scalar sh2 = p_lengths[2] * cos(rad(p_angles[0])); + scalar a2 = acos(sh2 / sh1); + + vec3 ox2 = hpr::rotate(ox, oy, a1); + if (!isnan(a2)) + ox2 = hpr::rotate(ox2, oz, a2); + print(ox2); + for (auto n = 0; n < 4; ++n) + p_controlPoints.push(hpr::translate(p_controlPoints[n], ox2 * p_lengths[2])); + + /*p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], 0}); + p_controlPoints.push(vec3{p_lengths[0], 0, 0}); + + p_controlPoints.push(vec3{0, 0, p_lengths[2]}); + p_controlPoints.push(vec3{0, p_lengths[1], p_lengths[2]}); + p_controlPoints.push(vec3{p_lengths[0], p_lengths[1], p_lengths[2]}); + p_controlPoints.push(vec3{p_lengths[0], 0, p_lengths[2]}); + + // central points on base faces + if (p_type == Type::BaseCentered || p_type == Type::FaceCentered) + { + for (int n = 0; n < 2; ++n) + { + vec3 center; + for (int k = 0; k < 4; ++k) + center += p_controlPoints[k + 4 * n]; + p_controlPoints.push(center * 0.25); + } + } + + // central point (center of mass) + if (p_type == Type::BodyCentered) + { + vec3 center; + for (const auto& point : p_controlPoints) + center += point; + p_controlPoints.push(center / p_controlPoints.size()); + } + + // central points on side faces + if (p_type == Type::FaceCentered) + { + for (int n = 0; n < 3; ++n) + { + vec3 center; + for (int k = 0; k < 2; ++k) + { + center += p_controlPoints[n + k]; + center += p_controlPoints[n + k + 4]; + } + p_controlPoints.push(center * 0.25); + } + vec3 center; + for (int n = 0; n < 2; ++n) + { + center += p_controlPoints[n * 3]; + center += p_controlPoints[4 + n * 3]; + } + p_controlPoints.push(center * 0.25); + } + + mat4 trans = mat4::identity(); + vec3 ox {1, 0, 0}; + vec3 oy {0, 1, 0}; + vec3 oz {0, 0, 1}; + int n = 0; + for (auto& point : p_controlPoints) + { + if (n == 0 || n == 3) + { + ++n; + continue; + } + trans.row(3, vec4(point, 0)); + trans = hpr::rotate(trans, oz, -radians(90 - p_angles[2])); + if (n >= 4 && n <= 7) + { + trans = hpr::rotate(trans, ox, -radians(90 - p_angles[1])); + trans = hpr::rotate(trans, oy, -radians(90 - p_angles[0])); + } + point = vec3(trans.row(3)[0], trans.row(3)[1], trans.row(3)[2]); + ++n; + }*/ + + } +}; + } \ No newline at end of file diff --git a/source/applications/periodic/periodic.cpp b/source/applications/periodic/periodic.cpp index 9285fab..c48155e 100644 --- a/source/applications/periodic/periodic.cpp +++ b/source/applications/periodic/periodic.cpp @@ -1,244 +1,244 @@ -#include "../../hpr/math.hpp" -#include "../../hpr/csg.hpp" - -#include -#include - -using namespace hpr; - -void print(vec3 vs) -{ - for (auto& v : vs) - std::cout << v << " "; - std::cout << std::endl; -} - -class Periodic -{ -protected: - scalar p_alpha; - scalar p_initialRadius; - scalar p_sideLength; - scalar p_filletScale; - vec3 p_direction; - -public: - Periodic() : - p_alpha {0.1}, - p_initialRadius {1}, - p_filletScale {0.8}, - p_direction {} - {} - - Periodic(scalar alpha, scalar initialRadius, scalar filletScale, const vec3& direction) : - p_alpha {alpha}, - p_initialRadius {initialRadius}, - p_filletScale {filletScale}, - p_direction {direction} - {} - - virtual - ~Periodic() = default; - - scalar& alpha() - { - return p_alpha; - } - - scalar& initialRadius() - { - return p_initialRadius; - } - - virtual - scalar sideLength() = 0; - - virtual - scalar gamma() = 0; - - scalar& filletScale() - { - return p_filletScale; - } - - scalar radius() const - { - return p_initialRadius / (1. - p_alpha); - } - - scalar filletRadius() - { - scalar analytical = p_initialRadius * sqrt(2) / sqrt(1 - cos(gamma())) - radius(); - return analytical * p_filletScale; - } - - vec3& direction() - { - return p_direction; - } - - virtual - void build() = 0; -}; - -class Simple : public Periodic, public csg::Shape -{ -public: - - Simple() : - csg::Shape {}, - Periodic {0.01, 1, 0.8, vec3(1., 0., 0.)} - {} - - Simple(scalar alpha, const vec3& direction, scalar filletScale = 0.8) : - Simple {} - { - p_alpha = alpha; - p_direction = direction; - p_filletScale = filletScale; - } - - Simple(scalar alpha, scalar initialRadius, scalar filletScale, const vec3& direction) : - Periodic {alpha, initialRadius, filletScale, direction} - {} - - ~Simple() override = default; - - scalar sideLength() override - { - return 2 * initialRadius(); - } - - scalar gamma() override - { - return hpr::PI - 2 * 0.5 * 0.5 * hpr::PI; - } - - csg::Shape lattice() - { - csg::Shape lattice; - darray spheres; - - for (int zn = 0; zn < 3; ++zn) - { - scalar z = zn * sideLength(); - for (int yn = 0; yn < 3; ++yn) - { - scalar y = yn * sideLength(); - for (int xn = 0; xn < 3; ++xn) - { - scalar x = xn * sideLength(); - spheres.push(csg::sphere(vec3(x, y, z), radius())); - } - } - } - - lattice = csg::fuse({spheres.front()}, spheres.slice(spheres.begin() + 1, spheres.end())); - - if (filletScale() > 0) - { - lattice = lattice.scale({0, 0, 0}, 1e+2); - lattice = lattice.fillet(lattice.edges(), filletRadius() * 1e+2); - lattice = lattice.scale({0, 0, 0}, 1e-2); - } - - std::cout << (int)lattice.type() << std::endl; - return lattice; - } - - csg::Shape boxCell() - { - scalar length = sideLength() * sqrt(2); - scalar width = sideLength() * sqrt(2); - scalar height = sideLength(); - scalar xl = sqrt(pow(length, 2) * 0.5); - scalar yw = xl; - scalar zh = height; - darray edges { - csg::Edge({xl, 0, 0}, {0, yw, 0}), - csg::Edge({0, yw, 0}, {0, yw, zh}), - csg::Edge({0, yw, zh}, {xl, 0, zh}), - csg::Edge({xl, 0, zh}, {xl, 0, 0}) - }; - csg::Face plgm {edges}; - - vec3 localX {csg::Surface(plgm).normal(0, 0)}; - vec3 localZ = vec3(0, 0, 1); - vec3 localY = cross(localX, localZ); - csg::Shape cell = plgm.extrude(localX, width); - - scalar angle; - hpr::vec3 normal; - - for (auto& face : cell.faces()) - { - normal = csg::Surface(csg::Face(face)).normal(0, 0); - angle = hpr::angle(localX, normal); - - if (face.tshape().Orientation() == TopAbs_FORWARD) - { - normal = -normal; - angle = hpr::angle(localX, normal); - } - - if (equal(angle, 0.)) - face.label("periodic-south"); - else if (equal(angle, hpr::PI)) - face.label("periodic-north"); - - angle = hpr::angle(localY, normal); - if (equal(angle, 0.)) - face.label("periodic-east"); - else if (equal(angle, hpr::PI)) - face.label("periodic-west"); - - angle = hpr::angle(localZ, normal); - if (equal(angle, hpr::PI)) - face.label("periodic-down"); - else if (equal(angle, 0.)) - face.label("periodic-up"); - } - - std::cout << (int)cell.type() << std::endl; - return cell; - } - - csg::Shape hexagonalPrismCell() - { - return csg::Shape(); - } - - void build() override - { - if (direction() == vec3(1., 0., 0.) || direction() == vec3(1., 0., 0.) || direction() == vec3(0., 0., 1.)) - p_shape = csg::cut(boxCell(), lattice()).tshape(); - else if (direction() == vec3(1., 1., 1.)) - p_shape = csg::cut(hexagonalPrismCell(), lattice()).tshape(); - else - throw std::runtime_error("Undefined cell for passed direction"); - - - p_shape = this->translate(-this->center()).tshape(); - p_shape = this->rotate(this->center(), {0, 0, 1}, 45).tshape(); - - for (auto& face : faces()) - if (face.label() == "default") - face.label("wall"); - } - -}; - -#include "lattice.hpp" - -int main(int argc, char** argv) -{ - /*Simple simple {0.01, {1., 0., 0.}}; - simple.build(); - - std::cout << (int)simple.type() << std::endl; - std::cout << simple.volume() << std::endl; - */ - csg::Lattice lattice {{2, 2, 2}, {90, 90, 90}, 1, csg::Lattice::Type::Primitive}; - lattice.dump("latticeTest.step", csg::Shape::Format::STEP); - return 0; +#include "../../hpr/math.hpp" +#include "../../hpr/csg.hpp" + +#include +#include + +using namespace hpr; + +void print(vec3 vs) +{ + for (auto& v : vs) + std::cout << v << " "; + std::cout << std::endl; +} + +class Periodic +{ +protected: + scalar p_alpha; + scalar p_initialRadius; + scalar p_sideLength; + scalar p_filletScale; + vec3 p_direction; + +public: + Periodic() : + p_alpha {0.1}, + p_initialRadius {1}, + p_filletScale {0.8}, + p_direction {} + {} + + Periodic(scalar alpha, scalar initialRadius, scalar filletScale, const vec3& direction) : + p_alpha {alpha}, + p_initialRadius {initialRadius}, + p_filletScale {filletScale}, + p_direction {direction} + {} + + virtual + ~Periodic() = default; + + scalar& alpha() + { + return p_alpha; + } + + scalar& initialRadius() + { + return p_initialRadius; + } + + virtual + scalar sideLength() = 0; + + virtual + scalar gamma() = 0; + + scalar& filletScale() + { + return p_filletScale; + } + + scalar radius() const + { + return p_initialRadius / (1. - p_alpha); + } + + scalar filletRadius() + { + scalar analytical = p_initialRadius * sqrt(2) / sqrt(1 - cos(gamma())) - radius(); + return analytical * p_filletScale; + } + + vec3& direction() + { + return p_direction; + } + + virtual + void build() = 0; +}; + +class Simple : public Periodic, public csg::Shape +{ +public: + + Simple() : + csg::Shape {}, + Periodic {0.01, 1, 0.8, vec3(1., 0., 0.)} + {} + + Simple(scalar alpha, const vec3& direction, scalar filletScale = 0.8) : + Simple {} + { + p_alpha = alpha; + p_direction = direction; + p_filletScale = filletScale; + } + + Simple(scalar alpha, scalar initialRadius, scalar filletScale, const vec3& direction) : + Periodic {alpha, initialRadius, filletScale, direction} + {} + + ~Simple() override = default; + + scalar sideLength() override + { + return 2 * initialRadius(); + } + + scalar gamma() override + { + return hpr::PI - 2 * 0.5 * 0.5 * hpr::PI; + } + + csg::Shape lattice() + { + csg::Shape lattice; + darray spheres; + + for (int zn = 0; zn < 3; ++zn) + { + scalar z = zn * sideLength(); + for (int yn = 0; yn < 3; ++yn) + { + scalar y = yn * sideLength(); + for (int xn = 0; xn < 3; ++xn) + { + scalar x = xn * sideLength(); + spheres.push(csg::sphere(vec3(x, y, z), radius())); + } + } + } + + lattice = csg::fuse({spheres.front()}, spheres.slice(spheres.begin() + 1, spheres.end())); + + if (filletScale() > 0) + { + lattice = lattice.scale({0, 0, 0}, 1e+2); + lattice = lattice.fillet(lattice.edges(), filletRadius() * 1e+2); + lattice = lattice.scale({0, 0, 0}, 1e-2); + } + + std::cout << (int)lattice.type() << std::endl; + return lattice; + } + + csg::Shape boxCell() + { + scalar length = sideLength() * sqrt(2); + scalar width = sideLength() * sqrt(2); + scalar height = sideLength(); + scalar xl = sqrt(pow(length, 2) * 0.5); + scalar yw = xl; + scalar zh = height; + darray edges { + csg::Edge({xl, 0, 0}, {0, yw, 0}), + csg::Edge({0, yw, 0}, {0, yw, zh}), + csg::Edge({0, yw, zh}, {xl, 0, zh}), + csg::Edge({xl, 0, zh}, {xl, 0, 0}) + }; + csg::Face plgm {edges}; + + vec3 localX {csg::Surface(plgm).normal(0, 0)}; + vec3 localZ = vec3(0, 0, 1); + vec3 localY = cross(localX, localZ); + csg::Shape cell = plgm.extrude(localX, width); + + scalar angle; + hpr::vec3 normal; + + for (auto& face : cell.faces()) + { + normal = csg::Surface(csg::Face(face)).normal(0, 0); + angle = hpr::angle(localX, normal); + + if (face.tshape().Orientation() == TopAbs_FORWARD) + { + normal = -normal; + angle = hpr::angle(localX, normal); + } + + if (equal(angle, 0.)) + face.label("periodic-south"); + else if (equal(angle, hpr::PI)) + face.label("periodic-north"); + + angle = hpr::angle(localY, normal); + if (equal(angle, 0.)) + face.label("periodic-east"); + else if (equal(angle, hpr::PI)) + face.label("periodic-west"); + + angle = hpr::angle(localZ, normal); + if (equal(angle, hpr::PI)) + face.label("periodic-down"); + else if (equal(angle, 0.)) + face.label("periodic-up"); + } + + std::cout << (int)cell.type() << std::endl; + return cell; + } + + csg::Shape hexagonalPrismCell() + { + return csg::Shape(); + } + + void build() override + { + if (direction() == vec3(1., 0., 0.) || direction() == vec3(1., 0., 0.) || direction() == vec3(0., 0., 1.)) + p_shape = csg::cut(boxCell(), lattice()).tshape(); + else if (direction() == vec3(1., 1., 1.)) + p_shape = csg::cut(hexagonalPrismCell(), lattice()).tshape(); + else + throw std::runtime_error("Undefined cell for passed direction"); + + + p_shape = this->translate(-this->center()).tshape(); + p_shape = this->rotate(this->center(), {0, 0, 1}, 45).tshape(); + + for (auto& face : faces()) + if (face.label() == "default") + face.label("wall"); + } + +}; + +#include "lattice.hpp" + +int main(int argc, char** argv) +{ + /*Simple simple {0.01, {1., 0., 0.}}; + simple.build(); + + std::cout << (int)simple.type() << std::endl; + std::cout << simple.volume() << std::endl; + */ + csg::Lattice lattice {{2, 2, 2}, {90, 90, 90}, 1, csg::Lattice::Type::Primitive}; + lattice.dump("latticeTest.step", csg::Shape::Format::STEP); + return 0; } \ No newline at end of file diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index bbe1c42..0e4cde4 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -1,3 +1,8 @@ +cmake_minimum_required (VERSION 3.16) + +include(${CMAKE_SOURCE_DIR}/cmake/external/imgui.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/external/implot.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/external/glm.cmake) project( hyporo-creator @@ -7,55 +12,36 @@ project( # Compiler options set(CMAKE_CXX_STANDARD 20) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # Project options -include(GNUInstallDirs) +#include(GNUInstallDirs) + +#include (InstallRequiredSystemLibraries) + +if (MINGW) + list(APPEND MINGW_SYSTEM_RUNTIME_LIBS + "/mingw64/bin/libgcc_s_seh-1.dll" + "/mingw64/bin/libwinpthread-1.dll" + "/mingw64/bin/libstdc++-6.dll" + ) +endif() -#add_executable(${PROJECT_NAME} -# creator.cpp -#) -include(${CMAKE_SOURCE_DIR}/cmake/external/imgui.cmake) -#message(STATUS "project name: ${PROJECT_NAME}") -#target_link_libraries(${PROJECT_NAME} -# hpr::hpr -# imgui -#) -#target_include_directories(${PROJECT_NAME} -# PRIVATE -# ../ -#) +#find_package(hpr REQUIRED) -#set(CMAKE_CXX_STANDARD 20) -#add_executable(testi -# test.cpp -#) - -#target_include_directories(testi -# PRIVATE -# ../ -#) - -#target_link_libraries(testi -# hpr::hpr -# imgui -#) -set(CMAKE_CXX_STANDARD 20) add_executable(hyporo-creator - test2.cpp - ) - -target_include_directories(hyporo-creator - PRIVATE - ../ - ) + test2.cpp +) target_link_libraries(hyporo-creator - hpr::gpu - hpr::window-system - imgui - ) + hpr::gpu + imgui::imgui + implot::implot + glm::glm +) + +target_link_libraries(hyporo-creator -static gcc stdc++ winpthread -dynamic) + diff --git a/source/creator/camera.hpp b/source/creator/camera.hpp new file mode 100644 index 0000000..1c3ca84 --- /dev/null +++ b/source/creator/camera.hpp @@ -0,0 +1,135 @@ +#pragma once + +#include + +class Camera +{ + +public: + + enum Projection + { + Perspective, + Orthographic + }; + +protected: + + Projection p_projectionType; + + hpr::scalar p_distance; + hpr::scalar p_aspect; + hpr::scalar p_fieldOfView; + hpr::scalar p_nearPlane; + hpr::scalar p_farPlane; + + hpr::vec3 p_target; + hpr::vec3 p_left; + hpr::vec3 p_front; + hpr::vec3 p_up; + hpr::vec3 p_angles; + + hpr::vec3 p_position; + +public: + + inline + Camera() : + p_projectionType {Perspective}, + p_distance {10}, + p_aspect {4.f / 3.f}, + p_fieldOfView {45}, + p_nearPlane {0.1},//{-100}, + p_farPlane {100}, + p_target {0, 0, 0}, + p_left {1, 0, 0}, + p_front {0, 0, -1}, + p_up {0, 0, 1}, + p_angles {45, 45, 0}, + p_position {} + {} + + virtual + ~Camera() = default; + + virtual inline + void projection(Projection projection) + { + p_projectionType = projection; + } + + hpr::scalar& aspect() + { + return p_aspect; + } + + virtual inline + hpr::mat4 projection() const + { + switch (p_projectionType) + { + case Perspective: + return hpr::perspective(hpr::rad(p_fieldOfView), p_aspect, p_nearPlane, p_farPlane); + case Orthographic: + return hpr::ortho(-p_distance * p_aspect, p_distance * p_aspect, -p_distance, p_distance, p_nearPlane, p_farPlane); + } + } + + virtual inline + hpr::mat4 view() = 0; + + virtual inline + hpr::vec3& position() + { + return p_position; + } +}; + +class OrbitCamera : public Camera +{ +public: + + inline + OrbitCamera() : + Camera {} + {} + + virtual + ~OrbitCamera() = default; + + inline + hpr::mat4 view() override + { + hpr::vec3 rotation { + hpr::cos(hpr::rad(p_angles[1])) * hpr::sin(hpr::rad(p_angles[0])), + hpr::cos(hpr::rad(p_angles[1])) * hpr::cos(hpr::rad(p_angles[0])), + hpr::sin(hpr::rad(p_angles[1]))}; + hpr::vec3 pos = p_target + p_distance * rotation; + + p_front = p_target - pos; + p_front /= hpr::length(p_front); + + p_up = hpr::vec3(0, 0, 1); + p_left = hpr::normalize(hpr::cross(p_up, p_front)); + p_up = hpr::cross(p_front, p_left); + + p_position = pos; + + return hpr::lookAt(pos, pos + p_front, p_up); + } + + void rotateEvent(float xdelta, float ydelta) + { + p_angles += hpr::vec3(xdelta, ydelta, 0); + } + + void moveEvent(float xdelta, float ydelta) + { + p_target += (p_left * xdelta + p_up * ydelta) * 1e-3f; + } + + void scrollEvent(float xdelta, float ydelta) + { + p_distance -= ydelta; + } +}; \ No newline at end of file diff --git a/source/creator/cmake/mingw-pre-pack.cmake.in b/source/creator/cmake/mingw-pre-pack.cmake.in new file mode 100644 index 0000000..cd434a1 --- /dev/null +++ b/source/creator/cmake/mingw-pre-pack.cmake.in @@ -0,0 +1,12 @@ + +execute_process( + COMMAND ldd "@CPACK_PACKAGE_DIRECTORY@/@PROJECT_NAME@.exe" + COMMAND grep "mingw" + COMMAND cut "-d" " " "-f" "3" + COMMAND xargs "cp" "-t" "@CMAKE_INSTALL_BINDIR@" + RESULT_VARIABLE EXIT_CODE +) + +if(NOT EXIT_CODE EQUAL 0) + message(STATUS "Running pre-build command failed with exit code ${EXIT_CODE}.") +endif() \ No newline at end of file diff --git a/source/creator/drawable.hpp b/source/creator/drawable.hpp new file mode 100644 index 0000000..e03132b --- /dev/null +++ b/source/creator/drawable.hpp @@ -0,0 +1,238 @@ +#pragma once + +#include +#include + +using hpr::darray; + +class Drawable +{ + +protected: + + gpu::ArrayObject p_arrayObject; + + gpu::BufferObject p_vertexBuffer; + gpu::BufferObject p_normalBuffer; + gpu::BufferObject p_colorBuffer; + gpu::BufferObject p_indexBuffer; + + gpu::ShaderProgram* p_shaderProgram; + + gpu::ArrayObject::Mode p_renderMode; + + hpr::vec4 p_color; + +public: + + gpu::ArrayObject& array() + { + return p_arrayObject; + } + friend constexpr void swap(Drawable& main, Drawable& other) + { + using std::swap; + //swap(main.p) + } + + Drawable() : + p_arrayObject {}, + p_vertexBuffer {gpu::BufferObject::Vertex}, + p_normalBuffer {gpu::BufferObject::Vertex}, + p_colorBuffer {gpu::BufferObject::Vertex}, + p_indexBuffer {gpu::BufferObject::Index}, + p_shaderProgram {nullptr}, + p_renderMode {gpu::ArrayObject::Triangles}, + p_color {0.7, 0.7, 0.7} + {} + + inline explicit + Drawable(gpu::ShaderProgram* shaderProgram) : + p_arrayObject {}, + p_vertexBuffer {gpu::BufferObject::Vertex}, + p_normalBuffer {gpu::BufferObject::Vertex}, + p_colorBuffer {gpu::BufferObject::Vertex}, + p_indexBuffer {gpu::BufferObject::Index}, + p_shaderProgram {shaderProgram}, + p_renderMode {gpu::ArrayObject::Triangles}, + p_color {0.7, 0.7, 0.7} + {} + + inline + Drawable(const Drawable& drawable) = default; + + virtual + ~Drawable() = default; + + void destroy() + { + p_arrayObject.destroy(); + p_vertexBuffer.destroy(); + p_normalBuffer.destroy(); + p_colorBuffer.destroy(); + p_indexBuffer.destroy(); + } + + [[nodiscard]] + constexpr + gpu::ShaderProgram* shaderProgram() const + { + return p_shaderProgram; + } + + constexpr virtual + void renderMode(gpu::ArrayObject::Mode mode) + { + p_renderMode = mode; + } + + [[nodiscard]] + constexpr virtual + gpu::ArrayObject::Mode renderMode() const + { + return p_renderMode; + } + + template + inline + void addVertices(const darray& vertices) + { + if (!p_arrayObject.valid()) + p_arrayObject.create(); + p_arrayObject.bind(); + + darray data; + data.resize(vertices.size() * vertices[0].size()); + for (auto v : vertices) for (auto c : v) data.push(c); + p_vertexBuffer.create(data); + + p_arrayObject.attribPointer(p_vertexBuffer, 0, vertices[0].size()); + p_arrayObject.unbind(); + } + + template + inline + void editVertices(const darray& vertices) + { + if (!p_vertexBuffer.valid()) + throw std::runtime_error("Invalid buffer object"); + p_arrayObject.bind(); + + darray data; + data.resize(vertices.size() * vertices[0].size()); + for (auto v : vertices) for (auto c : v) data.push(c); + + p_vertexBuffer.edit(data); + + p_arrayObject.unbind(); + } + + template + inline + void addNormals(const darray& normals) + { + if (!p_arrayObject.valid()) + p_arrayObject.create(); + p_arrayObject.bind(); + + darray data; + data.resize(normals.size() * normals[0].size()); + for (auto v : normals) for (auto c : v) data.push(c); + p_normalBuffer.create(data); + + p_arrayObject.attribPointer(p_normalBuffer, 1, normals[0].size()); + p_arrayObject.unbind(); + } + + template + inline + void addColors(const darray& colors) + { + if (!p_arrayObject.valid()) + p_arrayObject.create(); + p_arrayObject.bind(); + + darray data; + data.resize(colors.size() * colors[0].size()); + for (auto v : colors) for (auto c : v) data.push(c); + p_colorBuffer.create(data); + + p_arrayObject.attribPointer(p_colorBuffer, 2, colors[0].size()); + p_arrayObject.unbind(); + } + + template + inline + void editColors(const darray& colors) + { + if (!p_colorBuffer.valid()) + throw std::runtime_error("Invalid buffer object"); + p_arrayObject.bind(); + + darray data; + data.resize(colors.size() * colors[0].size()); + for (auto v : colors) for (auto c : v) data.push(c); + + p_colorBuffer.edit(data); + + p_arrayObject.unbind(); + } + + template + inline + void addIndices(const darray& indices) + { + if (!p_arrayObject.valid()) + p_arrayObject.create(); + p_arrayObject.bind(); + + darray data; + data.resize(indices.size() * indices[0].size()); + for (auto v : indices) for (auto c : v) data.push(c); + p_indexBuffer.create(data); + + p_arrayObject.unbind(); + } + + inline virtual + void render(gpu::ArrayObject::Mode mode) + { + p_shaderProgram->bind(); + //std::cout << p_shaderProgram->index() << std::endl; + p_arrayObject.bind(); + + if (!p_colorBuffer.valid()) { + + shaderProgram()->uniformVector("objectColor", 1, p_color.data()); + } + if (p_indexBuffer.valid()) + { + p_indexBuffer.bind(); + p_arrayObject.drawElements(mode, p_indexBuffer.size()); + } + else + { + p_arrayObject.drawArrays(mode, p_vertexBuffer.size()); + } + p_arrayObject.unbind(); + p_shaderProgram->unbind(); + } + + inline virtual + void render() + { + render(p_renderMode); + } + + inline virtual + void color(const hpr::vec4& color) + { + p_color = color; + } + + inline virtual + hpr::vec4& color() + { + return p_color; + } +}; diff --git a/source/creator/entity.hpp b/source/creator/entity.hpp new file mode 100644 index 0000000..87f8478 --- /dev/null +++ b/source/creator/entity.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +#include "drawable.hpp" + + +class Entity : public Drawable +{ + +protected: + + hpr::vec3 p_position; + hpr::quat p_rotation; + hpr::vec3 p_scale; + +public: + + Entity() : + Drawable {} + {} + + inline explicit + Entity(gpu::ShaderProgram* shaderProgram) : + Drawable {shaderProgram} + {} + + inline + Entity(const Entity& entity) = default; + /*{ + std::cout << "copy" << std::endl; + }*/ + + ~Entity() override = default; + + inline virtual + void rotation(const hpr::vec3& angles) + { + p_rotation = hpr::quat(hpr::quat::XYZ, angles); + } + + inline virtual + hpr::quat& rotation() + { + return p_rotation; + } + + inline virtual + void rotate(const hpr::vec3& axis, hpr::scalar angle) + { + p_rotation *= hpr::quat(axis, angle); + } + + hpr::mat4 model() + { + hpr::mat4 model = hpr::mat4::identity(); + hpr::translate(model, p_position); + hpr::rotate(model, p_rotation); + hpr::scale(model, p_scale); + return model; + } + + inline + void render() override + { + shaderProgram()->bind(); + //std::cout << shaderProgram()->index() << std::endl; + + //for (auto v : model) + // std::cout << v << " "; + //std::cout << std::endl; + shaderProgram()->uniformMatrix<4, 4>("model", 1, true, model().data()); + + Drawable::render(); + + shaderProgram()->unbind(); + } + +}; \ No newline at end of file diff --git a/source/creator/grid.hpp b/source/creator/grid.hpp new file mode 100644 index 0000000..4366624 --- /dev/null +++ b/source/creator/grid.hpp @@ -0,0 +1,157 @@ +#pragma once + +#include "entity.hpp" + + +class Grid : public Entity +{ + +public: + + enum Mode + { + XY, + XZ, + YZ + }; + +protected: + + hpr::scalar p_length; + hpr::scalar p_width; + hpr::scalar p_height; + hpr::scalar p_scale; + Mode p_mode; + +public: + + + Grid(gpu::ShaderProgram* shaderProgram, Mode mode = XY, hpr::scalar scale = 1, hpr::scalar length = 100, hpr::scalar width = 100, hpr::scalar height = 100) : + Entity {shaderProgram}, + p_length {length}, + p_width {width}, + p_height {height}, + p_scale {scale}, + p_mode {mode} + { + darray vertices; + darray colors; + + construct(vertices, colors); + + Entity::addVertices(vertices); + Entity::addColors(colors); + Entity::renderMode(gpu::ArrayObject::Lines); + } + +protected: + + void construct(darray& vertices, darray& colors) + { + const darray red {vec3(0.98f, 0.21f, 0.32f), vec3(0.98f, 0.21f, 0.32f)}; + const darray green {vec3(0.45f, 0.67f, 0.1f), vec3(0.45f, 0.67f, 0.1f)}; + const darray blue {vec3(0.17f, 0.47f, 0.80f), vec3(0.17f, 0.47f, 0.80f)}; + const darray white {vec3(0.5f, 0.5f, 0.5f), vec3(0.5f, 0.5f, 0.5f)}; + + switch (p_mode) { + case XY: { + // Y + vertices.push({vec3(0.f, -p_width, 0.f), vec3(0.f, p_width, 0.f)}); + colors.push(green); + for (hpr::scalar x = p_scale; x <= p_length; ) + { + vertices.push({vec3(x, -p_width, 0.f), vec3(x, p_width, 0.f)}); + colors.push(white); + vertices.push({vec3(-x, -p_width, 0.f), vec3(-x, p_width, 0.f)}); + colors.push(white); + x += p_scale; + } + // X + vertices.push({vec3(-p_length, 0.f, 0.f), vec3(p_length, 0.f, 0.f)}); + colors.push(red); + for (hpr::scalar y = p_scale; y <= p_width; ) + { + vertices.push({vec3(-p_length, y, 0.f), vec3(p_length, y, 0.f)}); + colors.push(white); + vertices.push({vec3(-p_length, -y, 0.f), vec3(p_length, -y, 0.f)}); + colors.push(white); + y += p_scale; + } + break; + } + case XZ: { + // Z + vertices.push({vec3(0.f, 0.f, -p_height), vec3(0.f, 0.f, p_height)}); + colors.push(blue); + for (hpr::scalar x = p_scale; x <= p_length; ) + { + vertices.push({vec3(x, 0.f, -p_height), vec3(x, 0.f, p_height)}); + colors.push(white); + vertices.push({vec3(-x, 0.f, -p_height), vec3(-x, 0.f, p_height)}); + colors.push(white); + x += p_scale; + } + // X + vertices.push({vec3(-p_length, 0.f, 0.f), vec3(p_length, 0.f, 0.f)}); + colors.push(red); + for (hpr::scalar z = p_scale; z <= p_height; ) + { + vertices.push({vec3(-p_length, 0.f, z), vec3(p_length, 0.f, z)}); + colors.push(white); + vertices.push({vec3(-p_length, 0.f, -z), vec3(p_length, 0.f, -z)}); + colors.push(white); + z += p_scale; + } + break; + } + case YZ: { + // Y + vertices.push({vec3(0.f, -p_width, 0.f), vec3(0.f, p_width, 0.f)}); + colors.push(green); + for (hpr::scalar z = p_scale; z <= p_height; ) + { + vertices.push({vec3(0.f, -p_width, z), vec3(0.f, p_width, z)}); + colors.push(white); + vertices.push({vec3(0.f, -p_width, -z), vec3(0.f, p_width, -z)}); + colors.push(white); + z += p_scale; + } + // Z + vertices.push({vec3(0.f, 0.f, -p_height), vec3(0.f, 0.f, p_height)}); + colors.push(blue); + for (hpr::scalar y = p_scale; y <= p_width; ) + { + vertices.push({vec3(0.f, y, -p_height), vec3(0.f, y, p_height)}); + colors.push(white); + vertices.push({vec3(0.f, -y, -p_height), vec3(0.f, -y, p_height)}); + colors.push(white); + y += p_scale; + } + } + } + } + +public: + + void rebuild() + { + darray vertices; + darray colors; + + construct(vertices, colors); + + Entity::editVertices(vertices); + Entity::editColors(colors); + Entity::renderMode(gpu::ArrayObject::Lines); + } + + void mode(Mode mode) + { + p_mode = mode; + } + + void scale(hpr::scalar scale) + { + p_scale = scale; + } +}; \ No newline at end of file diff --git a/source/creator/ray.hpp b/source/creator/ray.hpp new file mode 100644 index 0000000..857204a --- /dev/null +++ b/source/creator/ray.hpp @@ -0,0 +1,134 @@ +#pragma once + +#include +#include "camera.hpp" +#include "entity.hpp" + +using namespace hpr; + +vec3 unproject(const vec3& win, const mat4& model, const mat4& proj, const vec4& viewport) +{ + mat4 inverse = inv(proj * model); + vec4 tmp = vec4(win, 1.); + tmp[0] = (tmp[0] - viewport[0]) / viewport[2]; + tmp[1] = (tmp[1] - viewport[1]) / viewport[3]; + tmp = tmp * 2.f - 1.f; + vec4 obj = inverse * tmp; + obj /= obj[3]; + return vec3(obj); +} + +class Ray +{ +public: + vec3 p_position; + vec3 p_direction; + + + Ray() : + p_position {}, + p_direction {} + {} + + Ray(const vec3& position, const vec3& direction) : + p_position {position}, + p_direction {direction} + {} + + void fromScreen(int x, int y, int width, int height, Camera* camera, Entity* entity) + { + /*vec4 start {2.f * (float)x / (float)width - 1.f, 2.f * (float)y / (float)height - 1.f, 0.f, 1.f}; + vec4 end {2.f * (float)x / (float)width - 1.f, 2.f * (float)y / (float)height - 1.f, 1.f, 1.f}; + + mat4 invPV = inv(transpose(camera->projection()) * transpose(camera->view())); + vec4 startWorld = invPV * start; + startWorld /= startWorld[3]; + vec4 endWorld = invPV * end; + endWorld /= endWorld[3];*/ + + + vec3 end = unproject(vec3(x, y, 0), entity->model(), camera->projection(), vec4(0, 0, width, height)); + + p_position = vec3(startWorld); + p_direction = normalize(vec3(endWorld - startWorld)); + } + + bool obb(const vec3& aabbMin, const vec3& aabbMax, Entity* entity, float& tMin, float& tMax) + { + tMin = 0.; + tMax = 1e+5; + + mat4 model = entity->model(); + vec3 obbPos {model(0, 3), model(1, 3), model(2, 3)}; + vec3 delta = obbPos - p_position; + + for (auto n = 0; n < 3; ++n) + { + vec3 axis {model(0, n), model(1, n), model(2, n)}; + scalar e = dot(axis, delta); + scalar f = dot(p_direction, axis); + + if (hpr::abs(f) > 1e-3) + { + scalar t1 = (e + aabbMin[n]) / f; + scalar t2 = (e + aabbMax[n]) / f; + + if (t1 > t2) + std::swap(t1, t2); + if (t2 < tMax) + tMax = t2; + if (t1 > tMin) + tMin = t1; + if (tMax < tMin) + return false; + } + else + { + if (-e + aabbMin[n] > 0.f || -e + aabbMax[n] < 0.f) + return false; + } + } + //dist = tMin; + return true; + } +}; + + +/* +bool RayIntersectsTriangle(Vector3D rayOrigin, + Vector3D rayVector, + Triangle* inTriangle, + Vector3D& outIntersectionPoint) +{ + const float EPSILON = 0.0000001; + Vector3D vertex0 = inTriangle->vertex0; + Vector3D vertex1 = inTriangle->vertex1; + Vector3D vertex2 = inTriangle->vertex2; + Vector3D edge1, edge2, h, s, q; + float a,f,u,v; + edge1 = vertex1 - vertex0; + edge2 = vertex2 - vertex0; + h = rayVector.crossProduct(edge2); + a = edge1.dotProduct(h); + if (a > -EPSILON && a < EPSILON) + return false; // This ray is parallel to this triangle. + f = 1.0/a; + s = rayOrigin - vertex0; + u = f * s.dotProduct(h); + if (u < 0.0 || u > 1.0) + return false; + q = s.crossProduct(edge1); + v = f * rayVector.dotProduct(q); + if (v < 0.0 || u + v > 1.0) + return false; + // At this stage we can compute t to find out where the intersection point is on the line. + float t = f * edge2.dotProduct(q); + if (t > EPSILON) // ray intersection + { + outIntersectionPoint = rayOrigin + rayVector * t; + return true; + } + else // This means that there is a line intersection but not a ray intersection. + return false; +} + */ \ No newline at end of file diff --git a/source/creator/scene.hpp b/source/creator/scene.hpp new file mode 100644 index 0000000..c66afd2 --- /dev/null +++ b/source/creator/scene.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "camera.hpp" +#include "entity.hpp" + +#include + + +class Scene +{ + +protected: + + Camera* p_camera; + hpr::darray> p_nodes; + +public: + + inline + Scene() + {} + + virtual + ~Scene() + { + delete p_camera; + for (auto& node : p_nodes) + node.data()->destroy(); + } + + inline + void camera(Camera* camera) + { + p_camera = camera; + } + + inline + Camera* camera() + { + return p_camera; + } + + inline + void add(const hpr::TreeNode& entityNode) + { + p_nodes.push(entityNode); + } + + inline + darray>& nodes() + { + return p_nodes; + } + + void render() + { + for (auto node : p_nodes) + { + node.data()->render(); + + node.data()->shaderProgram()->bind(); + // camera + node.data()->shaderProgram()->uniformMatrix<4, 4>("view", 1, true, p_camera->view().data()); + node.data()->shaderProgram()->uniformMatrix<4, 4>("projection", 1, true, p_camera->projection().data()); + node.data()->shaderProgram()->uniformVector("viewPos", 1, p_camera->position().data()); + + // light + hpr::vec3 lightColor {1.0f, 1.0f, 1.0f}; + node.data()->shaderProgram()->uniformVector("lightColor", 1, lightColor.data()); + hpr::vec3 lightPos {1.0f, 1.0f, 1.0f}; + node.data()->shaderProgram()->uniformVector("lightPos", 1, lightPos.data()); + + node.data()->shaderProgram()->unbind(); + + //for (auto descendant : node.descendants()) + // descendant->data()->render(); + } + } + +}; diff --git a/source/creator/shaders.hpp b/source/creator/shaders.hpp new file mode 100644 index 0000000..3cb27e0 --- /dev/null +++ b/source/creator/shaders.hpp @@ -0,0 +1,145 @@ +#pragma once + +const char* vertexSource = R"glsl( + +#version 430 core +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec3 color; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +uniform vec3 lightPos; + +out vec3 Normal; +out vec3 Color; +out vec3 FragPos; +out vec3 LightPos; + +void main() +{ + gl_Position = projection * view * model * vec4(position, 1.0); + gl_PointSize = 5; + Normal = mat3(transpose(inverse(model))) * normal; + Color = color; + FragPos = vec3(view * model * vec4(position, 1.0)); + LightPos = lightPos; vec3(view * vec4(lightPos, 1.0)); +} + +)glsl"; + + +const char* fragmentSource = R"glsl( + +#version 430 core + +in vec3 Normal; +in vec3 Color; +in vec3 FragPos; +in vec3 LightPos; + +//uniform vec3 lightPos; +uniform vec3 lightColor; +uniform vec4 objectColor; +uniform vec3 viewPos; + +out vec4 FragColor; + +void main() +{ + float ambientStrength = 0.1; + vec3 ambient = ambientStrength * lightColor; + + // diffuse + vec3 norm = normalize(Normal); + vec3 lightDir = normalize(LightPos - FragPos); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * lightColor; + + // specular + float specularStrength = 0.2; + vec3 viewDir = normalize(viewPos - FragPos); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); + vec3 specular = specularStrength * spec * lightColor; + + vec3 result = (ambient + diffuse) * vec3(objectColor); + FragColor = vec4(result, 1.0); +} + +)glsl"; + +const char* gridVertexSource = R"glsl( + +#version 430 core +uniform mat4 view; +uniform mat4 projection; +vec3 position = vec3(0, 0, 0); + +// Grid position are in xy clipped space +vec3 gridPlane[6] = vec3[]( + vec3(1, 1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0), + vec3(-1, -1, 0), vec3(1, 1, 0), vec3(1, -1, 0) +); +// normal vertice projection +void main() { + gl_Position = projection * view * vec4(gridPlane[gl_VertexID].xyz, 1.0); +} + + +)glsl"; + +const char* gridFragmentSource = R"glsl( + +#version 430 core + +const float tileSize = 0.2; +const float borderSize = 0.468; +const float lineBlur = 0.2; + +vec2 aGrid(vec2 uv) { + return vec2(mod(uv.x, 1.0), mod(uv.y * 2.0, 1.0)); +} + +vec2 bGrid(vec2 uv) { + return vec2(mod(uv.x - 0.5, 1.0), mod((uv.y * 2.0) - 0.5, 1.0)); +} + +float los(vec2 pos) { + vec2 abspos = abs(pos - vec2(0.5)); + return smoothstep(borderSize, borderSize + lineBlur, abspos.x + abspos.y); +} +out vec4 fragColor; +void main() { + vec2 uv = vec2(1.0, 0.);//fragCoord;// / iResolution.xy; + vec2 size = uv / tileSize; + float alos = los(aGrid(size)); + float blos = los(bGrid(size)); + float color = min(alos, blos); + color = pow(color, 1.0 / 2.2); + fragColor = vec4(color); +} + +)glsl"; + +/* +float4 HeatMapColor(float value, float minValue, float maxValue) +{ + #define HEATMAP_COLORS_COUNT 6 + float4 colors[HEATMAP_COLORS_COUNT] = + { + float4(0.32, 0.00, 0.32, 1.00), + float4(0.00, 0.00, 1.00, 1.00), + float4(0.00, 1.00, 0.00, 1.00), + float4(1.00, 1.00, 0.00, 1.00), + float4(1.00, 0.60, 0.00, 1.00), + float4(1.00, 0.00, 0.00, 1.00), + }; + float ratio=(HEATMAP_COLORS_COUNT-1.0)*saturate((value-minValue)/(maxValue-minValue)); + float indexMin=floor(ratio); + float indexMax=min(indexMin+1,HEATMAP_COLORS_COUNT-1); + return lerp(colors[indexMin], colors[indexMax], ratio-indexMin); +} + * */ \ No newline at end of file diff --git a/source/creator/test.cpp b/source/creator/test.cpp index 719463b..5d934f5 100644 --- a/source/creator/test.cpp +++ b/source/creator/test.cpp @@ -1,269 +1,269 @@ -#ifndef __gl_h_ -#include -#endif -#include "hpr/window_system/window_system.hpp" -#include "hpr/window_system/glfw/window_system.hpp" -#include "hpr/window_system/glfw/window.hpp" -#include "hpr/gpu.hpp" -#include "hpr/math.hpp" -#include "hpr/mesh.hpp" - -#include -#include -#include -#include - -const char *vertexShaderSource = "#version 330 core\n" - "layout (location = 0) in vec3 aPos;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" - "}\0"; -const char *fragmentShaderSource = "#version 330 core\n" - "out vec4 FragColor;\n" - "void main()\n" - "{\n" - " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" - "}\n\0"; -const GLchar* vertexSource = R"glsl( - #version 150 core - in vec3 position; - in vec3 color; - in vec2 texcoord; - out vec3 Color; - out vec2 Texcoord; - uniform mat4 model; - uniform mat4 view; - uniform mat4 proj; - uniform vec3 overrideColor; - void main() - { - Color = overrideColor * color; - Texcoord = texcoord; - gl_Position = proj * view * model * vec4(position, 1.0); - } -)glsl"; -int main() -{ - using namespace hpr; - - gpu::WindowSystem *ws = gpu::WindowSystem::create(gpu::WindowContext::Provider::GLFW); - gpu::Window *w = ws->newWindow(); - w->init("test", gpu::Window::Style::Windowed, 0, 0, 600, 400, nullptr, nullptr); - - if (gpu::opengl::Device::loadLoader()) - std::cerr << "Load gl loader error" << std::endl; - - // build and compile our shader program - // ------------------------------------ - // vertex shader - /*unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); - glCompileShader(vertexShader); - // check for shader compile errors - int success; - char infoLog[512]; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; - } - // fragment shader - unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); - glCompileShader(fragmentShader); - // check for shader compile errors - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; - } - // link shaders - unsigned int shaderProgram = glCreateProgram(); - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - glLinkProgram(shaderProgram); - // check for linking errors - glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); - if (!success) { - glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; - } - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); -*/ - mesh::Mesh mesh; - mesh.addVertex(-1, 1, 0.5); - mesh.addVertex(1, 1, 0.5); - mesh.addVertex(1, -1, 0.5); - mesh.addVertex(-1, -1, 0.5); - mesh.addEdge(mesh.vertex(0), mesh.vertex(1)); - mesh.addEdge(mesh.vertex(1), mesh.vertex(2)); - mesh.addEdge(mesh.vertex(2), mesh.vertex(3)); - mesh.addEdge(mesh.vertex(3), mesh.vertex(0)); - mesh.addEdge(mesh.vertex(0), mesh.vertex(2)); - mesh.addFace(mesh.edge(0), mesh.edge(1), mesh.edge(4)); - mesh.addFace(mesh.edge(2), mesh.edge(3), mesh.edge(4)); - - /*darray data (3 * 6, 0.f); - auto arr = mesh.face(0)->vertices() + mesh.face(1)->vertices(); - for (auto n = 0; n < arr.size(); ++n) - for (auto k = 0; k < 3; ++k) - data[k + 3 * n] = *(arr[n]->data() + k);*/ - darray indices (6, 0); - darray data; - for (auto v : mesh.vertices()) - for (auto c : *v) - data.push(c); - - indices[0] = 3; - indices[1] = 1; - indices[2] = 0; - indices[3] = 1; - indices[4] = 2; - indices[5] = 3; - - std::cout << "Data: "; - for (auto p : data) - std::cout << p << " "; - std::cout << std::endl; - std::cout << "Indices: "; - for (auto p : indices) - std::cout << p << " "; - std::cout << std::endl; - - darray vertices { - 0.5f, 0.5f, 0.0f, // top right - 0.5f, -0.5f, 0.0f, // bottom right - -0.5f, -0.5f, 0.0f, // bottom left - -0.5f, 0.5f, 0.0f // top left - }; - darray indices2 { // note that we start from 0! - 0, 1, 3, // first Triangle - 1, 2, 3 // second Triangle - }; - - /* - unsigned int VBO, VAO, EBO; - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). - glBindVertexArray(VAO); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//data.size(), data.data(), GL_STATIC_DRAW); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);//indices.size(), indices.data(), GL_STATIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices2.size(), indices2.data(), GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); - - // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. - //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other - // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. - glBindVertexArray(0); -*/ - gpu::Device* device; - gpu::Device::create(&device, gpu::Device::DeviceAPI::OpenGL); - device->initialize(); - gpu::Shader* vertexShader; - device->createVertexShader(&vertexShader, "shaders/test.vert.glsl", "VS"); - gpu::Shader* fragmentShader; - device->createFragmentShader(&fragmentShader, "shaders/test.frag.glsl", "FS"); - gpu::ShaderProgram* shaderProgram; - device->createShaderProgram(&shaderProgram); - device->attachShader(shaderProgram, vertexShader); - device->attachShader(shaderProgram, fragmentShader); - device->linkProgram(shaderProgram); - - gpu::Buffer* vertexBuffer; - device->createVertexBuffer(&vertexBuffer, sizeof(float) * data.size(), (char*)data.data()); - gpu::Buffer* indexBuffer; - device->createIndexBuffer(&indexBuffer, sizeof(unsigned short) * indices.size(), (char*)indices.data()); - - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - - ImGui::StyleColorsDark(); - - ImGui_ImplGlfw_InitForOpenGL(dynamic_cast(w)->instance(), true); - ImGui_ImplOpenGL3_Init("#version 420"); - - while (w->isOpen()) - { - glViewport(0, 0, 600, 400); - - glEnable(GL_DEPTH_TEST); - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // draw our first triangle - /*glUseProgram(shaderProgram); - glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized - //glDrawArrays(GL_TRIANGLES, 0, 6); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);*/ - device->useShaderProgram(shaderProgram); - device->useVertexBuffer(vertexBuffer, 0, 0); - device->useIndexBuffer(indexBuffer, 0); - //dynamic_cast(device)->Draw(2, 0, 0); - glDrawArrays(GL_TRIANGLES, 0, 6); - //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - bool yes = true; - ImGui::ShowDemoWindow(&yes); - - ImGui::Begin("Hello, world!"); - { - if (ImGui::Button("Exit")) - w->state(gpu::Window::State::Closed); - ImGui::End(); - } - - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - dynamic_cast(w)->swapBuffers(); - dynamic_cast(w)->pollEvents(); - } - - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - device->destroyShaderProgram(shaderProgram, false); - device->destroyShader(vertexShader); - device->destroyShader(fragmentShader); - device->destroyBuffer(vertexBuffer); - device->destroyBuffer(indexBuffer); - delete dynamic_cast(device); - - /*glDeleteVertexArrays(1, &VAO); - glDeleteBuffers(1, &VBO); - glDeleteBuffers(1, &EBO); - glDeleteProgram(shaderProgram);*/ - - ws->destroyWindow(w); - gpu::WindowSystem::destroy(ws); - - return 0; +#ifndef __gl_h_ +#include +#endif +#include "hpr/window_system/window_system.hpp" +#include "hpr/window_system/glfw/window_system.hpp" +#include "hpr/window_system/glfw/window.hpp" +#include "hpr/gpu.hpp" +#include "hpr/math.hpp" +#include "hpr/mesh.hpp" + +#include +#include +#include +#include + +const char *vertexShaderSource = "#version 330 core\n" + "layout (location = 0) in vec3 aPos;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" + "}\0"; +const char *fragmentShaderSource = "#version 330 core\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" + "}\n\0"; +const GLchar* vertexSource = R"glsl( + #version 150 core + in vec3 position; + in vec3 color; + in vec2 texcoord; + out vec3 Color; + out vec2 Texcoord; + uniform mat4 model; + uniform mat4 view; + uniform mat4 proj; + uniform vec3 overrideColor; + void main() + { + Color = overrideColor * color; + Texcoord = texcoord; + gl_Position = proj * view * model * vec4(position, 1.0); + } +)glsl"; +int main() +{ + using namespace hpr; + + gpu::WindowSystem *ws = gpu::WindowSystem::create(gpu::WindowContext::Provider::GLFW); + gpu::Window *w = ws->newWindow(); + w->init("test", gpu::Window::Style::Windowed, 0, 0, 600, 400, nullptr, nullptr); + + if (gpu::opengl::Device::loadLoader()) + std::cerr << "Load gl loader error" << std::endl; + + // build and compile our shader program + // ------------------------------------ + // vertex shader + /*unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); + glCompileShader(vertexShader); + // check for shader compile errors + int success; + char infoLog[512]; + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // fragment shader + unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); + glCompileShader(fragmentShader); + // check for shader compile errors + glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; + } + // link shaders + unsigned int shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + glLinkProgram(shaderProgram); + // check for linking errors + glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); + std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; + } + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); +*/ + mesh::Mesh mesh; + mesh.addVertex(-1, 1, 0.5); + mesh.addVertex(1, 1, 0.5); + mesh.addVertex(1, -1, 0.5); + mesh.addVertex(-1, -1, 0.5); + mesh.addEdge(mesh.vertex(0), mesh.vertex(1)); + mesh.addEdge(mesh.vertex(1), mesh.vertex(2)); + mesh.addEdge(mesh.vertex(2), mesh.vertex(3)); + mesh.addEdge(mesh.vertex(3), mesh.vertex(0)); + mesh.addEdge(mesh.vertex(0), mesh.vertex(2)); + mesh.addFace(mesh.edge(0), mesh.edge(1), mesh.edge(4)); + mesh.addFace(mesh.edge(2), mesh.edge(3), mesh.edge(4)); + + /*darray data (3 * 6, 0.f); + auto arr = mesh.face(0)->vertices() + mesh.face(1)->vertices(); + for (auto n = 0; n < arr.size(); ++n) + for (auto k = 0; k < 3; ++k) + data[k + 3 * n] = *(arr[n]->data() + k);*/ + darray indices (6, 0); + darray data; + for (auto v : mesh.vertices()) + for (auto c : *v) + data.push(c); + + indices[0] = 3; + indices[1] = 1; + indices[2] = 0; + indices[3] = 1; + indices[4] = 2; + indices[5] = 3; + + std::cout << "Data: "; + for (auto p : data) + std::cout << p << " "; + std::cout << std::endl; + std::cout << "Indices: "; + for (auto p : indices) + std::cout << p << " "; + std::cout << std::endl; + + darray vertices { + 0.5f, 0.5f, 0.0f, // top right + 0.5f, -0.5f, 0.0f, // bottom right + -0.5f, -0.5f, 0.0f, // bottom left + -0.5f, 0.5f, 0.0f // top left + }; + darray indices2 { // note that we start from 0! + 0, 1, 3, // first Triangle + 1, 2, 3 // second Triangle + }; + + /* + unsigned int VBO, VAO, EBO; + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); + // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//data.size(), data.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);//indices.size(), indices.data(), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices2.size(), indices2.data(), GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + + // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. + //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other + // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. + glBindVertexArray(0); +*/ + gpu::Device* device; + gpu::Device::create(&device, gpu::Device::DeviceAPI::OpenGL); + device->initialize(); + gpu::Shader* vertexShader; + device->createVertexShader(&vertexShader, "shaders/test.vert.glsl", "VS"); + gpu::Shader* fragmentShader; + device->createFragmentShader(&fragmentShader, "shaders/test.frag.glsl", "FS"); + gpu::ShaderProgram* shaderProgram; + device->createShaderProgram(&shaderProgram); + device->attachShader(shaderProgram, vertexShader); + device->attachShader(shaderProgram, fragmentShader); + device->linkProgram(shaderProgram); + + gpu::Buffer* vertexBuffer; + device->createVertexBuffer(&vertexBuffer, sizeof(float) * data.size(), (char*)data.data()); + gpu::Buffer* indexBuffer; + device->createIndexBuffer(&indexBuffer, sizeof(unsigned short) * indices.size(), (char*)indices.data()); + + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + + ImGui::StyleColorsDark(); + + ImGui_ImplGlfw_InitForOpenGL(dynamic_cast(w)->instance(), true); + ImGui_ImplOpenGL3_Init("#version 420"); + + while (w->isOpen()) + { + glViewport(0, 0, 600, 400); + + glEnable(GL_DEPTH_TEST); + glClearColor(0.2f, 0.2f, 0.2f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // draw our first triangle + /*glUseProgram(shaderProgram); + glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized + //glDrawArrays(GL_TRIANGLES, 0, 6); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);*/ + device->useShaderProgram(shaderProgram); + device->useVertexBuffer(vertexBuffer, 0, 0); + device->useIndexBuffer(indexBuffer, 0); + //dynamic_cast(device)->Draw(2, 0, 0); + glDrawArrays(GL_TRIANGLES, 0, 6); + //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + bool yes = true; + ImGui::ShowDemoWindow(&yes); + + ImGui::Begin("Hello, world!"); + { + if (ImGui::Button("Exit")) + w->state(gpu::Window::State::Closed); + ImGui::End(); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + dynamic_cast(w)->swapBuffers(); + dynamic_cast(w)->pollEvents(); + } + + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + device->destroyShaderProgram(shaderProgram, false); + device->destroyShader(vertexShader); + device->destroyShader(fragmentShader); + device->destroyBuffer(vertexBuffer); + device->destroyBuffer(indexBuffer); + delete dynamic_cast(device); + + /*glDeleteVertexArrays(1, &VAO); + glDeleteBuffers(1, &VBO); + glDeleteBuffers(1, &EBO); + glDeleteProgram(shaderProgram);*/ + + ws->destroyWindow(w); + gpu::WindowSystem::destroy(ws); + + return 0; } \ No newline at end of file diff --git a/source/creator/test2-back.cpp b/source/creator/test2-back.cpp new file mode 100644 index 0000000..e6d4df5 --- /dev/null +++ b/source/creator/test2-back.cpp @@ -0,0 +1,551 @@ + + +/* +#include "hpr/gpu.hpp" +#include "hpr/window_system/window_system.hpp" +#include "hpr/window_system/glfw/window_system.hpp" +#include "hpr/window_system/glfw/window.hpp" +#include "hpr/math.hpp" +#include "hpr/mesh.hpp" + +#include +#include +#include +void GLAPIENTRY +MessageCallback( GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam ) +{ + fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n\n", + ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), + type, severity, message ); +} +*/ + +/* +const char *vertexShaderSource = "#version 430 core\n" + "layout (location = 0) in vec3 aPos;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" + "}\0"; +const char *fragmentShaderSource = "#version 430 core\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" + "}\n\0"; +const GLchar* vertexSource = R"glsl( + #version 150 core + in vec2 position; + in vec3 color; + out vec3 Color; + void main() + { + Color = color; + gl_Position = vec4(position, 0.0, 1.0); + } +)glsl"; +const GLchar* fragmentSource = R"glsl( + #version 150 core + in vec3 Color; + out vec4 outColor; + void main() + { + outColor = vec4(Color, 1.0); + } +)glsl"; +int main() +{ + using namespace hpr; + + gpu::WindowSystem *ws = gpu::WindowSystem::create(gpu::WindowContext::Provider::GLFW); + gpu::Window *w = ws->newWindow(); + w->init("test", gpu::Window::Style::Windowed, 50, 50, 600, 400, nullptr, nullptr); + + if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) + throw std::runtime_error("Cannot initialize gl context"); + +// During init, enable debug output + glEnable ( GL_DEBUG_OUTPUT ); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback( glDebugOutput, nullptr); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE); + gpu::Shader vshader {gpu::Shader::Type::Vertex, vertexShaderSource}; + gpu::Shader fshader {gpu::Shader::Type::Fragment, fragmentShaderSource}; + gpu::ShaderProgram sprogram {}; + + vshader.create(); + fshader.create(); + sprogram.create(); + sprogram.attach(vshader); + sprogram.attach(fshader); + sprogram.link(); + +gpu::Shader vshader2 {gpu::Shader::Type::Vertex, vertexSource}; + gpu::Shader fshader2 {gpu::Shader::Type::Fragment, fragmentSource}; + gpu::ShaderProgram sprogram2 {}; + + vshader2.create(); + fshader2.create(); + sprogram2.create(); + sprogram2.attach(vshader2); + sprogram2.attach(fshader2); + sprogram2.link(); + + //vshader.destroy(); + //fshader.destroy(); + for (auto& sh : sprogram.shaders()) + std::cout << sh.index() << std::endl; + std::cout << sprogram.index() << std::endl; + + darray vertices { + 0.5f, 0.5f, 0.0f, // top right + 0.5f, -0.5f, 0.0f, // bottom right + -0.5f, -0.5f, 0.0f, // bottom left + -0.5f, 0.5f, 0.0f // top left + }; + darray indices2 { // note that we start from 0! + 0, 1, 3, // first Triangle + 1, 2, 3 // second Triangle + }; + + gpu::ArrayObject vao {}; + gpu::BufferObject vbo {gpu::BufferObject::Type::Vertex}; + gpu::BufferObject ebo {gpu::BufferObject::Type::Index}; + + vao.create(); + vao.bind(); + vbo.create(vertices); + ebo.create(indices2); + vao.attribPointer(vbo, 0, 3); + vao.unbind(); + + // Create Vertex Array Object + GLuint vao2; + glGenVertexArrays(1, &vao2); + glBindVertexArray(vao2); + + // Create a Vertex Buffer Object and copy the vertex data to it + GLuint vbo2; + glGenBuffers(1, &vbo2); + + GLfloat vertices2[] = { + -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right + -0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left + }; + + glBindBuffer(GL_ARRAY_BUFFER, vbo2); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices2, GL_STATIC_DRAW); + + // Create an element array + GLuint ebo2; + glGenBuffers(1, &ebo2); + + GLuint elements2[] = { + 0, 1, 2, + 2, 3, 0 + }; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo2); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements2), elements2, GL_STATIC_DRAW); + // Specify the layout of the vertex data + GLint posAttrib = glGetAttribLocation(sprogram2.index(), "position"); + glEnableVertexAttribArray(posAttrib); + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0); + + GLint colAttrib = glGetAttribLocation(sprogram2.index(), "color"); + glEnableVertexAttribArray(colAttrib); + glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat))); + std::cout << sprogram2.index() << std::endl; + gpu::Viewport viewport {{0, 0}, {600, 400}}; + gpu::ColorBuffer colorBuffer; + gpu::DepthBuffer depthBuffer {true}; + + /*IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.IniFilename = nullptr; + io.LogFilename = nullptr; + + ImGui::StyleColorsDark(); + + ImGui_ImplGlfw_InitForOpenGL(dynamic_cast(w)->instance(), true); + ImGui_ImplOpenGL3_Init("#version 430"); + + while (w->isOpen()) + { + viewport.set(); + + //colorBuffer.clear({0.2f, 0.2f, 0.2f, 1.0f}); + //depthBuffer.clear(); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + sprogram.bind(); + vao.bind(); + ebo.bind(); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); + + sprogram2.bind(); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); +/* + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + bool yes = true; + ImGui::ShowDemoWindow(&yes); + + ImGui::Begin("Hello, world!"); + { + if (ImGui::Button("Exit")) + w->state(gpu::Window::State::Closed); + ImGui::End(); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + dynamic_cast(w)->swapBuffers(); + dynamic_cast(w)->pollEvents(); + } + + sprogram.destroy(); + + vbo.destroy(); + ebo.destroy(); + vao.destroy(); +/* + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + ws->destroyWindow(w); + gpu::WindowSystem::destroy(ws); + + return 0; +} +*/ + + +// Link statically with GLEW +#define GLEW_STATIC + +// Headers +//#include +//#include + +#include "hpr/gpu.hpp" + +#include + +void APIENTRY glDebugOutput( + GLenum source, + GLenum type, + unsigned int id, + GLenum severity, + GLsizei length, + const char* message, + const void* userParam +) +{ + // ignore non-significant error/warning codes + if (id == 131169 || id == 131185 || id == 131218 || id == 131204) + return; + + std::cout << "Debug::GL[" << id << "]: " << message << std::endl; + + switch (source) + { + case GL_DEBUG_SOURCE_API: + std::cout << "Source: API"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + std::cout << "Source: Window System"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + std::cout << "Source: Shader Compiler"; + break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + std::cout << "Source: Third Party"; + break; + case GL_DEBUG_SOURCE_APPLICATION: + std::cout << "Source: Application"; + break; + case GL_DEBUG_SOURCE_OTHER: + std::cout << "Source: Other"; + break; + } + std::cout << std::endl; + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: + std::cout << "Type: Error"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + std::cout << "Type: Deprecated Behaviour"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + std::cout << "Type: Undefined Behaviour"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + std::cout << "Type: Portability"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + std::cout << "Type: Performance"; + break; + case GL_DEBUG_TYPE_MARKER: + std::cout << "Type: Marker"; + break; + case GL_DEBUG_TYPE_PUSH_GROUP: + std::cout << "Type: Push Group"; + break; + case GL_DEBUG_TYPE_POP_GROUP: + std::cout << "Type: Pop Group"; + break; + case GL_DEBUG_TYPE_OTHER: + std::cout << "Type: Other"; + break; + } + std::cout << std::endl; + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: + std::cout << "Severity: high"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + std::cout << "Severity: medium"; + break; + case GL_DEBUG_SEVERITY_LOW: + std::cout << "Severity: low"; + break; + case GL_DEBUG_SEVERITY_NOTIFICATION: + std::cout << "Severity: notification"; + break; + } + std::cout << std::endl; +} + +// Shader sources +const GLchar* vertexSource = R"glsl( + #version 430 core +layout (location = 0) in vec2 position; +layout (location = 1) in vec3 color; + + //in vec2 position; + //in vec3 color; + out vec3 Color; + void main() + { + Color = color; + gl_Position = vec4(position, 0.0, 1.0); + } +)glsl"; +const GLchar* fragmentSource = R"glsl( + #version 430 core + in vec3 Color; + out vec4 outColor; + void main() + { + //outColor = vec4(1.0, 1.0, 1.0, 1.0); //vec4(Color, 1.0); + outColor = vec4(Color, 1.0); + } +)glsl"; + +int main() +{ + /*sf::ContextSettings settings; + settings.depthBits = 24; + settings.stencilBits = 8; + settings.majorVersion = 3; + settings.minorVersion = 2; + + sf::Window window(sf::VideoMode(800, 600, 32), "OpenGL", sf::Style::Titlebar | sf::Style::Close, settings); +*/ + + using namespace hpr; +//gpu::WindowSystem *ws = gpu::WindowSystem::create(gpu::WindowContext::Provider::GLFW); + //gpu::Window *w = ws->newWindow(); + //w->init("test", gpu::Window::Style::Windowed, 50, 50, 600, 400, nullptr, nullptr); + gpu::Window w {50, 50, 600, 400, "Test", gpu::Window::Style::Windowed, nullptr, nullptr}; + + w.keyClickCallback([](gpu::Window* window, int key, int scancode, int action, int mods) + { + if (key == GLFW_KEY_ESCAPE) + window->state(gpu::Window::Closed); + }); + + w.context().debug(); + // Initialize GLEW + //glewExperimental = GL_TRUE; + //glewInit(); + + // Create Vertex Array Object + /*GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao);*/ + + gpu::ArrayObject vao {}; + vao.create(); + vao.bind(); + + // Create a Vertex Buffer Object and copy the vertex data to it + //GLuint vbo; + //glGenBuffers(1, &vbo); + gpu::BufferObject vbo2 {gpu::BufferObject::Type::Vertex}; + + darray vertices { + -0.5f, 0.5f, //1.0f, 0.0f, 0.0f, // Top-left + 0.5f, 0.5f, //0.0f, 1.0f, 0.0f, // Top-right + 0.5f, -0.5f, //0.0f, 0.0f, 1.0f, // Bottom-right + -0.5f, -0.5f, //1.0f, 1.0f, 1.0f // Bottom-left + }; + darray colors { + 1.0f, 0.0f, 0.0f, // Top-left + 0.0f, 1.0f, 0.0f, // Top-right + 0.0f, 0.0f, 1.0f, // Bottom-right + 1.0f, 1.0f, 1.0f // Bottom-left + }; + float vertices2[] = { + -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left + 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right + -0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left + }; + + //glBindBuffer(GL_ARRAY_BUFFER, vbo); + //glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW); + //glBindBuffer(GL_ARRAY_BUFFER, vbo.index()); + //glBufferData(static_cast(gpu::BufferObject::Type::Vertex), sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); + //vbo.bind(); + vbo2.create(vertices); + vbo2.bind(); + + gpu::BufferObject vboColors {gpu::BufferObject::Type::Vertex}; + vboColors.create(colors); + vboColors.bind(); + //vbo2.destroy(); + + // Create an element array + /*GLuint ebo; + glGenBuffers(1, &ebo); + + GLuint elements[] = { + 0, 1, 2, + 2, 3, 0 + };*/ + darray elements { + 0, 1, 2, + 2, 3, 0 + }; +/* + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); +*/ + gpu::BufferObject els {gpu::BufferObject::Type::Index}; + els.create(elements); + els.bind(); + // Create and compile the vertex shader + /*GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexSource, NULL); + glCompileShader(vertexShader);*/ + + gpu::Shader vshader {gpu::Shader::Type::Vertex, vertexSource}; + vshader.create(); + + // Create and compile the fragment shader + /*GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentSource, NULL); + glCompileShader(fragmentShader);*/ + + gpu::Shader fshader {gpu::Shader::Type::Fragment, fragmentSource}; + fshader.create(); + + // Link the vertex and fragment shader into a shader program + /*GLuint shaderProgram = glCreateProgram(); + glAttachShader(shaderProgram, vertexShader); + glAttachShader(shaderProgram, fragmentShader); + //glBindFragDataLocation(shaderProgram, 0, "outColor"); + glLinkProgram(shaderProgram); + glUseProgram(shaderProgram);*/ + + gpu::ShaderProgram sprogram {}; + sprogram.create(); + sprogram.attach(vshader); + sprogram.attach(fshader); + sprogram.link(); + sprogram.bind(); + + // Specify the layout of the vertex data + /*GLint posAttrib = glGetAttribLocation(sprogram.index(), "position"); + glEnableVertexAttribArray(posAttrib); + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0);*/ + vao.attribPointer(vbo2, 0, 2); + vao.attribPointer(vboColors, 1, 3); + /*vbo2.bind(); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0); + vboColors.bind(); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);*/ + /*GLint colAttrib = glGetAttribLocation(sprogram.index(), "color"); + glEnableVertexAttribArray(colAttrib); + glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));*/ + + gpu::ColorBuffer cb; + + bool running = true; + while (w.state() != gpu::Window::Closed) + { + /*sf::Event windowEvent; + while (window.pollEvent(windowEvent)) + { + switch (windowEvent.type) + { + case sf::Event::Closed: + running = false; + break; + } + }*/ + + // Clear the screen to black + //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT); + cb.clear(vec4(0.0f, 0.0f, 0.0f, 1.0f)); + + // Draw a rectangle from the 2 triangles using 6 indices + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); + + // Swap buffers + //window.display(); + w.swapBuffers(); + w.pollEvents(); + } + + sprogram.destroy(); + vshader.destroy(); + fshader.destroy(); + /*glDeleteProgram(shaderProgram); + glDeleteShader(fragmentShader); + glDeleteShader(vertexShader);*/ + + //glDeleteBuffers(1, &ebo); + //glDeleteBuffers(1, &vbo); + vbo2.destroy(); + + //glDeleteVertexArrays(1, &vao); + vao.destroy(); + w.destroy(); + + return 0; +} diff --git a/source/creator/test2.cpp b/source/creator/test2.cpp index f388132..66f1215 100644 --- a/source/creator/test2.cpp +++ b/source/creator/test2.cpp @@ -1,133 +1,319 @@ - -#include "hpr/gpu.hpp" -#include "hpr/window_system/window_system.hpp" -#include "hpr/window_system/glfw/window_system.hpp" -#include "hpr/window_system/glfw/window.hpp" -#include "hpr/math.hpp" -#include "hpr/mesh.hpp" - -#include -#include -#include -#include - -const char *vertexShaderSource = "#version 330 core\n" - "layout (location = 0) in vec3 aPos;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" - "}\0"; -const char *fragmentShaderSource = "#version 330 core\n" - "out vec4 FragColor;\n" - "void main()\n" - "{\n" - " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" - "}\n\0"; - -int main() -{ - using namespace hpr; - - gpu::WindowSystem *ws = gpu::WindowSystem::create(gpu::WindowContext::Provider::GLFW); - gpu::Window *w = ws->newWindow(); - w->init("test", gpu::Window::Style::Windowed, 0, 0, 600, 400, nullptr, nullptr); - - if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) - throw std::runtime_error("Cannot initialize gl context"); - - gpu::Shader vshader {gpu::Shader::Type::Vertex, vertexShaderSource}; - gpu::Shader fshader {gpu::Shader::Type::Fragment, fragmentShaderSource}; - gpu::ShaderProgram sprogram {}; - - vshader.create(); - fshader.create(); - sprogram.create(); - sprogram.attach(vshader); - sprogram.attach(fshader); - sprogram.link(); - for (auto& sh : sprogram.shaders()) - std::cout << sh.index() << std::endl; - - - darray vertices { - 0.5f, 0.5f, 0.0f, // top right - 0.5f, -0.5f, 0.0f, // bottom right - -0.5f, -0.5f, 0.0f, // bottom left - -0.5f, 0.5f, 0.0f // top left - }; - darray indices2 { // note that we start from 0! - 0, 1, 3, // first Triangle - 1, 2, 3 // second Triangle - }; - - gpu::ArrayObject vao {}; - gpu::BufferObject vbo {gpu::BufferObject::Type::Vertex}; - gpu::BufferObject ebo {gpu::BufferObject::Type::Index}; - - vao.create(); - vao.bind(); - vbo.create(vertices); - ebo.create(indices2); - vao.attribPointer(vbo, 0, 3); - vao.unbind(); - - gpu::Viewport viewport {{0, 0}, {600, 400}}; - gpu::ColorBuffer colorBuffer; - gpu::DepthBuffer depthBuffer {true}; - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - - ImGui::StyleColorsDark(); - - ImGui_ImplGlfw_InitForOpenGL(dynamic_cast(w)->instance(), true); - ImGui_ImplOpenGL3_Init("#version 420"); - - while (w->isOpen()) - { - viewport.set(); - - colorBuffer.clear({0.8f, 0.2f, 0.2f, 1.0f}); - depthBuffer.clear(); - - sprogram.bind(); - vao.bind(); - - glDrawArrays(GL_TRIANGLES, 0, 6); - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - bool yes = true; - ImGui::ShowDemoWindow(&yes); - - ImGui::Begin("Hello, world!"); - { - if (ImGui::Button("Exit")) - w->state(gpu::Window::State::Closed); - ImGui::End(); - } - - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - dynamic_cast(w)->swapBuffers(); - dynamic_cast(w)->pollEvents(); - } - - sprogram.destroy(); - vshader.destroy(); - fshader.destroy(); - vbo.destroy(); - ebo.destroy(); - vao.destroy(); - - ws->destroyWindow(w); - gpu::WindowSystem::destroy(ws); - - return 0; -} \ No newline at end of file + +#include + +#include "visual.hpp" +#include "entity.hpp" +#include "ui.hpp" +//#include "transform.hpp" +#include "camera.hpp" +#include "scene.hpp" +#include "grid.hpp" +#include +#include "ray.hpp" + + +int main() +{ + + Visual visual; + + visual.window()->keyClickCallback([](gpu::Window* window, int key, int scancode, int action, int mods) + { + if (key == GLFW_KEY_ESCAPE) + window->state(gpu::Window::Closed); + }); + + visual.window()->context().debug(); + + UI ui {visual.window()}; + + + darray vertices { + /*vec2(-0.5f, 0.5f), + vec2(0.5f, 0.5f), + vec2(0.5f, -0.5f), + vec2(-0.5f, -0.5f)*/ + vec3(-0.5f, -0.5f, -0.5f), + vec3(0.5f, -0.5f, -0.5f), + vec3(0.5f, 0.5f, -0.5f), + vec3(0.5f, 0.5f, -0.5f), + vec3(-0.5f, 0.5f, -0.5f), + vec3(-0.5f, -0.5f, -0.5f), + + vec3(-0.5f, -0.5f, 0.5f), + vec3(0.5f, -0.5f, 0.5f), + vec3(0.5f, 0.5f, 0.5f), + vec3(0.5f, 0.5f, 0.5f), + vec3(-0.5f, 0.5f, 0.5f), + vec3(-0.5f, -0.5f, 0.5f), + + vec3(-0.5f, 0.5f, 0.5f), + vec3(-0.5f, 0.5f, -0.5f), + vec3(-0.5f, -0.5f, -0.5f), + vec3(-0.5f, -0.5f, -0.5f), + vec3(-0.5f, -0.5f, 0.5f), + vec3(-0.5f, 0.5f, 0.5f), + + vec3(0.5f, 0.5f, 0.5f), + vec3(0.5f, 0.5f, -0.5f), + vec3(0.5f, -0.5f, -0.5f), + vec3(0.5f, -0.5f, -0.5f), + vec3(0.5f, -0.5f, 0.5f), + vec3(0.5f, 0.5f, 0.5f), + + vec3(-0.5f, -0.5f, -0.5f), + vec3(0.5f, -0.5f, -0.5f), + vec3(0.5f, -0.5f, 0.5f), + vec3(0.5f, -0.5f, 0.5f), + vec3(-0.5f, -0.5f, 0.5f), + vec3(-0.5f, -0.5f, -0.5f), + + vec3(-0.5f, 0.5f, -0.5f), + vec3(0.5f, 0.5f, -0.5f), + vec3(0.5f, 0.5f, 0.5f), + vec3(0.5f, 0.5f, 0.5f), + vec3(-0.5f, 0.5f, 0.5f), + vec3(-0.5f, 0.5f, -0.5f) + }; + darray normals { + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, -1.0f), + + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, 1.0f), + + vec3(-1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f) + }; + darray colors { + vec3(1.0f, 0.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f) + }; + darray> indices { + Vector(0, 1, 2), + Vector(2, 3, 0) + }; + + Entity entity {visual.shaderProgram()}; + entity.addVertices(vertices); + entity.addNormals(normals); + //entity.addColors(colors); + //entity.addIndices(indices); + + Scene scene; + scene.camera(new OrbitCamera()); + scene.add(TreeNode(entity)); + //Transform transform {&entity}; + + //gpu::DepthBuffer depthBuffer {true}; + visual.depthBuffer().bind(); + //gpu::CullFace cullFace {gpu::CullFace::Mode::FrontAndBack}; + float angle = 0; + glEnable(GL_PROGRAM_POINT_SIZE); + + /*gpu::ShaderProgram shaderProgram; + gpu::Shader vertexShader {gpu::Shader::Type::Vertex, gridVertexSource}; + vertexShader.create(); + + gpu::Shader fragmentShader {gpu::Shader::Type::Fragment, gridFragmentSource}; + fragmentShader.create(); + + shaderProgram.create(); + shaderProgram.attach(vertexShader); + shaderProgram.attach(fragmentShader); + shaderProgram.link(); + + shaderProgram.bind(); + shaderProgram.uniformMatrix<4, 4>("view", 1, true, scene.camera()->view().data()); + shaderProgram.uniformMatrix<4, 4>("projection", 1, true, scene.camera()->projection().data()); + shaderProgram.unbind();*/ + + /*Entity grid {visual.shaderProgram()}; + + darray vertices2; + auto genVert = [](float x, float y){; + return darray{ + vec3(-1.0f + x, 0.f + y, 0.f), + vec3(1.0f + x, 0.f + y, 0.f), + vec3(0.f + x, -1.0f + y, 0.f), + vec3(0.f + x, 1.0f + y, 0.f) + };}; + for (auto x = -100; x < 100; ++x) + for (auto y = -100; y < 100; ++y) + vertices2.push(genVert(x, y)); + grid.addVertices(vertices2); + grid.color(vec4(1, 1, 1, 1)); + grid.renderMode(gpu::ArrayObject::Lines);*/ + //Grid grid {visual.shaderProgram()}; + //scene.add(TreeNode(grid)); + /* + gpu::ArrayObject ao; + gpu::BufferObject bo; + ao.create(); + ao.bind(); + bo.create(vertices2); + bo.bind(); + ao.attribPointer(bo, 0, 3); + ao.unbind(); + bo.unbind();*/ + glfwWindowHint(GLFW_SAMPLES, 4); + ImPlot::CreateContext(); + glEnable(GL_MULTISAMPLE); + /*gpu::Texture tex; + tex.create(); + gpu::Renderbuffer rb; + rb.create();*/ + gpu::Framebuffer framebuffer; + framebuffer.create(); + gpu::Viewport viewport; + /*framebuffer.bind(); + framebuffer.attach(tex); + framebuffer.attach(rb); + framebuffer.unbind();*/ + const vec4 background = vec4(0.2f, 0.2f, 0.2f, 1.0f); + while (visual.window()->state() != gpu::Window::Closed) + { + + visual.colorBuffer().clear(background); + visual.depthBuffer().clear(); + //cullFace.bind(); + //entity.render(hpr::gpu::ArrayObject::Triangles); + //angle += 1; + //transform.rotate({0, 1, 0}, angle); + //transform.rotate({0, 0, 1}, angle); + //transform.render(); + viewport.size() = vec2(framebuffer.width(), framebuffer.height()); + viewport.set(); + framebuffer.bind(); + framebuffer.rescale(); + + visual.colorBuffer().clear(background); + visual.depthBuffer().clear(); + + scene.camera()->aspect() = (float)framebuffer.width() / (float)framebuffer.height(); + scene.render(); + framebuffer.unbind(); + viewport.size() = vec2((float)visual.window()->width(), (float)visual.window()->height()); + viewport.set(); + //shaderProgram.bind(); + + ui.createFrame(); + bool yes = true; + ImGui::ShowDemoWindow(&yes); + ImPlot::ShowDemoWindow(&yes); + + ImGui::Begin("Hello, world!"); + { + + if (ImGui::Button("Exit")) + visual.window()->state(gpu::Window::Closed); + ImGui::End(); + } + + ui.render(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + if (ImGui::Begin("Scene")) + { + ImGui::PopStyleVar(); + if (!ImGui::IsWindowCollapsed()) + { + framebuffer.width() = static_cast(ImGui::GetContentRegionAvail().x); + framebuffer.height() = static_cast(ImGui::GetContentRegionAvail().y); + + ImGui::Image(reinterpret_cast(framebuffer.texture().index()), ImGui::GetContentRegionAvail(), + ImVec2{0, 1}, ImVec2{1, 0}); + + ImGuiIO& io = ImGui::GetIO(); + Ray ray; + ray.fromScreen(io.MousePos.x, io.MousePos.y, framebuffer.width(), framebuffer.height(), scene.camera()); + float tMin, tMax; + Entity* ent = scene.nodes()[0].data(); + bool rayOBB = ray.obb({-1.0f, -1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, ent, tMin, tMax); + //std::cout << rayOBB << std::endl; + if (rayOBB) + ent->color(vec4(1.f, 0.f, 0.f, 1.f)); + else + ent->color(vec4(0.f, 1.f, 0.f, 1.f)); + if (ImGui::Begin("Properties")) + { + ImGui::DragFloat3("position", ray.p_position.data()); + ImGui::DragFloat3("direction", ray.p_direction.data()); + vec2 mouse {io.MousePos.x, io.MousePos.y}; + ImGui::DragFloat2("mouse", mouse.data()); + ImGui::Checkbox("ray", &rayOBB); + ImGui::DragFloat("dist", &tMin); + ImGui::DragFloat("dist", &tMax); + ImGui::End(); + } + if (ImGui::IsWindowHovered()) + { + if (io.WantCaptureMouse) + { + dynamic_cast(scene.camera())->scrollEvent(0, io.MouseWheel); + + if (ImGui::IsMouseDown(ImGuiMouseButton_Middle)) //(io.MouseDown[ImGuiMouseButton_Middle]) + { + if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) //(io.KeysDown[ImGuiKey_LeftShift]) + { + dynamic_cast(scene.camera())->moveEvent(io.MouseDelta.x, io.MouseDelta.y); + } + else + { + dynamic_cast(scene.camera())->rotateEvent(io.MouseDelta.x, io.MouseDelta.y); + } + } + + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) + { + + + } + } + } + } + ImGui::End(); + } + ui.renderFrame(); + visual.render(); + + } + ImPlot::DestroyContext(); + framebuffer.destroy(); + return 0; +} diff --git a/source/creator/transform.hpp b/source/creator/transform.hpp new file mode 100644 index 0000000..962595f --- /dev/null +++ b/source/creator/transform.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include +#include + +#include "entity.hpp" +#include +#include +#include + + +class Transform +{ + +public: + + enum Projection + { + Perspective, + Orthographic + }; + +protected: + + Projection p_projection; + hpr::scalar p_distance; + hpr::scalar p_aspect; + hpr::scalar p_fieldOfView; + hpr::scalar p_nearPlane; + hpr::scalar p_farPlane; + + hpr::vec3 p_target; + hpr::vec3 p_left; + hpr::vec3 p_front; + hpr::vec3 p_up; + hpr::vec3 p_rotation; + + hpr::mat4 p_model; + + Entity* p_entity; + + hpr::vec3 p_position; + +public: + + inline Transform() = delete; + + inline Transform(Entity* entity) : + p_projection {Orthographic}, + p_distance {10}, + p_aspect {800.f / 600}, + p_fieldOfView {45}, + p_nearPlane {0.1}, + p_farPlane {100}, + p_target {0, 0, 0}, + p_left {1, 0, 0}, + p_front {0, 0, -1}, + p_up {0, 0, 1}, + p_rotation {45, 45, 0}, + p_model {hpr::mat4::identity()}, + p_entity {entity}, + p_position {} + { + //for (auto v : p_model) + // std::cout << v << std::endl; + } + + hpr::mat4 view() + { + hpr::vec3 rotation { + hpr::cos(hpr::rad(p_rotation[1])) * hpr::sin(hpr::rad(p_rotation[0])), + hpr::cos(hpr::rad(p_rotation[1])) * hpr::cos(hpr::rad(p_rotation[0])), + hpr::sin(hpr::rad(p_rotation[1]))}; + hpr::vec3 pos = p_target + p_distance * rotation; + + p_front = p_target - pos; + p_front /= hpr::length(p_front); + + p_up = hpr::vec3(0, 0, 1); + p_left = hpr::normalize(hpr::cross(p_up, p_front)); + p_up = hpr::cross(p_front, p_left); + auto dd = glm::lookAt(glm::vec3(pos[0], pos[1], pos[2]), glm::vec3(pos[0] + p_front[0], pos[1] + p_front[1], pos[2] + p_front[2]), glm::vec3(p_up[0], p_up[1], p_up[2])); + auto dd2 = hpr::lookAt(pos, pos + p_front, p_up); + p_position = pos; + //for (auto v : dd2) + // std::cout << v << " "; + //std::cout << std::endl; + return dd2; + } +/* + -0.707107 0.707107 0 -0 + -0.5 -0.5 0.707107 -1.90735e-06 + 0.5 0.5 0.707107 -10 + 0 0 0 1 + */ + void rotateEvent(float xdelta, float ydelta) + { + p_rotation += hpr::vec3(xdelta, ydelta, 0); + } + + void moveEvent(float xdelta, float ydelta) + { + p_target += (p_left * xdelta + p_up * ydelta) * 1e-3f; + } + + void scrollEvent(float xdelta, float ydelta) + { + p_distance -= ydelta; + } + + hpr::mat4 projection(Projection projection) + { + p_projection = projection; + switch (p_projection) + { + case Perspective: + return hpr::perspective(hpr::rad(p_fieldOfView), p_aspect, p_nearPlane, p_farPlane); + case Orthographic: + return hpr::ortho(-p_distance * p_aspect, p_distance * p_aspect, -p_distance, p_distance, p_nearPlane, p_farPlane); + } + } + + void clear() + { + p_model = hpr::mat4::identity(); + } + + void translate(const hpr::vec3& position) + { + p_model = hpr::translate(p_model, position); + } + + void rotate(const hpr::vec3& axis, hpr::scalar angle) + { + p_model = hpr::rotate(p_model, axis, hpr::rad(angle)); + } + + void scale(const hpr::vec3& size) + { + p_model = hpr::scale(p_model, size); + } + /*struct Vec { + float x, y, z, w; + };*/ + void render() + { + //double model[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + //Vec model2[] = {Vec{0, 0, 0, 0}, Vec{0, 0, 0, 0},Vec{0, 0, 0, 0},Vec{0, 0, 0, 0}}; + //static_assert(sizeof(model2) == sizeof(float) * 16 && std::is_standard_layout_v); + //static_assert((sizeof(hpr::StaticArray::pointer) == (sizeof(GLfloat) * 16)) && + // (std::is_standard_layout::value), + // "Matrix4 does not satisfy contiguous storage requirements"); + p_entity->shaderProgram()->bind(); + + //glUniformMatrix4fv(glGetUniformLocation(p_entity->shaderProgram()->index(), "model"), + // 1, GL_FALSE, p_model.data()); + p_entity->shaderProgram()->uniformMatrix<4, 4, float>("model", 1, true, p_model.data()); + hpr::mat4 _view = view(); + p_entity->shaderProgram()->uniformMatrix<4, 4, float>("view", 1, true, _view.data()); + hpr::mat4 _projection = projection(p_projection); + + p_entity->shaderProgram()->uniformVector("viewPos", 1, p_position.data()); + + //for (auto v : _projection) + // std::cout << v << std::endl; + glm::mat4 _proj = glm::ortho(-p_distance * p_aspect, p_distance * p_aspect, -p_distance, p_distance, p_nearPlane, p_farPlane); + + p_entity->shaderProgram()->uniformMatrix<4, 4, float>("projection", 1, true, _projection.data()); + + hpr::vec3 objectColor {1.0f, 0.5f, 0.31f}; + p_entity->shaderProgram()->bind(); + p_entity->shaderProgram()->uniformVector("objectColor", 1, objectColor.data()); + p_entity->render(gpu::ArrayObject::Mode::Triangles); + + objectColor = {1.0f, 1.0f, 1.0f}; + p_entity->shaderProgram()->bind(); + p_entity->shaderProgram()->uniformVector("objectColor", 1, objectColor.data()); + p_entity->render(gpu::ArrayObject::Mode::LineLoop); + + p_entity->shaderProgram()->unbind(); + + clear(); + } +}; \ No newline at end of file diff --git a/source/creator/ui.hpp b/source/creator/ui.hpp new file mode 100644 index 0000000..005525a --- /dev/null +++ b/source/creator/ui.hpp @@ -0,0 +1,157 @@ +#pragma once + +#include + +#include +#include +#include +#include +//#include + + +using namespace hpr; + +class UI +{ + + +public: + + UI(gpu::Window* window) + { + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGui_ImplGlfw_InitForOpenGL(window->instance(), true); + ImGui_ImplOpenGL3_Init("#version 430"); + io().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io().ConfigFlags |= ImGuiConfigFlags_DockingEnable; + } + + ~UI() + { + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + void createFrame() + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void renderFrame() + { + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + } + + inline + ImGuiIO& io() + { + return ImGui::GetIO(); + } + + inline + void render() + { + static auto first_time = true; + static bool show_object_explorer = true; + static bool show_properties = true; + static bool show_demo = false; + + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("Options")) + { + ImGui::MenuItem("Undo", "CTRL+Z"); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("View")) + { + ImGui::MenuItem("Object explorer", nullptr, &show_object_explorer); + ImGui::MenuItem("Properties", nullptr, &show_properties); + ImGui::MenuItem("Demo", nullptr, &show_demo); + ImGui::EndMenu(); + } + + ImGui::EndMainMenuBar(); + } + + if (show_demo) + ImGui::ShowDemoWindow(); + + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->WorkPos); + ImGui::SetNextWindowSize(viewport->WorkSize); + ImGui::SetNextWindowViewport(viewport->ID); + + ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar; // ImGuiWindowFlags_NoDocking; + window_flags |= ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; + //window_flags |= ImGuiWindowFlags_MenuBar; + //window_flags |= ImGuiWindowFlags_NoBackground; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; + + if (ImGui::Begin("Main dockspace", nullptr, window_flags)) + { + ImGui::PopStyleVar(3); + + ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); + ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); + + if (first_time) + { + first_time = false; + + ImGui::DockBuilderRemoveNode(dockspace_id); + ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace); + ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size); + + ImGuiID dock_id_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.2f, nullptr, &dockspace_id); + //ImGuiID dock_id_down = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 1.0f, &dockspace_id, nullptr); + ImGuiID dock_id_down = ImGui::DockBuilderSplitNode(dock_id_left, ImGuiDir_Down, 0.5f, nullptr, &dock_id_left); + + ImGuiDockNode* node = ImGui::DockBuilderGetNode(dockspace_id); + node->LocalFlags |= ImGuiDockNodeFlags_NoCloseButton; + + ImGui::DockBuilderDockWindow("Scene", dockspace_id); + ImGui::DockBuilderDockWindow("Object explorer", dock_id_left); + // Properties + node = ImGui::DockBuilderGetNode(dock_id_down); + node->LocalFlags |= ImGuiDockNodeFlags_NoCloseButton | ImGuiDockNodeFlags_NoTabBar; + ImGui::DockBuilderDockWindow("Properties", dock_id_down); + //ImGui::DockBuilderDockWindow("Scene_", dock_id_down); + ImGui::DockBuilderFinish(dockspace_id); + } + + ImGui::End(); + } + + ImGuiViewport* viewport2 = ImGui::GetMainViewport(); + ImGuiWindowFlags window_flags2 = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; + float height = ImGui::GetFrameHeight(); + + if (ImGui::BeginViewportSideBar("##SecondaryMenuBar", viewport2, ImGuiDir_Up, height, window_flags2)) { + if (ImGui::BeginMenuBar()) { + ImGui::Text("menu bar"); + ImGui::EndMenuBar(); + } + ImGui::End(); + } + + if (ImGui::BeginViewportSideBar("#MainStatusBar", viewport2, ImGuiDir_Down, height, window_flags2)) { + if (ImGui::BeginMenuBar()) { + ImGui::Text("status bar"); + ImGui::EndMenuBar(); + } + ImGui::End(); + } + } +}; \ No newline at end of file diff --git a/source/creator/visual.hpp b/source/creator/visual.hpp new file mode 100644 index 0000000..8e1802a --- /dev/null +++ b/source/creator/visual.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include +#include "shaders.hpp" + +using namespace hpr; + +class Visual +{ + +protected: + + gpu::Window* p_window; + gpu::ShaderProgram* p_shaderProgram; + gpu::ColorBuffer p_colorBuffer; + gpu::DepthBuffer p_depthBuffer; + +public: + + Visual() : + p_window {new gpu::Window{50, 50, 1000, 800, "Hyporo", gpu::Window::Windowed, nullptr, nullptr}}, + p_shaderProgram {new gpu::ShaderProgram}, + p_colorBuffer {}, + p_depthBuffer {} + { + gpu::Shader vertexShader {gpu::Shader::Type::Vertex, vertexSource}; + vertexShader.create(); + + gpu::Shader fragmentShader {gpu::Shader::Type::Fragment, fragmentSource}; + fragmentShader.create(); + + p_shaderProgram->create(); + p_shaderProgram->attach(vertexShader); + p_shaderProgram->attach(fragmentShader); + p_shaderProgram->link(); + + vertexShader.destroy(); + fragmentShader.destroy(); + + p_window->framebufferResizeCallback([](gpu::Window* w, int width, int height){ + w->size(width, height); + }); + } + + ~Visual() + { + p_shaderProgram->destroy(); + delete p_shaderProgram; + p_window->destroy(); + delete p_window; + } + + gpu::Window* window() + { + return p_window; + } + + gpu::ShaderProgram* shaderProgram() + { + return p_shaderProgram; + } + + gpu::ColorBuffer& colorBuffer() + { + return p_colorBuffer; + } + + gpu::DepthBuffer& depthBuffer() + { + return p_depthBuffer; + } + + void render() + { + p_window->swapBuffers(); + p_window->pollEvents(); + } +}; \ No newline at end of file diff --git a/source/hpr/CMakeLists.txt b/source/hpr/CMakeLists.txt index c4c542b..3dadbb8 100644 --- a/source/hpr/CMakeLists.txt +++ b/source/hpr/CMakeLists.txt @@ -1,22 +1,39 @@ - -# Modules -add_subdirectory(core) -add_subdirectory(containers) -add_subdirectory(math) -add_subdirectory(io) -add_subdirectory(mesh) -add_subdirectory(geometry) - -if(WITH_CSG) - include(${CMAKE_SOURCE_DIR}/cmake/external/occt.cmake) - add_subdirectory(csg) -endif() -if(WITH_GPU) - include(${CMAKE_SOURCE_DIR}/cmake/external/glad.cmake) - include(${CMAKE_SOURCE_DIR}/cmake/external/stb.cmake) - add_subdirectory(gpu) -endif() -if(WITH_WINDOW_SYSTEM) - include(${CMAKE_SOURCE_DIR}/cmake/external/glfw.cmake) - add_subdirectory(window_system) -endif() + +# Modules and dependencies + +if (HPR_WITH_CONTAINERS) + add_subdirectory(containers) +endif() + +if (HPR_WITH_MATH) + add_subdirectory(math) +endif() + +if (HPR_WITH_IO) + add_subdirectory(io) +endif() + +if (HPR_WITH_MESH) + add_subdirectory(mesh) +endif() + +if (HPR_WITH_GEOMETRY) + add_subdirectory(geometry) +endif() + +if(HPR_WITH_CSG) + include(${HPR_EXTERNAL_PATH}/occt.cmake) + add_subdirectory(csg) +endif() + +if(HPR_WITH_GPU) + include(${HPR_EXTERNAL_PATH}/glad.cmake) + include(${HPR_EXTERNAL_PATH}/glfw.cmake) + include(${HPR_EXTERNAL_PATH}/stb.cmake) + add_subdirectory(gpu) +endif() + +if(HPR_WITH_PARALLEL) + include(${HPR_EXTERNAL_PATH}/onetbb.cmake) + add_subdirectory(parallel) +endif() diff --git a/source/hpr/containers.hpp b/source/hpr/containers.hpp index 1ea4bf1..86ccdd8 100644 --- a/source/hpr/containers.hpp +++ b/source/hpr/containers.hpp @@ -1,3 +1,3 @@ -#pragma once - -#include "containers/array.hpp" +#pragma once + +#include diff --git a/source/hpr/containers/CMakeLists.txt b/source/hpr/containers/CMakeLists.txt index 499e70e..502295d 100644 --- a/source/hpr/containers/CMakeLists.txt +++ b/source/hpr/containers/CMakeLists.txt @@ -1,62 +1,21 @@ -cmake_minimum_required(VERSION 3.16) - -project(containers - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX -) - -add_library(${PROJECT_NAME} INTERFACE) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../containers.hpp" "*.hpp" "array/*.hpp" -) - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ -) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) - - -if(HPR_TEST) - add_subdirectory(tests) -endif() \ No newline at end of file +cmake_minimum_required(VERSION 3.16) + +project(containers + VERSION "${HPR_VERSION}" + LANGUAGES CXX +) + +hpr_add_library(${PROJECT_NAME} INTERFACE) + +hpr_collect_interface(${PROJECT_NAME} + "../containers.hpp" + "*.hpp" + "array/*.hpp" +) + +target_sources(${PROJECT_NAME} + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> +) + +hpr_tests(${PROJECT_NAME} tests) +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) \ No newline at end of file diff --git a/source/hpr/containers/array.hpp b/source/hpr/containers/array.hpp index 39bc1c7..d9bc6f0 100644 --- a/source/hpr/containers/array.hpp +++ b/source/hpr/containers/array.hpp @@ -1,4 +1,5 @@ -#pragma once - -#include "array/dynamic_array.hpp" -#include "array/static_array.hpp" \ No newline at end of file +#pragma once + +#include +#include +#include \ No newline at end of file diff --git a/source/hpr/containers/array/dynamic_array.hpp b/source/hpr/containers/array/dynamic_array.hpp index 5359c11..916ade0 100644 --- a/source/hpr/containers/array/dynamic_array.hpp +++ b/source/hpr/containers/array/dynamic_array.hpp @@ -1,427 +1,297 @@ -#pragma once - -#include "iterator.hpp" -#include -#include -#include - - -namespace hpr -{ - -template -class DynamicArray -{ - -public: - - using difference_type = std::ptrdiff_t; - using value_type = Type; - using size_type = size_t; - using pointer = Type*; - using reference = Type&; - using iterator = Iterator; - using const_pointer = Type const*; - using const_reference = Type const&; - using const_iterator = Iterator; - -protected: - - size_type p_size; - size_type p_capacity; - pointer p_start; - pointer p_end; - pointer p_storage_end; - -public: - - inline - DynamicArray() : - p_size {0}, - p_capacity {1}, - p_start {new value_type[p_capacity]}, - p_end {p_start}, - p_storage_end {p_end + p_capacity} - {} - - inline - DynamicArray(const DynamicArray& arr) : - p_size {arr.p_size}, - p_capacity {arr.p_capacity}, - p_start {new value_type[arr.p_size]}, - p_end {p_start + p_size}, - p_storage_end {p_start + p_capacity} - { - std::copy(arr.p_start, arr.p_end, p_start); - } - - //! Move constructor - inline - DynamicArray(DynamicArray&& arr) noexcept : - DynamicArray {} - { - swap(*this, arr); - } - - inline - DynamicArray(const_iterator start, const_iterator end) : - p_size {size_type(end.operator->() - start.operator->())}, - p_capacity {p_size}, - p_start {new value_type[p_size]}, - p_end {p_start + p_size}, - p_storage_end {p_start + p_capacity} - { - std::copy(start, end, p_start); - } - - inline - DynamicArray(iterator start, iterator end) : - p_size {size_type(end.operator->() - start.operator->())}, - p_capacity {p_size}, - p_start {new value_type[p_size]}, - p_end {p_start + p_size}, - p_storage_end {p_start + p_capacity} - { - std::copy(start, end, p_start); - } - - inline - DynamicArray(std::initializer_list list) : - p_size {list.size()}, - p_capacity {list.size()}, - p_start {new value_type[p_capacity]}, - p_end {p_start + p_size}, - p_storage_end {p_start + p_capacity} - { - std::copy(list.begin(), list.end(), p_start); - } - - inline - DynamicArray(size_type size, value_type value) : - p_size {0}, - p_capacity {size}, - p_start {new value_type[p_capacity]}, - p_end {p_start + p_size}, - p_storage_end {p_start + p_capacity} - { - for (auto n = 0; n < size; ++n) - push(value); - } - - inline - DynamicArray& operator=(const DynamicArray& vs) noexcept - { - delete[] p_start; - p_size = vs.p_size; - p_capacity = vs.p_size; - p_start = new value_type[p_capacity]; - p_end = p_start + p_size; - p_storage_end = p_start + p_capacity; - std::copy(vs.begin(), vs.end(), begin()); - return *this; - } - - inline - DynamicArray& operator=(DynamicArray&& arr) noexcept - { - swap(*this, arr); - return *this; - } - - virtual - ~DynamicArray() - { - //std::destroy(p_start, p_end); - delete[] p_start; - } - - // Member functions - - virtual - iterator begin() - { - return iterator(p_start); - } - - [[nodiscard]] virtual - const_iterator begin() const - { - return const_iterator(p_start); - } - - virtual - iterator end() - { - return iterator(p_end); - } - - virtual - const_iterator end() const - { - return const_iterator(p_end); - } - - - [[nodiscard]] virtual - size_type size() const - { - return size_type(p_end - p_start); - } - - [[nodiscard]] virtual - size_type capacity() const - { - return size_type(p_storage_end - p_start); - } - - [[nodiscard]] virtual - bool is_empty() const - { - return begin() == end(); - } - - virtual - reference operator[](size_type n) - { - if (n >= size()) - throw std::out_of_range("Index out of bounds"); - return *(p_start + n); - } - - virtual - const_reference operator[](size_type n) const - { - if (n >= size()) - throw std::out_of_range("Index out of bounds"); - return *(p_start + n); - } - - virtual - reference front() - { - return *p_start; - } - - virtual - reference back() - { - return *(p_end - 1); - } - - virtual - pointer data() - { - return p_start; - } - - [[nodiscard]] virtual - const_pointer data() const - { - return p_start; - } - - virtual - void resize(size_type newCapacity) - { - if (newCapacity == p_capacity) - return; - if (std::numeric_limits::max() - size() < newCapacity) - throw std::length_error("Wrong capacity value passed (possibly negative)"); - - pointer newStart = new value_type[newCapacity]; - - if (newCapacity > p_capacity) - { - std::move(p_start, p_end, newStart); - } - else if (newCapacity < p_capacity) - { - if (newCapacity < p_size) { - std::move(p_start, p_start + newCapacity, newStart); - p_size = newCapacity; - } - else - { - std::move(p_start, p_end, newStart); - } - } - - delete[] p_start; - std::swap(p_start, newStart); - p_capacity = newCapacity; - p_end = p_start + p_size; - p_storage_end = p_start + p_capacity; - } - - virtual - void push(const value_type& val) - { - if (p_end == p_storage_end) - resize(p_capacity * 2); - *p_end = val; - ++p_end; - ++p_size; - } - - virtual - void push(value_type&& val) - { - if (p_end == p_storage_end) - resize(p_capacity * 2); - *p_end = std::move(val); - ++p_end; - ++p_size; - } - - virtual - value_type pop() - { - if (is_empty()) - throw std::length_error("Cannot pop element from empty array"); - value_type val = back(); - std::destroy_at(p_end); - --p_end; - --p_size; - return val; - } - - virtual - void insert(size_type position, const value_type& val) - { - if (p_end == p_storage_end) - resize(p_capacity * 2); - for (size_type n = p_size; n > position; --n) - *(p_start + n) = std::move(*(p_start + n - 1)); - *(p_start + position) = val; - ++p_size; - ++p_end; - } - - virtual - void insert(size_type position, value_type&& val) - { - if (p_end == p_storage_end) - resize(p_capacity * 2); - for (size_type n = p_size; n > position; --n) - *(p_start + n) = std::move(*(p_start + n - 1)); - *(p_start + position) = std::move(val); - ++p_size; - ++p_end; - } - - /*virtual - int findByAddress(const value_type& value) - { - // TODO: make better approach - for (int n = 0; n < p_size; ++n) { - std::equal_to - pointer lhs = (p_start + n); //*std::addressof(*(p_start + n)); - pointer rhs = *value; //*std::addressof(value); - if (lhs == rhs) - return n; - } - return -1; - }*/ - - virtual - void remove(size_type position) - { - for (size_type n = position; n < p_size - 1; ++n) - *(p_start + n) = std::move(*(p_start + n + 1)); - std::destroy_at(p_end); - --p_end; - --p_size; - } - - virtual - void remove(iterator position) - { - if (position + 1 != end()) - std::copy(position + 1, end(), position); - std::destroy_at(p_end); - --p_end; - --p_size; - } - - virtual - void remove(const std::function& condition) - { - size_type newSize = p_size; - for (size_type offset = 0; offset < newSize; ++offset) - if (condition(*(p_start + offset))) { - for (size_type n = offset; n < newSize; ++n) { - *(p_start + n) = std::move(*(p_start + n + 1)); - } - --newSize; - --offset; - } - p_size = newSize; - p_end = p_start + p_size; - } - - /*virtual - void remove(const value_type& value) - { - int index = findByAddress(value); - if (index != -1) - remove(index); - else - throw std::runtime_error("Value is not found to remove it"); - }*/ - - virtual - void clear() - { - delete[] p_start; - p_size = 0; - p_capacity = 1; - p_start = new value_type[p_capacity]; - p_end = p_start; - p_storage_end = p_end + p_capacity; - } - - DynamicArray slice(iterator start, iterator end) - { - return DynamicArray {start, end}; - } - - // Friend functions - - friend - void swap(DynamicArray& lhs, DynamicArray& rhs) - { - std::swap(lhs.p_size, rhs.p_size); - std::swap(lhs.p_capacity, rhs.p_capacity); - std::swap(lhs.p_start, rhs.p_start); - std::swap(lhs.p_end, rhs.p_end); - std::swap(lhs.p_storage_end, rhs.p_storage_end); - } - - friend - bool operator==(const DynamicArray& lhs, const DynamicArray& rhs) - { - for (auto n = 0; n < lhs.size(); ++n) - if (lhs[n] != rhs[n]) - return false; - return true; - } - - friend - DynamicArray operator+(const DynamicArray& lhs, const DynamicArray& rhs) - { - DynamicArray arr {rhs.size() + lhs.size(), {}}; - for (auto n = 0; n < rhs.size(); ++n) - { - arr[n] = rhs[n]; - arr[n + rhs.size()] = lhs[n]; - } - return arr; - } -}; - -// Aliases - -template -using darray = DynamicArray; - +#pragma once + +#include + +#include +#include + + +namespace hpr +{ + +// forward declaration + +template +class DynamicArray; + +// type traits + +template +struct is_sequence> : public std::true_type +{}; + +// aliases + +template +using darray = DynamicArray; + +// class definition + +template +class DynamicArray : public Sequence +{ + + using base = Sequence; + +public: + + using difference_type = std::ptrdiff_t; + using value_type = T; + using size_type = Size; + using pointer = T*; + using reference = T&; + using iterator = Iterator; + using const_pointer = T const*; + using const_reference = T const&; + using const_iterator = Iterator; + +public: + + friend constexpr + void swap(DynamicArray& main, DynamicArray& other) noexcept + { + using std::swap; + swap(static_cast(main), static_cast(other)); + } + + constexpr + DynamicArray() noexcept : + base {} + {} + + constexpr explicit + DynamicArray(const base& b) noexcept : + base {b} + {} + + constexpr + DynamicArray(const DynamicArray& arr) noexcept : + base {static_cast(arr)} + {} + + //! Move constructor + constexpr + DynamicArray(DynamicArray&& arr) noexcept : + base {std::forward(static_cast(arr))} + {} + + template + constexpr + DynamicArray(Iter start, Iter end) : + base {start, end} + {} + + constexpr + DynamicArray(typename base::iterator start, typename base::iterator end) : + base {start, end} + {} + + constexpr + DynamicArray(typename base::const_iterator start, typename base::const_iterator end) : + base {start, end} + {} + + constexpr + DynamicArray(typename base::iterator start, typename base::iterator end, size_type capacity) : + base {start, end, capacity} + {} + + constexpr + DynamicArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) : + base {start, end, capacity} + {} + + constexpr + DynamicArray(std::initializer_list list) : + base {list.begin(), list.end()} + {} + + constexpr + DynamicArray(size_type size, value_type value) noexcept : + base {size, value} + {} + + constexpr + DynamicArray& operator=(DynamicArray other) noexcept + { + swap(*this, other); + return *this; + } + + constexpr + DynamicArray& operator=(DynamicArray&& arr) noexcept + { + swap(*this, arr); + return *this; + } + + virtual + ~DynamicArray() = default; + + // Member functions + + [[nodiscard]] virtual constexpr + size_type capacity() const noexcept + { + return base::p_capacity; + } + + [[nodiscard]] virtual constexpr + bool is_empty() const + { + return base::begin() == base::end(); + } + + virtual constexpr + iterator storage_end() + { + return iterator(base::p_start + base::p_capacity); + } + + virtual constexpr + const_iterator storage_end() const + { + return const_iterator(base::p_start + base::p_capacity); + } + + virtual constexpr + void resize(size_type newCapacity) + { + if (newCapacity == base::p_capacity) + return; + + if (std::numeric_limits::max() - base::size() < newCapacity) + throw hpr::LengthError("Invalid capacity value passed"); + + if (newCapacity > base::p_capacity) + { + DynamicArray tmp {base::begin(), base::end(), newCapacity}; + swap(*this, tmp); + } + else + { + if (newCapacity >= base::p_size) + { + DynamicArray tmp {base::begin(), base::end()}; + swap(*this, tmp); + } + else + { + DynamicArray tmp {base::begin(), base::begin() + newCapacity}; + swap(*this, tmp); + } + } + } + + virtual constexpr + void push(const value_type& val) + { + if (base::end() == storage_end()) + resize(base::p_capacity * 2); + *base::end() = val; + ++base::p_size; + } + + virtual constexpr + void push(value_type&& val) + { + if (base::end() == storage_end()) + resize(base::p_capacity * 2); + *base::end() = std::move(val); + ++base::p_size; + } + + virtual constexpr + void push(const DynamicArray& arr) + { + for (const value_type& el : arr) + push(el); + } + + virtual constexpr + value_type pop() + { + if (is_empty()) + throw hpr::LengthError("Cannot pop element from empty array"); + value_type val = base::back(); + std::destroy_at(base::p_start + base::p_size); + --base::p_size; + return val; + } + + virtual constexpr + void insert(size_type position, const value_type& val) + { + if (base::end() == storage_end()) + resize(base::p_capacity * 2); + for (size_type n = base::p_size; n > position; --n) + *(base::p_start + n) = std::move(*(base::p_start + n - 1)); + *(base::p_start + position) = val; + ++base::p_size; + } + + virtual constexpr + void insert(size_type position, value_type&& val) + { + if (base::end() == storage_end()) + resize(base::p_capacity * 2); + for (size_type n = base::p_size; n > position; --n) + *(base::p_start + n) = std::move(*(base::p_start + n - 1)); + *(base::p_start + position) = std::move(val); + ++base::p_size; + } + + virtual constexpr + void remove(size_type position) + { + for (size_type n = position; n < base::p_size - 1; ++n) + *(base::p_start + n) = std::move(*(base::p_start + n + 1)); + std::destroy_at(base::p_start + base::p_size); + --base::p_size; + } + + virtual constexpr + void remove(iterator position) + { + if (position + 1 != base::end()) + std::copy(position + 1, base::end(), position); + std::destroy_at(base::p_start + base::p_size); + --base::p_size; + } + + virtual constexpr + void remove(const std::function& condition) + { + size_type newSize = base::p_size; + for (size_type offset = 0; offset < newSize; ++offset) + { + if (condition(*(base::p_start + offset))) + { + for (size_type n = offset; n < newSize; ++n) + *(base::p_start + n) = std::move(*(base::p_start + n + 1)); + + --newSize; + --offset; + } + } + base::p_size = newSize; + } + + virtual constexpr + void clear() + { + delete[] base::p_start; + base::p_size = 0; + base::p_capacity = 1; + base::p_start = new value_type[base::p_capacity]; + } + + DynamicArray slice(iterator start, iterator end) + { + return DynamicArray {start, end}; + } + +}; + + } \ No newline at end of file diff --git a/source/hpr/containers/array/iterator.hpp b/source/hpr/containers/array/iterator.hpp index 67f815c..42fd721 100644 --- a/source/hpr/containers/array/iterator.hpp +++ b/source/hpr/containers/array/iterator.hpp @@ -1,95 +1,98 @@ -#pragma once - -#include - - -namespace hpr -{ - -template -class Iterator -{ -public: - using iterator_category = Category; - using difference_type = std::ptrdiff_t; - using value_type = Type; - using pointer = Type*; - using reference = Type&; - using iterator = Iterator; - using const_pointer = Type const*; - using const_reference = Type const&; - using const_iterator = Iterator const; - -protected: - pointer p_ptr; - -public: - - Iterator() : - p_ptr {nullptr} - {} - - Iterator(pointer ptr) : - p_ptr {ptr} - {} - - reference operator*() - { - return *p_ptr; - } - - const_reference operator*() const - { - return *p_ptr; - } - - pointer operator->() - { - return p_ptr; - } - - const_pointer operator->() const - { - return p_ptr; - } - - iterator& operator++() - { - p_ptr++; - return *this; - } - - const_iterator& operator++() const - { - p_ptr++; - return *this; - } - - iterator operator++(int) - { - iterator temp {*this}; - ++(*this); - return temp; - } - - iterator operator+(int value) - { - iterator temp {*this}; - temp.p_ptr += value; - return temp; - } - - friend - bool operator==(const iterator& lhs, const iterator& rhs) - { - return lhs.p_ptr == rhs.p_ptr; - } - - friend - bool operator!=(const iterator& lhs, const iterator& rhs) - { - return lhs.p_ptr != rhs.p_ptr; - } -}; - -} +#pragma once + +#include + + +namespace hpr +{ + +template +class Iterator +{ + +public: + + using iterator_category = Category; + using difference_type = std::ptrdiff_t; + using value_type = Type; + using pointer = Type*; + using reference = Type&; + using iterator = Iterator; + using const_pointer = Type const*; + using const_reference = Type const&; + using const_iterator = Iterator const; + +protected: + + pointer p_ptr; + +public: + + Iterator() : + p_ptr {nullptr} + {} + + Iterator(pointer ptr) : + p_ptr {ptr} + {} + + reference operator*() + { + return *p_ptr; + } + + const_reference operator*() const + { + return *p_ptr; + } + + pointer operator->() + { + return p_ptr; + } + + const_pointer operator->() const + { + return p_ptr; + } + + iterator& operator++() + { + p_ptr++; + return *this; + } + + const_iterator& operator++() const + { + p_ptr++; + return *this; + } + + iterator operator++(int) + { + iterator temp {*this}; + ++(*this); + return temp; + } + + iterator operator+(int value) + { + iterator temp {*this}; + temp.p_ptr += value; + return temp; + } + + friend + bool operator==(const iterator& lhs, const iterator& rhs) + { + return lhs.p_ptr == rhs.p_ptr; + } + + friend + bool operator!=(const iterator& lhs, const iterator& rhs) + { + return lhs.p_ptr != rhs.p_ptr; + } +}; + +} diff --git a/source/hpr/containers/array/sequence.hpp b/source/hpr/containers/array/sequence.hpp new file mode 100644 index 0000000..2df9665 --- /dev/null +++ b/source/hpr/containers/array/sequence.hpp @@ -0,0 +1,314 @@ +#pragma once + +#include +#include +#include + +namespace hpr +{ + +// forward declaration + +template +class Sequence; + +// type traits + +template +struct is_sequence : public std::false_type +{}; + +template +struct is_sequence> : public std::true_type +{}; + +// class definition + +template +class Sequence +{ + +public: + + using difference_type = std::ptrdiff_t; + using value_type = T; + using size_type = Size; + using pointer = T*; + using reference = T&; + using iterator = Iterator; + using const_pointer = T const*; + using const_reference = T const&; + using const_iterator = Iterator; + +protected: + + size_type p_size; + size_type p_capacity; + pointer p_start; + +protected: + + constexpr + Sequence(size_type size, size_type capacity, pointer start) : + p_size {size}, + p_capacity {capacity}, + p_start {start} + {} + + constexpr explicit + Sequence(size_type size, size_type capacity) : + p_size {size}, + p_capacity {capacity}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + {} + +public: + + friend constexpr + void swap(Sequence& main, Sequence& other) noexcept + { + using std::swap; + swap(main.p_size, other.p_size); + swap(main.p_capacity, other.p_capacity); + swap(main.p_start, other.p_start); + } + + constexpr + Sequence() noexcept : + p_size {0}, + p_capacity {1}, + p_start {new value_type[p_capacity]} + {} + + constexpr + Sequence(const Sequence& seq) noexcept : + p_size {seq.p_size}, + p_capacity {seq.p_capacity}, + p_start {p_capacity ? new value_type[seq.p_capacity] : nullptr} + { + std::copy(seq.p_start, seq.p_start + seq.p_size, p_start); + } + + //! Move constructor + constexpr + Sequence(Sequence&& seq) noexcept : + Sequence {} + { + swap(*this, seq); + } + + template + constexpr + Sequence(Iter start, Iter end) : + p_size {static_cast(std::distance(start, end))},//size_type(end.operator->() - start.operator->())}, + p_capacity {p_size}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + std::copy(start, end, p_start); + } + + constexpr + Sequence(iterator start, iterator end) : + p_size {static_cast(std::distance(start, end))},//size_type(end.operator->() - start.operator->())}, + p_capacity {p_size}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + std::copy(start, end, p_start); + } + + constexpr + Sequence(const_iterator start, const_iterator end) : + p_size {std::distance(start, end)},//{size_type(end.operator->() - start.operator->())}, + p_capacity {p_size}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + std::copy(start, end, p_start); + } + + constexpr + Sequence(iterator start, iterator end, size_type capacity) : + p_size {static_cast(std::distance(start, end))},//size_type(end.operator->() - start.operator->())}, + p_capacity {capacity}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + std::copy(start, end, p_start); + } + + constexpr + Sequence(const_iterator start, const_iterator end, size_type capacity) : + p_size {std::distance(start, end)},//{size_type(end.operator->() - start.operator->())}, + p_capacity {capacity}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + std::copy(start, end, p_start); + } + + /*constexpr + Sequence(std::initializer_list list) : + Sequence {list.begin(), list.end()} + {}*/ + + constexpr + Sequence(size_type size, value_type value) noexcept: + p_size {size}, + p_capacity {size}, + p_start {p_capacity ? new value_type[p_capacity] : nullptr} + { + for (auto n = 0; n < size; ++n) + *(p_start + n) = value; + } + + constexpr + Sequence& operator=(Sequence other) noexcept + { + swap(*this, other); + return *this; + } + + constexpr + Sequence& operator=(Sequence&& seq) noexcept + { + swap(*this, seq); + return *this; + } + + virtual + ~Sequence() + { + delete[] p_start; + } + + + // Member functions + + virtual constexpr + iterator begin() + { + return iterator(p_start); + } + + [[nodiscard]] virtual constexpr + const_iterator begin() const + { + return const_iterator(p_start); + } + + virtual constexpr + iterator end() + { + return iterator(p_start + p_size); + } + + virtual constexpr + const_iterator end() const + { + return const_iterator(p_start + p_size); + } + + virtual constexpr + iterator storage_end() + { + return iterator(p_start + p_capacity); + } + + virtual constexpr + const_iterator storage_end() const + { + return const_iterator(p_start + p_capacity); + } + + [[nodiscard]] virtual constexpr + size_type size() const noexcept + { + return p_size; + } + + virtual constexpr + reference operator[](size_type n) + { + if (n >= size()) + throw hpr::OutOfRange(); + return *(p_start + n); + } + + virtual constexpr + const_reference operator[](size_type n) const + { + if (n >= size()) + throw hpr::OutOfRange(); + return *(p_start + n); + } + + virtual constexpr + reference at(size_type n) + { + return operator[](n); + } + + virtual constexpr + const_reference at(size_type n) const + { + return operator[](n); + } + + virtual constexpr + reference front() + { + return *begin(); + } + + virtual constexpr + const_reference front() const + { + return *begin(); + } + + virtual constexpr + reference back() + { + return *(p_start + p_size - 1); + } + + virtual constexpr + const_reference back() const + { + return *(p_start + p_size - 1); + } + + virtual constexpr + pointer data() + { + return p_start; + } + + [[nodiscard]] virtual constexpr + const_pointer data() const + { + return p_start; + } + + // Friend functions + + friend + bool operator==(const Sequence& lhs, const Sequence& rhs) + { + for (auto n = 0; n < lhs.size(); ++n) + if (lhs[n] != rhs[n]) + return false; + return true; + } + + friend + Sequence operator+(const Sequence& lhs, const Sequence& rhs) + { + Sequence seq {rhs.size() + lhs.size(), {}}; + for (auto n = 0; n < rhs.size(); ++n) + { + seq[n] = rhs[n]; + seq[n + rhs.size()] = lhs[n]; + } + return seq; + } +}; + +} \ No newline at end of file diff --git a/source/hpr/containers/array/static_array.hpp b/source/hpr/containers/array/static_array.hpp index 76783d6..da2ca54 100644 --- a/source/hpr/containers/array/static_array.hpp +++ b/source/hpr/containers/array/static_array.hpp @@ -1,257 +1,150 @@ -#pragma once - -#include "iterator.hpp" - -#include -#include -#include - - -namespace hpr -{ - -template -class StaticArray -{ - -public: - - using difference_type = std::ptrdiff_t; - using value_type = Type; - using size_type = size_t; - using pointer = Type*; - using reference = Type&; - using iterator = Iterator; - using const_pointer = Type const*; - using const_reference = Type const&; - using const_iterator = Iterator; - -protected: - - const size_type p_size; - pointer p_start; - pointer p_end; - -protected: - - inline - StaticArray(size_type size, pointer start, pointer end) : - p_size {size}, - p_start {start}, - p_end {end} - {} - -public: - - inline - StaticArray() : - p_size {Size}, - p_start {new value_type[p_size] {}}, - p_end {p_start + p_size} - {} - - inline - StaticArray(const StaticArray& arr) : - p_size {arr.p_size}, - p_start {new value_type[arr.p_size]}, - p_end {p_start + p_size} - { - std::copy(arr.p_start, arr.p_end, p_start); - } - - //! Move constructor - inline - StaticArray(StaticArray&& arr) noexcept : - StaticArray {} - { - swap(*this, arr); - } - - inline - StaticArray(const_iterator start, const_iterator end) : - p_size {Size}, - p_start {new value_type[p_size]}, - p_end {p_start + p_size} - { - std::copy(start, end, p_start); - } - - inline - StaticArray(iterator start, iterator end) : - p_size {Size}, - p_start {new value_type[p_size]}, - p_end {p_start + p_size} - { - std::copy(start, end, p_start); - } - - inline - StaticArray(std::initializer_list list) : - StaticArray {list.begin(), list.end()} - {} - - template ... Args> - inline - StaticArray(const value_type& v, const Args& ...args) : - StaticArray {std::initializer_list({std::forward(v), - std::forward(static_cast(args))...})} - { - static_assert(1 + sizeof...(args) == Size, "Number of arguments must be equal to size of array"); - } - - template ... Args> - inline - StaticArray(value_type&& v, Args&& ...args) : - StaticArray {std::initializer_list({std::forward(v), - std::forward(static_cast(args))...})} - { - static_assert(1 + sizeof...(args) == Size, "Number of arguments must be equal to size of array"); - } - - template ... Args> - inline - StaticArray(const StaticArray& subarr, const value_type& v, const Args& ...args) : - p_size {Size}, - p_start {new value_type[p_size]}, - p_end {p_start + p_size} - { - static_assert(SubSize + 1 + sizeof...(args) == Size, - "Number of arguments and sub-array elements must be equal to size of main array"); - std::initializer_list list {v, static_cast(args)...}; - std::copy(subarr.begin(), subarr.end(), begin()); - size_type pos {subarr.size()}; - for (auto& val : list) - (*this)[pos++] = val; - } - - inline - StaticArray& operator=(const StaticArray& vs) - { - std::copy(vs.begin(), vs.end(), begin()); - return *this; - } - - inline - StaticArray& operator=(StaticArray&& arr) noexcept - { - swap(*this, arr); - return *this; - } - - virtual - ~StaticArray() - { - //std::destroy(p_start, p_end); - delete[] p_start; - } - - // Member functions - - virtual - iterator begin() - { - return iterator(p_start); - } - - [[nodiscard]] virtual - const_iterator begin() const - { - return const_iterator(p_start); - } - - virtual - iterator end() - { - return iterator(p_end); - } - - virtual - const_iterator end() const - { - return const_iterator(p_end); - } - - [[nodiscard]] virtual constexpr - size_type size() const - { - return size_type(p_end - p_start); - } - - [[nodiscard]] virtual - bool is_empty() const - { - return begin() == end(); - } - - virtual - reference operator[](size_type n) - { - if (n >= size()) - throw std::out_of_range("Index out of bounds"); - return *(p_start + n); - } - - virtual - const_reference operator[](size_type n) const - { - if (n >= size()) - throw std::out_of_range("Index out of bounds"); - return *(p_start + n); - } - - virtual - reference front() - { - return *p_start; - } - - virtual - reference back() - { - return *(p_end - 1); - } - - virtual - pointer data() - { - return p_start; - } - - [[nodiscard]] virtual - const_pointer data() const - { - return p_start; - } - - // Friend functions - - friend - void swap(StaticArray& lhs, StaticArray& rhs) - { - std::swap(lhs.p_start, rhs.p_start); - std::swap(lhs.p_end, rhs.p_end); - } - - friend - void swap(StaticArray&& lhs, StaticArray&& rhs) - { - std::swap(lhs.p_start, rhs.p_start); - std::swap(lhs.p_end, rhs.p_end); - } - - friend - bool operator==(const StaticArray& lhs, const StaticArray& rhs) - { - for (auto n = 0; n < Size; ++n) - if (lhs[n] != rhs[n]) - return false; - return true; - } -}; - -// Aliases - -template -using sarray = StaticArray; - -} +#pragma once + +#include + + +namespace hpr +{ + +// forward declaration + +template +requires (S > 0) +class StaticArray; + +// type traits + +template +struct is_sequence> : public std::true_type +{}; + +// aliases + +template +using sarray = StaticArray; + +// class definition + +template +requires (S > 0) +class StaticArray : public Sequence +{ + + using base = Sequence; + +public: + + using difference_type = std::ptrdiff_t; + using value_type = T; + using size_type = Size; + using pointer = T*; + using reference = T&; + using iterator = Iterator; + using const_pointer = T const*; + using const_reference = T const&; + using const_iterator = Iterator; + +public: + + friend constexpr + void swap(StaticArray& main, StaticArray& other) noexcept + { + using std::swap; + swap(static_cast(main), static_cast(other)); + } + + //! Default constructor + constexpr + StaticArray() noexcept : + base {S, S, new value_type[S] {}} + {} + + constexpr explicit + StaticArray(const base& b) noexcept : + base {b} + {} + + //! Copy constructor + constexpr + StaticArray(const StaticArray& arr) noexcept : + base {static_cast(arr)} + {} + + //! Move constructor + constexpr + StaticArray(StaticArray&& arr) noexcept : + base {std::forward(static_cast(arr))} + {} + + constexpr + StaticArray(typename base::iterator start, typename base::iterator end) : + base {start, end} + {} + + constexpr + StaticArray(typename base::const_iterator start, typename base::const_iterator end) : + base {start, end} + {} + + constexpr + StaticArray(typename base::iterator start, typename base::iterator end, size_type capacity) : + base {start, end, capacity} + {} + + constexpr + StaticArray(typename base::const_iterator start, typename base::const_iterator end, size_type capacity) : + base {start, end, capacity} + {} + + constexpr + StaticArray(std::initializer_list list) : + base {list.begin(), list.end()} + {} + + template ... Args> + constexpr explicit + StaticArray(const value_type& v, const Args& ...args) + requires (1 + sizeof...(args) == S) : + StaticArray {std::initializer_list({v, static_cast(args)...})} + {} + + template ... Args> + constexpr explicit + StaticArray(value_type&& v, Args&& ...args) + requires (1 + sizeof...(args) == S) : + StaticArray {std::initializer_list({std::forward(v), std::forward(static_cast(args))...})} + {} + + template ... Args> + constexpr + StaticArray(const StaticArray& subArr, const value_type& v, const Args& ...args) noexcept + requires (SS + 1 + sizeof...(args) == S) : + base {S, S, new value_type[S] {}} + { + std::copy(subArr.begin(), subArr.end(), base::begin()); + std::initializer_list list {v, static_cast(args)...}; + std::copy(list.begin(), list.end(), base::begin() + subArr.size()); + } + + constexpr + StaticArray& operator=(StaticArray other) + { + swap(*this, other); + return *this; + } + + constexpr + StaticArray& operator=(StaticArray&& other) noexcept + { + swap(*this, other); + return *this; + } + + virtual + ~StaticArray() = default; + + +}; + + +} diff --git a/source/hpr/containers/graph.hpp b/source/hpr/containers/graph.hpp new file mode 100644 index 0000000..d951bd5 --- /dev/null +++ b/source/hpr/containers/graph.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include \ No newline at end of file diff --git a/source/hpr/containers/graph/tree_node.hpp b/source/hpr/containers/graph/tree_node.hpp new file mode 100644 index 0000000..67d7108 --- /dev/null +++ b/source/hpr/containers/graph/tree_node.hpp @@ -0,0 +1,180 @@ +#pragma once + +#include +#include + + +namespace hpr +{ + +template +class TreeNode +{ + +public: + + using value_type = Type; + using pointer = Type*; + using reference = Type&; + using const_pointer = Type const*; + using const_reference = Type const&; + +protected: + + pointer p_data; + + darray p_descendants; + TreeNode* p_ancestor; + +public: + + friend constexpr + void swap(TreeNode& main, TreeNode& other) noexcept + { + using std::swap; + swap(main.p_data, other.p_data); + swap(main.p_descendants, other.p_descendants); + swap(main.p_ancestor, other.p_ancestor); + } + + inline + TreeNode() : + p_data {new value_type {}}, + p_descendants {}, + p_ancestor {} + {} + + inline + TreeNode(const TreeNode& node) : + p_data {new value_type {*node.p_data}}, + p_descendants {}, + p_ancestor {} + {} + + inline + TreeNode(TreeNode&& node) noexcept : + p_data {}, + p_descendants {}, + p_ancestor {} + { + swap(*this, node); + /*std::swap(p_data, node.p_data); + std::swap(p_descendants, node.p_descendants); + std::swap(p_ancestor, node.p_ancestor);*/ + } + + inline + TreeNode& operator=(TreeNode other) + { + swap(*this, other); + return *this; + } + + inline explicit + TreeNode(const value_type& data) : + p_data {new value_type {data}}, + p_descendants {}, + p_ancestor {} + {} + + inline + TreeNode(const value_type& data, const darray& descendants, TreeNode* ancestor) : + p_data {new value_type {data}}, + p_descendants {descendants}, + p_ancestor {ancestor} + { + for (auto descendant : p_descendants) + descendant->ancestor(this); + } + + inline + TreeNode(const value_type& data, const darray& descendants) : + p_data {new value_type {data}}, + p_descendants {descendants}, + p_ancestor {} + { + for (auto descendant : p_descendants) + descendant->ancestor(this); + } + + virtual + ~TreeNode() + { + delete p_data; + //delete p_ancestor; + } + + // Member functions + + inline + pointer data() + { + return p_data; + } + + inline + void ancestor(TreeNode* node) + { + p_ancestor = node; + } + + inline + TreeNode* ancestor() + { + return p_ancestor; + } + + inline + void descendants(const darray& descendants) + { + p_descendants = descendants; + } + + inline + darray& descendants() + { + return p_descendants; + } + + darray traverse_descendants() + { + std::function(TreeNode*)> collect = [&](TreeNode* node) + { + darray ds; + + if (!node->descendants().is_empty()) + { + for (TreeNode* dnode: node->descendants()) + { + ds.push(dnode); + if (!dnode->descendants().is_empty()) + ds.push(collect(dnode)); + } + } + + return ds; + }; + + return collect(this); + } + + darray traverse_ancestors() + { + std::function(TreeNode*)> collect = [&](TreeNode* node) + { + darray ds; + + if (node->p_ancestor) + { + ds.push(node); + ds.push(collect(node->p_ancestor)); + } + + return ds; + }; + + return collect(this); + } +}; + +} \ No newline at end of file diff --git a/source/hpr/containers/tests/CMakeLists.txt b/source/hpr/containers/tests/CMakeLists.txt deleted file mode 100644 index 731b2ca..0000000 --- a/source/hpr/containers/tests/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -file(GLOB tests_cpp "*.cpp") - -add_executable(${PROJECT_NAME}-tests - ${tests_cpp} -) - -target_link_libraries(${PROJECT_NAME}-tests - PUBLIC - hpr::containers - PRIVATE - GTest::gtest_main -) - -gtest_add_tests(TARGET ${PROJECT_NAME}-tests) \ No newline at end of file diff --git a/source/hpr/containers/tests/containers-test.cpp b/source/hpr/containers/tests/containers-test.cpp index 837f23c..9789623 100644 --- a/source/hpr/containers/tests/containers-test.cpp +++ b/source/hpr/containers/tests/containers-test.cpp @@ -1,37 +1,93 @@ -#include - -#include "../array.hpp" - - -TEST(containers, StaticArray) -{ -hpr::StaticArray arr {1, 3, 2}; -hpr::StaticArray sarr {arr, 5}; -hpr::StaticArray sarr2 {1, 3, 2, 5}; -EXPECT_EQ(sarr, sarr2); -} - -TEST(containers, DynamicArray) -{ -hpr::DynamicArray arr {1, 3, 2}; -hpr::DynamicArray arr2 {1, 3, 2}; -EXPECT_EQ(arr, arr2); -arr.remove(1); -EXPECT_EQ(arr, hpr::darray({1, 2})); -auto iter = arr2.begin(); -++iter; -arr2.remove(iter); -EXPECT_EQ(arr2, hpr::darray({1, 2})); - -hpr::DynamicArray arr3 {1, 3, 0, 2, 9, 0, 5}; -arr3.remove([](float num) { return num == 0; }); -EXPECT_EQ(arr3, hpr::darray({1, 3, 2, 9, 5})); -EXPECT_EQ(arr3.size(), 5); - -hpr::DynamicArray arr4; -arr4.push(new float(5)); -arr4.push(new float(7)); -arr4.push(new float(9)); -EXPECT_EQ(*arr4[0], 5.f); -EXPECT_EQ(*arr4[2], 9.f); -} +#include + +#include +#include + + +TEST(containers, StaticArray) +{ + hpr::StaticArray arr {7, 3, 2}; + hpr::StaticArray sarr {arr, 5}; + hpr::StaticArray sarr2 {7, 3, 2, 5}; + //hpr::StaticArray sarr4; + + EXPECT_EQ(sarr, sarr2); + //EXPECT_EQ(sarr4.data(), nullptr); + //EXPECT_EQ(sarr4.is_empty(), true); + EXPECT_EQ(sarr.size(), 4); + EXPECT_EQ(sarr2.size(), 4); + EXPECT_EQ(sarr[0], 7); + EXPECT_EQ(sarr[1], 3); + EXPECT_EQ(sarr[2], 2); + EXPECT_EQ(sarr[3], 5); +} + +TEST(containers, DynamicArray) +{ + hpr::DynamicArray arr {1, 3, 2}; + hpr::DynamicArray arr2 {1, 3, 2}; + EXPECT_EQ(arr, arr2); + EXPECT_TRUE(arr == arr2); + arr.remove(1); + EXPECT_EQ(arr, hpr::darray({1, 2})); + auto iter = arr2.begin(); + ++iter; + arr2.remove(iter); + EXPECT_EQ(arr2, hpr::darray({1, 2})); + + hpr::DynamicArray arr3 {1, 3, 0, 2, 9, 0, 5}; + arr3.remove([](float num) { return num == 0; }); + EXPECT_EQ(arr3, hpr::darray({1, 3, 2, 9, 5})); + EXPECT_EQ(arr3.size(), 5); + arr3.insert(3, 19); + EXPECT_EQ(arr3.size(), 6); + EXPECT_EQ(arr3[3], 19); + EXPECT_EQ(arr3.pop(), 5); + EXPECT_EQ(arr3.size(), 5); + arr3.resize(3); + EXPECT_EQ(arr3.size(), 3); + EXPECT_EQ(arr3.capacity(), 3); + EXPECT_EQ(arr3.back(), 2); + arr3.resize(4); + EXPECT_EQ(arr3.back(), 2); + arr3.push(17); + arr3.push(14); + EXPECT_EQ(arr3.back(), 14); + EXPECT_EQ(arr3.size(), 5); + + arr3.clear(); + EXPECT_EQ(arr3.is_empty(), true); + + + + hpr::DynamicArray arr4; + arr4.push(new float(5)); + arr4.push(new float(7)); + arr4.push(new float(9)); + EXPECT_EQ(*arr4[0], 5.f); + EXPECT_EQ(*arr4[2], 9.f); + for (auto& v : arr4) + delete v; + + +} + +TEST(containers, TreeNode) +{ + hpr::TreeNode node1 (5); + //std::shared_ptr> ptr {node1}; + hpr::TreeNode node2 {7, {&node1}}; + hpr::TreeNode node3 {9, {&node2, &node1}}; + hpr::TreeNode node4 {11, {&node3}}; + + EXPECT_EQ(*node1.data(), 5); + //EXPECT_EQ(*node1->data(), *node2.ancestor()->data()); + + hpr::darray*> tr = node1.traverse_descendants(); + EXPECT_EQ(tr.size(), 0); + hpr::darray*> tr2 = node4.traverse_descendants(); + EXPECT_EQ(tr2.size(), 4); + hpr::darray*> tr3 = node1.traverse_ancestors(); + EXPECT_EQ(tr3.size(), 2); // node1 has changed ancestor + // +} diff --git a/source/hpr/core.hpp b/source/hpr/core.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/source/hpr/core/CMakeLists.txt b/source/hpr/core/CMakeLists.txt deleted file mode 100644 index 6335592..0000000 --- a/source/hpr/core/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(core - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX -) - -add_library(${PROJECT_NAME} INTERFACE) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS "../core.hpp" "*.hpp") - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ -) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) diff --git a/source/hpr/core/common.hpp b/source/hpr/core/common.hpp deleted file mode 100644 index bdc652a..0000000 --- a/source/hpr/core/common.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define HPR_VERSION_MAJOR 0 -#define HPR_VERSION_MINOR 10 -#define HPR_VERSION_PATCH 0 \ No newline at end of file diff --git a/source/hpr/csg.hpp b/source/hpr/csg.hpp index 089f115..4677564 100644 --- a/source/hpr/csg.hpp +++ b/source/hpr/csg.hpp @@ -1,12 +1,12 @@ -#pragma once - -#include "csg/shape.hpp" -#include "csg/vertex.hpp" -#include "csg/edge.hpp" -#include "csg/wire.hpp" -#include "csg/face.hpp" -#include "csg/shell.hpp" -#include "csg/solid.hpp" -#include "csg/compound.hpp" -#include "csg/geometry.hpp" -#include "csg/surface.hpp" \ No newline at end of file +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/source/hpr/csg/CMakeLists.txt b/source/hpr/csg/CMakeLists.txt index 2b0c56c..cb71843 100644 --- a/source/hpr/csg/CMakeLists.txt +++ b/source/hpr/csg/CMakeLists.txt @@ -1,77 +1,33 @@ -cmake_minimum_required(VERSION 3.16) - -project(csg - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX -) - -add_library(${PROJECT_NAME}) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../csg.hpp" "*.hpp" -) - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES - "*.cpp" -) - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ - PRIVATE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES} -) - -target_link_libraries(${PROJECT_NAME} - ${OCCT_LIBRARIES} -) - -target_include_directories(${PROJECT_NAME} - PUBLIC - ${OCCT_INCLUDE_DIRS} -) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) - - -if(HPR_TEST) - add_subdirectory(tests) -endif() +cmake_minimum_required(VERSION 3.16) + +project(csg + VERSION "${HPR_VERSION}" + LANGUAGES CXX +) + +hpr_add_library(${PROJECT_NAME} STATIC) + +hpr_collect_interface(${PROJECT_NAME} + "../csg.hpp" + "*.hpp" +) + +hpr_collect_sources(${PROJECT_NAME} + "*.cpp" +) + +target_sources(${PROJECT_NAME} + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> + PRIVATE ${${PROJECT_NAME}_SOURCES} +) + +target_link_libraries(${PROJECT_NAME} + ${OpenCASCADE_LIBS} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC ${OpenCASCADE_INCLUDE_DIR} +) + +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) +hpr_tests(${PROJECT_NAME} tests) diff --git a/source/hpr/csg/compound.hpp b/source/hpr/csg/compound.hpp index 4e083eb..79db61c 100644 --- a/source/hpr/csg/compound.hpp +++ b/source/hpr/csg/compound.hpp @@ -1,45 +1,45 @@ -#pragma once - -#include "shape.hpp" -#include "solid.hpp" - - -namespace hpr::csg -{ - - class Compound : public Shape - { - - public: - - Compound() = default; - - ~Compound() override = default; - - explicit - Compound(const Shape& shape) : - Shape {shape.type() == Type::Compound ? shape : throw std::runtime_error("")} - {} - - explicit - Compound(const darray& shapes) : - Shape {} - { - BRep_Builder builder; - TopoDS_Compound compound; - builder.MakeCompound(compound); - - for (auto& shape : shapes) - builder.Add(compound, shape.tshape()); - - p_shape = compound; - } - - [[nodiscard]] - TopoDS_Compound tcast() const - { - return TopoDS::Compound(p_shape); - } - }; - -} +#pragma once + +#include +#include + + +namespace hpr::csg +{ + + class Compound : public Shape + { + + public: + + Compound() = default; + + ~Compound() override = default; + + explicit + Compound(const Shape& shape) : + Shape {shape.type() == Type::Compound ? shape : throw std::runtime_error("")} + {} + + explicit + Compound(const darray& shapes) : + Shape {} + { + BRep_Builder builder; + TopoDS_Compound compound; + builder.MakeCompound(compound); + + for (auto& shape : shapes) + builder.Add(compound, shape.tshape()); + + p_shape = compound; + } + + [[nodiscard]] + TopoDS_Compound tcast() const + { + return TopoDS::Compound(p_shape); + } + }; + +} diff --git a/source/hpr/csg/edge.hpp b/source/hpr/csg/edge.hpp index c04f316..0e419ff 100644 --- a/source/hpr/csg/edge.hpp +++ b/source/hpr/csg/edge.hpp @@ -1,39 +1,39 @@ -#pragma once - -#include "shape.hpp" -#include "vertex.hpp" - - -namespace hpr::csg -{ - -class Edge : public Shape -{ - -public: - - Edge() = default; - - ~Edge() override = default; - - explicit - Edge(const Shape& shape) : - Shape {shape.type() == Type::Edge ? shape : throw std::runtime_error("")} - {} - - Edge(const vec3& p1, const vec3& p2) : - Shape {BRepBuilderAPI_MakeEdge(gp_Pnt(p1[0], p1[1], p1[2]), gp_Pnt(p2[0], p2[1], p2[2])).Shape()} - {} - - Edge(const Vertex& v1, const Vertex& v2) : - Shape {BRepBuilderAPI_MakeEdge(v1.tcast(), v2.tcast()).Shape()} - {} - - [[nodiscard]] - TopoDS_Edge tcast() const - { - return TopoDS::Edge(p_shape); - } -}; - -} +#pragma once + +#include +#include + + +namespace hpr::csg +{ + +class Edge : public Shape +{ + +public: + + Edge() = default; + + ~Edge() override = default; + + explicit + Edge(const Shape& shape) : + Shape {shape.type() == Type::Edge ? shape : throw std::runtime_error("")} + {} + + Edge(const vec3& p1, const vec3& p2) : + Shape {BRepBuilderAPI_MakeEdge(gp_Pnt(p1[0], p1[1], p1[2]), gp_Pnt(p2[0], p2[1], p2[2])).Shape()} + {} + + Edge(const Vertex& v1, const Vertex& v2) : + Shape {BRepBuilderAPI_MakeEdge(v1.tcast(), v2.tcast()).Shape()} + {} + + [[nodiscard]] + TopoDS_Edge tcast() const + { + return TopoDS::Edge(p_shape); + } +}; + +} diff --git a/source/hpr/csg/face.hpp b/source/hpr/csg/face.hpp index d68199d..241a52c 100644 --- a/source/hpr/csg/face.hpp +++ b/source/hpr/csg/face.hpp @@ -1,42 +1,42 @@ -#pragma once - -#include "shape.hpp" -#include "wire.hpp" - - -namespace hpr::csg -{ - -class Face : public Shape -{ - -public: - - Face() = default; - - ~Face() override = default; - - explicit - Face(const Shape& shape) : - Shape {shape.type() == Type::Face ? shape : throw std::runtime_error("")} - {} - - explicit - Face(const Wire& wire) : - Shape {BRepBuilderAPI_MakeFace(wire.tcast()).Shape()} - {} - - explicit - Face(const darray& edges) : - Face {Wire(edges)} - {} - - [[nodiscard]] - TopoDS_Face tcast() const - { - return TopoDS::Face(p_shape); - } -}; - -} - +#pragma once + +#include +#include + + +namespace hpr::csg +{ + +class Face : public Shape +{ + +public: + + Face() = default; + + ~Face() override = default; + + explicit + Face(const Shape& shape) : + Shape {shape.type() == Type::Face ? shape : throw std::runtime_error("")} + {} + + explicit + Face(const Wire& wire) : + Shape {BRepBuilderAPI_MakeFace(wire.tcast()).Shape()} + {} + + explicit + Face(const darray& edges) : + Face {Wire(edges)} + {} + + [[nodiscard]] + TopoDS_Face tcast() const + { + return TopoDS::Face(p_shape); + } +}; + +} + diff --git a/source/hpr/csg/geometry.hpp b/source/hpr/csg/geometry.hpp index 4d5f0ca..ceebdbe 100644 --- a/source/hpr/csg/geometry.hpp +++ b/source/hpr/csg/geometry.hpp @@ -1,21 +1,21 @@ -#pragma once - -#include "shape.hpp" - - -namespace hpr::csg -{ - -class Geometry -{ - -public: - - Geometry() = default; - - virtual - ~Geometry() = default; - -}; - +#pragma once + +#include + + +namespace hpr::csg +{ + +class Geometry +{ + +public: + + Geometry() = default; + + virtual + ~Geometry() = default; + +}; + } \ No newline at end of file diff --git a/source/hpr/csg/shape.cpp b/source/hpr/csg/shape.cpp index 5f06224..8d49637 100644 --- a/source/hpr/csg/shape.cpp +++ b/source/hpr/csg/shape.cpp @@ -1,27 +1,27 @@ -#include "shape.hpp" - - -bool std::less::operator()(const hpr::csg::Shape& s1, const hpr::csg::Shape& s2) const -{ - return s1.tshape().HashCode(std::numeric_limits::max()) < - s2.tshape().HashCode(std::numeric_limits::max()); -} -namespace hpr::csg -{ - -std::map Shape::metadata; - - -Shape sphere(vec3 center, double radius) -{ - BRepPrimAPI_MakeSphere prim {gp_Pnt(center[0], center[1], center[2]), radius}; - return Shape {prim.Shape()}; -} - -Shape box(vec3 corner, double dx, double dy, double dz) -{ - BRepPrimAPI_MakeBox prim {gp_Pnt(corner[0], corner[1], corner[2]), dx, dy, dz}; - return Shape {prim.Shape()}; -} - -} +#include + + +bool std::less::operator()(const hpr::csg::Shape& s1, const hpr::csg::Shape& s2) const +{ + return s1.tshape().HashCode(std::numeric_limits::max()) < + s2.tshape().HashCode(std::numeric_limits::max()); +} +namespace hpr::csg +{ + +std::map Shape::metadata; + + +Shape sphere(vec3 center, double radius) +{ + BRepPrimAPI_MakeSphere prim {gp_Pnt(center[0], center[1], center[2]), radius}; + return Shape {prim.Shape()}; +} + +Shape box(vec3 corner, double dx, double dy, double dz) +{ + BRepPrimAPI_MakeBox prim {gp_Pnt(corner[0], corner[1], corner[2]), dx, dy, dz}; + return Shape {prim.Shape()}; +} + +} diff --git a/source/hpr/csg/shape.hpp b/source/hpr/csg/shape.hpp index e8dadb0..fc72cc7 100644 --- a/source/hpr/csg/shape.hpp +++ b/source/hpr/csg/shape.hpp @@ -1,490 +1,490 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar.hpp" -#include "../math/vector.hpp" - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - - -namespace hpr::csg -{ - class Shape; -} - -namespace std -{ - template<> - struct less - { - bool operator() (const hpr::csg::Shape& s1, const hpr::csg::Shape& s2) const; - }; -} - -namespace hpr::csg -{ - -// Forward declaration of friend functions - -double distance(const Shape& lhs, const Shape& rhs); - -Shape fuse(const Shape& lhs, const Shape& rhs); - -Shape fuse(const darray& args, const darray& tools); - -Shape common(const Shape& lhs, const Shape& rhs); - -Shape cut(const Shape& lhs, const Shape& rhs); - - -// Class declaration - -class Shape -{ - -public: - - enum class Type - { - Compound, - Compsolid, - Solid, - Shell, - Face, - Wire, - Edge, - Vertex, - Shape, - Unknown - }; - - enum class Format - { - Unknown, - STEP - }; - - class Metadata - { - public: - std::string label; - public: - Metadata() : - label {"default"} - {} - void merge(const Metadata& data) - { - if (label == "default" && data.label != "default") - label = data.label; - } - }; - -public: - - // TODO: clean up map - static - std::map metadata; - -protected: - - TopoDS_Shape p_shape; - -public: - - [[nodiscard]] - TopoDS_Shape tshape() const { return p_shape; } - - Shape(const TopoDS_Shape& s) : - p_shape {s} - {} - - Shape(TopoDS_Shape&& s) noexcept: - p_shape {std::forward(s)} - {} - -public: - - Shape() : - p_shape {} - {} - - virtual - ~Shape() = default; - //{ - //if (metadata.contains(*this)) - // metadata.erase(*this); - //} - - [[nodiscard]] - Type type() const - { - switch (p_shape.ShapeType()) - { - case TopAbs_VERTEX: - return Type::Vertex; - case TopAbs_EDGE: - return Type::Edge; - case TopAbs_FACE: - return Type::Face; - case TopAbs_WIRE: - return Type::Wire; - case TopAbs_SHELL: - return Type::Shell; - case TopAbs_SOLID: - return Type::Solid; - case TopAbs_COMPOUND: - return Type::Compound; - case TopAbs_COMPSOLID: - return Type::Compsolid; - case TopAbs_SHAPE: - return Type::Shape; - default: - return Type::Unknown; - } - } - - [[nodiscard]] - vec3 center() const - { - GProp_GProps props; - - switch (type()) - { - case Type::Solid: - case Type::Compsolid: - case Type::Compound: - BRepGProp::VolumeProperties(p_shape, props); - case Type::Shell: - case Type::Face: - BRepGProp::SurfaceProperties(p_shape, props); - default: - BRepGProp::LinearProperties(p_shape, props); - } - - gp_Pnt center {props.CentreOfMass()}; - - return vec3 {center.X(), center.Y(), center.Z()}; - } - - [[nodiscard]] - double length() const - { - GProp_GProps props; - - switch (type()) - { - case Type::Vertex: - return 0; - default: - BRepGProp::LinearProperties(p_shape, props); - return props.Mass(); - } - } - - [[nodiscard]] - double area() const - { - GProp_GProps props; - - switch (type()) - { - case Type::Vertex: - case Type::Edge: - case Type::Wire: - return 0; - default: - BRepGProp::SurfaceProperties(p_shape, props); - return props.Mass(); - } - } - - [[nodiscard]] - double volume() const - { - GProp_GProps props; - - switch (type()) - { - case Type::Compsolid: - case Type::Solid: - BRepGProp::VolumeProperties(p_shape, props); - return props.Mass(); - - default: - return 0; - } - } - - void label(const std::string& label) const - { - metadata[*this].label = label; - } - - [[nodiscard]] - std::string label() const - { - return metadata[*this].label; - } - - void dump(const std::string& filename, Format format) const - { - if (p_shape.IsNull()) - throw std::runtime_error("Trying to export null shape"); - - switch (format) - { - case Format::STEP: - { - STEPControl_Writer writer; - Interface_Static::SetCVal("xstep.cascade.unit", "MM"); - Interface_Static::SetCVal("write.step.unit", "MM"); - Interface_Static::SetIVal("write.step.nonmanifold", 1); - - writer.Transfer(p_shape, STEPControl_AsIs); - writer.Write(filename.c_str()); - break; - } - case Format::Unknown: - default: - throw std::invalid_argument("Unknown export format"); - } - } - - // - - [[nodiscard]] - sarray boundingBox() const - { - Bnd_Box bbox; - BRepBndLib::Add(p_shape, bbox, true); - gp_Pnt p1 {bbox.CornerMin()}; - gp_Pnt p2 {bbox.CornerMax()}; - - return sarray {{p1.X(), p1.Y(), p1.Z()}, {p2.X(), p2.Y(), p2.Z()}}; - } - - void incrementalMesh(double deflection) - { - BRepTools::Clean(p_shape); - BRepMesh_IncrementalMesh(p_shape, deflection, true); - } - - darray subShapes(Type type) const - { - darray subshapes; - for (TopExp_Explorer exp(p_shape, static_cast(type)); exp.More(); exp.Next()) - subshapes.push(Shape(exp.Current())); - return subshapes; - } - - darray edges() const - { - return subShapes(Type::Edge); - } - - darray faces() const - { - return subShapes(Type::Face); - } - - darray shells() const - { - return subShapes(Type::Shell); - } - - // Member functions: transformations - - Shape translate(const vec3& dir) - { - gp_Trsf transform; - transform.SetTranslation(gp_Vec(dir[0], dir[1], dir[2])); - BRepBuilderAPI_Transform builder {p_shape, transform, true}; - - return builder.Shape(); - } - - Shape rotate(const vec3& pos, const vec3& axis, double angle) - { - gp_Trsf transform; - transform.SetRotation(gp_Ax1({pos[0], pos[1], pos[2]}, {axis[0], axis[1], axis[2]}), rad(angle)); - BRepBuilderAPI_Transform builder {p_shape, transform, true}; - - return builder.Shape(); - } - - Shape scale(const vec3& center, double scale) - { - gp_Trsf transform; - transform.SetScale(gp_Pnt(center[0], center[1], center[2]), scale); - BRepBuilderAPI_Transform builder {p_shape, transform, true}; - - return builder.Shape(); - } - - Shape& scaled(const vec3& center, double scale) - { - p_shape = this->scale(center, scale).p_shape; - return *this; - } - - Shape extrude(const vec3& dir, double length) - { - BRepPrimAPI_MakePrism builder {p_shape, length * gp_Vec(dir[0], dir[1], dir[2]), true}; - - for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) - for (TopExp_Explorer exp {p_shape, static_cast(type)}; exp.More(); exp.Next()) - { - auto data = metadata[Shape(exp.Current())]; - - for (auto& mod : builder.Generated(exp.Current())) - metadata[Shape(mod)].merge(data); - } - - return builder.Shape(); - } - - Shape fillet(darray edges, double radius) - { - BRepFilletAPI_MakeFillet fillet {p_shape}; - - for (auto& e : edges) - fillet.Add(radius, TopoDS::Edge(e.p_shape)); - fillet.Build(); - - return fillet.Shape(); - } - - // Friend functions - - friend - double distance(const Shape& lhs, const Shape& rhs) - { - return BRepExtrema_DistShapeShape(lhs.tshape(), rhs.tshape()).Value(); - } - - friend - Shape fuse(const Shape& lhs, const Shape& rhs) - { - BRepAlgoAPI_Fuse builder {lhs.p_shape, rhs.p_shape}; - builder.Build(); - return Shape {builder.Shape()}; - } - - friend - Shape fuse(const darray& args, const darray& tools) - { - BRepAlgoAPI_Fuse builder; - NCollection_List args_, tools_; - for (auto& arg : args) - args_.Append(arg.tshape()); - for (auto& tool : tools) - tools_.Append(tool.tshape()); - builder.SetArguments(args_); - builder.SetTools(tools_); - builder.Build(); - return Shape {builder.Shape()}; - } - - friend - Shape common(const Shape& lhs, const Shape& rhs) - { - BRepAlgoAPI_Common builder {lhs.p_shape, rhs.p_shape}; - builder.Build(); - return Shape {builder.Shape()}; - } - - friend - Shape cut(const Shape& lhs, const Shape& rhs) - { - BRepAlgoAPI_Cut builder {lhs.p_shape, rhs.p_shape}; - builder.Build(); - for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) - for (TopExp_Explorer exp {lhs.p_shape, static_cast(type)}; exp.More(); exp.Next()) - { - auto data = metadata[Shape(exp.Current())]; - - for (auto& mod : builder.Modified(exp.Current())) - metadata[Shape(mod)].merge(data); - } - for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) - for (TopExp_Explorer exp {rhs.p_shape, static_cast(type)}; exp.More(); exp.Next()) - { - auto data = metadata[Shape(exp.Current())]; - - for (auto& mod : builder.Modified(exp.Current())) - metadata[Shape(mod)].merge(data); - } - return Shape {builder.Shape()}; - } - -}; - -// Global functions: primitives - -Shape sphere(vec3 center, double radius); - -Shape box(vec3 corner, double dx, double dy, double dz); - -} - - - - +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +namespace hpr::csg +{ + class Shape; +} + +namespace std +{ + template<> + struct less + { + bool operator() (const hpr::csg::Shape& s1, const hpr::csg::Shape& s2) const; + }; +} + +namespace hpr::csg +{ + +// Forward declaration of friend functions + +double distance(const Shape& lhs, const Shape& rhs); + +Shape fuse(const Shape& lhs, const Shape& rhs); + +Shape fuse(const darray& args, const darray& tools); + +Shape common(const Shape& lhs, const Shape& rhs); + +Shape cut(const Shape& lhs, const Shape& rhs); + + +// Class declaration + +class Shape +{ + +public: + + enum class Type + { + Compound, + Compsolid, + Solid, + Shell, + Face, + Wire, + Edge, + Vertex, + Shape, + Unknown + }; + + enum class Format + { + Unknown, + STEP + }; + + class Metadata + { + public: + std::string label; + public: + Metadata() : + label {"default"} + {} + void merge(const Metadata& data) + { + if (label == "default" && data.label != "default") + label = data.label; + } + }; + +public: + + // TODO: clean up map + static + std::map metadata; + +protected: + + TopoDS_Shape p_shape; + +public: + + [[nodiscard]] + TopoDS_Shape tshape() const { return p_shape; } + + Shape(const TopoDS_Shape& s) : + p_shape {s} + {} + + Shape(TopoDS_Shape&& s) noexcept: + p_shape {std::forward(s)} + {} + +public: + + Shape() : + p_shape {} + {} + + virtual + ~Shape() = default; + //{ + //if (metadata.contains(*this)) + // metadata.erase(*this); + //} + + [[nodiscard]] + Type type() const + { + switch (p_shape.ShapeType()) + { + case TopAbs_VERTEX: + return Type::Vertex; + case TopAbs_EDGE: + return Type::Edge; + case TopAbs_FACE: + return Type::Face; + case TopAbs_WIRE: + return Type::Wire; + case TopAbs_SHELL: + return Type::Shell; + case TopAbs_SOLID: + return Type::Solid; + case TopAbs_COMPOUND: + return Type::Compound; + case TopAbs_COMPSOLID: + return Type::Compsolid; + case TopAbs_SHAPE: + return Type::Shape; + default: + return Type::Unknown; + } + } + + [[nodiscard]] + vec3 center() const + { + GProp_GProps props; + + switch (type()) + { + case Type::Solid: + case Type::Compsolid: + case Type::Compound: + BRepGProp::VolumeProperties(p_shape, props); + case Type::Shell: + case Type::Face: + BRepGProp::SurfaceProperties(p_shape, props); + default: + BRepGProp::LinearProperties(p_shape, props); + } + + gp_Pnt center {props.CentreOfMass()}; + + return vec3 {center.X(), center.Y(), center.Z()}; + } + + [[nodiscard]] + double length() const + { + GProp_GProps props; + + switch (type()) + { + case Type::Vertex: + return 0; + default: + BRepGProp::LinearProperties(p_shape, props); + return props.Mass(); + } + } + + [[nodiscard]] + double area() const + { + GProp_GProps props; + + switch (type()) + { + case Type::Vertex: + case Type::Edge: + case Type::Wire: + return 0; + default: + BRepGProp::SurfaceProperties(p_shape, props); + return props.Mass(); + } + } + + [[nodiscard]] + double volume() const + { + GProp_GProps props; + + switch (type()) + { + case Type::Compsolid: + case Type::Solid: + BRepGProp::VolumeProperties(p_shape, props); + return props.Mass(); + + default: + return 0; + } + } + + void label(const std::string& label) const + { + metadata[*this].label = label; + } + + [[nodiscard]] + std::string label() const + { + return metadata[*this].label; + } + + void dump(const std::string& filename, Format format) const + { + if (p_shape.IsNull()) + throw std::runtime_error("Trying to export null shape"); + + switch (format) + { + case Format::STEP: + { + STEPControl_Writer writer; + Interface_Static::SetCVal("xstep.cascade.unit", "MM"); + Interface_Static::SetCVal("write.step.unit", "MM"); + Interface_Static::SetIVal("write.step.nonmanifold", 1); + + writer.Transfer(p_shape, STEPControl_AsIs); + writer.Write(filename.c_str()); + break; + } + case Format::Unknown: + default: + throw std::invalid_argument("Unknown export format"); + } + } + + // + + [[nodiscard]] + sarray boundingBox() const + { + Bnd_Box bbox; + BRepBndLib::Add(p_shape, bbox, true); + gp_Pnt p1 {bbox.CornerMin()}; + gp_Pnt p2 {bbox.CornerMax()}; + + return sarray {{p1.X(), p1.Y(), p1.Z()}, {p2.X(), p2.Y(), p2.Z()}}; + } + + void incrementalMesh(double deflection) + { + BRepTools::Clean(p_shape); + BRepMesh_IncrementalMesh(p_shape, deflection, true); + } + + darray subShapes(Type type) const + { + darray subshapes; + for (TopExp_Explorer exp(p_shape, static_cast(type)); exp.More(); exp.Next()) + subshapes.push(Shape(exp.Current())); + return subshapes; + } + + darray edges() const + { + return subShapes(Type::Edge); + } + + darray faces() const + { + return subShapes(Type::Face); + } + + darray shells() const + { + return subShapes(Type::Shell); + } + + // Member functions: transformations + + Shape translate(const vec3& dir) + { + gp_Trsf transform; + transform.SetTranslation(gp_Vec(dir[0], dir[1], dir[2])); + BRepBuilderAPI_Transform builder {p_shape, transform, true}; + + return builder.Shape(); + } + + Shape rotate(const vec3& pos, const vec3& axis, double angle) + { + gp_Trsf transform; + transform.SetRotation(gp_Ax1({pos[0], pos[1], pos[2]}, {axis[0], axis[1], axis[2]}), rad(angle)); + BRepBuilderAPI_Transform builder {p_shape, transform, true}; + + return builder.Shape(); + } + + Shape scale(const vec3& center, double scale) + { + gp_Trsf transform; + transform.SetScale(gp_Pnt(center[0], center[1], center[2]), scale); + BRepBuilderAPI_Transform builder {p_shape, transform, true}; + + return builder.Shape(); + } + + Shape& scaled(const vec3& center, double scale) + { + p_shape = this->scale(center, scale).p_shape; + return *this; + } + + Shape extrude(const vec3& dir, double length) + { + BRepPrimAPI_MakePrism builder {p_shape, length * gp_Vec(dir[0], dir[1], dir[2]), true}; + + for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) + for (TopExp_Explorer exp {p_shape, static_cast(type)}; exp.More(); exp.Next()) + { + auto data = metadata[Shape(exp.Current())]; + + for (auto& mod : builder.Generated(exp.Current())) + metadata[Shape(mod)].merge(data); + } + + return builder.Shape(); + } + + Shape fillet(darray edges, double radius) + { + BRepFilletAPI_MakeFillet fillet {p_shape}; + + for (auto& e : edges) + fillet.Add(radius, TopoDS::Edge(e.p_shape)); + fillet.Build(); + + return fillet.Shape(); + } + + // Friend functions + + friend + double distance(const Shape& lhs, const Shape& rhs) + { + return BRepExtrema_DistShapeShape(lhs.tshape(), rhs.tshape()).Value(); + } + + friend + Shape fuse(const Shape& lhs, const Shape& rhs) + { + BRepAlgoAPI_Fuse builder {lhs.p_shape, rhs.p_shape}; + builder.Build(); + return Shape {builder.Shape()}; + } + + friend + Shape fuse(const darray& args, const darray& tools) + { + BRepAlgoAPI_Fuse builder; + NCollection_List args_, tools_; + for (auto& arg : args) + args_.Append(arg.tshape()); + for (auto& tool : tools) + tools_.Append(tool.tshape()); + builder.SetArguments(args_); + builder.SetTools(tools_); + builder.Build(); + return Shape {builder.Shape()}; + } + + friend + Shape common(const Shape& lhs, const Shape& rhs) + { + BRepAlgoAPI_Common builder {lhs.p_shape, rhs.p_shape}; + builder.Build(); + return Shape {builder.Shape()}; + } + + friend + Shape cut(const Shape& lhs, const Shape& rhs) + { + BRepAlgoAPI_Cut builder {lhs.p_shape, rhs.p_shape}; + builder.Build(); + for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) + for (TopExp_Explorer exp {lhs.p_shape, static_cast(type)}; exp.More(); exp.Next()) + { + auto data = metadata[Shape(exp.Current())]; + + for (auto& mod : builder.Modified(exp.Current())) + metadata[Shape(mod)].merge(data); + } + for (auto& type : { Type::Solid, Type::Face, Type::Edge, Type::Vertex }) + for (TopExp_Explorer exp {rhs.p_shape, static_cast(type)}; exp.More(); exp.Next()) + { + auto data = metadata[Shape(exp.Current())]; + + for (auto& mod : builder.Modified(exp.Current())) + metadata[Shape(mod)].merge(data); + } + return Shape {builder.Shape()}; + } + +}; + +// Global functions: primitives + +Shape sphere(vec3 center, double radius); + +Shape box(vec3 corner, double dx, double dy, double dz); + +} + + + + diff --git a/source/hpr/csg/shell.hpp b/source/hpr/csg/shell.hpp index 9044425..7de4424 100644 --- a/source/hpr/csg/shell.hpp +++ b/source/hpr/csg/shell.hpp @@ -1,52 +1,52 @@ -#pragma once - -#include "shape.hpp" -#include "face.hpp" - - -namespace hpr::csg -{ - -class Shell : public Shape -{ - -public: - - Shell() = default; - - ~Shell() override = default; - - explicit - Shell(const Shape& shape) : - Shape {shape.type() == Type::Shell ? shape : throw std::runtime_error("")} - {} - - explicit - Shell(const darray& faces) : - Shape {} - { - BRep_Builder builder; - TopoDS_Shell shell; - builder.MakeShell(shell); - - for (auto& shape : faces) - switch (shape.type()) - { - case Type::Face: - builder.Add(shell, Face(shape).tcast()); - break; - default: - throw std::runtime_error(""); - } - - p_shape = shell; - } - - [[nodiscard]] - TopoDS_Shell tcast() const - { - return TopoDS::Shell(p_shape); - } -}; - -} +#pragma once + +#include +#include + + +namespace hpr::csg +{ + +class Shell : public Shape +{ + +public: + + Shell() = default; + + ~Shell() override = default; + + explicit + Shell(const Shape& shape) : + Shape {shape.type() == Type::Shell ? shape : throw std::runtime_error("")} + {} + + explicit + Shell(const darray& faces) : + Shape {} + { + BRep_Builder builder; + TopoDS_Shell shell; + builder.MakeShell(shell); + + for (auto& shape : faces) + switch (shape.type()) + { + case Type::Face: + builder.Add(shell, Face(shape).tcast()); + break; + default: + throw std::runtime_error(""); + } + + p_shape = shell; + } + + [[nodiscard]] + TopoDS_Shell tcast() const + { + return TopoDS::Shell(p_shape); + } +}; + +} diff --git a/source/hpr/csg/solid.hpp b/source/hpr/csg/solid.hpp index 88320a1..1631b1d 100644 --- a/source/hpr/csg/solid.hpp +++ b/source/hpr/csg/solid.hpp @@ -1,45 +1,45 @@ -#pragma once - -#include "shape.hpp" -#include "shell.hpp" - - -namespace hpr::csg -{ - - class Solid : public Shape - { - - public: - - Solid() = default; - - ~Solid() override = default; - - explicit - Solid(const Shape& shape) : - Shape {shape.type() == Type::Solid ? shape : throw std::runtime_error("")} - {} - - explicit - Solid(const Shell& shell) : - Shape {} - { - BRep_Builder builder; - TopoDS_Solid solid; - - builder.MakeSolid(solid); - builder.Add(solid, shell.tcast()); - - p_shape = solid; - } - - [[nodiscard]] - TopoDS_Solid tcast() const - { - return TopoDS::Solid(p_shape); - } - }; - -} - +#pragma once + +#include +#include + + +namespace hpr::csg +{ + + class Solid : public Shape + { + + public: + + Solid() = default; + + ~Solid() override = default; + + explicit + Solid(const Shape& shape) : + Shape {shape.type() == Type::Solid ? shape : throw std::runtime_error("")} + {} + + explicit + Solid(const Shell& shell) : + Shape {} + { + BRep_Builder builder; + TopoDS_Solid solid; + + builder.MakeSolid(solid); + builder.Add(solid, shell.tcast()); + + p_shape = solid; + } + + [[nodiscard]] + TopoDS_Solid tcast() const + { + return TopoDS::Solid(p_shape); + } + }; + +} + diff --git a/source/hpr/csg/surface.hpp b/source/hpr/csg/surface.hpp index cf95fb5..9868ec1 100644 --- a/source/hpr/csg/surface.hpp +++ b/source/hpr/csg/surface.hpp @@ -1,64 +1,64 @@ -#pragma once - -#include "geometry.hpp" -#include "face.hpp" - - -namespace hpr::csg -{ - - class Surface : public Geometry - { - - protected: - - Handle(Geom_Surface) p_surface; - - public: - - Surface() = default; - - ~Surface() override = default; - - explicit - Surface(const Face& face) : - Geometry {}, - p_surface {BRep_Tool::Surface(face.tcast())} - {} - - [[nodiscard]] - Handle(Geom_Surface) tcast() const - { - return p_surface; - } - - [[nodiscard]] - vec3 value(double u, double v) const - { - gp_Pnt p {p_surface->Value(u, v)}; - - return vec3 {p.X(), p.Y(), p.Z()}; - } - - [[nodiscard]] - vec3 normal(double u, double v) const - { - GeomLProp_SLProps props {p_surface, u, v, 1, 1e-8}; - gp_Dir dir {props.Normal()}; - - return vec3 {dir.X(), dir.Y(), dir.Z()}; - } - - vec3 normal() - { - gp_Vec du, dv; - gp_Pnt p; - p_surface->D1(0, 0, p, du, dv); - gp_Vec dir {du ^ dv}; - return vec3 {dir.X(), dir.Y(), dir.Z()}; - } - }; - -} - - +#pragma once + +#include +#include + + +namespace hpr::csg +{ + + class Surface : public Geometry + { + + protected: + + Handle(Geom_Surface) p_surface; + + public: + + Surface() = default; + + ~Surface() override = default; + + explicit + Surface(const Face& face) : + Geometry {}, + p_surface {BRep_Tool::Surface(face.tcast())} + {} + + [[nodiscard]] + Handle(Geom_Surface) tcast() const + { + return p_surface; + } + + [[nodiscard]] + vec3 value(double u, double v) const + { + gp_Pnt p {p_surface->Value(u, v)}; + + return vec3 {p.X(), p.Y(), p.Z()}; + } + + [[nodiscard]] + vec3 normal(double u, double v) const + { + GeomLProp_SLProps props {p_surface, u, v, 1, 1e-8}; + gp_Dir dir {props.Normal()}; + + return vec3 {dir.X(), dir.Y(), dir.Z()}; + } + + vec3 normal() + { + gp_Vec du, dv; + gp_Pnt p; + p_surface->D1(0, 0, p, du, dv); + gp_Vec dir {du ^ dv}; + return vec3 {dir.X(), dir.Y(), dir.Z()}; + } + }; + +} + + diff --git a/source/hpr/csg/tests/CMakeLists.txt b/source/hpr/csg/tests/CMakeLists.txt deleted file mode 100644 index dcdd184..0000000 --- a/source/hpr/csg/tests/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -file(GLOB tests_cpp "*.cpp") - -add_executable(${PROJECT_NAME}-tests - ${tests_cpp} - ) - -target_link_libraries(${PROJECT_NAME}-tests - PUBLIC - hpr::${PROJECT_NAME} - PRIVATE - GTest::gtest_main - ) - -gtest_add_tests(TARGET ${PROJECT_NAME}-tests) diff --git a/source/hpr/csg/tests/csg-test.cpp b/source/hpr/csg/tests/csg-test.cpp index 73cbc48..4718825 100644 --- a/source/hpr/csg/tests/csg-test.cpp +++ b/source/hpr/csg/tests/csg-test.cpp @@ -1,24 +1,25 @@ -#include -#include "../../csg.hpp" - -TEST(csgTest, Shape) -{ - using namespace hpr; - double radius = 1.; - double volume = 4. / 3. * PI; - auto sphere = csg::sphere({0, 0, 0}, radius); - EXPECT_TRUE(equal(sphere.volume(), volume, 1e-6)); - auto box = csg::box({0, 0, 0}, 1, 1, 1); - EXPECT_TRUE(equal(box.volume(), 1.)); - auto edge = csg::Edge(); - int n = 0; - for (auto& face : box.subShapes(csg::Shape::Type::Face)) - { - std::stringstream name; - name << "face" << n; - csg::Face(face).label(name.str()); - ++n; - } - box.scale(box.center(), 5); - EXPECT_EQ(box.subShapes(csg::Shape::Type::Face)[2].label(), "face2"); +#include +#include + + +TEST(csgTest, Shape) +{ + using namespace hpr; + double radius = 1.; + double volume = 4. / 3. * pi(); + auto sphere = csg::sphere({0, 0, 0}, radius); + EXPECT_TRUE(equal(sphere.volume(), volume, 1e-6)); + auto box = csg::box({0, 0, 0}, 1, 1, 1); + EXPECT_TRUE(equal(box.volume(), 1.)); + auto edge = csg::Edge(); + int n = 0; + for (auto& face : box.subShapes(csg::Shape::Type::Face)) + { + std::stringstream name; + name << "face" << n; + csg::Face(face).label(name.str()); + ++n; + } + box.scale(box.center(), 5); + EXPECT_EQ(box.subShapes(csg::Shape::Type::Face)[2].label(), "face2"); } \ No newline at end of file diff --git a/source/hpr/csg/vertex.hpp b/source/hpr/csg/vertex.hpp index 031a2ba..f0f6591 100644 --- a/source/hpr/csg/vertex.hpp +++ b/source/hpr/csg/vertex.hpp @@ -1,43 +1,43 @@ -#pragma once - -#include "shape.hpp" - - -namespace hpr::csg -{ - -class Vertex : public Shape -{ - -public: - - Vertex() = default; - - ~Vertex() override = default; - - explicit - Vertex(const Shape& shape) : - Shape {shape.type() == Type::Vertex ? shape : throw std::runtime_error("")} - {} - - explicit - Vertex(const vec3& point) : - Shape {BRepBuilderAPI_MakeVertex(gp_Pnt(point[0], point[1], point[2])).Shape()} - {} - - [[nodiscard]] - TopoDS_Vertex tcast() const - { - return TopoDS::Vertex(p_shape); - } - - [[nodiscard]] - vec3 cast() const - { - gp_Pnt point = BRep_Tool::Pnt(tcast()); - return vec3 {point.X(), point.Y(), point.Z()}; - } -}; - -} - +#pragma once + +#include + + +namespace hpr::csg +{ + +class Vertex : public Shape +{ + +public: + + Vertex() = default; + + ~Vertex() override = default; + + explicit + Vertex(const Shape& shape) : + Shape {shape.type() == Type::Vertex ? shape : throw std::runtime_error("")} + {} + + explicit + Vertex(const vec3& point) : + Shape {BRepBuilderAPI_MakeVertex(gp_Pnt(point[0], point[1], point[2])).Shape()} + {} + + [[nodiscard]] + TopoDS_Vertex tcast() const + { + return TopoDS::Vertex(p_shape); + } + + [[nodiscard]] + vec3 cast() const + { + gp_Pnt point = BRep_Tool::Pnt(tcast()); + return vec3 {point.X(), point.Y(), point.Z()}; + } +}; + +} + diff --git a/source/hpr/csg/wire.hpp b/source/hpr/csg/wire.hpp index 104d8ee..cd6e1d3 100644 --- a/source/hpr/csg/wire.hpp +++ b/source/hpr/csg/wire.hpp @@ -1,53 +1,53 @@ -#pragma once - -#include "shape.hpp" -#include "edge.hpp" - - -namespace hpr::csg -{ - -class Wire : public Shape -{ - -public: - - Wire() = default; - - ~Wire() override = default; - - explicit - Wire(const Shape& shape) : - Shape {shape.type() == Type::Wire ? shape : throw std::runtime_error("")} - {} - - explicit - Wire(const darray& edges) : - Shape {} - { - BRepBuilderAPI_MakeWire builder; - - for (auto& shape : edges) - switch (shape.type()) - { - case Type::Edge: - builder.Add(Edge(shape).tcast()); - break; - case Type::Wire: - builder.Add(Wire(shape).tcast()); - break; - default: - throw std::runtime_error(""); - } - - p_shape = builder.Shape(); - } - - [[nodiscard]] - TopoDS_Wire tcast() const - { - return TopoDS::Wire(p_shape); - } -}; - -} +#pragma once + +#include +#include + + +namespace hpr::csg +{ + +class Wire : public Shape +{ + +public: + + Wire() = default; + + ~Wire() override = default; + + explicit + Wire(const Shape& shape) : + Shape {shape.type() == Type::Wire ? shape : throw std::runtime_error("")} + {} + + explicit + Wire(const darray& edges) : + Shape {} + { + BRepBuilderAPI_MakeWire builder; + + for (auto& shape : edges) + switch (shape.type()) + { + case Type::Edge: + builder.Add(Edge(shape).tcast()); + break; + case Type::Wire: + builder.Add(Wire(shape).tcast()); + break; + default: + throw std::runtime_error(""); + } + + p_shape = builder.Shape(); + } + + [[nodiscard]] + TopoDS_Wire tcast() const + { + return TopoDS::Wire(p_shape); + } +}; + +} diff --git a/source/hpr/exception.hpp b/source/hpr/exception.hpp new file mode 100644 index 0000000..25ca37a --- /dev/null +++ b/source/hpr/exception.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace hpr +{ + class Exception : public std::exception + { + protected: + std::string p_message; + public: + inline explicit + Exception(std::source_location location = std::source_location::current()) : + p_message {} + { + std::stringstream _message; + _message << "\t" << p_message + << "\n where:\t\t" << location.file_name() << ":" << location.line() << ":" << location.column() + << "\n function:\t" << location.function_name(); + p_message = _message.str(); + } + inline explicit + Exception(const std::string& message, std::source_location location = std::source_location::current()) : + p_message {message} + { + std::stringstream _message; + _message << "\t" << p_message + << "\n where:\t" << location.file_name() << ":" << location.line() << ":" << location.column() + << "\n function:\t" << location.function_name(); + p_message = _message.str(); + } + [[nodiscard]] const char* what() const noexcept override { + std::vector vv; + return p_message.data(); + } + }; + + struct OutOfRange : public Exception + { + inline explicit OutOfRange(std::source_location location = std::source_location::current()) : Exception {"Out of range", location} {} + inline explicit OutOfRange(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {} + }; + + struct LengthError : public Exception + { + inline explicit LengthError(std::source_location location = std::source_location::current()) : Exception {"Length error", location} {} + inline explicit LengthError(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {} + }; +} \ No newline at end of file diff --git a/source/hpr/geometry.hpp b/source/hpr/geometry.hpp index d3e9d51..9dce06f 100644 --- a/source/hpr/geometry.hpp +++ b/source/hpr/geometry.hpp @@ -1,5 +1,5 @@ -#pragma once - -#include "geometry/polytope.hpp" -#include "geometry/triangle.hpp" -#include "geometry/tetrahedron.hpp" +#pragma once + +#include +#include +#include diff --git a/source/hpr/geometry/CMakeLists.txt b/source/hpr/geometry/CMakeLists.txt index 475011b..8ab1f93 100644 --- a/source/hpr/geometry/CMakeLists.txt +++ b/source/hpr/geometry/CMakeLists.txt @@ -1,57 +1,21 @@ cmake_minimum_required(VERSION 3.16) project(geometry - VERSION "${HPR_PROJECT_VERSION}" + VERSION "${HPR_VERSION}" LANGUAGES CXX ) -add_library(${PROJECT_NAME} INTERFACE) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) +hpr_add_library(${PROJECT_NAME} INTERFACE) -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../geometry.hpp" "*.hpp" +hpr_collect_interface(${PROJECT_NAME} + "../geometry.hpp" + "*.hpp" ) -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> ) -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) + +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) + diff --git a/source/hpr/geometry/polytope.hpp b/source/hpr/geometry/polytope.hpp index e614614..1e793c4 100644 --- a/source/hpr/geometry/polytope.hpp +++ b/source/hpr/geometry/polytope.hpp @@ -1,48 +1,48 @@ -#pragma once - -#include "../containers.hpp" -#include "../math.hpp" - - -namespace hpr::geometry -{ - -template -class Polytope -{ - -public: - - enum class Type - { - Nullitope = -1, - Monon, - Dion, - Polygon, - Polyhedron, - Polychoron, - Unknown - }; - -protected: - - const int p_dimension; - const int p_space; - Type p_type; - darray> p_points; - -public: - - Polytope() : - p_dimension {Dim}, - p_space {Space}, - p_type {Type::Unknown}, - p_points {} - {} - - virtual - ~Polytope() = default; - -}; - +#pragma once + +#include +#include + + +namespace hpr::geometry +{ + +template +class Polytope +{ + +public: + + enum class Type + { + Nullitope = -1, + Monon, + Dion, + Polygon, + Polyhedron, + Polychoron, + Unknown + }; + +protected: + + const int p_dimension; + const int p_space; + Type p_type; + darray> p_points; + +public: + + Polytope() : + p_dimension {Dim}, + p_space {Space}, + p_type {Type::Unknown}, + p_points {} + {} + + virtual + ~Polytope() = default; + +}; + } \ No newline at end of file diff --git a/source/hpr/geometry/tetrahedron.hpp b/source/hpr/geometry/tetrahedron.hpp index c082838..ed226ab 100644 --- a/source/hpr/geometry/tetrahedron.hpp +++ b/source/hpr/geometry/tetrahedron.hpp @@ -1,19 +1,21 @@ -#include "../math.hpp" - -namespace hpr::geometry -{ - -vec3 circumCentre(vec3 p1, vec3 p2, vec3 p3, vec3 p4) -{ - vec3 e1 = p2 - p1; - vec3 e2 = p3 - p1; - vec3 e3 = p4 - p1; - mat3 A; - A.row(0, e1); - A.row(1, e2); - A.row(2, e3); - vec3 B = 0.5 * vec3(sum(pow(p2, 2)) - sum(pow(p1, 2)), sum(pow(p3, 2)) - sum(pow(p1, 2)), sum(pow(p4, 2)) - sum(pow(p1, 2))); - return A.inv() * B; -} - +#pragma once + +#include + +namespace hpr::geometry +{ + +vec3 circumCentre(vec3 p1, vec3 p2, vec3 p3, vec3 p4) +{ + vec3 e1 = p2 - p1; + vec3 e2 = p3 - p1; + vec3 e3 = p4 - p1; + mat3 A; + A.row(0, e1); + A.row(1, e2); + A.row(2, e3); + vec3 B = 0.5 * vec3(sum(pow(p2, 2)) - sum(pow(p1, 2)), sum(pow(p3, 2)) - sum(pow(p1, 2)), sum(pow(p4, 2)) - sum(pow(p1, 2))); + return A.inv() * B; +} + } \ No newline at end of file diff --git a/source/hpr/geometry/triangle.hpp b/source/hpr/geometry/triangle.hpp index e138c25..fb6a794 100644 --- a/source/hpr/geometry/triangle.hpp +++ b/source/hpr/geometry/triangle.hpp @@ -1,15 +1,17 @@ -#include "../math.hpp" - -namespace hpr::geometry -{ - -vec2 circumCentre(vec2 p1, vec2 p2, vec2 p3) -{ - vec2 pb1 {(p1 + p2) * 0.5}; - vec2 pb2 {(p2 + p3) * 0.5}; - scalar s1 = (p2[1] - p1[1]) / (p2[0] - p1[0]); - scalar s2 = (p3[1] - p2[1]) / (p3[0] - p2[0]); - return vec2(pb1[0] + s1 * pb1[1], pb2[0] + s2 * pb2[1]) * mat2(1, s1, 1, s2).inv(); -} - +#pragma once + +#include + +namespace hpr::geometry +{ + +vec2 circumCentre(vec2 p1, vec2 p2, vec2 p3) +{ + vec2 pb1 {(p1 + p2) * 0.5}; + vec2 pb2 {(p2 + p3) * 0.5}; + scalar s1 = (p2[1] - p1[1]) / (p2[0] - p1[0]); + scalar s2 = (p3[1] - p2[1]) / (p3[0] - p2[0]); + return vec2(pb1[0] + s1 * pb1[1], pb2[0] + s2 * pb2[1]) * mat2(1, s1, 1, s2).inv(); +} + } \ No newline at end of file diff --git a/source/hpr/gpu.hpp b/source/hpr/gpu.hpp index 08ec17a..cd6a92f 100644 --- a/source/hpr/gpu.hpp +++ b/source/hpr/gpu.hpp @@ -1,15 +1,18 @@ -#pragma once - - -#include "gpu/array_object.hpp" -#include "gpu/buffer_object.hpp" -#include "gpu/color_buffer.hpp" -#include "gpu/cull_face.hpp" -#include "gpu/depth_buffer.hpp" -#include "gpu/framebuffer.hpp" -#include "gpu/renderbuffer.hpp" -#include "gpu/shader.hpp" -#include "gpu/shader_program.hpp" -#include "gpu/stencil_buffer.hpp" -#include "gpu/texture.hpp" -#include "gpu/viewport.hpp" +#pragma once + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/source/hpr/gpu/CMakeLists.txt b/source/hpr/gpu/CMakeLists.txt index 0a76d9e..a4a7d32 100644 --- a/source/hpr/gpu/CMakeLists.txt +++ b/source/hpr/gpu/CMakeLists.txt @@ -1,68 +1,32 @@ -cmake_minimum_required(VERSION 3.16) - -project(gpu - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX -) - -add_library(${PROJECT_NAME}) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../gpu.hpp" "*.hpp" -) - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES - "*.cpp" -) - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ - PRIVATE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES} -) - -target_link_libraries(${PROJECT_NAME} - glad - stb -) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) +cmake_minimum_required(VERSION 3.16) + +project(gpu + VERSION "${HPR_VERSION}" + LANGUAGES CXX +) + +hpr_add_library(${PROJECT_NAME} INTERFACE) + +hpr_collect_interface(${PROJECT_NAME} + "../gpu.hpp" + "*.hpp" +) + +#hpr_collect_sources(${PROJECT_NAME} +# "*.cpp" +#) + +target_sources(${PROJECT_NAME} + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> + PRIVATE ${${PROJECT_NAME}_SOURCES} +) + +target_link_libraries(${PROJECT_NAME} + INTERFACE + glad::glad + glfw::glfw + stb::stb +) + + +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) diff --git a/source/hpr/gpu/array_object.cpp b/source/hpr/gpu/array_object.cpp deleted file mode 100644 index 462e940..0000000 --- a/source/hpr/gpu/array_object.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include "array_object.hpp" diff --git a/source/hpr/gpu/array_object.hpp b/source/hpr/gpu/array_object.hpp index ec98aff..231db94 100644 --- a/source/hpr/gpu/array_object.hpp +++ b/source/hpr/gpu/array_object.hpp @@ -1,104 +1,125 @@ -#pragma once - -#include "buffer_object.hpp" - -#include - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - - class ArrayObject - { - - - protected: - - unsigned int p_index; - int p_size; - int p_stride; - bool p_binded; - - public: - - inline - ArrayObject() : - p_index {0}, - p_size {0}, - p_stride {0}, - p_binded {false} - {} - - virtual - ~ArrayObject() = default; - - [[nodiscard]] - int size() const - { - return p_size; - } - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - void create() - { - glGenVertexArrays(1, &p_index); - } - - void bind() - { - glBindVertexArray(p_index); - p_binded = true; - } - - void unbind() - { - glBindVertexArray(0); - p_binded = false; - } - - bool binded() const - { - return p_binded; - } - - void destroy() - { - glDeleteVertexArrays(1, &p_index); - } - - void attribPointer(BufferObject& buffer, unsigned int location, unsigned int size) - { - if (buffer.type() == BufferObject::Type::Unknown) - throw std::runtime_error("Unknown buffer type"); - if (!binded()) - throw std::runtime_error("ArrayObject is not binded"); - if (!buffer.valid()) - throw std::runtime_error("BufferObject is invalid"); - - buffer.bind(); - glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE, sizeof(float) * buffer.offset(), static_cast(nullptr)); - glEnableVertexAttribArray(location); - buffer.unbind(); - } - - void draw() - { - - } - - inline - bool valid() const - { - return p_index > 0; - } - }; - -} +#pragma once + +#include + +#include + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + + class ArrayObject + { + public: + + enum Mode + { + Points = GL_POINTS, + LineStrip = GL_LINE_STRIP, + LineLoop = GL_LINE_LOOP, + Lines = GL_LINES, + LineStripAdjacency = GL_LINE_STRIP_ADJACENCY, + LinesAdjacency = GL_LINES_ADJACENCY, + TriangleStrip = GL_TRIANGLE_STRIP, + TriangleFan = GL_TRIANGLE_FAN, + Triangles = 0x0004, //GL_TRIANGLES, + TriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY, + TrianglesAdjacency = GL_TRIANGLES_ADJACENCY, + Patches = GL_PATCHES + }; + + protected: + + GLuint p_index; + int p_size; + int p_stride; + bool p_binded; + + public: + + inline + ArrayObject() : + p_index {0}, + p_size {0}, + p_stride {0}, + p_binded {false} + {} + + virtual + ~ArrayObject() = default; + + [[nodiscard]] + int size() const + { + return p_size; + } + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + void create() + { + glGenVertexArrays(1, &p_index); + } + + void bind() + { + glBindVertexArray(p_index); + p_binded = true; + } + + void unbind() + { + glBindVertexArray(0); + p_binded = false; + } + + bool binded() const + { + return p_binded; + } + + void destroy() + { + glDeleteVertexArrays(1, &p_index); + } + + void attribPointer(BufferObject& buffer, unsigned int location, int size) + { + if (buffer.type() == BufferObject::Type::Unknown) + throw std::runtime_error("Unknown buffer type"); + if (!binded()) + throw std::runtime_error("ArrayObject is not binded"); + if (!buffer.valid()) + throw std::runtime_error("BufferObject is invalid"); + + buffer.bind(); + glEnableVertexAttribArray(location); + glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE, sizeof(float) * buffer.offset(), static_cast(nullptr)); + buffer.unbind(); + } + + void drawElements(Mode mode, int count) const + { + glDrawElements(mode, count, GL_UNSIGNED_INT, nullptr); + } + + void drawArrays(Mode mode, int count) const + { + glDrawArrays(mode, 0, count); + } + + inline + bool valid() const + { + return p_index > 0; + } + }; + +} diff --git a/source/hpr/gpu/buffer_object.cpp b/source/hpr/gpu/buffer_object.cpp deleted file mode 100644 index 1d4a436..0000000 --- a/source/hpr/gpu/buffer_object.cpp +++ /dev/null @@ -1,27 +0,0 @@ - -#include -#include "buffer_object.hpp" - -namespace hpr::gpu -{ - - void BufferObject::bind() - { - glBindBuffer((GLenum)p_type, p_index); - p_binded = true; - } - - void BufferObject::unbind() - { - glBindBuffer((GLenum)p_type, 0); - p_binded = false; - } - - void BufferObject::destroy() - { - if (p_type == Type::Unknown) - std::runtime_error("Unknown buffer type"); - - glDeleteBuffers(1, &p_index); - } -} diff --git a/source/hpr/gpu/buffer_object.hpp b/source/hpr/gpu/buffer_object.hpp index 02001df..89e5bb6 100644 --- a/source/hpr/gpu/buffer_object.hpp +++ b/source/hpr/gpu/buffer_object.hpp @@ -1,134 +1,153 @@ -#pragma once - -#include "../containers.hpp" - -#include -#ifndef __gl_h_ -#include -#endif - - -namespace hpr::gpu -{ - -class BufferObject -{ - -public: - - enum class Type - { - Vertex = 0x8892, //GL_ARRAY_BUFFER, - Index = 0x8893, //GL_ELEMENT_ARRAY_BUFFER, - Uniform = 0x8A11, //GL_UNIFORM_BUFFER, - Unknown = -1 - }; - -protected: - - Type p_type; - unsigned int p_index; - int p_size; - int p_offset; - bool p_binded; - -public: - - inline - BufferObject() : - p_type {Type::Unknown}, - p_index {0}, - p_size {0}, - p_offset {0}, - p_binded {false} - {} - - explicit inline - BufferObject(Type type) : - p_type {type}, - p_index {0}, - p_size {0}, - p_offset {0}, - p_binded {false} - {} - - virtual - ~BufferObject() = default; - - [[nodiscard]] - int size() const - { - return p_size; - } - - [[nodiscard]] - Type type() const - { - return p_type; - } - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - [[nodiscard]] - unsigned int offset() const - { - return p_offset; - } - - void bind() ; - - void unbind(); - - [[nodiscard]] - bool binded() const - { - return p_binded; - } - - template - void create(const darray& data, unsigned int offset = 0) - { - if (p_type == Type::Unknown) - std::runtime_error("Unknown buffer type"); - - unsigned int drawType; - - if (p_type == Type::Uniform) - drawType = GL_DYNAMIC_DRAW; - else - drawType = GL_STATIC_DRAW; - - glGenBuffers(1, &p_index); - bind(); - glBufferData((GLenum)p_type, sizeof(T) * data.size(), data.data(), drawType); - unbind(); - - p_offset = offset; - } - - template - void edit(const darray& data, unsigned int offset = 0) - { - if (p_type == Type::Unknown) - std::runtime_error("Unknown buffer type"); - - bind(); - glBufferSubData(p_type, offset, sizeof(T) * data.size(), data.data()); - unbind(); - } - - void destroy(); - - [[nodiscard]] - inline - bool valid() const - { - return p_index > 0; - } -}; - +#pragma once + +#include + + +#include +#ifndef __gl_h_ +#include +#endif + + +namespace hpr::gpu +{ + +class BufferObject +{ + +public: + + enum Type + { + Vertex = 0x8892, // GL_ARRAY_BUFFER, + Index = 0x8893, // GL_ELEMENT_ARRAY_BUFFER, + Uniform = 0x8A11, // GL_UNIFORM_BUFFER, + Unknown = -1 + }; + +protected: + + Type p_type; + unsigned int p_index; + int p_size; + unsigned int p_offset; + bool p_binded; + +public: + + inline + BufferObject() : + p_type {Type::Unknown}, + p_index {0}, + p_size {0}, + p_offset {0}, + p_binded {false} + {} + + explicit inline + BufferObject(Type type) : + p_type {type}, + p_index {0}, + p_size {0}, + p_offset {0}, + p_binded {false} + {} + + virtual + ~BufferObject() = default; + + [[nodiscard]] + int size() const + { + return p_size; + } + + [[nodiscard]] + Type type() const + { + return p_type; + } + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + [[nodiscard]] + unsigned int offset() const + { + return p_offset; + } + + void bind() + { + glBindBuffer((GLenum)p_type, p_index); + p_binded = true; + } + + void unbind() + { + glBindBuffer((GLenum)p_type, 0); + p_binded = false; + } + + [[nodiscard]] + bool binded() const + { + return p_binded; + } + + template + void create(const darray& data, unsigned int offset = 0) + { + if (p_type == Type::Unknown) + throw std::runtime_error("Unknown buffer type"); + + unsigned int drawType; + + if (p_type == Type::Uniform) + drawType = GL_DYNAMIC_DRAW; + else + drawType = GL_STATIC_DRAW; + + glGenBuffers(1, &p_index); + bind(); + glBufferData(static_cast(p_type), sizeof(T) * data.size(), data.data(), drawType); + unbind(); + + p_offset = offset; + p_size = data.size(); + } + + template + void edit(const darray& data, unsigned int offset = 0) + { + if (p_type == Type::Unknown) + throw std::runtime_error("Unknown buffer type"); + + bind(); + glBufferSubData(p_type, offset, sizeof(T) * data.size(), data.data()); + unbind(); + + p_offset = offset; + p_size = data.size(); + } + + void destroy() + { + if (p_type == Type::Unknown) + throw std::runtime_error("Unknown buffer type"); + + glDeleteBuffers(1, &p_index); + } + + [[nodiscard]] + inline + bool valid() const + { + return p_index > 0; + } +}; + } \ No newline at end of file diff --git a/source/hpr/gpu/camera.hpp b/source/hpr/gpu/camera.hpp index e11d835..8ac8793 100644 --- a/source/hpr/gpu/camera.hpp +++ b/source/hpr/gpu/camera.hpp @@ -1,40 +1,40 @@ -#pragma once - -#include "../math.hpp" - - -namespace hpr::gpu -{ - -class Camera -{ - -protected: - - vec3 p_front; - vec3 p_up; - vec3 p_left; - - scalar p_yaw; - scalar p_pitch; - scalar p_roll; - - vec3 p_position; - vec3 p_target; - - scalar p_distance; - -public: - - Camera() : - p_front {0., 0., -1.}, - p_up {0., 0., 1.}, - p_left {1., 0., 0.} - {} - - virtual - ~Camera() = default; - -}; - +#pragma once + +#include + + +namespace hpr::gpu +{ + +class Camera +{ + +protected: + + vec3 p_front; + vec3 p_up; + vec3 p_left; + + scalar p_yaw; + scalar p_pitch; + scalar p_roll; + + vec3 p_position; + vec3 p_target; + + scalar p_distance; + +public: + + Camera() : + p_front {0., 0., -1.}, + p_up {0., 0., 1.}, + p_left {1., 0., 0.} + {} + + virtual + ~Camera() = default; + +}; + } \ No newline at end of file diff --git a/source/hpr/gpu/color_buffer.hpp b/source/hpr/gpu/color_buffer.hpp index 6201485..f3c83d3 100644 --- a/source/hpr/gpu/color_buffer.hpp +++ b/source/hpr/gpu/color_buffer.hpp @@ -1,68 +1,70 @@ -#pragma once - -#include "../math/vector.hpp" -#ifndef __gl_h_ -#include -#endif - - - -namespace hpr::gpu -{ - - class ColorBuffer - { - - protected: - - bool p_enabledRed; - bool p_enabledGreen; - bool p_enabledBlue; - bool p_enabledAlpha; - vec4 p_color; - - public: - - inline - ColorBuffer() : - p_enabledRed {true}, - p_enabledGreen {true}, - p_enabledBlue {true}, - p_enabledAlpha {true}, - p_color {} - {} - - inline - ColorBuffer(bool red, bool green, bool blue, bool alpha) : - p_enabledRed {red}, - p_enabledGreen {green}, - p_enabledBlue {blue}, - p_enabledAlpha {alpha}, - p_color {} - {} - - virtual - ~ColorBuffer() = default; - - void mask(bool red, bool green, bool blue, bool alpha) - { - glColorMask(red, green, blue, alpha); - } - - inline - void clear(const vec4& color) - { - p_color = color; - glClearColor(color[0], color[1], color[2], color[3]); - glClear(GL_COLOR_BUFFER_BIT); - } - - inline - void clear() - { - clear(p_color); - } - }; - -} - +#pragma once + +#include + +#ifndef __gl_h_ +#include +#endif + + + +namespace hpr::gpu +{ + + class ColorBuffer + { + + protected: + + bool p_enabledRed; + bool p_enabledGreen; + bool p_enabledBlue; + bool p_enabledAlpha; + vec4 p_color; + + public: + + inline + ColorBuffer() : + p_enabledRed {true}, + p_enabledGreen {true}, + p_enabledBlue {true}, + p_enabledAlpha {true}, + p_color {} + {} + + inline + ColorBuffer(bool red, bool green, bool blue, bool alpha) : + p_enabledRed {red}, + p_enabledGreen {green}, + p_enabledBlue {blue}, + p_enabledAlpha {alpha}, + p_color {} + {} + + virtual + ~ColorBuffer() = default; + + inline + void mask(bool red, bool green, bool blue, bool alpha) const + { + glColorMask(red, green, blue, alpha); + } + + inline + void clear(const vec4& color) + { + p_color = color; + glClearColor(color[0], color[1], color[2], color[3]); + glClear(GL_COLOR_BUFFER_BIT); + } + + inline + void clear() + { + clear(p_color); + } + }; + +} + diff --git a/source/hpr/gpu/common.hpp b/source/hpr/gpu/common.hpp index 2b382c7..03f83bc 100644 --- a/source/hpr/gpu/common.hpp +++ b/source/hpr/gpu/common.hpp @@ -1,4 +1,4 @@ -#pragma once - -#include - +#pragma once + +#include + diff --git a/source/hpr/gpu/context.hpp b/source/hpr/gpu/context.hpp new file mode 100644 index 0000000..1f9061f --- /dev/null +++ b/source/hpr/gpu/context.hpp @@ -0,0 +1,122 @@ +#pragma once + +#ifndef __gl_h_ +#include +#endif +#include + +#include +#include + + +namespace hpr::gpu +{ + +class Context +{ + +protected: + + bool p_glInitialized; + bool p_glfwInitialized; + +public: + + inline + Context() : + p_glInitialized {false}, + p_glfwInitialized {false} + { + if (glfwInit()) + p_glfwInitialized = true; + else + throw std::runtime_error("Cannot initialize GLFW context"); + + } + + void link() + { + if (gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) + p_glInitialized = true; + else + throw std::runtime_error("Cannot initialize GLAD context"); + } + + constexpr + bool valid() const + { + return p_glInitialized && p_glfwInitialized; + } + + inline + void destroy() const + { + glfwTerminate(); + } + + inline + void debug(bool enable = true) + { + const auto debugOutput = [](GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length, const char* message, const void* userParam) + { + // ignore non-significant error/warning codes + if (id == 131169 || id == 131185 || id == 131218 || id == 131204) + return; + + std::cout << "Debug::GL[" << id << "]::"; + + switch (source) + { + case GL_DEBUG_SOURCE_API: std::cout << "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: std::cout << "Window_System"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout << "Shader_Compiler"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: std::cout << "Third_Party"; break; + case GL_DEBUG_SOURCE_APPLICATION: std::cout << "Application"; break; + case GL_DEBUG_SOURCE_OTHER: std::cout << "Other"; break; + default: break; + } + std::cout << "::"; + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: std::cout << "Error";break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout << "Deprecated_Behaviour"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: std::cout << "Undefined_Behaviour"; break; + case GL_DEBUG_TYPE_PORTABILITY: std::cout << "Portability"; break; + case GL_DEBUG_TYPE_PERFORMANCE: std::cout << "Performance"; break; + case GL_DEBUG_TYPE_MARKER: std::cout << "Marker"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: std::cout << "Push_Group"; break; + case GL_DEBUG_TYPE_POP_GROUP: std::cout << "Pop_Group"; break; + case GL_DEBUG_TYPE_OTHER: std::cout << "Other"; break; + default: break; + } + std::cout << " "; + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: std::cout << "(high)"; break; + case GL_DEBUG_SEVERITY_MEDIUM: std::cout << "(medium)"; break; + case GL_DEBUG_SEVERITY_LOW: std::cout << "(low)"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout << "(notification)"; break; + default: break; + } + std::cout << ": " << message << std::endl; + }; + + if (enable) + { + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(debugOutput, nullptr); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE); + } + else + { + glDisable(GL_DEBUG_OUTPUT); + glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } + } + +}; + +} diff --git a/source/hpr/gpu/cull_face.hpp b/source/hpr/gpu/cull_face.hpp index e6e9faa..cd2c6a8 100644 --- a/source/hpr/gpu/cull_face.hpp +++ b/source/hpr/gpu/cull_face.hpp @@ -1,76 +1,80 @@ -#pragma once - -#ifndef __gl_h_ -#include -#endif - - - -namespace hpr::gpu -{ - -class CullFace -{ - - enum class Mode - { - Front = GL_FRONT, - Back = GL_BACK, - FrontAndBack = GL_FRONT_AND_BACK, - None = GL_NONE - }; - -protected: - - bool p_binded; - Mode p_mode; - -public: - - inline - CullFace() : - p_binded {false}, - p_mode {Mode::FrontAndBack} - {} - - inline - CullFace(Mode mode) : - p_binded {false}, - p_mode {mode} - {} - - virtual - ~CullFace() = default; - - inline - void bind() - { - p_binded = true; - glEnable(GL_CULL_FACE); - } - - inline - void unbind() - { - p_binded = false; - glDisable(GL_CULL_FACE); - - } - - inline - bool binded() const - { - return p_binded; - } - - inline - void set(Mode mode) - { - p_mode = mode; - glCullFace(static_cast(mode)); - } - -}; - -} - +#pragma once + +#ifndef __gl_h_ +#include +#endif + + + +namespace hpr::gpu +{ + +class CullFace +{ + +public: + + enum Mode + { + Front = GL_FRONT, + Back = GL_BACK, + FrontAndBack = GL_FRONT_AND_BACK, + None = GL_NONE + }; + +protected: + + bool p_binded; + Mode p_mode; + +public: + + inline + CullFace() : + p_binded {false}, + p_mode {Mode::FrontAndBack} + {} + + inline + CullFace(Mode mode) : + p_binded {false}, + p_mode {mode} + { + set(mode); + } + + virtual + ~CullFace() = default; + + inline + void bind() + { + p_binded = true; + glEnable(GL_CULL_FACE); + } + + inline + void unbind() + { + p_binded = false; + glDisable(GL_CULL_FACE); + + } + + inline + bool binded() const + { + return p_binded; + } + + inline + void set(Mode mode) + { + p_mode = mode; + glCullFace(static_cast(mode)); + } + +}; + +} + diff --git a/source/hpr/gpu/depth_buffer.hpp b/source/hpr/gpu/depth_buffer.hpp index 21187ee..19c3773 100644 --- a/source/hpr/gpu/depth_buffer.hpp +++ b/source/hpr/gpu/depth_buffer.hpp @@ -1,84 +1,84 @@ -#pragma once - -#ifndef __gl_h_ -#include -#endif - - -namespace hpr::gpu -{ - -class DepthBuffer -{ - -protected: - - bool p_enabled; - bool p_binded; - -public: - - inline - DepthBuffer() : - p_enabled {true}, - p_binded {false} - {} - - inline - DepthBuffer(bool enabled) : - p_enabled {enabled}, - p_binded {false} - {} - - virtual - ~DepthBuffer() = default; - - inline - void bind() - { - p_binded = true; - glEnable(GL_DEPTH_TEST); - } - - inline - void unbind() - { - p_binded = false; - glDisable(GL_DEPTH_TEST); - } - - inline - bool binded() const - { - return p_binded; - } - - inline - void enable() - { - p_enabled = true; - glDepthMask(GL_TRUE); - } - - inline - void disable() - { - p_enabled = false; - glDepthMask(GL_FALSE); - } - - [[nodiscard]] - inline - bool enabled() const - { - return p_enabled; - } - - inline - void clear() const - { - glClear(GL_DEPTH_BUFFER_BIT); - } -}; - -} +#pragma once + +#ifndef __gl_h_ +#include +#endif + + +namespace hpr::gpu +{ + +class DepthBuffer +{ + +protected: + + bool p_enabled; + bool p_binded; + +public: + + inline + DepthBuffer() : + p_enabled {true}, + p_binded {false} + {} + + inline + DepthBuffer(bool enabled) : + p_enabled {enabled}, + p_binded {false} + {} + + virtual + ~DepthBuffer() = default; + + inline + void bind() + { + p_binded = true; + glEnable(GL_DEPTH_TEST); + } + + inline + void unbind() + { + p_binded = false; + glDisable(GL_DEPTH_TEST); + } + + inline + bool binded() const + { + return p_binded; + } + + inline + void enable() + { + p_enabled = true; + glDepthMask(GL_TRUE); + } + + inline + void disable() + { + p_enabled = false; + glDepthMask(GL_FALSE); + } + + [[nodiscard]] + inline + bool enabled() const + { + return p_enabled; + } + + inline + void clear() const + { + glClear(GL_DEPTH_BUFFER_BIT); + } +}; + +} diff --git a/source/hpr/gpu/framebuffer.hpp b/source/hpr/gpu/framebuffer.hpp index 7534e65..05ba276 100644 --- a/source/hpr/gpu/framebuffer.hpp +++ b/source/hpr/gpu/framebuffer.hpp @@ -1,131 +1,178 @@ -#pragma once - -#include "texture.hpp" -#include "renderbuffer.hpp" - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - -class Framebuffer -{ - -protected: - - Texture p_texture; - Renderbuffer p_renderbuffer; - unsigned int p_index; - bool p_binded; - -public: - - inline - Framebuffer() : - p_index {0}, - p_texture {}, - p_renderbuffer {} - {} - - virtual - ~Framebuffer() = default; - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - void bind() - { - glBindFramebuffer(GL_FRAMEBUFFER, p_index); - p_binded = true; - } - - void unbind() - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - p_binded = false; - } - - bool binded() const - { - return p_binded; - } - - void attach(const Texture& texture) - { - if (!binded() && valid()) - std::runtime_error("Framebuffer not binded or invalid"); - if (!texture.valid()) - std::runtime_error("Texture is not valid"); - - p_texture = texture; - p_texture.bind(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture.index(), 0); - - p_texture.unbind(); - } - - void attach(const Renderbuffer& renderbuffer) - { - if (!binded() && valid()) - std::runtime_error("Framebuffer not binded or invalid"); - if (!renderbuffer.valid()) - std::runtime_error("Renderbuffer is not valid"); - - p_renderbuffer = renderbuffer; - p_renderbuffer.bind(); - p_renderbuffer.storage(p_texture.width(), p_texture.height()); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, p_renderbuffer.index()); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - throw std::runtime_error("Framebuffer is not complete"); - - p_renderbuffer.unbind(); - } - - void create() - { - glGenFramebuffers(1, &p_index); - bind(); - - if (!p_texture.valid()) - p_texture.create(); - attach(p_texture); - - if (!p_renderbuffer.valid()) - p_renderbuffer.create(); - attach(p_renderbuffer); - - unbind(); - } - - void rescale(int width, int height) - { - p_texture.bind(); - p_texture.rescale(width, height); - - p_renderbuffer.bind(); - p_renderbuffer.storage(p_texture.width(), p_texture.height()); - - p_texture.unbind(); - p_renderbuffer.unbind(); - } - - void destroy() - { - p_texture.destroy(); - p_renderbuffer.destroy(); - glDeleteFramebuffers(1, &p_index); - } - - bool valid() const - { - return p_index != 0; - } -}; - +#pragma once + +#include +#include + + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + +class Framebuffer +{ + +protected: + + Texture p_texture; + Renderbuffer p_renderbuffer; + unsigned int p_index; + bool p_binded; + +public: + + inline + Framebuffer() : + p_index {0}, + p_texture {1, 1}, // non zero + p_renderbuffer {} + {} + + virtual + ~Framebuffer() = default; + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + void bind() + { + glBindFramebuffer(GL_FRAMEBUFFER, p_index); + p_binded = true; + } + + void unbind() + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + p_binded = false; + } + + bool binded() const + { + return p_binded; + } + + void attach(const Texture& texture) + { + if (!binded() && valid()) + throw std::runtime_error("Framebuffer not binded or invalid"); + if (!texture.valid()) + throw std::runtime_error("Texture is not valid"); + + p_texture = texture; + p_texture.bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture.index(), 0); + + p_texture.unbind(); + } + + void attach(const Renderbuffer& renderbuffer) + { + if (!binded() && valid()) + throw std::runtime_error("Framebuffer not binded or invalid"); + if (!renderbuffer.valid()) + throw std::runtime_error("Renderbuffer is not valid"); + + p_renderbuffer = renderbuffer; + p_renderbuffer.bind(); + p_renderbuffer.storage(p_texture.width(), p_texture.height()); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, p_renderbuffer.index()); + + std::stringstream ss; + ss << "Framebuffer is not complete: " << glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error(ss.str()); + + p_renderbuffer.unbind(); + } + + void create() + { + glGenFramebuffers(1, &p_index); + bind(); + + if (!p_texture.valid()) + { + p_texture.create(); + attach(p_texture); + } + + if (!p_renderbuffer.valid()) + { + p_renderbuffer.create(); + attach(p_renderbuffer); + } + + unbind(); + } + + void rescale() + { + p_texture.bind(); + p_texture.rescale(); + + p_renderbuffer.bind(); + p_renderbuffer.storage(p_texture.width(), p_texture.height()); + + p_texture.unbind(); + p_renderbuffer.unbind(); + } + + void rescale(int width, int height) + { + p_texture.bind(); + p_texture.rescale(width, height); + + p_renderbuffer.bind(); + p_renderbuffer.storage(p_texture.width(), p_texture.height()); + + p_texture.unbind(); + p_renderbuffer.unbind(); + } + + void destroy() + { + p_texture.destroy(); + p_renderbuffer.destroy(); + glDeleteFramebuffers(1, &p_index); + } + + [[nodiscard]] + bool valid() const + { + return p_index != 0; + } + + Texture& texture() + { + return p_texture; + } + + int& width() + { + return p_texture.width(); + } + + [[nodiscard]] + int width() const + { + return p_texture.width(); + } + + int& height() + { + return p_texture.height(); + } + + [[nodiscard]] + int height() const + { + return p_texture.height(); + } +}; + } \ No newline at end of file diff --git a/source/hpr/gpu/gpu.cpp b/source/hpr/gpu/gpu.cpp index d2e1102..e69de29 100644 --- a/source/hpr/gpu/gpu.cpp +++ b/source/hpr/gpu/gpu.cpp @@ -1,3 +0,0 @@ -// -// Created by L-Nafaryus on 12/16/2022. -// diff --git a/source/hpr/gpu/monitor.hpp b/source/hpr/gpu/monitor.hpp new file mode 100644 index 0000000..b0a35f7 --- /dev/null +++ b/source/hpr/gpu/monitor.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + + +namespace hpr::gpu +{ + +class Monitor +{ + +protected: + + GLFWmonitor* p_instance; + +public: + + inline + Monitor() : + p_instance {glfwGetPrimaryMonitor()} + {} + + virtual + ~Monitor() = default; + + inline + GLFWmonitor* instance() const + { + return p_instance; + } + +}; + +} \ No newline at end of file diff --git a/source/hpr/gpu/renderbuffer.hpp b/source/hpr/gpu/renderbuffer.hpp index b38c079..f4205a6 100644 --- a/source/hpr/gpu/renderbuffer.hpp +++ b/source/hpr/gpu/renderbuffer.hpp @@ -1,69 +1,69 @@ -#pragma once - -#ifndef __gl_h_ -#include -#endif - - - -namespace hpr::gpu -{ - - class Renderbuffer - { - - protected: - - unsigned int p_index; - - public: - - inline - Renderbuffer() : - p_index {0} - {} - - virtual - ~Renderbuffer() = default; - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - void bind() - { - glBindRenderbuffer(GL_RENDERBUFFER, p_index); - } - - void unbind() - { - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - - void create() - { - glGenRenderbuffers(1, &p_index); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, p_index); - } - - void storage(int width, int height) - { - glBindRenderbuffer(GL_RENDERBUFFER, p_index); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - } - - void destroy() - { - glDeleteRenderbuffers(1, &p_index); - } - - bool valid() const - { - return p_index != 0; - } - }; - -} +#pragma once + +#ifndef __gl_h_ +#include +#endif + + + +namespace hpr::gpu +{ + + class Renderbuffer + { + + protected: + + unsigned int p_index; + + public: + + inline + Renderbuffer() : + p_index {0} + {} + + virtual + ~Renderbuffer() = default; + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + void bind() + { + glBindRenderbuffer(GL_RENDERBUFFER, p_index); + } + + void unbind() + { + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + void create() + { + glGenRenderbuffers(1, &p_index); + //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, p_index); + } + + void storage(int width, int height) + { + glBindRenderbuffer(GL_RENDERBUFFER, p_index); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + void destroy() + { + glDeleteRenderbuffers(1, &p_index); + } + + bool valid() const + { + return p_index != 0; + } + }; + +} diff --git a/source/hpr/gpu/scene.hpp b/source/hpr/gpu/scene.hpp index 8049e89..e69de29 100644 --- a/source/hpr/gpu/scene.hpp +++ b/source/hpr/gpu/scene.hpp @@ -1,8 +0,0 @@ -// -// Created by L-Nafaryus on 12/16/2022. -// - -#ifndef HPR_SCENE_HPP -#define HPR_SCENE_HPP - -#endif //HPR_SCENE_HPP diff --git a/source/hpr/gpu/shader.hpp b/source/hpr/gpu/shader.hpp index 17380a0..b797498 100644 --- a/source/hpr/gpu/shader.hpp +++ b/source/hpr/gpu/shader.hpp @@ -1,129 +1,129 @@ -#pragma once - -#include - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - -class Shader -{ - -public: - - enum class Type - { - Vertex = GL_VERTEX_SHADER, - TessControl = GL_TESS_CONTROL_SHADER, - TessEvaluation = GL_TESS_EVALUATION_SHADER, - Geometry = GL_GEOMETRY_SHADER, - Fragment = GL_FRAGMENT_SHADER, - Compute = GL_COMPUTE_SHADER, - Unknown = -1 - }; - -protected: - - std::string p_filename; - std::string p_source; - std::string p_label; - Type p_type; - - unsigned int p_index; - -public: - - // Constructors - - inline - Shader() : - p_filename {}, - p_source {}, - p_label {}, - p_type {Type::Unknown}, - p_index {0} - {} - - inline - Shader(Type type) : - p_filename {}, - p_source {}, - p_label {}, - p_type {type} - {} - - inline - Shader(Type type, const std::string& source) : - p_filename {}, - p_source {source}, - p_label {}, - p_type {type}, - p_index {0} - {} - - virtual - ~Shader() = default; - - // Member functions - - [[nodiscard]] - std::string filename() const - { - return p_filename; - } - - [[nodiscard]] - std::string label() const - { - return p_label; - } - - [[nodiscard]] - Type type() const - { - return p_type; - } - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - void create(const std::string& label = "") - { - if (p_type == Type::Unknown) - throw std::runtime_error("Unknown shader type"); - - p_index = glCreateShader(static_cast(p_type)); - if (p_index == 0) - throw std::runtime_error("Cannot create shader"); - - const char* shaderSource = p_source.c_str(); - glShaderSource(p_index, 1, &shaderSource, nullptr); - GLenum result = glGetError(); - glCompileShader(p_index); - - int shaderStatus; - glGetShaderiv(p_index, GL_COMPILE_STATUS, &shaderStatus); - if (!shaderStatus) - { - char error[2048 + 1]; - glGetShaderInfoLog(p_index, 2048, nullptr, error); - - throw std::runtime_error(error); - } - - p_label = label; - } - - void destroy() - { - glDeleteShader(p_index); - } -}; - +#pragma once + +#include + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + +class Shader +{ + +public: + + enum class Type + { + Vertex = GL_VERTEX_SHADER, + TessControl = GL_TESS_CONTROL_SHADER, + TessEvaluation = GL_TESS_EVALUATION_SHADER, + Geometry = GL_GEOMETRY_SHADER, + Fragment = GL_FRAGMENT_SHADER, + Compute = GL_COMPUTE_SHADER, + Unknown = -1 + }; + +protected: + + std::string p_filename; + std::string p_source; + std::string p_label; + Type p_type; + + unsigned int p_index; + +public: + + // Constructors + + inline + Shader() : + p_filename {}, + p_source {}, + p_label {}, + p_type {Type::Unknown}, + p_index {0} + {} + + inline + Shader(Type type) : + p_filename {}, + p_source {}, + p_label {}, + p_type {type} + {} + + inline + Shader(Type type, const std::string& source) : + p_filename {}, + p_source {source}, + p_label {}, + p_type {type}, + p_index {0} + {} + + virtual + ~Shader() = default; + + // Member functions + + [[nodiscard]] + std::string filename() const + { + return p_filename; + } + + [[nodiscard]] + std::string label() const + { + return p_label; + } + + [[nodiscard]] + Type type() const + { + return p_type; + } + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + void create(const std::string& label = "") + { + if (p_type == Type::Unknown) + throw std::runtime_error("Unknown shader type"); + + p_index = glCreateShader(static_cast(p_type)); + if (p_index == 0) + throw std::runtime_error("Cannot create shader"); + + const char* shaderSource = p_source.c_str(); + glShaderSource(p_index, 1, &shaderSource, nullptr); + GLenum result = glGetError(); + glCompileShader(p_index); + + int shaderStatus; + glGetShaderiv(p_index, GL_COMPILE_STATUS, &shaderStatus); + if (!shaderStatus) + { + char error[2048 + 1]; + glGetShaderInfoLog(p_index, 2048, nullptr, error); + + throw std::runtime_error(error); + } + + p_label = label; + } + + void destroy() + { + glDeleteShader(p_index); + } +}; + } \ No newline at end of file diff --git a/source/hpr/gpu/shader_program.hpp b/source/hpr/gpu/shader_program.hpp index c5d76cb..cd8b2ef 100644 --- a/source/hpr/gpu/shader_program.hpp +++ b/source/hpr/gpu/shader_program.hpp @@ -1,96 +1,268 @@ -#pragma once - -#include "../containers.hpp" - -#include - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - - class ShaderProgram - { - - protected: - - unsigned int p_index; - darray p_shaders; - - public: - - // Constructors - - inline - ShaderProgram() : - p_index {0} - {} - - virtual - ~ShaderProgram() = default; - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - darray shaders() - { - return p_shaders; - } - - void create(const std::string& label = "") - { - p_index = glCreateProgram(); - } - - void attach(const Shader& shader) - { - glAttachShader(p_index, shader.index()); - p_shaders.push(shader); - } - - void detach(const Shader& shader) - { - // WARNING: segfault, destroy_at (char) - p_shaders.remove([shader](const Shader& _shader) - { - return shader.index() == _shader.index(); - }); - - glDetachShader(p_index, shader.index()); - } - - void link() - { - glLinkProgram(p_index); - - GLint status; - glGetProgramiv(p_index, GL_LINK_STATUS, &status); - - if (status == GL_FALSE) - throw std::runtime_error("Shader program link error"); - } - - void destroy() - { - //for (auto& shader : p_shaders) - // detach(shader); - glDeleteShader(p_index); - } - - void bind() - { - glUseProgram(p_index); - } - - void unbind() - { - glUseProgram(0); - } - }; - -} +#pragma once + +#include +#include +#include + +#include + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + + struct ShaderProgramLinkError : public Exception + { + inline explicit ShaderProgramLinkError(std::source_location location = std::source_location::current()) : Exception {"Shader program link error", location} {} + inline explicit ShaderProgramLinkError(const std::string& message, std::source_location location = std::source_location::current()) : Exception {message, location} {} + }; + + class ShaderProgram + { + + protected: + + unsigned int p_index; + + public: + + // Constructors + + inline + ShaderProgram() : + p_index {0} + {} + + virtual + ~ShaderProgram() = default; + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + void create() + { + p_index = glCreateProgram(); + } + + void attach(const Shader& shader) + { + glAttachShader(p_index, shader.index()); + } + + void detach(const Shader& shader) + { + glDetachShader(p_index, shader.index()); + } + + void link() + { + glLinkProgram(p_index); + + GLint status; + glGetProgramiv(p_index, GL_LINK_STATUS, &status); + + if (status == GL_FALSE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetProgramInfoLog(p_index, 1024, &log_length, message); + throw ShaderProgramLinkError(message); + } + } + + void destroy() + { + glDeleteProgram(p_index); + } + + void bind() + { + glUseProgram(p_index); + } + + void unbind() + { + glUseProgram(0); + } + + inline + int uniformLocation(const std::string& label) const + { + return glGetUniformLocation(p_index, label.c_str()); + } + + template ... Args> + inline + void uniformValue(int location, T value, Args ...args) + { + auto arr = {value, static_cast(args)...}; + if constexpr (std::is_same::value) + { + switch (arr.size()) + { + case 1: glUniform1i(location, arr[0]); break; + case 2: glUniform2i(location, arr[0], arr[1]); break; + case 3: glUniform3i(location, arr[0], arr[1], arr[2]); break; + case 4: glUniform4i(location, arr[0], arr[1], arr[2], arr[3]); break; + } + } + else if constexpr (std::is_same::value) + { + switch (arr.size()) + { + case 1: glUniform1ui(location, arr[0]); break; + case 2: glUniform2ui(location, arr[0], arr[1]); break; + case 3: glUniform3ui(location, arr[0], arr[1], arr[2]); break; + case 4: glUniform4ui(location, arr[0], arr[1], arr[2], arr[3]); break; + } + } + else if constexpr (std::is_same::value) + { + switch (arr.size()) + { + case 1: glUniform1f(location, arr[0]); break; + case 2: glUniform2f(location, arr[0], arr[1]); break; + case 3: glUniform3f(location, arr[0], arr[1], arr[2]); break; + case 4: glUniform4f(location, arr[0], arr[1], arr[2], arr[3]); break; + } + } + else if constexpr (std::is_same::value) + { + switch (arr.size()) + { + case 1: glUniform1d(location, arr[0]); break; + case 2: glUniform2d(location, arr[0], arr[1]); break; + case 3: glUniform3d(location, arr[0], arr[1], arr[2]); break; + case 4: glUniform4d(location, arr[0], arr[1], arr[2], arr[3]); break; + } + } + else + throw std::runtime_error("Unsupported value type"); + } + + template ... Args> + inline + void uniformValue(const std::string& label, T value, Args ...args) + { + uniformValue(uniformLocation(label), value, std::forward(args)...); + } + + template + inline + void uniformVector(int location, hpr::Size size, T* data) + { + if constexpr (std::is_same::value) + { + switch (S) + { + case 1: glUniform1iv(location, size, data); break; + case 2: glUniform2iv(location, size, data); break; + case 3: glUniform3iv(location, size, data); break; + case 4: glUniform4iv(location, size, data); break; + } + } + else if constexpr (std::is_same::value) + { + switch (S) + { + case 1: glUniform1uiv(location, size, data); break; + case 2: glUniform2uiv(location, size, data); break; + case 3: glUniform3uiv(location, size, data); break; + case 4: glUniform4uiv(location, size, data); break; + } + } + else if constexpr (std::is_same::value) + { + switch (S) + { + case 1: glUniform1fv(location, size, data); break; + case 2: glUniform2fv(location, size, data); break; + case 3: glUniform3fv(location, size, data); break; + case 4: glUniform4fv(location, size, data); break; + } + } + else if constexpr (std::is_same::value) + { + switch (size) + { + case 1: glUniform1dv(location, size, data); break; + case 2: glUniform2dv(location, size, data); break; + case 3: glUniform3dv(location, size, data); break; + case 4: glUniform4dv(location, size, data); break; + } + } + else + throw std::runtime_error("Unsupported value type"); + } + + template + inline + void uniformVector(const std::string& label, hpr::Size size, T* data) + { + uniformVector(uniformLocation(label), size, data); + } + + template + inline + void uniformMatrix(int location, hpr::Size size, bool transpose, T* data) + { + if constexpr (std::is_same::value) + { + if constexpr (C == 2 && R == 2) + glUniformMatrix2fv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 3) + glUniformMatrix3fv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 4) + glUniformMatrix4fv(location, static_cast(size), transpose, data); + else if constexpr (C == 2 && R == 3) + glUniformMatrix2x3fv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 2) + glUniformMatrix3x2fv(location, static_cast(size), transpose, data); + else if constexpr (C == 2 && R == 4) + glUniformMatrix2x4fv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 2) + glUniformMatrix4x2fv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 4) + glUniformMatrix3x4fv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 3) + glUniformMatrix4x3fv(location, static_cast(size), transpose, data); + } + else if constexpr (std::is_same::value) + { + if constexpr (C == 2 && R == 2) + glUniformMatrix2dv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 3) + glUniformMatrix3dv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 4) + glUniformMatrix4dv(location, static_cast(size), transpose, data); + else if constexpr (C == 2 && R == 3) + glUniformMatrix2x3dv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 2) + glUniformMatrix3x2dv(location, static_cast(size), transpose, data); + else if constexpr (C == 2 && R == 4) + glUniformMatrix2x4dv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 2) + glUniformMatrix4x2dv(location, static_cast(size), transpose, data); + else if constexpr (C == 3 && R == 4) + glUniformMatrix3x4dv(location, static_cast(size), transpose, data); + else if constexpr (C == 4 && R == 3) + glUniformMatrix4x3dv(location, static_cast(size), transpose, data); + } + else + throw std::runtime_error("Unsupported value type"); + } + + template + inline + void uniformMatrix(const std::string& label, hpr::Size size, bool transpose, T* data) + { + uniformMatrix(uniformLocation(label), size, transpose, data); + } + }; + +} diff --git a/source/hpr/gpu/shaders/test.frag.glsl b/source/hpr/gpu/shaders/test.frag.glsl index eef439c..edb04f7 100644 --- a/source/hpr/gpu/shaders/test.frag.glsl +++ b/source/hpr/gpu/shaders/test.frag.glsl @@ -1,9 +1,9 @@ -#version 330 -uniform vec3 color; - -out vec4 out_color; - -void main(void) -{ - out_color = vec4(color, 0.5f); +#version 330 +uniform vec3 color; + +out vec4 out_color; + +void main(void) +{ + out_color = vec4(color, 0.5f); } \ No newline at end of file diff --git a/source/hpr/gpu/shaders/test.vert.glsl b/source/hpr/gpu/shaders/test.vert.glsl index cc518f1..658f988 100644 --- a/source/hpr/gpu/shaders/test.vert.glsl +++ b/source/hpr/gpu/shaders/test.vert.glsl @@ -1,11 +1,11 @@ -#version 330 core -layout (location = 0) in vec3 aPos; - -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -void main() -{ - gl_Position = projection * view * model * vec4(aPos, 1.0); +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); } \ No newline at end of file diff --git a/source/hpr/gpu/stencil_buffer.hpp b/source/hpr/gpu/stencil_buffer.hpp index c7bbb65..414121a 100644 --- a/source/hpr/gpu/stencil_buffer.hpp +++ b/source/hpr/gpu/stencil_buffer.hpp @@ -1,84 +1,84 @@ -#pragma once - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - - class StencilBuffer - { - - protected: - - bool p_enabled; - bool p_binded; - - public: - - inline - StencilBuffer() : - p_enabled {false}, - p_binded {false} - {} - - inline - StencilBuffer(bool enabled) : - p_enabled {enabled}, - p_binded {false} - {} - - virtual - ~StencilBuffer() = default; - - - inline - void bind() - { - p_binded = true; - glEnable(GL_STENCIL_TEST); - } - - inline - void unbind() - { - p_binded = false; - glDisable(GL_STENCIL_TEST); - } - - inline - bool binded() const - { - return p_binded; - } - - inline - void enable() - { - p_enabled = true; - glStencilMask(GL_TRUE); - } - - inline - void disable() - { - p_enabled = false; - glStencilMask(GL_FALSE); - } - - [[nodiscard]] - inline - bool enabled() const - { - return p_enabled; - } - - inline - void clear() const - { - glClear(GL_STENCIL_BUFFER_BIT); - } - }; - -} +#pragma once + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + + class StencilBuffer + { + + protected: + + bool p_enabled; + bool p_binded; + + public: + + inline + StencilBuffer() : + p_enabled {false}, + p_binded {false} + {} + + inline + StencilBuffer(bool enabled) : + p_enabled {enabled}, + p_binded {false} + {} + + virtual + ~StencilBuffer() = default; + + + inline + void bind() + { + p_binded = true; + glEnable(GL_STENCIL_TEST); + } + + inline + void unbind() + { + p_binded = false; + glDisable(GL_STENCIL_TEST); + } + + inline + bool binded() const + { + return p_binded; + } + + inline + void enable() + { + p_enabled = true; + glStencilMask(GL_TRUE); + } + + inline + void disable() + { + p_enabled = false; + glStencilMask(GL_FALSE); + } + + [[nodiscard]] + inline + bool enabled() const + { + return p_enabled; + } + + inline + void clear() const + { + glClear(GL_STENCIL_BUFFER_BIT); + } + }; + +} diff --git a/source/hpr/gpu/texture.hpp b/source/hpr/gpu/texture.hpp index 0194f5b..6de71e8 100644 --- a/source/hpr/gpu/texture.hpp +++ b/source/hpr/gpu/texture.hpp @@ -1,193 +1,223 @@ -#pragma once - -#include "../containers.hpp" - -#include -#include -#define STB_IMAGE_IMPLEMENTATION -#include - -#ifndef __gl_h_ -#include -#endif - -namespace hpr::gpu -{ - - class Texture - { - - public: - - using ustring = std::basic_string; - - public: - - enum class Format - { - RGB = GL_RGB, - RGBA = GL_RGBA - }; - - protected: - - unsigned int p_index; - std::string p_filename; - ustring p_source; - - int p_width; - int p_height; - Format p_internalFormat; - Format p_imageFormat; - - public: - - inline - Texture() : - p_index {0}, - p_filename {}, - p_source {}, - p_width {}, - p_height {}, - p_internalFormat {Format::RGBA}, - p_imageFormat {Format::RGBA} - {} - - inline - Texture(const std::string& filename) : - p_index {0}, - p_filename {filename}, - p_source {}, - p_width {}, - p_height {}, - p_internalFormat {Format::RGB}, - p_imageFormat {Format::RGB} - {} - - virtual - ~Texture() = default; - - [[nodiscard]] - unsigned int index() const - { - return p_index; - } - - [[nodiscard]] - unsigned int width() const - { - return p_width; - } - - [[nodiscard]] - unsigned int height() const - { - return p_height; - } - - void active() - { - glActiveTexture(GL_TEXTURE0 + p_index); - } - - void bind() - { - glBindTexture(GL_TEXTURE_2D, p_index); - } - - void unbind() - { - glBindTexture(GL_TEXTURE_2D, 0); - } - - void alphaChannel(bool enabled) - { - if (enabled) - { - p_internalFormat = Format::RGBA; - p_imageFormat = Format::RGBA; - } - else - { - p_internalFormat = Format::RGB; - p_imageFormat = Format::RGB; - } - } - - void load(const std::string& filename) - { - auto filepath = std::filesystem::canonical(std::filesystem::path(filename)).string(); - - stbi_set_flip_vertically_on_load(true); - int channelsCount; - unsigned char* source = stbi_load(filepath.c_str(), &p_width, &p_height, &channelsCount, 0); - - if (!source) - throw std::runtime_error("Failed to load texture source"); - else - create(source); - - stbi_image_free(source); - } - - void load() - { - load(p_filename); - } - - void create() - { - glGenTextures(1, &p_index); - bind(); - - glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, nullptr); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - unbind(); - } - - void create(const ustring& source) - { - glGenTextures(1, &p_index); - bind(); - - glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, source.data()); - - p_source = source; - - glGenerateMipmap(GL_TEXTURE_2D); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - unbind(); - } - - void rescale(int width, int height) - { - bind(); - glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, !p_source.empty() ? p_source.data() : nullptr); - unbind(); - } - - void destroy() - { - glDeleteTextures(1, &p_index); - } - - bool valid() const - { - return p_index != 0; - } - }; - -} - +#pragma once + +#include + +#include +#include +#define STB_IMAGE_IMPLEMENTATION +#include + +#ifndef __gl_h_ +#include +#endif + +namespace hpr::gpu +{ + + class Texture + { + + public: + + using ustring = std::basic_string; + + public: + + enum class Format + { + RGB = GL_RGB, + RGBA = GL_RGBA + }; + + protected: + + unsigned int p_index; + std::string p_filename; + ustring p_source; + + int p_width; + int p_height; + Format p_internalFormat; + Format p_imageFormat; + + public: + + inline + Texture() : + p_index {0}, + p_filename {}, + p_source {}, + p_width {}, + p_height {}, + p_internalFormat {Format::RGBA}, + p_imageFormat {Format::RGBA} + {} + + inline + Texture(int width, int height) : + p_index {0}, + p_filename {}, + p_source {}, + p_width {width}, + p_height {height}, + p_internalFormat {Format::RGBA}, + p_imageFormat {Format::RGBA} + {} + + inline + Texture(const std::string& filename) : + p_index {0}, + p_filename {filename}, + p_source {}, + p_width {}, + p_height {}, + p_internalFormat {Format::RGB}, + p_imageFormat {Format::RGB} + {} + + virtual + ~Texture() = default; + + [[nodiscard]] + unsigned int index() const + { + return p_index; + } + + int& width() + { + return p_width; + } + + [[nodiscard]] + int width() const + { + return p_width; + } + + int& height() + { + return p_height; + } + + [[nodiscard]] + int height() const + { + return p_height; + } + + void active() const + { + glActiveTexture(GL_TEXTURE0 + p_index); + } + + void bind() const + { + glBindTexture(GL_TEXTURE_2D, p_index); + } + + void unbind() const + { + glBindTexture(GL_TEXTURE_2D, 0); + } + + void alphaChannel(bool enabled) + { + if (enabled) + { + p_internalFormat = Format::RGBA; + p_imageFormat = Format::RGBA; + } + else + { + p_internalFormat = Format::RGB; + p_imageFormat = Format::RGB; + } + } + + void load(const std::string& filename) + { + auto filepath = std::filesystem::canonical(std::filesystem::path(filename)).string(); + + stbi_set_flip_vertically_on_load(true); + int channelsCount; + unsigned char* source = stbi_load(filepath.c_str(), &p_width, &p_height, &channelsCount, 0); + + if (!source) + throw std::runtime_error("Failed to load texture source"); + else + create(source); + + stbi_image_free(source); + } + + void load() + { + load(p_filename); + } + + void create() + { + glGenTextures(1, &p_index); + bind(); + + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, nullptr); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + unbind(); + } + + void create(const ustring& source) + { + glGenTextures(1, &p_index); + bind(); + + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, source.data()); + + p_source = source; + + glGenerateMipmap(GL_TEXTURE_2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + unbind(); + } + + void rescale() + { + bind(); + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, !p_source.empty() ? p_source.data() : nullptr); + unbind(); + } + + void rescale(int width, int height) + { + p_width = width; + p_height = height; + bind(); + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)p_internalFormat, p_width, p_height, 0, (GLint)p_imageFormat, GL_UNSIGNED_BYTE, !p_source.empty() ? p_source.data() : nullptr); + unbind(); + } + + void destroy() + { + glDeleteTextures(1, &p_index); + } + + bool valid() const + { + return p_index != 0; + } + }; + +} + diff --git a/source/hpr/gpu/viewer.hpp b/source/hpr/gpu/viewer.hpp index 1cf0c0f..e69de29 100644 --- a/source/hpr/gpu/viewer.hpp +++ b/source/hpr/gpu/viewer.hpp @@ -1,8 +0,0 @@ -// -// Created by L-Nafaryus on 12/16/2022. -// - -#ifndef HPR_VIEWER_HPP -#define HPR_VIEWER_HPP - -#endif //HPR_VIEWER_HPP diff --git a/source/hpr/gpu/viewport.hpp b/source/hpr/gpu/viewport.hpp index 4e71440..bf6fe0a 100644 --- a/source/hpr/gpu/viewport.hpp +++ b/source/hpr/gpu/viewport.hpp @@ -1,45 +1,56 @@ -#pragma once - -#include "../math/vector.hpp" -#ifndef __gl_h_ -#include -#endif - - -namespace hpr::gpu -{ - -class Viewport -{ - -protected: - - vec2 p_pos; - vec2 p_size; - -public: - - inline - Viewport() : - p_pos {0.f, 0.f}, - p_size {0.f, 0.f} - {} - - inline - Viewport(const vec2& pos, const vec2& size) : - p_pos {pos}, - p_size {size} - {} - - virtual - ~Viewport() = default; - - inline - void set() - { - glViewport(p_pos[0], p_pos[1], p_size[0], p_size[1]); - } - -}; - +#pragma once + +#include + +#ifndef __gl_h_ +#include +#endif + + +namespace hpr::gpu +{ + +class Viewport +{ + +protected: + + vec2 p_pos; + vec2 p_size; + +public: + + inline + Viewport() : + p_pos {0.f, 0.f}, + p_size {0.f, 0.f} + {} + + inline + Viewport(const vec2& pos, const vec2& size) : + p_pos {pos}, + p_size {size} + {} + + virtual + ~Viewport() = default; + + vec2& pos() + { + return p_pos; + } + + vec2& size() + { + return p_size; + } + + inline + void set() + { + glViewport(p_pos[0], p_pos[1], p_size[0], p_size[1]); + } + +}; + } \ No newline at end of file diff --git a/source/hpr/gpu/window.hpp b/source/hpr/gpu/window.hpp new file mode 100644 index 0000000..4bfc12f --- /dev/null +++ b/source/hpr/gpu/window.hpp @@ -0,0 +1,296 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include + + +namespace hpr::gpu +{ + +class Window +{ + +public: + + enum State + { + Visible, + Hidden, + Maximized, + Minimized, + Closed, + }; + + enum Style + { + Windowed, + Fullscreen, + Popup + }; + +protected: + + int p_posX; + int p_posY; + int p_width; + int p_height; + std::string p_title; + + State p_state; + Style p_style; + Window* p_parent; + Monitor* p_monitor; + + bool p_isActive; + bool p_isResizing; + + GLFWwindow* p_instance; + Context p_context; + +public: + + inline + Window() : + p_posX {0}, + p_posY {0}, + p_width {0}, + p_height {0}, + p_title {}, + p_state {State::Hidden}, + p_style {Style::Windowed}, + p_parent {nullptr}, + p_monitor {nullptr}, + p_isActive {true}, + p_isResizing {false}, + p_context {} + { + p_instance = glfwCreateWindow(p_width, p_height, p_title.c_str(), p_monitor != nullptr ? p_monitor->instance() : nullptr, p_parent != nullptr ? p_parent->p_instance : nullptr); + if (p_instance == nullptr) + throw std::runtime_error("Cannot create Window"); + + glfwMakeContextCurrent(p_instance); + p_context.link(); + + glfwSetWindowUserPointer(p_instance, this); + + glfwSetWindowPos(p_instance, p_posX, p_posY); + + this->state(p_state); + this->style(p_style); + } + + inline + Window(int x, int y, int width, int height, const std::string& title, Style style, Window* parent, Monitor* monitor) : + p_posX {x}, + p_posY {y}, + p_width {width}, + p_height {height}, + p_title {title}, + p_state {State::Visible}, + p_style {style}, + p_parent {parent}, + p_monitor {monitor}, + p_isActive {true}, + p_isResizing {false}, + p_context {} + { + //glfwInit(); + + p_instance = glfwCreateWindow(p_width, p_height, p_title.c_str(), p_monitor != nullptr ? p_monitor->instance() : nullptr, p_parent != nullptr ? p_parent->p_instance : nullptr); + if (p_instance == nullptr) + throw std::runtime_error("Cannot create window"); + + glfwMakeContextCurrent(p_instance); + p_context.link(); + + glfwSetWindowUserPointer(p_instance, this); + + glfwSetWindowPos(p_instance, p_posX, p_posY); + + this->state(p_state); + this->style(p_style); + } + + virtual + ~Window() + { + p_context.destroy(); + } + + // member functions + + inline + GLFWwindow* instance() const + { + return p_instance; + } + + inline + Context& context() + { + return p_context; + } + + inline + void pos(int x, int y) + { + p_posX = x; + p_posY = y; + } + + inline + int x() const + { + return p_posX; + } + + inline + int y() const + { + return p_posY; + } + + inline + void size(int width, int height) + { + p_width = width; + p_height = height; + } + + inline + int width() const + { + return p_width; + } + + inline + int height() const + { + return p_height; + } + + inline + void title(const std::string& title) + { + p_title = title; + } + + inline + std::string title() const + { + return p_title; + } + + inline + void state(State state) + { + switch (state) + { + case State::Visible: + glfwShowWindow(p_instance); + break; + case State::Hidden: + glfwHideWindow(p_instance); + break; + case State::Maximized: + glfwMaximizeWindow(p_instance); + break; + case State::Minimized: + glfwIconifyWindow(p_instance); + break; + case State::Closed: + glfwSetWindowShouldClose(p_instance, GLFW_TRUE); + break; + default: + break; + } + p_state = state; + } + + inline + State state() const + { + return p_state; + } + + inline + void style(Style style) + { + switch (style) + { + case Style::Windowed: + glfwSetWindowMonitor(p_instance, nullptr, p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE); + break; + case Style::Fullscreen: + glfwSetWindowMonitor(p_instance, glfwGetPrimaryMonitor(), p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE); + break; + default: + break; + } + p_style = style; + } + + inline + Style style() const + { + return p_style; + } + + inline + void destroy() + { + glfwDestroyWindow(p_instance); + p_instance = nullptr; + } + + inline + void swapBuffers() + { + glfwSwapBuffers(p_instance); + } + + inline + void pollEvents() + { + glfwPollEvents(); + } + +protected: + + std::function onFramebufferResize; + std::function onKeyClick; + +public: + + void framebufferResizeCallback(const std::function& event) + { + onFramebufferResize = event; + + glfwSetFramebufferSizeCallback(p_instance, [](GLFWwindow* window, int width, int height) + { + auto p = static_cast(glfwGetWindowUserPointer(window)); + if (p->onFramebufferResize) + p->onFramebufferResize(p, width, height); + }); + } + + void keyClickCallback(const std::function& event) + { + onKeyClick = event; + + glfwSetKeyCallback(p_instance, [](GLFWwindow* window, int key, int scancode, int action, int mods) + { + auto p = static_cast(glfwGetWindowUserPointer(window)); + if (p->onKeyClick) + p->onKeyClick(p, key, scancode, action, mods); + }); + } +}; + +} \ No newline at end of file diff --git a/source/hpr/hpr.cpp b/source/hpr/hpr.cpp index 40aea07..f1db6ee 100644 --- a/source/hpr/hpr.cpp +++ b/source/hpr/hpr.cpp @@ -1 +1 @@ -#include "hpr.hpp" \ No newline at end of file +#include "hpr.hpp" diff --git a/source/hpr/hpr.hpp b/source/hpr/hpr.hpp index f3344d7..83308c9 100644 --- a/source/hpr/hpr.hpp +++ b/source/hpr/hpr.hpp @@ -1,49 +1,37 @@ -#pragma once - - -namespace hpr -{ - /* Core */ - // containers - // math - // io - - /* Graphics */ - namespace gpu - { - // gpu - // window_system - } - - /* Mesh */ - namespace mesh - { - // mesh - } - - /* CSG */ - namespace csg - { - // csg - } -} - -#include "containers.hpp" -#include "math.hpp" -#include "io.hpp" - -#if WITH_GPU -#include "gpu.hpp" -#endif - -#if WITH_WS -#include "window_system.hpp" -#endif - -#if WITH_MESH -#include "mesh.hpp" -#endif - -#if WITH_CSG -#include "csg.hpp" -#endif +#pragma once + +#define HPR_VERSION_MAJOR 0 +#define HPR_VERSION_MINOR 10 +#define HPR_VERSION_PATCH 0 + +#if HPR_WITH_CONTAINERS +#include +#endif + +#if HPR_WITH_MATH +#include +#endif + +#if HPR_WITH_IO +#include +#endif + +#if HPR_WITH_GPU +#include +#endif + +#if HPR_WITH_MESH +#include +#endif + +#if HPR_WITH_CSG +#include +#endif + +#if HPR_WITH_GEOMETRY +#include +#endif + +#if HPR_WITH_PARALLEL +#include +#endif \ No newline at end of file diff --git a/source/hpr/io.hpp b/source/hpr/io.hpp index b0e8169..2aef663 100644 --- a/source/hpr/io.hpp +++ b/source/hpr/io.hpp @@ -1,3 +1,3 @@ -#pragma once - -#include "io/file.hpp" +#pragma once + +#include diff --git a/source/hpr/io/CMakeLists.txt b/source/hpr/io/CMakeLists.txt index 6085647..63d22a7 100644 --- a/source/hpr/io/CMakeLists.txt +++ b/source/hpr/io/CMakeLists.txt @@ -1,68 +1,27 @@ -cmake_minimum_required(VERSION 3.16) - -project(io - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX - ) - -add_library(${PROJECT_NAME}) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../io.hpp" "*.hpp" - ) - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES - "*.cpp" - ) - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ - PRIVATE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES} - ) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) - - -if(HPR_TEST) - add_subdirectory(tests) -endif() +cmake_minimum_required(VERSION 3.16) + +project(io + VERSION "${HPR_VERSION}" + LANGUAGES CXX +) + +hpr_add_library(${PROJECT_NAME} STATIC) + +hpr_collect_interface(${PROJECT_NAME} + "../io.hpp" + "*.hpp" +) + +hpr_collect_sources(${PROJECT_NAME} + "*.cpp" +) + +target_sources(${PROJECT_NAME} + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> + PRIVATE ${${PROJECT_NAME}_SOURCES} +) + + +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) +hpr_tests(${PROJECT_NAME} tests) + diff --git a/source/hpr/io/file.cpp b/source/hpr/io/file.cpp index dfca020..82577ed 100644 --- a/source/hpr/io/file.cpp +++ b/source/hpr/io/file.cpp @@ -1,70 +1,70 @@ - -#include "file.hpp" - - -namespace hpr -{ - -File::File() : - p_name {"\0"}, - p_mode {File::Read} -{} - -File::File(const std::string &filename) : - p_name {filename}, - p_mode {File::Read} -{} - -File::File(const char *filename) : - p_name {filename}, - p_mode {File::Read} -{} - -File::~File() -{ - if (p_file.is_open()) - p_file.close(); -} - -void File::open(const std::string &filename, unsigned int filemode) -{ - std::ios::openmode mode = filemode & File::Read ? std::ios::in : std::ios::out; - - if (filemode & File::Binary) - mode |= std::ios::binary; - - p_file.open(filename, mode); - - if (!p_file.is_open()) - throw std::ios::failure("Could not open file"); -} - -void File::close() -{ - if (p_file.is_open()) - p_file.close(); -} - -size_t File::length() -{ - std::streampos size = 0; - std::streampos oldPos = p_file.tellg(); - - p_file.seekg(0, std::ios::beg); - size = p_file.tellg(); - p_file.seekg(0, std::ios::end); - size = p_file.tellg() - size; - p_file.seekg(oldPos, std::ios::beg); - - return (size_t)size; -} - -std::stringstream File::read() -{ - std::stringstream content; - content << p_file.rdbuf(); - - return content; -} - + +#include + + +namespace hpr +{ + +File::File() : + p_name {"\0"}, + p_mode {File::Read} +{} + +File::File(const std::string &filename) : + p_name {filename}, + p_mode {File::Read} +{} + +File::File(const char *filename) : + p_name {filename}, + p_mode {File::Read} +{} + +File::~File() +{ + if (p_file.is_open()) + p_file.close(); +} + +void File::open(const std::string &filename, unsigned int filemode) +{ + std::ios::openmode mode = filemode & File::Read ? std::ios::in : std::ios::out; + + if (filemode & File::Binary) + mode |= std::ios::binary; + + p_file.open(filename, mode); + + if (!p_file.is_open()) + throw std::ios::failure("Could not open file"); +} + +void File::close() +{ + if (p_file.is_open()) + p_file.close(); +} + +size_t File::length() +{ + std::streampos size = 0; + std::streampos oldPos = p_file.tellg(); + + p_file.seekg(0, std::ios::beg); + size = p_file.tellg(); + p_file.seekg(0, std::ios::end); + size = p_file.tellg() - size; + p_file.seekg(oldPos, std::ios::beg); + + return (size_t)size; +} + +std::stringstream File::read() +{ + std::stringstream content; + content << p_file.rdbuf(); + + return content; +} + } \ No newline at end of file diff --git a/source/hpr/io/file.hpp b/source/hpr/io/file.hpp index 320ede0..9de5b99 100644 --- a/source/hpr/io/file.hpp +++ b/source/hpr/io/file.hpp @@ -1,53 +1,53 @@ -#pragma once - -#include -#include -#include -#include - -namespace hpr -{ - -class File -{ - -public: - - enum FileMode - { - Write = std::ios::out, - Read = std::ios::in, - Binary = std::ios::binary, - Append = std::ios::app - }; - -protected: - - std::string p_name; - unsigned int p_mode; - std::fstream p_file; - -public: - - // Constructors - - File(); - - File(const std::string& filename); - - File(const char* filename); - - ~File(); - - // Member functions - - void open(const std::string& filename, unsigned int filemode = File::Read); - - void close(); - - size_t length(); - - std::stringstream read(); -}; - -} +#pragma once + +#include +#include +#include +#include + +namespace hpr +{ + +class File +{ + +public: + + enum FileMode + { + Write = std::ios::out, + Read = std::ios::in, + Binary = std::ios::binary, + Append = std::ios::app + }; + +protected: + + std::string p_name; + unsigned int p_mode; + std::fstream p_file; + +public: + + // Constructors + + File(); + + File(const std::string& filename); + + File(const char* filename); + + ~File(); + + // Member functions + + void open(const std::string& filename, unsigned int filemode = File::Read); + + void close(); + + size_t length(); + + std::stringstream read(); +}; + +} diff --git a/source/hpr/io/logger.hpp b/source/hpr/io/logger.hpp index b6f8ece..0192a7c 100644 --- a/source/hpr/io/logger.hpp +++ b/source/hpr/io/logger.hpp @@ -1,274 +1,554 @@ -#pragma once - -#include "../containers/array.hpp" -#include -#include -#include -#include - -namespace hpr -{ - - -namespace logging -{ - enum Severity - { - Emergency, - Alert, - Critical, - Error, - Warning, - Notice, - Info, - Debug - }; - - class Sink - { - //friend class Logger; - - protected: - - Severity p_severity; - std::string_view p_message; - - public: - - Sink() : - p_severity {Emergency}, - p_message {} - {} - - Sink(Severity severity) : - p_severity {severity}, - p_message {} - {} - - void addMessage(const std::string_view& message) - { - p_message = message; - } - - virtual - void flush() = 0; - - - virtual - ~Sink() = default; - - }; - - class StandardOutput : public Sink - { - - public: - - StandardOutput() : - Sink() - {} - - explicit - StandardOutput(Severity severity) : - Sink(severity) - {} - - void flush() override - { - if (p_severity < Error) - std::cerr << p_message << "\n"; - if (p_severity < Debug) - std::cout << p_message << "\n"; - std::cout.flush(); - } - - - ~StandardOutput() override = default; - - }; - - enum class LoggerState - { - Endline, - Flush, - Exception, - Exit - }; - - class Logger - { - static Logger g_instance; - static darray g_sinks; - - protected: - - Severity p_severity; - std::ostringstream p_stream; - int p_exitcode; - sarray p_levelNames; - darray p_buffer; - - protected: - - Logger() : - p_severity {Emergency}, - p_stream {}, - p_exitcode {-1}, - p_levelNames { "Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug"} - {} - - static Logger& instance() - { - return g_instance; - } - - public: - - static void destroy() - { - for (Sink* sink : g_sinks) - delete sink; - g_sinks.clear(); - } - - static darray& sinks() - { - return g_sinks; - } - - static void addSink(Sink* sink) - { - if (sink != nullptr) - g_sinks.push(sink); - } - - static Severity severity() - { - return g_instance.p_severity; - } - - static void severity(Severity severity) - { - g_instance.p_severity = severity; - } - - // begin functions - friend - std::ostringstream&& log(Severity severity); - - - - // end functions - friend - LoggerState endl(); - - friend - LoggerState flush(); - - friend - LoggerState exception(); - - friend - LoggerState exit(int code); - - // - friend - std::ostream& operator<<(std::ostream& stream, const LoggerState& state); - }; - - // - Logger Logger::g_instance; - darray Logger::g_sinks; - - // - std::ostringstream&& log(Severity severity) - { - Logger& instance = Logger::instance(); - instance.p_severity = severity; - //std::ostringstream oss; - //return instance.p_stream; - return std::move(std::ostringstream());// oss;//std::forward(oss); - } - - std::ostringstream&& error() - { - return log(Error); - } - - // - LoggerState endl() - { - return LoggerState::Endline; - } - - LoggerState flush() - { - return LoggerState::Flush; - } - - LoggerState exception() - { - return LoggerState::Exception; - } - - LoggerState exit(int code) - { - Logger& instance = Logger::instance(); - instance.p_exitcode = code; - return LoggerState::Exit; - } - - - std::ostream& operator<<(std::ostream& stream, const LoggerState& state) - { - stream << std::endl; - std::ostringstream oss; - oss << stream.rdbuf(); - std::string test = oss.str(); - std::cout << test << std::endl; - //static std::mutex mtx; - //std::lock_guard lock(mtx); - Logger& instance = Logger::instance(); - - if (state >= LoggerState::Endline) - { - stream << "\n"; - } - - //instance.p_stream << stream.rdbuf(); - - - if (state >= LoggerState::Flush) - { - // default sink - if (Logger::sinks().is_empty()) - { - std::unique_ptr sink = std::make_unique(Logger::severity()); - sink->addMessage(oss.str()); - sink->flush(); - //delete sink; - } - - // global sinks - for (Sink* sink : Logger::sinks()) - { - sink->addMessage(oss.str()); - sink->flush(); - } - } - - if (state == LoggerState::Exception) - { - throw std::runtime_error(oss.str()); - } - - if (state == LoggerState::Exit) - { - std::exit(instance.p_exitcode); - } - - //instance.p_stream.flush(); - return stream; - } -} -} +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace hpr::logging +{ + + enum Severity + { + Emergency, + Alert, + Critical, + Error, + Warning, + Notice, + Info, + Debug + }; + + class Sink + { + //friend class Logger; + + protected: + + Severity p_severity; + std::string p_message; + + public: + + Sink() : + p_severity {Emergency}, + p_message {} + {} + + Sink(Severity severity) : + p_severity {severity}, + p_message {} + {} + + void addMessage(const std::string& message) + { + p_message = message; + } + + virtual + void flush() = 0; + /*{ + p_message.clear(); + }*/ + + virtual + Sink* clone() const = 0; + + + virtual + ~Sink() = default; + + }; + + class StandardOutput : public Sink + { + + public: + + StandardOutput() : + Sink() + {} + + explicit + StandardOutput(Severity severity) : + Sink(severity) + {} + + void flush() override + { + if (p_severity <= Error) + std::cerr << p_message;// << "\n"; + if (p_severity > Error && p_severity <= Debug) + std::cout << p_message;// << "\n"; + std::cout.flush(); + //p_message.clear(); + } + + StandardOutput* clone() const override + { + return new StandardOutput(*this); + } + + ~StandardOutput() override = default; + + }; + + class FileOutput : public Sink + { + + protected: + + std::string p_filename; + static std::mutex mutex; + public: + + FileOutput() = delete; + + FileOutput(Severity severity, const std::string& filename) : + Sink {severity}, + p_filename {filename} + {} + + void flush() override + { + auto path = std::filesystem::canonical(std::filesystem::path(p_filename)); + std::ofstream sf {path, std::ios::app}; + + if (!sf.is_open()) + throw std::runtime_error("Failed to open file"); + else + { + std::lock_guard lock(mutex); + sf << p_message; + } + } + + FileOutput* clone() const override + { + return new FileOutput(*this); + } + + ~FileOutput() override = default; + + }; + + std::mutex FileOutput::mutex; + + class DumbassOutput : public Sink + { + + public: + + DumbassOutput() : + Sink() + {} + + explicit + DumbassOutput(Severity severity) : + Sink(severity) + {} + + void flush() override + { + std::cout << "BLUAARUARA";// << "\n"; + std::cout.flush(); + p_message.clear(); + } + + DumbassOutput* clone() const override + { + return new DumbassOutput(*this); + } + + ~DumbassOutput() override = default; + + }; + + + class Logger + { + + public: + + enum class State + { + Endline, + Flush, + Exception, + Exit + }; + + private: + + static std::mutex mutex; + + protected: + + Severity p_severity; + std::ostringstream p_stream; + int p_exitcode; + std::array p_levelNames; + std::vector p_sinks; + std::source_location p_location; + bool p_isGlobal; + std::string p_format; + + public: + + Logger() : + p_severity {Emergency}, + p_stream {"", std::ios::out | std::ios::ate }, + p_exitcode {-1}, + p_levelNames { "Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug"}, + p_sinks {}, + p_location {}, + p_isGlobal {false}, + p_format {"{levelname}({location}): {message}"} + {} + + explicit + Logger(Severity severity) : + p_severity {severity}, + p_stream {}, + p_exitcode {-1}, + p_levelNames { "Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug"}, + p_sinks {}, + p_location {}, + p_isGlobal {false}, + p_format {"{levelname}: {filename}:{location}: {message}"} + {} + + Logger(const Logger& logger) + { + copy(*this, logger); + } + + Logger& operator=(const Logger& logger) + { + copy(*this, logger); + return *this; + } + + virtual + ~Logger() + { + for (auto& sink : p_sinks) + delete sink; + } + + inline + void severity(Severity severity) + { + p_severity = severity; + } + + inline + Severity severity() + { + return p_severity; + } + + inline + std::string stream() + { + return p_stream.str(); + } + + inline + void levelname(Severity severity, const std::string& name) + { + p_levelNames[severity] = name; + } + + inline + std::string levelname(Severity severity) + { + return p_levelNames[severity]; + } + + inline + void location(const std::source_location& location) + { + p_location = location; + } + + inline + std::source_location location() + { + return p_location; + } + + inline + void format(const std::string& format) + { + p_format = format; + } + + inline + std::string format() + { + return p_format; + } + + inline + const std::vector& sinks() + { + return p_sinks; + } + + inline + void addSink(Sink* sink) + { + if (sink != nullptr) + { + p_sinks.push_back(sink->clone()); + //p_sinks.push_back(new T()); + //*p_sinks.back() = *sink; + //p_sinks.emplace_back(); + //p_sinks.back() = reinterpret_cast(&sink); + } + } + + inline + void removeSink(std::size_t n) + { + p_sinks.erase(p_sinks.begin() + n); + } + + inline + Sink* defaultSink() + { + return new StandardOutput(p_severity); + } + + std::string formatMessage(const std::string& message) + { + auto replace = [](std::string& lhs, const std::string& rep, const std::string& replacement) + { + std::size_t index = 0; + while ((index = lhs.find(rep, index)) != std::string::npos) + { + lhs.replace(index, rep.length(), replacement); + index += replacement.length(); + } + return lhs; + }; + + std::string target = p_format; + target = replace(target, "{levelname}", p_levelNames[p_severity]); + target = replace(target, "{location}", std::to_string(p_location.line())); + target = replace(target, "{function}", p_location.function_name()); + target = replace(target, "{filename}", p_location.file_name()); + target = replace(target, "{message}", message); + + return target; + } + + template + Logger& operator<<(const T& message) + { + if constexpr (std::is_same_v) + { + //std::lock_guard lock(mutex); + + if (message >= State::Endline) + { + p_stream << "\n"; + } + + if (message >= State::Flush) + { + std::string formattedMessage = formatMessage(p_stream.str()); + + if (p_sinks.empty()) + { + std::cout << "default sink" << std::endl; + Sink* sink = defaultSink(); + sink->addMessage(formattedMessage); + sink->flush(); + delete sink; + } + else + { + std::cout << "local sinks" << std::endl; + for (auto& sink : p_sinks) + { + if (sink != nullptr) + { + sink->addMessage(formattedMessage); + sink->flush(); + } + } + } + + p_stream.flush(); + } + + if (message == State::Exception) + { + throw std::runtime_error(p_stream.str()); + } + + if (message == State::Exit) + { + std::exit(p_exitcode); + } + + } + else + { + std::lock_guard lock(mutex); + p_stream << message; + } + return *this; + } + + + friend inline + Logger log(Severity severity, std::source_location location); + + public: + + static void copy(Logger& lhs, const Logger& rhs) + { + lhs.p_severity = rhs.p_severity; + + lhs.p_stream.flush(); + lhs.p_stream << rhs.p_stream.str(); + + lhs.p_exitcode = rhs.p_exitcode; + lhs.p_levelNames = rhs.p_levelNames; + lhs.p_isGlobal = false; + lhs.p_location = rhs.p_location; + lhs.p_format = rhs.p_format; + + if (!rhs.p_sinks.empty()) + { + lhs.p_sinks.reserve(rhs.p_sinks.size()); + for (const auto& sink : rhs.p_sinks) + { + lhs.p_sinks.push_back(sink->clone()); + //*lhs.p_sinks.back() = *sink; + //lhs.p_sinks.push_back(std::unique_ptr(sink)); + } + } + } + + private: + + static std::shared_ptr globalLogger; + + public: + + friend inline + void create(); + + friend inline + void destroy(); + + friend inline + std::shared_ptr& get(); + }; + + std::shared_ptr Logger::globalLogger; + std::mutex Logger::mutex; + + inline + Logger::State flush() + { + return Logger::State::Flush; + } + + inline + Logger log(Severity severity, std::source_location location = std::source_location::current()) + { + if (Logger::globalLogger != nullptr) + { + Logger::globalLogger->severity(severity); + Logger logger = *Logger::globalLogger; + logger.location(location); + return logger; + } + else + { + Logger logger = Logger(severity); + logger.location(location); + return logger; + } + } + + inline + void create() + { + Logger::globalLogger = std::make_shared(); + Logger::globalLogger->p_isGlobal = true; + } + + inline + void destroy() + { + if (Logger::globalLogger != nullptr) + Logger::globalLogger.reset(); + } + + inline + std::shared_ptr& get() + { + return Logger::globalLogger; + } + + + inline + Logger emergency(std::source_location location = std::source_location::current()) + { + return log(Emergency, location); + } + + inline + Logger alert(std::source_location location = std::source_location::current()) + { + return log(Alert, location); + } + + inline + Logger critical(std::source_location location = std::source_location::current()) + { + return log(Critical, location); + } + + inline + Logger error(std::source_location location = std::source_location::current()) + { + return log(Error, location); + } + + inline + Logger warning(std::source_location location = std::source_location::current()) + { + return log(Warning, location); + } + + inline + Logger notice(std::source_location location = std::source_location::current()) + { + return log(Notice, location); + } + + inline + Logger info(std::source_location location = std::source_location::current()) + { + return log(Info, location); + } + + inline + Logger debug(std::source_location location = std::source_location::current()) + { + return log(Debug, location); + } + +} \ No newline at end of file diff --git a/source/hpr/io/tests/CMakeLists.txt b/source/hpr/io/tests/CMakeLists.txt deleted file mode 100644 index 1644c07..0000000 --- a/source/hpr/io/tests/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -file(GLOB tests_cpp "*.cpp") - -add_executable(${PROJECT_NAME}-tests - ${tests_cpp} -) - -target_link_libraries(${PROJECT_NAME}-tests - PUBLIC - hpr::${PROJECT_NAME} - PRIVATE - GTest::gtest_main -) - -gtest_add_tests(TARGET ${PROJECT_NAME}-tests) diff --git a/source/hpr/io/tests/io-test.cpp b/source/hpr/io/tests/io-test.cpp index ed615a5..4e6149f 100644 --- a/source/hpr/io/tests/io-test.cpp +++ b/source/hpr/io/tests/io-test.cpp @@ -1,8 +1,9 @@ #include -#include "../logger.hpp" +#include #include + void task1() { using namespace hpr; diff --git a/source/hpr/math.hpp b/source/hpr/math.hpp index bf29022..131be38 100644 --- a/source/hpr/math.hpp +++ b/source/hpr/math.hpp @@ -1,5 +1,6 @@ -#pragma once - -#include "math/scalar.hpp" -#include "math/vector.hpp" -#include "math/matrix.hpp" \ No newline at end of file +#pragma once + +#include +#include +#include +#include diff --git a/source/hpr/math/CMakeLists.txt b/source/hpr/math/CMakeLists.txt index 781214f..b62cdb4 100644 --- a/source/hpr/math/CMakeLists.txt +++ b/source/hpr/math/CMakeLists.txt @@ -1,62 +1,25 @@ cmake_minimum_required(VERSION 3.16) project(math - VERSION "${HPR_PROJECT_VERSION}" + VERSION "${HPR_VERSION}" LANGUAGES CXX ) -add_library(${PROJECT_NAME} INTERFACE) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) +hpr_add_library(${PROJECT_NAME} INTERFACE) -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../math.hpp" "*.hpp" "scalar/*.hpp" "vector/*.hpp" "matrix/*.hpp" "quaternion/*.hpp" +hpr_collect_interface(${PROJECT_NAME} + "../math.hpp" + "*.hpp" + "scalar/*.hpp" + "vector/*.hpp" + "matrix/*.hpp" + "quaternion/*.hpp" ) -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ -) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> ) -if(HPR_TEST) - add_subdirectory(tests) -endif() \ No newline at end of file +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) +hpr_tests(${PROJECT_NAME} tests) diff --git a/source/hpr/math/integer.hpp b/source/hpr/math/integer.hpp index 28c1742..7bea965 100644 --- a/source/hpr/math/integer.hpp +++ b/source/hpr/math/integer.hpp @@ -1,4 +1,4 @@ -#pragma once - -#include "integer/integer.hpp" -#include "integer/size.hpp" +#pragma once + +#include +#include diff --git a/source/hpr/math/integer/integer.hpp b/source/hpr/math/integer/integer.hpp index 270559a..3512c36 100644 --- a/source/hpr/math/integer/integer.hpp +++ b/source/hpr/math/integer/integer.hpp @@ -1,17 +1,17 @@ -#pragma once - -#include - - -namespace hpr -{ - // type traits - - template - struct is_integer : public std::is_integral {}; - - // concepts - - template - concept IsInteger = is_integer::value; +#pragma once + +#include + + +namespace hpr +{ + // type traits + + template + struct is_integer : public std::is_integral {}; + + // concepts + + template + concept IsInteger = is_integer::value; } \ No newline at end of file diff --git a/source/hpr/math/integer/size.hpp b/source/hpr/math/integer/size.hpp index ca5e851..92a8617 100644 --- a/source/hpr/math/integer/size.hpp +++ b/source/hpr/math/integer/size.hpp @@ -1,22 +1,22 @@ -#pragma once - -#include - -namespace hpr -{ - - using Size = std::size_t; - - // type traits - - template - struct is_size : public std::integral_constant::value && std::is_unsigned::value> {}; - - // concepts - - template - concept IsSize = is_size::value || std::convertible_to; - - - //using Size = typename IsSize::type; +#pragma once + +#include + +namespace hpr +{ + + using Size = std::size_t; + + // type traits + + template + struct is_size : public std::integral_constant::value && std::is_unsigned::value> {}; + + // concepts + + template + concept IsSize = is_size::value || std::convertible_to; + + + //using Size = typename IsSize::type; } \ No newline at end of file diff --git a/source/hpr/math/matrix.hpp b/source/hpr/math/matrix.hpp index a23fe30..c00e1c4 100644 --- a/source/hpr/math/matrix.hpp +++ b/source/hpr/math/matrix.hpp @@ -1,5 +1,5 @@ #pragma once -#include "matrix/matrix_space.hpp" -#include "matrix/transform.hpp" -#include "matrix/clip_space.hpp" +#include +#include +#include diff --git a/source/hpr/math/matrix/clip_space.hpp b/source/hpr/math/matrix/clip_space.hpp index 9b3b15e..35ea754 100644 --- a/source/hpr/math/matrix/clip_space.hpp +++ b/source/hpr/math/matrix/clip_space.hpp @@ -1,54 +1,52 @@ -#pragma once - -#include "../matrix.hpp" - - -namespace hpr -{ - -template -inline -Matrix ortho(T left, T right, T bottom, T top) -{ - Matrix ms; - ms.fill(1); - ms(0, 0) = 2 / (right - left); - ms(1, 1) = 2 / (top - bottom); - ms(2, 2) = -1; - ms(3, 0) = -(right + left) / (right - left); - ms(3, 1) = -(top + bottom) / (top - bottom); - return ms; -} - -template -inline -Matrix ortho(T left, T right, T bottom, T top, T zNear, T zFar) -{ - Matrix ms {1}; - //ms.fill(1); - ms(0, 0) = 2 / (right - left); - ms(1, 1) = 2 / (top - bottom); - ms(2, 2) = 2 / (zFar - zNear); - ms(3, 0) = -(right + left) / (right - left); - ms(3, 1) = -(top + bottom) / (top - bottom); - ms(3, 2) = -(zFar + zNear) / (zFar - zNear); - return ms; -} - -template -inline -Matrix perspective(T fovy, T aspect, T zNear, T zFar) -{ - assert(abs(aspect - std::numeric_limits::epsilon()) > 0); - Matrix ms; - const T halfFovyTan = tan(fovy / 2); - ms(0, 0) = 1 / (aspect * halfFovyTan); - ms(1, 1) = 1 / halfFovyTan; - ms(2, 2) = (zFar + zNear) / (zFar - zNear); - ms(2, 3) = 1; - ms(3, 2) = -(2 * zFar * zNear) / (zFar - zNear); - return ms; -} - - -} +#pragma once + +#include + + +namespace hpr +{ + +template +inline +Matrix ortho(T left, T right, T bottom, T top) +{ + Matrix ms = Matrix::identity(); + ms(0, 0) = static_cast(2) / (right - left); + ms(1, 1) = static_cast(2) / (top - bottom); + ms(2, 2) = -static_cast(1); + ms(3, 0) = -(right + left) / (right - left); + ms(3, 1) = -(top + bottom) / (top - bottom); + return ms; +} + +template +inline +Matrix ortho(T left, T right, T bottom, T top, T zNear, T zFar) +{ + Matrix ms = Matrix::identity(); + ms(0, 0) = static_cast(2) / (right - left); + ms(1, 1) = static_cast(2) / (top - bottom); + ms(2, 2) = -static_cast(2) / (zFar - zNear); + ms(0, 3) = -(right + left) / (right - left); + ms(1, 3) = -(top + bottom) / (top - bottom); + ms(2, 3) = -(zFar + zNear) / (zFar - zNear); + return ms; +} + +template +inline +Matrix perspective(T fovy, T aspect, T zNear, T zFar) +{ + assert(abs(aspect - std::numeric_limits::epsilon()) > 0); + Matrix ms; + const T halfFovyTan = tan(fovy / 2); + ms(0, 0) = static_cast(1) / (aspect * halfFovyTan); + ms(1, 1) = static_cast(1) / halfFovyTan; + ms(2, 2) = -(zFar + zNear) / (zFar - zNear); + ms(3, 2) = -static_cast(1); + ms(2, 3) = -(static_cast(2) * zFar * zNear) / (zFar - zNear); + return ms; +} + + +} diff --git a/source/hpr/math/matrix/matrix_space.hpp b/source/hpr/math/matrix/matrix.hpp similarity index 81% rename from source/hpr/math/matrix/matrix_space.hpp rename to source/hpr/math/matrix/matrix.hpp index f14167c..0e1c187 100644 --- a/source/hpr/math/matrix/matrix_space.hpp +++ b/source/hpr/math/matrix/matrix.hpp @@ -1,364 +1,392 @@ -#pragma once - -#include "../integer.hpp" -#include "../scalar.hpp" -#include "../../containers/array/static_array.hpp" - - -namespace hpr -{ - -// forward declarations - -template requires (Rows >= 0 && Cols >= 0) -class Matrix; - -template -using SubMatrix = typename std::conditional<(Rows >= 2 && Cols >= 2), Matrix, Matrix>::type; - -// type traits - -template -struct is_matrix : public std::false_type {}; - -template -struct is_matrix> : public std::true_type {}; - -// concepts - -template -concept IsMatrix = is_matrix::value; - -} - -namespace hpr -{ - -template requires (Rows >= 0 && Cols >= 0) -class Matrix : public StaticArray -{ - - using base = StaticArray; - -public: - - using value_type = Type; - using size_type = Size; - using pointer = Type*; - using reference = Type&; - using iterator = Iterator; - using const_reference = Type const&; - using const_iterator = Iterator; - -protected: - - size_type p_rows; - size_type p_cols; - -public: - - inline - Matrix() : - base {}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(const Matrix& ms) : - base {static_cast(ms)}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(Matrix&& ms) noexcept: - base {std::forward(static_cast(ms))}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix& operator=(const Matrix& ms) - { - base::operator=(ms); - return *this; - } - - inline explicit - Matrix(const base& vs) : - base {vs}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline explicit - Matrix(base&& vs) noexcept: - base {std::forward(vs)}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(typename base::iterator start, typename base::iterator end) : - base {start, end}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(typename base::const_iterator start, typename base::const_iterator end) : - base {start, end}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(std::initializer_list list) : - base {list}, - p_rows {Rows}, - p_cols {Cols} - {} - - template - inline - Matrix(value_type&& v, Args&& ...args) requires (1 + sizeof...(args) == Rows * Cols): - base {v, static_cast(std::forward(args))...}, - p_rows {Rows}, - p_cols {Cols} - {} - - inline - Matrix(const value_type& v) : - base {}, - p_rows {Rows}, - p_cols {Cols} - { - for (Size n = 0; n < Rows * Cols; ++n) - (*this)[n] = v; - } - - inline - Matrix& operator=(const value_type& v) - { - for (Size n = 0; n < Rows * Cols; ++n) - (*this)[n] = v; - return *this; - } - - // access - - inline - reference operator()(size_type row, size_type col) - { - if (row >= p_rows || std::numeric_limits::max() - p_rows < row) - throw std::out_of_range("Row index is out of range"); - if (col >= p_cols || std::numeric_limits::max() - p_cols < col) - throw std::out_of_range("Column index is out of range"); - return (*this)[col + p_rows * row]; - } - - inline - const_reference operator()(size_type row, size_type col) const - { - if (row >= p_rows || std::numeric_limits::max() - p_rows < row) - throw std::out_of_range("Row index is out of range"); - if (col >= p_cols || std::numeric_limits::max() - p_cols < col) - throw std::out_of_range("Column index is out of range"); - return (*this)[col + p_rows * row]; - } - - Vector row(size_type row) - { - Vector vs; - for (auto n = 0; n < Cols; ++n) - vs[n] = (*this)(row, n); - return vs; - } - - Vector row(size_type row) const - { - Vector vs; - for (auto n = 0; n < Cols; ++n) - vs[n] = (*this)(row, n); - return vs; - } - - void row(size_type row, const Vector& vs) - { - for (auto n = 0; n < Cols; ++n) - (*this)(n, row) = vs[n]; - } - - Vector col(size_type col) - { - Vector vs; - for (auto n = 0; n < Rows; ++n) - vs[n] = (*this)(n, col); - return vs; - } - - void col(size_type col, const Vector& vs) - { - for (auto n = 0; n < Rows; ++n) - (*this)(n, col) = vs[n]; - } - - [[nodiscard]] constexpr size_type rows() const { return p_rows; } - [[nodiscard]] constexpr size_type cols() const { return p_cols; } - - // member functions - - [[nodiscard]] - constexpr - bool is_square() const - { - return p_rows == p_cols; - } - - inline - Matrix& fill(value_type value) - { - for (auto n = 0; n < this->size(); ++n) - (*this)[n] = value; - return *this; - } - - // Global functions - - static inline - Matrix identity() - { - Matrix ms; - for (auto n = 0; n < Rows; ++n) - for (auto k = 0; k < Cols; ++k) - ms(n, k) = 1; - return ms; - } -}; - -// global operators - -template inline Matrix operator+(const Matrix& lhs) { Matrix ms; for (Size n = 0; n < lhs.size(); ++n) ms[n] = lhs[n]; return ms; } -template inline Matrix operator-(const Matrix& lhs) { Matrix ms; for (Size n = 0; n < lhs.size(); ++n) ms[n] = -lhs[n]; return ms; } - -template inline Matrix& operator+=(Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] += rhs[n]; return lhs; } -template inline Matrix& operator-=(Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] -= rhs[n]; return lhs; } -template requires (R == C2 && R2 == C) inline Matrix& operator*=(Matrix& lhs, const Matrix& rhs) { Matrix temp {lhs}; for (Size n = 0; n < R; ++n) for (Size k = 0; k < C; ++k) lhs(n, k) = sum(temp.col(k) * rhs.row(n)); return lhs; } - -template inline Matrix operator+(const Matrix& lhs, const Matrix& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] += rhs[n]; return ms; } -template inline Matrix operator-(const Matrix& lhs, const Matrix& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] -= rhs[n]; return ms; } -template requires (R == C2 && R2 == C) inline Matrix operator*(const Matrix& lhs, const Matrix& rhs) { Matrix ms; for (Size n = 0; n < R; ++n) for (Size k = 0; k < C; ++k) ms(n, k) = sum(lhs.col(k) * rhs.row(n)); return ms; } - -template inline bool operator==(const Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) if (lhs[n] != rhs[n]) return false; return true; } -template inline bool operator!=(const Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) if (lhs[n] == rhs[n]) return false; return true; } - - -template inline Matrix& operator+=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] += rhs; return lhs; } -template inline Matrix& operator-=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] -= rhs; return lhs; } -template inline Matrix& operator*=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] *= rhs; return lhs; } -template inline Matrix& operator/=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] /= rhs; return lhs; } - -template inline Matrix operator+(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] += rhs; return ms; } -template inline Matrix operator-(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] -= rhs; return ms; } -template inline Matrix operator*(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] *= rhs; return ms; } -template inline Matrix operator/(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] /= rhs; return ms; } - - -template inline Vector operator*(const Matrix& ms, const Vector& vs) { Vector res; for (Size n = 0; n < R; ++n) res[0] = sum(ms.row(n) * vs); return res; } -template inline Vector operator*(const Vector& vs, const Matrix& ms) { Vector res; for (Size n = 0; n < C; ++n) res[0] = sum(ms.col(n) * vs); return res; } - -template inline bool operator==(const Matrix& lhs, const Vector& rhs) { return false; } -template inline bool operator!=(const Matrix& lhs, const Vector& rhs) { return true; } - -// matrix operations - -//! Transpose matrix -template -inline -Matrix transpose(const Matrix& ms) -{ - Matrix res; - for (Size n = 0; n < R; ++n) - for (Size k = 0; k < C; ++k) - res(k, n) = ms(n, k); - return res; -} - -//! Trace of a matrix -template -inline -T trace(const Matrix& ms) requires (R == C) -{ - T res; - for (auto n = 0; n < R; ++n) - res += ms(n, n); - return res; -} - -//! Minor of a matrix -template -inline -SubMatrix minor(const Matrix& ms, Size row, Size col) -{ - if (ms.size() < 4) - throw std::runtime_error("Matrix should be greater 2x2"); - - SubMatrix minor; - auto minor_iter = minor.begin(); - for (auto n = 0; n < R; ++n) - for (auto k = 0; k < C; ++k) - if (k != col && n != row) - *(minor_iter++) = ms[k + ms.rows() * n]; - return minor; -} - -//! Determinant of a matrix -template -inline -scalar det(const Matrix& ms) requires (R == C) -{ - if (ms.size() == 1) - return ms[0]; - - else if (ms.size() == 4) - return ms(0, 0) * ms(1, 1) - ms(0, 1) * ms(1, 0); - - else { - scalar res = 0; - for (auto n = 0; n < ms.cols(); ++n) - res += pow(-1, n) * ms(0, n) * det(minor(ms, 0, n)); - return res; - } -} - -//! Adjoint matrix -template -inline -Matrix adj(const Matrix& ms) -{ - Matrix res; - for (auto n = 0; n < R; ++n) - for (auto k = 0; k < C; ++k) - res(n, k) = pow(-1, n + k) * det(minor(ms, n, k)); - return transpose(res); -} - -//! Inverse matrix -template -inline -Matrix inv(const Matrix& ms) -{ - return adj(ms) / det(ms); -} - -// Aliases - -template -using mat = Matrix; - -using mat2 = Matrix; -using mat3 = Matrix; -using mat4 = Matrix; - +#pragma once + +#include +#include +#include +#include + + +namespace hpr +{ + +// forward declarations + +template requires (Rows >= 0 && Cols >= 0) +class Matrix; + +template +using SubMatrix = typename std::conditional<(Rows >= 2 && Cols >= 2), Matrix, Matrix>::type; + +// type traits + +template +struct is_matrix : public std::false_type {}; + +template +struct is_matrix> : public std::true_type {}; + +// concepts + +template +concept IsMatrix = is_matrix::value; + +} + +namespace hpr +{ + +template requires (Rows >= 0 && Cols >= 0) +class Matrix : public StaticArray +{ + + using base = StaticArray; + +public: + + using value_type = Type; + using size_type = Size; + using pointer = Type*; + using reference = Type&; + using iterator = Iterator; + using const_reference = Type const&; + using const_iterator = Iterator; + +protected: + + size_type p_rows; + size_type p_cols; + +public: + + friend constexpr + void swap(Matrix& main, Matrix& other) + { + using std::swap; + swap(static_cast(main), static_cast(other)); + swap(main.p_rows, other.p_rows); + swap(main.p_cols, other.p_cols); + } + + inline + Matrix() : + base {}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(const Matrix& ms) : + base {static_cast(ms)}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(Matrix&& ms) noexcept: + base {std::forward(static_cast(ms))}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix& operator=(const Matrix& ms) + { + //base::operator=(ms); + swap(*this, ms); + return *this; + } + + inline explicit + Matrix(const base& vs) : + base {vs}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline explicit + Matrix(base&& vs) noexcept: + base {std::forward(vs)}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(typename base::iterator start, typename base::iterator end) : + base {start, end}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(typename base::const_iterator start, typename base::const_iterator end) : + base {start, end}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(std::initializer_list list) : + base {list}, + p_rows {Rows}, + p_cols {Cols} + {} + + template + inline + Matrix(value_type&& v, Args&& ...args) requires (1 + sizeof...(args) == Rows * Cols): + base {v, static_cast(std::forward(args))...}, + p_rows {Rows}, + p_cols {Cols} + {} + + inline + Matrix(const value_type& v) : + base {}, + p_rows {Rows}, + p_cols {Cols} + { + for (Size n = 0; n < Rows * Cols; ++n) + (*this)[n] = v; + } + + inline + Matrix& operator=(const value_type& v) + { + for (Size n = 0; n < Rows * Cols; ++n) + (*this)[n] = v; + return *this; + } + + inline explicit + Matrix(const Quaternion& q) requires (Rows == 3 && Cols == 3 || Rows == 4 && Cols == 4) : + base {}, + p_rows {Rows}, + p_cols {Cols} + { + const scalar s = pow(norm(q), -2); + + (*this)(0, 0) = 1 - 2 * s * (q[2] * q[2] + q[3] * q[3]); + (*this)(1, 0) = 2 * s * (q[1] * q[2] - q[3] * q[0]); + (*this)(2, 0) = 2 * s * (q[1] * q[3] - q[2] * q[0]); + + (*this)(0, 1) = 2 * s * (q[1] * q[2] + q[3] * q[0]); + (*this)(1, 1) = 1 - 2 * s * (q[1] * q[1] + q[3] * q[3]); + (*this)(2, 1) = 2 * s * (q[2] * q[3] + q[1] * q[0]); + + (*this)(0, 2) = 2 * s * (q[1] * q[3] + q[2] * q[0]); + (*this)(1, 2) = 2 * s * (q[2] * q[3] + q[1] * q[0]); + (*this)(2, 2) = 1 - 2 * s * (q[1] * q[1] + q[2] * q[2]); + + if constexpr (Rows == 4) + (*this)(3, 3) = 1; + } + + + // access + + inline + reference operator()(size_type row, size_type col) + { + if (row >= p_rows || std::numeric_limits::max() - p_rows < row) + throw std::out_of_range("Row index is out of range"); + if (col >= p_cols || std::numeric_limits::max() - p_cols < col) + throw std::out_of_range("Column index is out of range"); + return (*this)[col + p_rows * row]; + } + + inline + const_reference operator()(size_type row, size_type col) const + { + if (row >= p_rows || std::numeric_limits::max() - p_rows < row) + throw std::out_of_range("Row index is out of range"); + if (col >= p_cols || std::numeric_limits::max() - p_cols < col) + throw std::out_of_range("Column index is out of range"); + return (*this)[col + p_rows * row]; + } + + Vector row(size_type row) const + { + Vector vs; + for (auto n = 0; n < Cols; ++n) + vs[n] = (*this)(row, n); + return vs; + } + + void row(size_type row, const Vector& vs) + { + for (auto n = 0; n < Cols; ++n) + (*this)(row, n) = vs[n]; + } + + Vector col(size_type col) const + { + Vector vs; + for (auto n = 0; n < Rows; ++n) + vs[n] = (*this)(n, col); + return vs; + } + + void col(size_type col, const Vector& vs) + { + for (auto n = 0; n < Rows; ++n) + (*this)(n, col) = vs[n]; + } + + [[nodiscard]] constexpr size_type rows() const { return p_rows; } + [[nodiscard]] constexpr size_type cols() const { return p_cols; } + + // member functions + + [[nodiscard]] + constexpr + bool is_square() const + { + return p_rows == p_cols; + } + + inline + Matrix& fill(value_type value) + { + for (auto n = 0; n < this->size(); ++n) + (*this)[n] = value; + return *this; + } + + // Global functions + + static inline + Matrix identity() + { + Matrix ms; + for (auto n = 0; n < Rows; ++n) + //for (auto k = 0; k < Cols; ++k) + ms(n, n) = 1; + return ms; + } +}; + +// global operators + +template inline Matrix operator+(const Matrix& lhs) { Matrix ms; for (Size n = 0; n < lhs.size(); ++n) ms[n] = lhs[n]; return ms; } +template inline Matrix operator-(const Matrix& lhs) { Matrix ms; for (Size n = 0; n < lhs.size(); ++n) ms[n] = -lhs[n]; return ms; } + +template inline Matrix& operator+=(Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] += rhs[n]; return lhs; } +template inline Matrix& operator-=(Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] -= rhs[n]; return lhs; } +template inline Matrix& operator*=(Matrix& lhs, const Matrix& rhs) { Matrix temp {lhs}; for (Size n = 0; n < R; ++n) for (Size k = 0; k < C; ++k) lhs(n, k) = sum(temp.col(k) * rhs.row(n)); return lhs; } + +template inline Matrix operator+(const Matrix& lhs, const Matrix& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] += rhs[n]; return ms; } +template inline Matrix operator-(const Matrix& lhs, const Matrix& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] -= rhs[n]; return ms; } +template inline Matrix operator*(const Matrix& lhs, const Matrix& rhs) { Matrix ms; for (Size n = 0; n < R; ++n) for (Size k = 0; k < C; ++k) ms(n, k) = sum(lhs.col(k) * rhs.row(n)); return ms; } + +template inline bool operator==(const Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) if (lhs[n] != rhs[n]) return false; return true; } +template inline bool operator!=(const Matrix& lhs, const Matrix& rhs) { for (Size n = 0; n < lhs.size(); ++n) if (lhs[n] == rhs[n]) return false; return true; } + + +template inline Matrix& operator+=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] += rhs; return lhs; } +template inline Matrix& operator-=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] -= rhs; return lhs; } +template inline Matrix& operator*=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] *= rhs; return lhs; } +template inline Matrix& operator/=(Matrix& lhs, const T& rhs) { for (Size n = 0; n < lhs.size(); ++n) lhs[n] /= rhs; return lhs; } + +template inline Matrix operator+(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] += rhs; return ms; } +template inline Matrix operator-(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] -= rhs; return ms; } +template inline Matrix operator*(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] *= rhs; return ms; } +template inline Matrix operator/(const Matrix& lhs, const T& rhs) { Matrix ms {lhs}; for (Size n = 0; n < lhs.size(); ++n) ms[n] /= rhs; return ms; } + + +template inline Vector operator*(const Matrix& ms, const Vector& vs) { Vector res; for (Size n = 0; n < R; ++n) res[n] = sum(ms.row(n) * vs); return res; } +template inline Vector operator*(const Vector& vs, const Matrix& ms) { Vector res; for (Size n = 0; n < C; ++n) res[n] = sum(ms.col(n) * vs); return res; } + +template inline bool operator==(const Matrix& lhs, const Vector& rhs) { return false; } +template inline bool operator!=(const Matrix& lhs, const Vector& rhs) { return true; } + +// matrix operations + +//! Transpose matrix +template +inline +Matrix transpose(const Matrix& ms) +{ + Matrix res; + for (Size n = 0; n < R; ++n) + for (Size k = 0; k < C; ++k) + res(k, n) = ms(n, k); + return res; +} + +//! Trace of a matrix +template +inline +T trace(const Matrix& ms) requires (R == C) +{ + T res; + for (auto n = 0; n < R; ++n) + res += ms(n, n); + return res; +} + +//! Minor of a matrix +template +inline +SubMatrix minor(const Matrix& ms, Size row, Size col) +{ + if (ms.size() < 4) + throw std::runtime_error("Matrix should be greater 2x2"); + + SubMatrix minor; + auto minor_iter = minor.begin(); + for (auto n = 0; n < R; ++n) + for (auto k = 0; k < C; ++k) + if (k != col && n != row) + *(minor_iter++) = ms[k + ms.rows() * n]; + return minor; +} + +//! Determinant of a matrix +template +inline +scalar det(const Matrix& ms) requires (R == C) +{ + if (ms.size() == 1) + return ms[0]; + + else if (ms.size() == 4) + return ms(0, 0) * ms(1, 1) - ms(0, 1) * ms(1, 0); + + else { + scalar res = 0; + for (auto n = 0; n < ms.cols(); ++n) + res += pow(-1, n) * ms(0, n) * det(minor(ms, 0, n)); + return res; + } +} + +//! Adjoint matrix +template +inline +Matrix adj(const Matrix& ms) +{ + Matrix res; + for (auto n = 0; n < R; ++n) + for (auto k = 0; k < C; ++k) + res(n, k) = pow(-1, n + k) * det(minor(ms, n, k)); + return transpose(res); +} + +//! Inverse matrix +template +inline +Matrix inv(const Matrix& ms) +{ + return adj(ms) / det(ms); +} + +// Aliases + +template +using mat = Matrix; + +using mat2 = Matrix; +using mat3 = Matrix; +using mat4 = Matrix; + } \ No newline at end of file diff --git a/source/hpr/math/matrix/transform.hpp b/source/hpr/math/matrix/transform.hpp index 9836ddd..665ae3e 100644 --- a/source/hpr/math/matrix/transform.hpp +++ b/source/hpr/math/matrix/transform.hpp @@ -1,101 +1,90 @@ -#pragma once - -#include "../matrix.hpp" - - -namespace hpr -{ - -template -inline -Matrix translate(const Matrix& ms, const Vector& vs) -{ - Matrix res {ms}; - res.col(3, ms.row(0) * vs[0] + ms.row(1) * vs[1] + ms.row(2) * vs[2] + ms.row(3)); - - return res; -} - -template -inline -Vector translate(const Vector& vs1, const Vector& vs2) -{ - Matrix res = Matrix::identity(); - res.row(3, Vector(vs1, 0.)); - res = translate(res, vs2); - - return Vector(res.row(3)); -} - -template -inline -Matrix rotate(const Matrix& ms, const Vector& vs, T angle) -{ - const T cosv = cos(angle); - const T sinv = sin(angle); - Vector axis {normalize(vs)}; - Vector temp {(1. - cosv) * axis}; - - Matrix rot; - rot(0, 0) = cosv + temp[0] * axis[0]; - rot(0, 1) = temp[0] * axis[1] + sinv * axis[2]; - rot(0, 2) = temp[0] * axis[2] - sinv * axis[1]; - rot(1, 0) = temp[1] * axis[0] - sinv * axis[2]; - rot(1, 1) = cosv + temp[1] * axis[1]; - rot(1, 2) = temp[1] * axis[2] + sinv * axis[0]; - rot(2, 0) = temp[2] * axis[0] + sinv * axis[1]; - rot(2, 1) = temp[2] * axis[1] - sinv * axis[0]; - rot(2, 2) = cosv + temp[2] * axis[2]; - - Matrix res {ms}; - res.row(0, ms.row(0) * rot(0, 0) + ms.row(1) * rot(0, 1) + ms.row(2) * rot(0, 2)); - res.row(1, ms.row(0) * rot(1, 0) + ms.row(1) * rot(1, 1) + ms.row(2) * rot(1, 2)); - res.row(2, ms.row(0) * rot(2, 0) + ms.row(1) * rot(2, 1) + ms.row(2) * rot(2, 2)); - res.row(3, ms.row(3)); - - return res; -} - -template -inline -Vector rotate(const Vector& vs1, const Vector& vs2, T angle) -{ - Matrix res = Matrix::identity(); - res.row(3, Vector(vs1, 0.)); - res = rotate(res, vs2, angle); - - return Vector(res.row(3)); -} - -template -inline -Matrix scale(const Matrix& ms, const Vector& vs) -{ - Matrix res; - res.row(0, ms.row(0) * vs[0]); - res.row(1, ms.row(1) * vs[1]); - res.row(2, ms.row(2) * vs[2]); - res.row(3, ms.row(3)); - - return res; -} - - -template -inline -Matrix lookAt(const Matrix& ms, const Vector& eye, const Vector& center, const Vector& up) -{ - const Vector forward {normalize(center - eye)}; - const Vector left {normalize(cross(up, forward))}; - const Vector nup {cross(forward, left)}; - - Matrix res; - res.col(0, Vector(left, 0)); - res.col(1, Vector(nup, 0)); - res.col(2, Vector(forward, 0)); - res.row(3, -Vector(dot(left, eye), dot(nup, eye), dot(forward, eye), -1.)); - - return res; -} - -} +#pragma once + +#include +#include + + + +namespace hpr +{ + +template +inline +Matrix translate(const Matrix& ms, const Vector& vs) +{ + Matrix res {ms}; + res.col(3, ms.row(0) * vs[0] + ms.row(1) * vs[1] + ms.row(2) * vs[2] + ms.row(3)); + + return res; +} + +template +inline +Matrix rotate(const Matrix& ms, const Vector& vs, T angle) +{ + const T cosv = cos(angle); + const T sinv = sin(angle); + Vector axis {normalize(vs)}; + Vector temp {(static_cast(1) - cosv) * axis}; + + Matrix rot; + rot(0, 0) = cosv + temp[0] * axis[0]; + rot(0, 1) = temp[0] * axis[1] + sinv * axis[2]; + rot(0, 2) = temp[0] * axis[2] - sinv * axis[1]; + rot(1, 0) = temp[1] * axis[0] - sinv * axis[2]; + rot(1, 1) = cosv + temp[1] * axis[1]; + rot(1, 2) = temp[1] * axis[2] + sinv * axis[0]; + rot(2, 0) = temp[2] * axis[0] + sinv * axis[1]; + rot(2, 1) = temp[2] * axis[1] - sinv * axis[0]; + rot(2, 2) = cosv + temp[2] * axis[2]; + + Matrix res {ms}; + res.row(0, ms.row(0) * rot(0, 0) + ms.row(1) * rot(0, 1) + ms.row(2) * rot(0, 2)); + res.row(1, ms.row(0) * rot(1, 0) + ms.row(1) * rot(1, 1) + ms.row(2) * rot(1, 2)); + res.row(2, ms.row(0) * rot(2, 0) + ms.row(1) * rot(2, 1) + ms.row(2) * rot(2, 2)); + res.row(3, ms.row(3)); + + return res; +} + + +template +inline +Matrix rotate(const Matrix& ms, const Quaternion& q) +{ + return ms * Matrix(q); +} + +template +inline +Matrix scale(const Matrix& ms, const Vector& vs) +{ + Matrix res; + res.row(0, ms.row(0) * vs[0]); + res.row(1, ms.row(1) * vs[1]); + res.row(2, ms.row(2) * vs[2]); + res.row(3, ms.row(3)); + + return res; +} + + +template +inline +Matrix lookAt(const Vector& eye, const Vector& center, const Vector& up) +{ + const Vector forward {normalize(center - eye)}; + const Vector right {normalize(cross(forward, up))}; + const Vector nup {cross(right, forward)}; + const Vector translation {dot(right, eye), dot(nup, eye), -dot(forward, eye)}; + + Matrix res = Matrix::identity(); + res.row(0, Vector(right, 0)); + res.row(1, Vector(nup, 0)); + res.row(2, Vector(-forward, 0)); + res.col(3, Vector(-translation, static_cast(1))); + + return res; +} + +} diff --git a/source/hpr/math/quaternion.hpp b/source/hpr/math/quaternion.hpp index b488e42..cf9e97a 100644 --- a/source/hpr/math/quaternion.hpp +++ b/source/hpr/math/quaternion.hpp @@ -1,3 +1,3 @@ -#pragma once - -#include "quaternion/quaternion.hpp" \ No newline at end of file +#pragma once + +#include \ No newline at end of file diff --git a/source/hpr/math/quaternion/quaternion.hpp b/source/hpr/math/quaternion/quaternion.hpp index 1180e33..c1cf146 100644 --- a/source/hpr/math/quaternion/quaternion.hpp +++ b/source/hpr/math/quaternion/quaternion.hpp @@ -1,259 +1,291 @@ -#pragma once - -#include "../vector.hpp" - - -namespace hpr -{ - -// Forward declaration - -class Quaternion; - -inline -Quaternion inverse(const Quaternion& q); - -inline -Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs); - -// Class declaration -class Quaternion -{ - -public: - - enum RotationSequence - { - ZYX, ZYZ, ZXY, ZXZ, YXZ, YXY, YZX, YZY, XYZ, XYX, XZY, XZX - }; - -protected: - - scalar p_real; - vec3 p_imag; - -public: - - inline - Quaternion() : - p_real{}, - p_imag{} - {} - - inline - Quaternion(const scalar real, const vec3& imag) : - p_real {real}, - p_imag {imag} - {} - - inline explicit - Quaternion(const scalar real) : - p_real {real}, - p_imag {} - {} - - inline explicit - Quaternion(const vec3& imag) : - p_real {}, - p_imag {imag} - {} - - inline - Quaternion(const vec3& vs, const scalar& theta) : - p_real {cos(0.5 * theta)}, - p_imag {sin(0.5 * theta) * vs / mag(vs)} - {} - - static inline - Quaternion unit(const vec3& vs) - { - return Quaternion(sqrt(1 - norm(vs)), vs); - } - - inline - Quaternion(const RotationSequence rs, const vec3& angles) - { - switch (rs) - { - case XYZ: - *this = Quaternion(vec3(0, 1, 0), angles[0]) * - Quaternion(vec3(0, 1, 0), angles[1]) * - Quaternion(vec3(0, 0, 1), angles[2]); - break; - - default: - throw std::runtime_error("Unknown rotation sequence"); - } - } - - inline - scalar real() const - { - return p_real; - } - - inline - scalar& real() - { - return p_real; - } - - inline - vec3 imag() const - { - return p_imag; - } - - inline - vec3& imag() - { - return p_imag; - } - - inline - void operator+=(const Quaternion& q) - { - p_real += q.p_real; - p_imag += q.p_imag; - } - - inline - void operator-=(const Quaternion& q) - { - p_real -= q.p_real; - p_imag -= q.p_imag; - } - - inline - void operator*=(const Quaternion& q) - { - scalar temp = p_real; - p_real = p_real * q.p_real - dot(p_imag, q.p_imag); - p_imag = temp * q.p_imag + q.p_real * p_imag + cross(p_imag, q.p_imag); - } - - inline - void operator/=(const Quaternion& q) - { - operator*=(inverse(q)); - } - - inline - void operator*=(const scalar s) - { - p_real *= s; - p_imag *= s; - } - - inline - void operator/=(const scalar s) - { - p_real /= s; - p_imag /= s; - } -}; - -inline -bool equal(const Quaternion& lhs, const Quaternion& rhs) -{ - return lhs.real() == rhs.real() && lhs.imag() == rhs.imag(); -} - -inline -bool operator==(const Quaternion& lhs, const Quaternion& rhs) -{ - return equal(lhs, rhs); -} - -inline -bool operator!=(const Quaternion& lhs, const Quaternion& rhs) -{ - return !equal(lhs, rhs); -} - -inline -Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs) -{ - return {lhs.real() + rhs.real(), lhs.imag() + rhs.imag()}; -} - -inline -Quaternion operator-(const Quaternion& q) -{ - return {q.real(), q.imag()}; -} - -inline -Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs) -{ - return {lhs.real() - rhs.real(), lhs.imag() - rhs.imag()}; -} - -inline -Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs) -{ - return {lhs.real() * rhs.real() - dot(lhs.imag(), rhs.imag()), - lhs.real() * rhs.imag() + rhs.real() * lhs.imag() + cross(lhs.imag(), rhs.imag())}; -} - -inline -Quaternion operator/(const Quaternion& lhs, const Quaternion& rhs) -{ - return lhs * inverse(rhs); -} - -inline -Quaternion operator*(const scalar s, const Quaternion& q) -{ - return {s * q.real(), s * q.imag()}; -} - -inline -Quaternion operator*(const Quaternion& q, const scalar s) -{ - return {q.real() * s, q.imag() * s}; -} - -inline -Quaternion operator/(const Quaternion& q, const scalar s) -{ - return {q.real() / s, q.imag() / s}; -} - -inline -scalar norm(const Quaternion& q) -{ - return sqrt(pow(q.real(), 2) + dot(q.imag(), q.imag())); -} - -inline -Quaternion conjugate(const Quaternion& q) -{ - return {q.real(), -q.imag()}; -} - -inline -Quaternion inverse(const Quaternion& q) -{ - return conjugate(q) / pow(norm(q), 2); -} - -inline -Quaternion normalize(const Quaternion& q) -{ - return q / norm(q); -} - -inline -vec3 rotate(const vec3& point, const vec3& axis, const scalar& angle) -{ - Quaternion p {point}; - Quaternion q {normalize(axis), angle}; - return (q * p * inverse(q)).imag(); -} - -// Aliases - -using quat = Quaternion; - +#pragma once + +#include +#include + +namespace hpr +{ + +// Forward declaration + +class Quaternion; + +inline +Quaternion inverse(const Quaternion& q); + +inline +Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs); + +// Class declaration +class Quaternion +{ + +public: + + enum RotationSequence + { + ZYX, ZYZ, ZXY, ZXZ, YXZ, YXY, YZX, YZY, XYZ, XYX, XZY, XZX + }; + +protected: + + scalar p_real; + vec3 p_imag; + +public: + + inline + Quaternion() : + p_real{}, + p_imag{} + {} + + inline + Quaternion(const scalar real, const vec3& imag) : + p_real {real}, + p_imag {imag} + {} + + inline explicit + Quaternion(const scalar real) : + p_real {real}, + p_imag {} + {} + + inline explicit + Quaternion(const vec3& imag) : + p_real {}, + p_imag {imag} + {} + + inline + Quaternion(const vec3& vs, const scalar& theta) : + p_real {cos(0.5 * theta)}, + p_imag {sin(0.5 * theta) * vs / mag(vs)} + {} + + static inline + Quaternion unit(const vec3& vs) + { + return Quaternion(sqrt(1 - norm(vs)), vs); + } + + inline + Quaternion(const RotationSequence rs, const vec3& angles) + { + switch (rs) + { + case XYZ: + *this = Quaternion(vec3(0, 1, 0), angles[0]) * + Quaternion(vec3(0, 1, 0), angles[1]) * + Quaternion(vec3(0, 0, 1), angles[2]); + break; + + default: + throw std::runtime_error("Unknown rotation sequence"); + } + } + + inline + scalar real() const + { + return p_real; + } + + inline + scalar& real() + { + return p_real; + } + + inline + vec3 imag() const + { + return p_imag; + } + + inline + vec3& imag() + { + return p_imag; + } + + inline + scalar& operator[](Size n) + { + if (n > 3) + throw hpr::OutOfRange(); + if (n == 0) + return p_real; + else + return p_imag[n - 1]; + } + + inline + scalar operator[](Size n) const + { + if (n > 3) + throw hpr::OutOfRange(); + if (n == 0) + return p_real; + else + return p_imag[n - 1]; + } + + inline + void operator+=(const Quaternion& q) + { + p_real += q.p_real; + p_imag += q.p_imag; + } + + inline + void operator-=(const Quaternion& q) + { + p_real -= q.p_real; + p_imag -= q.p_imag; + } + + inline + void operator*=(const Quaternion& q) + { + scalar temp = p_real; + p_real = p_real * q.p_real - dot(p_imag, q.p_imag); + p_imag = temp * q.p_imag + q.p_real * p_imag + cross(p_imag, q.p_imag); + } + + inline + void operator/=(const Quaternion& q) + { + operator*=(inverse(q)); + } + + inline + void operator*=(const scalar s) + { + p_real *= s; + p_imag *= s; + } + + inline + void operator/=(const scalar s) + { + p_real /= s; + p_imag /= s; + } +}; + +inline +bool equal(const Quaternion& lhs, const Quaternion& rhs) +{ + return lhs.real() == rhs.real() && lhs.imag() == rhs.imag(); +} + +inline +bool operator==(const Quaternion& lhs, const Quaternion& rhs) +{ + return equal(lhs, rhs); +} + +inline +bool operator!=(const Quaternion& lhs, const Quaternion& rhs) +{ + return !equal(lhs, rhs); +} + +inline +Quaternion operator+(const Quaternion& lhs, const Quaternion& rhs) +{ + return {lhs.real() + rhs.real(), lhs.imag() + rhs.imag()}; +} + +inline +Quaternion operator-(const Quaternion& q) +{ + return {q.real(), q.imag()}; +} + +inline +Quaternion operator-(const Quaternion& lhs, const Quaternion& rhs) +{ + return {lhs.real() - rhs.real(), lhs.imag() - rhs.imag()}; +} + +inline +Quaternion operator*(const Quaternion& lhs, const Quaternion& rhs) +{ + return { + lhs.real() * rhs.real() - dot(lhs.imag(), rhs.imag()), + lhs.real() * rhs.imag() + rhs.real() * lhs.imag() + cross(lhs.imag(), rhs.imag()) + }; +} + +inline +Quaternion operator/(const Quaternion& lhs, const Quaternion& rhs) +{ + return lhs * inverse(rhs); +} + +inline +Quaternion operator*(const scalar s, const Quaternion& q) +{ + return {s * q.real(), s * q.imag()}; +} + +inline +Quaternion operator*(const Quaternion& q, const scalar s) +{ + return {q.real() * s, q.imag() * s}; +} + +inline +Quaternion operator/(const Quaternion& q, const scalar s) +{ + return {q.real() / s, q.imag() / s}; +} + +inline +scalar norm(const Quaternion& q) +{ + return sqrt(pow(q.real(), 2) + dot(q.imag(), q.imag())); +} + +inline +Quaternion conjugate(const Quaternion& q) +{ + return {q.real(), -q.imag()}; +} + +inline +Quaternion inverse(const Quaternion& q) +{ + return conjugate(q) / pow(norm(q), 2); +} + +inline +Quaternion normalize(const Quaternion& q) +{ + return q / norm(q); +} + +inline +vec3 rotate(const vec3& point, const vec3& axis, const scalar& angle) +{ + Quaternion p {point}; + Quaternion q {normalize(axis), angle}; + return (q * p * inverse(q)).imag(); +} + +void decompose(const Quaternion& q, vec3& axis, scalar& angle) +{ + const scalar qnorm = norm(q.imag()); + axis = q.imag() / qnorm; + angle = 2 * atan2(qnorm, q.real()); +} + + +// Aliases + +using quat = Quaternion; + } \ No newline at end of file diff --git a/source/hpr/math/scalar.hpp b/source/hpr/math/scalar.hpp index 1b8a4e1..a63eaba 100644 --- a/source/hpr/math/scalar.hpp +++ b/source/hpr/math/scalar.hpp @@ -1,3 +1,3 @@ -#pragma once - -#include "scalar/scalar.hpp" +#pragma once + +#include diff --git a/source/hpr/math/scalar/scalar.hpp b/source/hpr/math/scalar/scalar.hpp index 3583857..c9f39c5 100644 --- a/source/hpr/math/scalar/scalar.hpp +++ b/source/hpr/math/scalar/scalar.hpp @@ -2,6 +2,8 @@ #include #include +#include + namespace hpr { @@ -83,7 +85,7 @@ public: // properties -protected: +/*protected: static value_type s_precision; @@ -95,23 +97,44 @@ public: static constexpr Scalar inf() { return std::numeric_limits::infinity(); } - static constexpr Scalar epsilon() { return std::numeric_limits::epsilon(); } + static constexpr Scalar epsilon() { return std::numeric_limits::epsilon(); }*/ }; // specialization type +#if defined(HPR_SCALAR_IMPLEMENTAION) #if defined(HPR_SCALAR_LONGDOUBLE) + using scalar_type = long double; using scalar = Scalar; #elif defined(HPR_SCALAR_DOUBLE) + using scalar_type = double; using scalar = Scalar; #elif defined(HPR_SCALAR_FLOAT) + using scalar_type = float; using scalar = Scalar; #else + using scalar_type = double; using scalar = Scalar; #endif +#else +#if defined(HPR_SCALAR_LONGDOUBLE) + using scalar_type = long double; + using scalar = long double; +#elif defined(HPR_SCALAR_DOUBLE) + using scalar_type = double; + using scalar = double; +#elif defined(HPR_SCALAR_FLOAT) + using scalar_type = float; + using scalar = float; +#else + using scalar_type = float; + using scalar = float; +#endif +#endif // +#if defined(HPR_SCALAR_IMPLEMENTATION) template<> scalar::value_type scalar::s_precision = static_cast(1e-15); // global operators @@ -141,6 +164,8 @@ constexpr bool operator<(const scalar& lhs, const scalar& rhs) { return lhs.valu constexpr bool operator>=(const scalar& lhs, const scalar& rhs) { return lhs.value() >= rhs.value(); } constexpr bool operator<=(const scalar& lhs, const scalar& rhs) { return lhs.value() <= rhs.value(); } +//std::ostream& operator<<(std::ostream& stream, const scalar& s) { return stream << s.value(); } + /// scalar vs Scalar template constexpr scalar& operator+=(scalar& lhs, const Scalar& rhs) { lhs.value() += static_cast(rhs.value()); return lhs; } @@ -215,67 +240,103 @@ template constexpr bool operator>=(const T& lhs, const scalar& rhs) { template constexpr bool operator<=(const scalar& lhs, const T& rhs) { return lhs.value() <= static_cast(rhs); } template constexpr bool operator<=(const T& lhs, const scalar& rhs) { return static_cast(lhs) <= rhs.value(); } +#endif + // transcendentals -template constexpr scalar cos(const T& s) { return std::cos(static_cast(s));} +template constexpr scalar cos(const T& s) { return std::cos(static_cast(s));} -template constexpr scalar acos(const T& s) { return std::acos(scalar(s).value()); } +template constexpr scalar acos(const T& s) { return std::acos(static_cast(s)); } -template constexpr scalar cosh(const T& s) { return std::cosh(scalar(s).value()); } +template constexpr scalar cosh(const T& s) { return std::cosh(static_cast(s)); } -template constexpr scalar acosh(const T& s) { return std::acosh(scalar(s).value()); } +template constexpr scalar acosh(const T& s) { return std::acosh(static_cast(s)); } -template constexpr scalar sin(const T& s) { return std::sin(scalar(s).value()); } +template constexpr scalar sin(const T& s) { return std::sin(static_cast(s)); } -template constexpr scalar asin(const T& s) { return std::asin(scalar(s).value()); } +template constexpr scalar asin(const T& s) { return std::asin(static_cast(s)); } -template constexpr scalar sinh(const T& s) { return std::sinh(scalar(s).value()); } +template constexpr scalar sinh(const T& s) { return std::sinh(static_cast(s)); } -template constexpr scalar asinh(const T& s) { return std::asinh(scalar(s).value()); } +template constexpr scalar asinh(const T& s) { return std::asinh(static_cast(s)); } -template constexpr scalar tan(const T& s) { return std::tan(scalar(s).value()); } +template constexpr scalar tan(const T& s) { return std::tan(static_cast(s)); } -template constexpr scalar atan(const T& s) { return std::atan(scalar(s).value()); } +template constexpr scalar atan(const T& s) { return std::atan(static_cast(s)); } -template constexpr scalar tanh(const T& s) { return std::tanh(scalar(s).value()); } +template constexpr scalar atan2(const T& s, const X& s2) { return std::atan2(static_cast(s), static_cast(s2)); } -template constexpr scalar atanh(const T& s) { return std::atanh(scalar(s).value()); } +template constexpr scalar tanh(const T& s) { return std::tanh(static_cast(s)); } -template constexpr scalar exp(const T& s) { return std::exp(scalar(s).value()); } +template constexpr scalar atanh(const T& s) { return std::atanh(static_cast(s)); } -template constexpr scalar log(const T& s) { return std::log(scalar(s).value()); } +template constexpr scalar exp(const T& s) { return std::exp(static_cast(s)); } -template constexpr scalar log10(const T& s) { return std::log10(scalar(s).value()); } +template constexpr scalar log(const T& s) { return std::log(static_cast(s)); } -template constexpr scalar pow(const T& s, const X& d) { return std::pow(scalar(s).value(), scalar(d).value()); } +template constexpr scalar log10(const T& s) { return std::log10(static_cast(s)); } -template constexpr scalar sqrt(const T& s) { return std::sqrt(scalar(s).value()); } +template constexpr scalar pow(const T& s, const X& d) { return std::pow(static_cast(s), static_cast(d)); } -template constexpr scalar isqrt(const T& s) { return static_cast(1) / sqrt(scalar(s).value()); } +template constexpr scalar sqrt(const T& s) { return std::sqrt(static_cast(s)); } + +template constexpr scalar isqrt(const T& s) { return static_cast(1) / sqrt(static_cast(s)); } // constants -constexpr inline scalar pi() { return std::numbers::pi_v; } +constexpr scalar pi() { return std::numbers::pi_v; } -constexpr inline scalar e() { return std::numbers::e_v; } +constexpr scalar e() { return std::numbers::e_v; } // etc -constexpr scalar abs(const scalar& s) { return std::abs(s.value()); } +static float _scalar_float_precision = 1e-15f; +static double _scalar_double_precision = 1e-15; +static long double _scalar_long_double_precision = 1e-15l; -constexpr scalar mag(const scalar& s) { return std::abs(s.value()); } +template inline void precision(const T& precision) +{ + if constexpr (std::is_same::value) + _scalar_float_precision = precision; + else if constexpr (std::is_same::value) + _scalar_double_precision = precision; + else if constexpr (std::is_same::value) + _scalar_long_double_precision = precision; +} -constexpr bool equal(const scalar& lhs, const scalar& rhs, const scalar& precision = scalar::precision()) { return abs(lhs - rhs) < precision; } +template inline T precision() +{ + if constexpr (std::is_same::value) + return _scalar_float_precision; + else if constexpr (std::is_same::value) + return _scalar_double_precision; + else if constexpr (std::is_same::value) + return _scalar_long_double_precision; +} + + + +constexpr scalar inf() { return std::numeric_limits::infinity(); } + +constexpr scalar epsilon() { return std::numeric_limits::epsilon(); } + +constexpr scalar isnan(const scalar& s) { return std::isnan(static_cast(s)); } + +constexpr scalar abs(const scalar& s) { return std::abs(static_cast(s)); } + +constexpr scalar mag(const scalar& s) { return std::abs(static_cast(s)); } + +constexpr bool equal(const scalar& lhs, const scalar& rhs, const scalar& precision = hpr::precision()) { return abs(lhs - rhs) < precision; } //! Convert degrees to radians -constexpr scalar rad(const scalar& s) { return s * pi() / static_cast(180); } +constexpr scalar rad(const scalar& s) { return s * pi() / static_cast(180); } //! Convert radians to degrees -constexpr scalar deg(const scalar& s) { return s * static_cast(180) / pi(); } +constexpr scalar deg(const scalar& s) { return s * static_cast(180) / pi(); } -constexpr scalar min(const scalar& s1, const scalar& s2) { return std::min(s1.value(),s2.value());} +constexpr scalar min(const scalar& s1, const scalar& s2) { return std::min(static_cast(s1), static_cast(s2));} -constexpr scalar max(const scalar& s1, const scalar& s2) { return std::max(s1.value(), s2.value()); } +constexpr scalar max(const scalar& s1, const scalar& s2) { return std::max(static_cast(s1), static_cast(s2)); } constexpr scalar clip(const scalar& s, const scalar& sMin, const scalar& sMax) { return min(sMax, max(s, sMin)); } diff --git a/source/hpr/math/tests/CMakeLists.txt b/source/hpr/math/tests/CMakeLists.txt deleted file mode 100644 index 1644c07..0000000 --- a/source/hpr/math/tests/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -file(GLOB tests_cpp "*.cpp") - -add_executable(${PROJECT_NAME}-tests - ${tests_cpp} -) - -target_link_libraries(${PROJECT_NAME}-tests - PUBLIC - hpr::${PROJECT_NAME} - PRIVATE - GTest::gtest_main -) - -gtest_add_tests(TARGET ${PROJECT_NAME}-tests) diff --git a/source/hpr/math/tests/math-test.cpp b/source/hpr/math/tests/math-test.cpp index 26e8df8..3d7083c 100644 --- a/source/hpr/math/tests/math-test.cpp +++ b/source/hpr/math/tests/math-test.cpp @@ -1,22 +1,25 @@ #include -#include "../vector.hpp" -#include "../matrix.hpp" -#include "../quaternion.hpp" +#include +#include +#include + #include + TEST(math, Scalar) { EXPECT_EQ(hpr::scalar(5) + hpr::scalar(7), hpr::scalar(12)); EXPECT_TRUE(std::is_floating_point_v>); EXPECT_TRUE(std::is_arithmetic_v>); - EXPECT_EQ(5.f, hpr::Scalar(5)); + //EXPECT_EQ(5.f, hpr::Scalar(5)); EXPECT_EQ(hpr::rad(180), hpr::pi()); EXPECT_EQ(hpr::deg(hpr::pi()), 180); EXPECT_EQ(hpr::cos(0), 1); EXPECT_EQ(hpr::sin(0), 0); EXPECT_EQ(hpr::abs(hpr::scalar(-1)), 1); EXPECT_EQ(hpr::pow(2, 2), 4); + EXPECT_EQ(hpr::precision(), static_cast(1e-15)); EXPECT_TRUE(typeid(static_cast(hpr::scalar(5))) == typeid(float)); EXPECT_FALSE(!hpr::scalar(-1.)); @@ -87,4 +90,5 @@ TEST(math, Quaternion) hpr::quat q; hpr::vec3 np = hpr::rotate(hpr::vec3(0, 1, 0), {1, 0, 0}, hpr::pi() * 0.5); EXPECT_TRUE(hpr::all(hpr::equal(np, hpr::vec3(0, 0, 1)))); + EXPECT_EQ(hpr::norm(hpr::quat(np)), 1); } \ No newline at end of file diff --git a/source/hpr/math/vector.hpp b/source/hpr/math/vector.hpp index 2f33a32..dc94473 100644 --- a/source/hpr/math/vector.hpp +++ b/source/hpr/math/vector.hpp @@ -1,4 +1,4 @@ #pragma once -#include "vector/vector_space.hpp" +#include diff --git a/source/hpr/math/vector/vector_space.hpp b/source/hpr/math/vector/vector.hpp similarity index 95% rename from source/hpr/math/vector/vector_space.hpp rename to source/hpr/math/vector/vector.hpp index fe37183..1dc1314 100644 --- a/source/hpr/math/vector/vector_space.hpp +++ b/source/hpr/math/vector/vector.hpp @@ -1,328 +1,328 @@ -#pragma once - -#include "../integer.hpp" -#include "../scalar.hpp" -#include "../../containers/array/static_array.hpp" - - -namespace hpr -{ - -// forward declarations - -template requires (S >= 0) -class Vector; - -template -using SubVector = typename std::conditional= 2, Vector, Vector>::type; - -// type traits - -template -struct is_vector : public std::false_type {}; - -template -struct is_vector> : public std::true_type {}; - -// concepts - -template -concept IsVector = is_vector::value; - -} - -namespace hpr -{ - -template requires (S >= 0) -class Vector : public StaticArray -{ - - using base = StaticArray; - -public: - - using value_type = Type; - using size_type = Size; - using pointer = Type*; - using reference = Type&; - using iterator = Iterator; - using const_iterator = Iterator; - -public: - - //! null constructor - constexpr - Vector() : - base {} - {} - - //! copy constructor - constexpr - Vector(const Vector& vs) : - base {static_cast(vs)} - {} - - //! move constructor - constexpr - Vector(Vector&& vs) noexcept : - base {std::forward(static_cast(vs))} - {} - - //! copy assignment operator - constexpr - Vector& operator=(const Vector& vs) - { - base::operator=(vs); - return *this; - } - - //! move assignment operator - constexpr - Vector& operator=(Vector&& vs) noexcept - { - swap(*this, vs); - return *this; - } - - //! destructor - virtual - ~Vector() = default; - - //! copy constructor from base - constexpr - Vector(const base& arr) : - base {arr} - {} - - //! move constructor from base - constexpr - Vector(base&& arr) : - base {std::forward(arr)} - {} - - //! construct from iterators - constexpr - Vector(typename base::iterator start, typename base::iterator end) : - base {start, end} - {} - - //! construct from constant iterators - constexpr - Vector(typename base::const_iterator start, typename base::const_iterator end) : - base {start, end} - {} - - //! construct from initializer list - constexpr - Vector(std::initializer_list list) : - base {list} - {} - - //! copy constructor with variadic args - template - constexpr - Vector(const value_type& v, const Args& ...args) requires (S == 1 + sizeof...(args)): - base {v, static_cast(args)...} - {} - - //! move constructor with variadic args - template - constexpr - Vector(value_type&& v, Args&& ...args) requires (S == 1 + sizeof...(args)): - base {v, static_cast(std::forward(args))...} - {} - - //! copy constructor with sub vector and value - constexpr - Vector(const SubVector& svs, const value_type& v) requires (S >= 1): - base {} - { - for (auto n = 0; n < svs.size(); ++n) - (*this)[n] = svs[n]; - (*this)[svs.size()] = v; - } - - //! copy constructor from greater vector - template requires (GS > S) - constexpr explicit - Vector(const Vector& vs) : - base {vs.begin(), vs.begin() + S} - {} - -}; - -// global operators - -template inline Vector operator+(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = lhs[n]; return vs; } -template inline Vector operator-(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = -lhs[n]; return vs; } - -template inline Vector& operator+=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs[n]; return lhs; } -template inline Vector& operator-=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs[n]; return lhs; } -template inline Vector& operator*=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs[n]; return lhs; } -template inline Vector& operator/=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs[n]; return lhs; } - -template inline Vector operator+(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs[n]; return vs; } -template inline Vector operator-(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs[n]; return vs; } -template inline Vector operator*(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs[n]; return vs; } -template inline Vector operator/(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs[n]; return vs; } - -template inline bool operator==(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] != rhs[n]) return false; return true; } -template inline bool operator!=(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] == rhs[n]) return false; return true; } - - -template inline Vector& operator+=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs; return lhs; } -template inline Vector& operator-=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs; return lhs; } -template inline Vector& operator*=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs; return lhs; } -template inline Vector& operator/=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs; return lhs; } - -template inline Vector operator+(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs; return vs; } -template inline Vector operator-(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs; return vs; } -template inline Vector operator*(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs; return vs; } -template inline Vector operator/(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs; return vs; } - -template inline Vector operator+(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] += lhs; return vs; } -template inline Vector operator-(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] -= lhs; return vs; } -template inline Vector operator*(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] *= lhs; return vs; } -template inline Vector operator/(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] /= lhs; return vs; } - -// boolean operations - -template -inline -Vector equal(const Vector& lhs, const Vector& rhs, const scalar& precision = scalar::precision()) -{ - Vector vs; - for (auto n = 0; n < S; ++n) - vs[n] = equal(lhs[n], rhs[n], precision); - return vs; -} - -template -inline -bool any(const Vector& vs) -{ - bool res = false; - for (auto e : vs) - res = res || e; - return res; -} - -template -inline -bool all(const Vector& vs) -{ - bool res = true; - for (auto e : vs) - res = res && e; - return res; -} - -// per element operations - -template -inline -Vector abs(const Vector& vs) -{ - Vector res; - for (auto n = 0; n < S; ++n) - res[n] = abs(vs[n]); - return res; -} - -template -inline -Type sum(const Vector& vs) -{ - Type sum {}; - for (const Type& v : vs) - sum += v; - return sum; -} - -template -inline -Vector pow(const Vector& vs, scalar degree) -{ - Vector res; - for (auto n = 0; n < S; ++n) - res[n] = pow(vs[n], degree); - return res; -} - -// vector operations - -template -inline -Type norm(const Vector& vs) -{ - return sqrt(sum(pow(abs(vs), 2))); -} - -template -inline -Type dot(const Vector& lhs, const Vector& rhs) -{ - return sum(lhs * rhs); -} - -template -inline -Type length(const Vector& vs) -{ - return sqrt(dot(vs, vs)); -} - -template -inline -Type mag(const Vector& vs) -{ - return length(vs); -} - -template -inline -Type distance(const Vector& vs1, const Vector& vs2) -{ - return length(vs1 - vs2); -} - -template -inline -Vector normalize(const Vector& vs) -{ - return vs * isqrt(dot(vs, vs)); -} - -template -inline -Type angle(const Vector& lhs, const Vector& rhs) -{ - scalar cos = dot(lhs, rhs) / (norm(lhs) * norm(rhs)); - return acos(cos); //clip(cos, -1., 1.)); -} - -// vector 3 operations - -template -inline -Vector cross(const Vector& lhs, const Vector& rhs) -{ - return Vector( - lhs[1] * rhs[2] - lhs[2] * rhs[1], - lhs[2] * rhs[0] - lhs[0] * rhs[2], - lhs[0] * rhs[1] - lhs[1] * rhs[0] - ); -} - - -// aliases - -template -using vec = Vector; - -using vec2 = Vector; -using vec3 = Vector; -using vec4 = Vector; - -} +#pragma once + +#include +#include +#include + + +namespace hpr +{ + +// forward declarations + +template requires (S >= 0) +class Vector; + +template +using SubVector = typename std::conditional= 2, Vector, Vector>::type; + +// type traits + +template +struct is_vector : public std::false_type {}; + +template +struct is_vector> : public std::true_type {}; + +// concepts + +template +concept IsVector = is_vector::value; + +} + +namespace hpr +{ + +template requires (S >= 0) +class Vector : public StaticArray +{ + + using base = StaticArray; + +public: + + using value_type = Type; + using size_type = Size; + using pointer = Type*; + using reference = Type&; + using iterator = Iterator; + using const_iterator = Iterator; + +public: + + //! null constructor + constexpr + Vector() : + base {} + {} + + //! copy constructor + constexpr + Vector(const Vector& vs) : + base {static_cast(vs)} + {} + + //! move constructor + constexpr + Vector(Vector&& vs) noexcept : + base {std::forward(static_cast(vs))} + {} + + //! copy assignment operator + constexpr + Vector& operator=(const Vector& vs) + { + base::operator=(vs); + return *this; + } + + //! move assignment operator + constexpr + Vector& operator=(Vector&& vs) noexcept + { + swap(*this, vs); + return *this; + } + + //! destructor + virtual + ~Vector() = default; + + //! copy constructor from base + constexpr + Vector(const base& arr) : + base {arr} + {} + + //! move constructor from base + constexpr + Vector(base&& arr) : + base {std::forward(arr)} + {} + + //! construct from iterators + constexpr + Vector(typename base::iterator start, typename base::iterator end) : + base {start, end} + {} + + //! construct from constant iterators + constexpr + Vector(typename base::const_iterator start, typename base::const_iterator end) : + base {start, end} + {} + + //! construct from initializer list + constexpr + Vector(std::initializer_list list) : + base {list} + {} + + //! copy constructor with variadic args + template + constexpr + Vector(const value_type& v, const Args& ...args) requires (S == 1 + sizeof...(args)): + base {v, static_cast(args)...} + {} + + //! move constructor with variadic args + template + constexpr + Vector(value_type&& v, Args&& ...args) requires (S == 1 + sizeof...(args)): + base {v, static_cast(std::forward(args))...} + {} + + //! copy constructor with sub vector and value + constexpr + Vector(const SubVector& svs, const value_type& v) requires (S >= 1): + base {} + { + for (auto n = 0; n < svs.size(); ++n) + (*this)[n] = svs[n]; + (*this)[svs.size()] = v; + } + + //! copy constructor from greater vector + template requires (GS > S) + constexpr explicit + Vector(const Vector& vs) : + base {vs.begin(), vs.begin() + S} + {} + +}; + +// global operators + +template inline Vector operator+(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = lhs[n]; return vs; } +template inline Vector operator-(const Vector& lhs) { Vector vs; for (Size n = 0; n < S; ++n) vs[n] = -lhs[n]; return vs; } + +template inline Vector& operator+=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs[n]; return lhs; } +template inline Vector& operator-=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs[n]; return lhs; } +template inline Vector& operator*=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs[n]; return lhs; } +template inline Vector& operator/=(Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs[n]; return lhs; } + +template inline Vector operator+(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs[n]; return vs; } +template inline Vector operator-(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs[n]; return vs; } +template inline Vector operator*(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs[n]; return vs; } +template inline Vector operator/(const Vector& lhs, const Vector& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs[n]; return vs; } + +template inline bool operator==(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] != rhs[n]) return false; return true; } +template inline bool operator!=(const Vector& lhs, const Vector& rhs) { for (Size n = 0; n < S; ++n) if (lhs[n] == rhs[n]) return false; return true; } + + +template inline Vector& operator+=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] += rhs; return lhs; } +template inline Vector& operator-=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] -= rhs; return lhs; } +template inline Vector& operator*=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] *= rhs; return lhs; } +template inline Vector& operator/=(Vector& lhs, const T& rhs) { for (Size n = 0; n < S; ++n) lhs[n] /= rhs; return lhs; } + +template inline Vector operator+(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] += rhs; return vs; } +template inline Vector operator-(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] -= rhs; return vs; } +template inline Vector operator*(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] *= rhs; return vs; } +template inline Vector operator/(const Vector& lhs, const T& rhs) { Vector vs {lhs}; for (Size n = 0; n < S; ++n) vs[n] /= rhs; return vs; } + +template inline Vector operator+(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] += lhs; return vs; } +template inline Vector operator-(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] -= lhs; return vs; } +template inline Vector operator*(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] *= lhs; return vs; } +template inline Vector operator/(const T& lhs, const Vector& rhs) { Vector vs {rhs}; for (Size n = 0; n < S; ++n) vs[n] /= lhs; return vs; } + +// boolean operations + +template +inline +Vector equal(const Vector& lhs, const Vector& rhs, const scalar& precision = hpr::precision()) +{ + Vector vs; + for (auto n = 0; n < S; ++n) + vs[n] = equal(lhs[n], rhs[n], precision); + return vs; +} + +template +inline +bool any(const Vector& vs) +{ + bool res = false; + for (auto e : vs) + res = res || e; + return res; +} + +template +inline +bool all(const Vector& vs) +{ + bool res = true; + for (auto e : vs) + res = res && e; + return res; +} + +// per element operations + +template +inline +Vector abs(const Vector& vs) +{ + Vector res; + for (auto n = 0; n < S; ++n) + res[n] = abs(vs[n]); + return res; +} + +template +inline +Type sum(const Vector& vs) +{ + Type sum {}; + for (const Type& v : vs) + sum += v; + return sum; +} + +template +inline +Vector pow(const Vector& vs, scalar degree) +{ + Vector res; + for (auto n = 0; n < S; ++n) + res[n] = pow(vs[n], degree); + return res; +} + +// vector operations + +template +inline +Type norm(const Vector& vs) +{ + return sqrt(sum(pow(abs(vs), 2))); +} + +template +inline +Type dot(const Vector& lhs, const Vector& rhs) +{ + return sum(lhs * rhs); +} + +template +inline +Type length(const Vector& vs) +{ + return sqrt(dot(vs, vs)); +} + +template +inline +Type mag(const Vector& vs) +{ + return length(vs); +} + +template +inline +Type distance(const Vector& vs1, const Vector& vs2) +{ + return length(vs1 - vs2); +} + +template +inline +Vector normalize(const Vector& vs) +{ + return vs * isqrt(dot(vs, vs)); +} + +template +inline +Type angle(const Vector& lhs, const Vector& rhs) +{ + scalar cos = dot(lhs, rhs) / (norm(lhs) * norm(rhs)); + return acos(cos); //clip(cos, -1., 1.)); +} + +// vector 3 operations + +template +inline +Vector cross(const Vector& lhs, const Vector& rhs) +{ + return Vector( + lhs[1] * rhs[2] - lhs[2] * rhs[1], + lhs[2] * rhs[0] - lhs[0] * rhs[2], + lhs[0] * rhs[1] - lhs[1] * rhs[0] + ); +} + + +// aliases + +template +using vec = Vector; + +using vec2 = Vector; +using vec3 = Vector; +using vec4 = Vector; + +} diff --git a/source/hpr/math/vector/vector_space.cpp b/source/hpr/math/vector/vector_space.cpp deleted file mode 100644 index 56a2e66..0000000 --- a/source/hpr/math/vector/vector_space.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by L-Nafaryus on 10/17/2022. -// -#include "vector_space.hpp" \ No newline at end of file diff --git a/source/hpr/mesh.hpp b/source/hpr/mesh.hpp index 3b00b03..600fd1c 100644 --- a/source/hpr/mesh.hpp +++ b/source/hpr/mesh.hpp @@ -1,3 +1,3 @@ -#pragma once - -#include "mesh/mesh.hpp" \ No newline at end of file +#pragma once + +#include \ No newline at end of file diff --git a/source/hpr/mesh/CMakeLists.txt b/source/hpr/mesh/CMakeLists.txt index 021c16f..4ad5286 100644 --- a/source/hpr/mesh/CMakeLists.txt +++ b/source/hpr/mesh/CMakeLists.txt @@ -1,70 +1,29 @@ cmake_minimum_required(VERSION 3.16) project(mesh - VERSION "${HPR_PROJECT_VERSION}" + VERSION "${HPR_VERSION}" LANGUAGES CXX ) -add_library(${PROJECT_NAME}) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) +hpr_add_library(${PROJECT_NAME} STATIC) -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../mesh.hpp" "*.hpp" - ) +hpr_collect_interface(${PROJECT_NAME} + "../mesh.hpp" + "*.hpp" +) -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES - "*.cpp" - ) +hpr_collect_sources(${PROJECT_NAME} + "*.cpp" +) target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ - PRIVATE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES} - ) - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> + PRIVATE ${${PROJECT_NAME}_SOURCES} ) -if(HPR_TEST) - add_subdirectory(tests) -endif() +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) +hpr_tests(${PROJECT_NAME} tests) + diff --git a/source/hpr/mesh/cell.hpp b/source/hpr/mesh/cell.hpp index cc30687..026bdfa 100644 --- a/source/hpr/mesh/cell.hpp +++ b/source/hpr/mesh/cell.hpp @@ -1,38 +1,38 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar/scalar.hpp" -#include "../math/vector.hpp" - - -namespace hpr::mesh -{ - -class Face; - -class Cell : public darray -{ - - using face_pointer = Face*; - using base = darray; - -public: - - Cell() : - base {} - {} - - Cell(std::initializer_list faces) : - base{faces} - {} - - ~Cell() override = default; - - darray& faces() - { - return *this; - } - -}; - +#pragma once + +#include +#include +#include + + +namespace hpr::mesh +{ + +class Face; + +class Cell : public darray +{ + + using face_pointer = Face*; + using base = darray; + +public: + + Cell() : + base {} + {} + + Cell(std::initializer_list faces) : + base{faces} + {} + + ~Cell() override = default; + + darray& faces() + { + return *this; + } + +}; + } \ No newline at end of file diff --git a/source/hpr/mesh/edge.hpp b/source/hpr/mesh/edge.hpp index 36ca52c..4364d05 100644 --- a/source/hpr/mesh/edge.hpp +++ b/source/hpr/mesh/edge.hpp @@ -1,66 +1,66 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar/scalar.hpp" -#include "../math/vector.hpp" - - - -namespace hpr::mesh -{ - -class Vertex; -class Face; - -class Edge : public sarray -{ - friend class Mesh; - - using vertex_pointer = Vertex*; - using base = sarray; - -protected: - darray p_refFaces; - -public: - Edge() : - base{} - {} - - Edge(vertex_pointer v1, vertex_pointer v2) : - base{v1, v2} - {} - - ~Edge() override - { - for (auto& f: p_refFaces) - f = nullptr; - } - - darray& refFaces() - { - return p_refFaces; - } - - void addRefFace(Face* face) - { - p_refFaces.push(face); - } - - sarray& vertices() - { - return *this; - } - - vertex_pointer vertex(size_type n) - { - return (*this)[n]; - } - - bool isValid() - { - return *front() != *back(); - } -}; - +#pragma once + +#include +#include +#include + + + +namespace hpr::mesh +{ + +class Vertex; +class Face; + +class Edge : public sarray +{ + friend class Mesh; + + using vertex_pointer = Vertex*; + using base = sarray; + +protected: + darray p_refFaces; + +public: + Edge() : + base{} + {} + + Edge(vertex_pointer v1, vertex_pointer v2) : + base{v1, v2} + {} + + ~Edge() override + { + for (auto& f: p_refFaces) + f = nullptr; + } + + darray& refFaces() + { + return p_refFaces; + } + + void addRefFace(Face* face) + { + p_refFaces.push(face); + } + + sarray& vertices() + { + return *this; + } + + vertex_pointer vertex(size_type n) + { + return (*this)[n]; + } + + bool isValid() + { + return *front() != *back(); + } +}; + } \ No newline at end of file diff --git a/source/hpr/mesh/face.hpp b/source/hpr/mesh/face.hpp index b3eb833..8f3cb61 100644 --- a/source/hpr/mesh/face.hpp +++ b/source/hpr/mesh/face.hpp @@ -1,72 +1,72 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar/scalar.hpp" -#include "../math/vector.hpp" - - - -namespace hpr::mesh -{ - -class Vertex; -class Edge; -class Cell; - -class Face : public darray -{ - friend class Mesh; - - using edge_pointer = Edge*; - using vertex_pointer = Vertex*; - using base = darray; - -protected: - darray p_refCells; - -public: - Face() : - base{} - {} - - Face(std::initializer_list edges) : - base{edges} - {} - - ~Face() override - { - for (auto& c: p_refCells) - c = nullptr; - } - - darray& refCells() - { - return p_refCells; - } - - void addRefCell(Cell* cell) - { - p_refCells.push(cell); - } - - darray& edges() - { - return *this; - } - - edge_pointer edge(size_type n) - { - return (*this)[n]; - } - - darray vertices() - { - darray vertices_ {size(), nullptr}; - for (auto n = 0; n < size(); ++n) - vertices_[n] = edge(n)->vertex(0); - return vertices_; - } - -}; - +#pragma once + +#include +#include +#include + + + +namespace hpr::mesh +{ + +class Vertex; +class Edge; +class Cell; + +class Face : public darray +{ + friend class Mesh; + + using edge_pointer = Edge*; + using vertex_pointer = Vertex*; + using base = darray; + +protected: + darray p_refCells; + +public: + Face() : + base{} + {} + + Face(std::initializer_list edges) : + base{edges} + {} + + ~Face() override + { + for (auto& c: p_refCells) + c = nullptr; + } + + darray& refCells() + { + return p_refCells; + } + + void addRefCell(Cell* cell) + { + p_refCells.push(cell); + } + + darray& edges() + { + return *this; + } + + edge_pointer edge(size_type n) + { + return (*this)[n]; + } + + darray vertices() + { + darray vertices_ {size(), nullptr}; + for (auto n = 0; n < size(); ++n) + vertices_[n] = edge(n)->vertex(0); + return vertices_; + } + +}; + } \ No newline at end of file diff --git a/source/hpr/mesh/mesh.cpp b/source/hpr/mesh/mesh.cpp index 724b70e..e10b429 100644 --- a/source/hpr/mesh/mesh.cpp +++ b/source/hpr/mesh/mesh.cpp @@ -1 +1 @@ -#include "mesh.hpp" +#include diff --git a/source/hpr/mesh/mesh.hpp b/source/hpr/mesh/mesh.hpp index 13a5d02..3efb682 100644 --- a/source/hpr/mesh/mesh.hpp +++ b/source/hpr/mesh/mesh.hpp @@ -1,229 +1,229 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar/scalar.hpp" -#include "../math/vector.hpp" - -#include "vertex.hpp" -#include "edge.hpp" -#include "face.hpp" -#include "cell.hpp" - - -namespace hpr::mesh -{ - -class Mesh -{ - -public: - using size_type = std::size_t; - using vertex_pointer = Vertex*; - using edge_pointer = Edge*; - using face_pointer = Face*; - using cell_pointer = Cell*; - -protected: - darray p_vertices; - darray p_edges; - darray p_faces; - darray p_cells; - -public: - - Mesh() = default; - - Mesh(const Mesh&) = default; - - ~Mesh() - { - for (auto& v : p_vertices) - delete v; - for (auto& e : p_edges) - delete e; - for (auto& f : p_faces) - delete f; - for (auto& c : p_cells) - delete c; - } - - int indexOf(vertex_pointer v) - { - for (int n = 0; n < vertices().size(); ++n) - if (vertex(n) == v) - return n; - return -1; - } - - int indexOf(edge_pointer e) - { - for (int n = 0; n < edges().size(); ++n) - if (edge(n) == e) - return n; - return -1; - } - - int indexOf(face_pointer e) - { - for (int n = 0; n < faces().size(); ++n) - if (face(n) == e) - return n; - return -1; - } - - int indexOf(cell_pointer e) - { - for (int n = 0; n < cells().size(); ++n) - if (cell(n) == e) - return n; - return -1; - } - - darray& vertices() - { - return p_vertices; - } - - [[nodiscard]] - vertex_pointer vertex(size_type n) const - { - return p_vertices[n]; - } - - void addVertex(const scalar& x, const scalar& y, const scalar& z) - { - p_vertices.push(new Vertex(x, y, z)); - } - - void removeNullVertices() - { - vertices().remove([](vertex_pointer vertex){ return vertex == nullptr; }); - } - - void removeVertex(size_type n, bool erase = true, bool cascade = true) - { - if (cascade) - { - for (auto &refEdge: vertex(n)->refEdges()) - removeEdge(indexOf(refEdge), false); - removeNullEdges(); - } - delete vertex(n); - if (erase) - vertices().remove(n); - } - - darray& edges() - { - return p_edges; - } - - [[nodiscard]] - edge_pointer edge(size_type n) const - { - return p_edges[n]; - } - - void addEdge(vertex_pointer v1, vertex_pointer v2) - { - edges().push(new Edge {v1, v2}); - v1->addRefEdge(edges().back()); - v2->addRefEdge(edges().back()); - } - - void removeNullEdges() - { - edges().remove([](edge_pointer edge){ return edge == nullptr; }); - } - - void removeEdge(size_type n, bool erase = true, bool cascade = true) - { - if (cascade) - { - for (auto &refFace: edge(n)->refFaces()) - removeFace(indexOf(refFace), false); - removeNullFaces(); - } - for (auto& vertex : edge(n)->vertices()) - vertex->refEdges().remove([this, n](edge_pointer e){ return e == edge(n); }); - delete edge(n); - if (erase) - edges().remove(n); - } - - darray& faces() - { - return p_faces; - } - - [[nodiscard]] - face_pointer face(size_type n) const - { - return p_faces[n]; - } - - template ... Edges> - void addFace(const Edges& ...edges) - { - faces().push(new Face {static_cast(edges)...}); - for (auto& edge : *faces().back()) - edge->addRefFace(faces().back()); - } - - void removeNullFaces() - { - faces().remove([](face_pointer face){ return face == nullptr; }); - } - - void removeFace(size_type n, bool erase = true, bool cascade = true) - { - if (cascade) - { - for (auto &refCell: face(n)->refCells()) - removeCell(indexOf(refCell), false); - removeNullFaces(); - } - for (auto& edge : face(n)->edges()) - edge->refFaces().remove([this, n](face_pointer f){ return f == face(n); }); - delete face(n); - if (erase) - faces().remove(n); - } - - darray& cells() - { - return p_cells; - } - - [[nodiscard]] - cell_pointer cell(size_type n) const - { - return p_cells[n]; - } - - template ... Faces> - void addCell(const Faces& ...faces) - { - cells().push(new Cell {static_cast(faces)...}); - for (auto& face : *cells().back()) - face->addRefCell(cells().back()); - } - - void removeNullCells() - { - cells().remove([](cell_pointer cell){ return cell == nullptr; }); - } - - void removeCell(size_type n, bool erase = true, bool cascade = true) - { - static_cast(cascade); - for (auto& face : cell(n)->faces()) - face->refCells().remove([this, n](cell_pointer c){ return c == cell(n); }); - delete cell(n); - if (erase) - cells().remove(n); - } - -}; - +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + + +namespace hpr::mesh +{ + +class Mesh +{ + +public: + using size_type = std::size_t; + using vertex_pointer = Vertex*; + using edge_pointer = Edge*; + using face_pointer = Face*; + using cell_pointer = Cell*; + +protected: + darray p_vertices; + darray p_edges; + darray p_faces; + darray p_cells; + +public: + + Mesh() = default; + + Mesh(const Mesh&) = default; + + ~Mesh() + { + for (auto& v : p_vertices) + delete v; + for (auto& e : p_edges) + delete e; + for (auto& f : p_faces) + delete f; + for (auto& c : p_cells) + delete c; + } + + int indexOf(vertex_pointer v) + { + for (int n = 0; n < vertices().size(); ++n) + if (vertex(n) == v) + return n; + return -1; + } + + int indexOf(edge_pointer e) + { + for (int n = 0; n < edges().size(); ++n) + if (edge(n) == e) + return n; + return -1; + } + + int indexOf(face_pointer e) + { + for (int n = 0; n < faces().size(); ++n) + if (face(n) == e) + return n; + return -1; + } + + int indexOf(cell_pointer e) + { + for (int n = 0; n < cells().size(); ++n) + if (cell(n) == e) + return n; + return -1; + } + + darray& vertices() + { + return p_vertices; + } + + [[nodiscard]] + vertex_pointer vertex(size_type n) const + { + return p_vertices[n]; + } + + void addVertex(const scalar& x, const scalar& y, const scalar& z) + { + p_vertices.push(new Vertex(x, y, z)); + } + + void removeNullVertices() + { + vertices().remove([](vertex_pointer vertex){ return vertex == nullptr; }); + } + + void removeVertex(size_type n, bool erase = true, bool cascade = true) + { + if (cascade) + { + for (auto &refEdge: vertex(n)->refEdges()) + removeEdge(indexOf(refEdge), false); + removeNullEdges(); + } + delete vertex(n); + if (erase) + vertices().remove(n); + } + + darray& edges() + { + return p_edges; + } + + [[nodiscard]] + edge_pointer edge(size_type n) const + { + return p_edges[n]; + } + + void addEdge(vertex_pointer v1, vertex_pointer v2) + { + edges().push(new Edge {v1, v2}); + v1->addRefEdge(edges().back()); + v2->addRefEdge(edges().back()); + } + + void removeNullEdges() + { + edges().remove([](edge_pointer edge){ return edge == nullptr; }); + } + + void removeEdge(size_type n, bool erase = true, bool cascade = true) + { + if (cascade) + { + for (auto &refFace: edge(n)->refFaces()) + removeFace(indexOf(refFace), false); + removeNullFaces(); + } + for (auto& vertex : edge(n)->vertices()) + vertex->refEdges().remove([this, n](edge_pointer e){ return e == edge(n); }); + delete edge(n); + if (erase) + edges().remove(n); + } + + darray& faces() + { + return p_faces; + } + + [[nodiscard]] + face_pointer face(size_type n) const + { + return p_faces[n]; + } + + template ... Edges> + void addFace(const Edges& ...edges) + { + faces().push(new Face {static_cast(edges)...}); + for (auto& edge : *faces().back()) + edge->addRefFace(faces().back()); + } + + void removeNullFaces() + { + faces().remove([](face_pointer face){ return face == nullptr; }); + } + + void removeFace(size_type n, bool erase = true, bool cascade = true) + { + if (cascade) + { + for (auto &refCell: face(n)->refCells()) + removeCell(indexOf(refCell), false); + removeNullFaces(); + } + for (auto& edge : face(n)->edges()) + edge->refFaces().remove([this, n](face_pointer f){ return f == face(n); }); + delete face(n); + if (erase) + faces().remove(n); + } + + darray& cells() + { + return p_cells; + } + + [[nodiscard]] + cell_pointer cell(size_type n) const + { + return p_cells[n]; + } + + template ... Faces> + void addCell(const Faces& ...faces) + { + cells().push(new Cell {static_cast(faces)...}); + for (auto& face : *cells().back()) + face->addRefCell(cells().back()); + } + + void removeNullCells() + { + cells().remove([](cell_pointer cell){ return cell == nullptr; }); + } + + void removeCell(size_type n, bool erase = true, bool cascade = true) + { + static_cast(cascade); + for (auto& face : cell(n)->faces()) + face->refCells().remove([this, n](cell_pointer c){ return c == cell(n); }); + delete cell(n); + if (erase) + cells().remove(n); + } + +}; + } \ No newline at end of file diff --git a/source/hpr/mesh/tests/CMakeLists.txt b/source/hpr/mesh/tests/CMakeLists.txt deleted file mode 100644 index 1644c07..0000000 --- a/source/hpr/mesh/tests/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -file(GLOB tests_cpp "*.cpp") - -add_executable(${PROJECT_NAME}-tests - ${tests_cpp} -) - -target_link_libraries(${PROJECT_NAME}-tests - PUBLIC - hpr::${PROJECT_NAME} - PRIVATE - GTest::gtest_main -) - -gtest_add_tests(TARGET ${PROJECT_NAME}-tests) diff --git a/source/hpr/mesh/tests/hmesh-test.cpp b/source/hpr/mesh/tests/hmesh-test.cpp index 4afaf49..45dfd40 100644 --- a/source/hpr/mesh/tests/hmesh-test.cpp +++ b/source/hpr/mesh/tests/hmesh-test.cpp @@ -1,5 +1,5 @@ #include -#include "../mesh.hpp" +#include TEST(hmeshTest, Mesh) { diff --git a/source/hpr/mesh/vertex.hpp b/source/hpr/mesh/vertex.hpp index e5d3611..ec136ad 100644 --- a/source/hpr/mesh/vertex.hpp +++ b/source/hpr/mesh/vertex.hpp @@ -1,50 +1,50 @@ -#pragma once - -#include "../containers/array.hpp" -#include "../math/scalar/scalar.hpp" -#include "../math/vector.hpp" - - - -namespace hpr::mesh -{ - -class Edge; - -class Vertex : public vec -{ - friend class Mesh; - - using base = vec; - -protected: - darray p_refEdges; - -public: - Vertex() : - base{} - {} - - Vertex(const scalar& x, const scalar& y, const scalar& z) : - base{x, y, z} - {} - - ~Vertex() override - { - for (auto& e: p_refEdges) - e = nullptr; - } - - darray& refEdges() - { - return p_refEdges; - } - - void addRefEdge(Edge* edge) - { - p_refEdges.push(edge); - } - -}; - +#pragma once + +#include +#include +#include + + + +namespace hpr::mesh +{ + +class Edge; + +class Vertex : public vec +{ + friend class Mesh; + + using base = vec; + +protected: + darray p_refEdges; + +public: + Vertex() : + base{} + {} + + Vertex(const scalar& x, const scalar& y, const scalar& z) : + base{x, y, z} + {} + + ~Vertex() override + { + for (auto& e: p_refEdges) + e = nullptr; + } + + darray& refEdges() + { + return p_refEdges; + } + + void addRefEdge(Edge* edge) + { + p_refEdges.push(edge); + } + +}; + } \ No newline at end of file diff --git a/source/hpr/parallel.hpp b/source/hpr/parallel.hpp new file mode 100644 index 0000000..5b51fcc --- /dev/null +++ b/source/hpr/parallel.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/source/hpr/parallel/CMakeLists.txt b/source/hpr/parallel/CMakeLists.txt new file mode 100644 index 0000000..3db2206 --- /dev/null +++ b/source/hpr/parallel/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.16) + +project(parallel + VERSION "${HPR_VERSION}" + LANGUAGES CXX +) + +hpr_add_library(${PROJECT_NAME} INTERFACE) + +hpr_collect_interface(${PROJECT_NAME} + "../parallel.hpp" + "*.hpp" +) + +target_sources(${PROJECT_NAME} + INTERFACE ${${PROJECT_NAME}_HEADERS_INTERFACE} ${HPR_INSTALL_INTERFACE}/${PROJECT_NAME}> +) + +target_link_libraries(${PROJECT_NAME} + INTERFACE + tbb +) + +hpr_install(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}) diff --git a/source/hpr/parallel/parallel.hpp b/source/hpr/parallel/parallel.hpp new file mode 100644 index 0000000..d859456 --- /dev/null +++ b/source/hpr/parallel/parallel.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + + +template diff --git a/source/hpr/window_system.hpp b/source/hpr/window_system.hpp deleted file mode 100644 index 9ee48f5..0000000 --- a/source/hpr/window_system.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - - -#include "window_system/monitor.hpp" -#include "window_system/window_context.hpp" -#include "window_system/window.hpp" -#include "window_system/window_system.hpp" - -#include "window_system/glfw/monitor.hpp" -#include "window_system/glfw/window.hpp" -#include "window_system/glfw/window_system.hpp" diff --git a/source/hpr/window_system/CMakeLists.txt b/source/hpr/window_system/CMakeLists.txt deleted file mode 100644 index 07acbae..0000000 --- a/source/hpr/window_system/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(window-system - VERSION "${HPR_PROJECT_VERSION}" - LANGUAGES CXX -) - -add_library(${PROJECT_NAME}) -add_library(${CMAKE_PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -add_module(${PROJECT_NAME}) - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS - "../window_system.hpp" "*.hpp" "glfw/*.hpp" -) - -foreach(_header_path ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS}) - list(APPEND ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE "$") -endforeach() - -file(GLOB ${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES - "*.cpp" "glfw/*.cpp" -) - -target_sources(${PROJECT_NAME} - INTERFACE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_HEADERS_INTERFACE} - $ - PRIVATE - ${${CMAKE_PROJECT_NAME}_${PROJECT_NAME}_SOURCES} -) - -target_link_libraries(${PROJECT_NAME} - glfw -) - - -install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}Targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_SKIP - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - EXPORT ${PROJECT_NAME}Targets - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}-${HPR_PROJECT_VERSION} - NAMESPACE ${CMAKE_PROJECT_NAME}:: -) -install( - TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME} - NAMELINK_ONLY - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install( - DIRECTORY ${PROJECT_SOURCE_DIR} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel - FILES_MATCHING - PATTERN "*.h" - PATTERN "*.hpp" - PATTERN "tests" EXCLUDE -) -install( - FILES ../${PROJECT_NAME}.hpp - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} - COMPONENT devel -) diff --git a/source/hpr/window_system/glfw/monitor.cpp b/source/hpr/window_system/glfw/monitor.cpp deleted file mode 100644 index e87002b..0000000 --- a/source/hpr/window_system/glfw/monitor.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "monitor.hpp" - - -namespace hpr::gpu::glfw -{ - -Monitor::Monitor() : - gpu::Monitor {Provider::GLFW}, - p_instance {nullptr} -{} - -Monitor::~Monitor() = default; - -} \ No newline at end of file diff --git a/source/hpr/window_system/glfw/monitor.hpp b/source/hpr/window_system/glfw/monitor.hpp deleted file mode 100644 index cb70949..0000000 --- a/source/hpr/window_system/glfw/monitor.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "../monitor.hpp" - -#include - - -namespace hpr::gpu::glfw -{ - -class Monitor : public gpu::Monitor -{ - friend class WindowSystem; - friend class Window; - -protected: - - GLFWmonitor* p_instance; - -public: - - Monitor(); - - ~Monitor(); - -}; - -} \ No newline at end of file diff --git a/source/hpr/window_system/glfw/window.cpp b/source/hpr/window_system/glfw/window.cpp deleted file mode 100644 index 156c770..0000000 --- a/source/hpr/window_system/glfw/window.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "window.hpp" -#include "monitor.hpp" - -#include - - -namespace hpr::gpu::glfw -{ - -Window::Window() : - gpu::Window {Provider::GLFW}, - p_instance {nullptr} -{} - -Window::~Window() = default; - -void Window::init(const std::string& title, Style style, int x, int y, int width, int height, gpu::Window* parent, gpu::Monitor* monitor) -{ - if (!checkCompability(parent)) - throw std::invalid_argument("Incompatible window provider passed"); - - gpu::Window::init(title, style, x, y, width, height, parent, monitor); - - glfw::Window* parent_ = dynamic_cast(parent); - glfw::Monitor* monitor_ = dynamic_cast(monitor); - - p_instance = glfwCreateWindow(width, height, title.c_str(), - monitor_ != nullptr ? monitor_->p_instance : nullptr, parent_ != nullptr ? parent_->p_instance : nullptr); - if (p_instance == nullptr) - throw std::runtime_error("Cannot create GLFW window"); - glfwMakeContextCurrent(p_instance); - glfwSetWindowPos(p_instance, x, y); - this->style(style); -} - -void Window::init(const std::string& title, Style style, gpu::Window* parent, gpu::Monitor* monitor) -{ - init(title, style, monitor->originX(), monitor->originY(), monitor->width(), monitor->height(), parent, monitor); -} - -void Window::state(State state) -{ - gpu::Window::state(state); - switch (state) - { - case State::Visible: - glfwShowWindow(p_instance); - break; - case State::Hidden: - glfwHideWindow(p_instance); - break; - case State::Maximized: - glfwMaximizeWindow(p_instance); - break; - case State::Minimized: - glfwIconifyWindow(p_instance); - break; - case State::Closed: - glfwSetWindowShouldClose(p_instance, GLFW_TRUE); - break; - default: - break; - } -} - -void Window::close() -{ - gpu::Window::close(); - glfwDestroyWindow(p_instance); - p_instance = nullptr; -} - -void Window::style(Style style) -{ - gpu::Window::style(style); - if (style == Style::Windowed) - { - glfwSetWindowMonitor(p_instance, nullptr, p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE); - } - else if (style == Style::Fullscreen) - { - glfwSetWindowMonitor(p_instance, glfwGetPrimaryMonitor(), p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE); - } - else if (style == Style::Popup) - { - //throw std::runtime_error("Popup style is not supported"); - } -} - -void Window::swapBuffers() -{ - glfwSwapBuffers(p_instance); -} - -void Window::pollEvents() -{ - glfwPollEvents(); -} - -} \ No newline at end of file diff --git a/source/hpr/window_system/glfw/window.hpp b/source/hpr/window_system/glfw/window.hpp deleted file mode 100644 index 0edc571..0000000 --- a/source/hpr/window_system/glfw/window.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "../window.hpp" - -#include - - -namespace hpr::gpu::glfw -{ - -class Window : public gpu::Window -{ - friend class WindowSystem; - -protected: - - GLFWwindow* p_instance; - -public: - - Window(); - - virtual - ~Window(); - - GLFWwindow* instance() const - { - return p_instance; - } - void init(const std::string& title, Style style, int x, int y, int width, int height, gpu::Window* parent, gpu::Monitor* monitor) override; - - void init(const std::string& title, Style style, gpu::Window* parent, gpu::Monitor* monitor) override; - - void state(State state) override; - - void close() override; - - void style(Style style) override; - - void swapBuffers(); - - void pollEvents(); -}; - -} \ No newline at end of file diff --git a/source/hpr/window_system/glfw/window_system.cpp b/source/hpr/window_system/glfw/window_system.cpp deleted file mode 100644 index 8564a7b..0000000 --- a/source/hpr/window_system/glfw/window_system.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "monitor.hpp" -#include "window.hpp" -#include "window_system.hpp" - -#include - - -namespace hpr::gpu::glfw -{ - -WindowSystem::WindowSystem() : - gpu::WindowSystem {Provider::GLFW} -{ - if (!glfwInit()) - throw std::runtime_error("Cannot initialize GLFW"); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); -} - -WindowSystem::~WindowSystem() -{ - for (auto& window : p_windows) - window->close(); - glfwTerminate(); -} - -gpu::Window* WindowSystem::newWindow() -{ - p_windows.push(new glfw::Window); - - return static_cast(p_windows.back()); -} - -} \ No newline at end of file diff --git a/source/hpr/window_system/glfw/window_system.hpp b/source/hpr/window_system/glfw/window_system.hpp deleted file mode 100644 index c4bfdf5..0000000 --- a/source/hpr/window_system/glfw/window_system.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "../window_system.hpp" - - -namespace hpr::gpu::glfw -{ - -class WindowSystem : public gpu::WindowSystem -{ - -public: - - WindowSystem(); - - ~WindowSystem() override; - - gpu::Window* newWindow() override; - -}; - -} \ No newline at end of file diff --git a/source/hpr/window_system/monitor.cpp b/source/hpr/window_system/monitor.cpp deleted file mode 100644 index 5250d30..0000000 --- a/source/hpr/window_system/monitor.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "monitor.hpp" - - -namespace hpr::gpu -{ - -Monitor::Monitor() : - WindowContext(Provider::Unknown), - p_deviceName {}, - p_originX {0}, - p_originY {0}, - p_width {0}, - p_height {0}, - p_logicalWidth {0}, - p_logicalHeight {0} -{} - -Monitor::Monitor(Provider provider) : - WindowContext(provider), - p_deviceName {}, - p_originX {0}, - p_originY {0}, - p_width {0}, - p_height {0}, - p_logicalWidth {0}, - p_logicalHeight {0} -{} - -Monitor::~Monitor() = default; - -void Monitor::origin(int x, int y) -{ - p_originX = x; - p_originY = y; -} - -void Monitor::size(int width, int height) -{ - p_width = width; - p_height = height; -} - -void Monitor::logicalSize(int width, int height) -{ - p_logicalWidth = width; - p_logicalHeight = height; -} - -void Monitor::deviceName(const std::string &name) -{ - p_deviceName = name; -} - - -} \ No newline at end of file diff --git a/source/hpr/window_system/monitor.hpp b/source/hpr/window_system/monitor.hpp deleted file mode 100644 index ce79cca..0000000 --- a/source/hpr/window_system/monitor.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include "window_context.hpp" - -#include - - -namespace hpr::gpu -{ - -class Monitor : public WindowContext -{ - -protected: - - std::string p_deviceName; - int p_originX; - int p_originY; - int p_width; - int p_height; - int p_logicalWidth; - int p_logicalHeight; - -public: - - Monitor(); - - Monitor(Provider provider); - - virtual - ~Monitor(); - - // Member functions - - void origin(int x, int y); - void size(int width, int height); - void logicalSize(int width, int height); - void deviceName(const std::string& name); - - inline - int width() const - { - return p_width; - } - - inline - int height() const - { - return p_height; - } - - inline - int logicalWidth() const - { - return p_logicalWidth; - } - - inline - int logicalHeight() const - { - return p_logicalHeight; - } - - inline - int originX() const - { - return p_originX; - } - - inline - int originY() const - { - return p_originY; - } - - inline - std::string deviceName() const - { - return p_deviceName; - } - -}; - -} \ No newline at end of file diff --git a/source/hpr/window_system/window.cpp b/source/hpr/window_system/window.cpp deleted file mode 100644 index afe21d6..0000000 --- a/source/hpr/window_system/window.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "window.hpp" - - -namespace hpr::gpu -{ - -Window::Window() : - WindowContext(Provider::Unknown), - p_width {0}, - p_height {0}, - p_posX {0}, - p_posY {0}, - p_title {}, - p_state {State::Hidden}, - p_style {Style::Unknown}, - p_parent {nullptr}, - p_monitor {nullptr}, - p_isActive {true}, - p_isResizing {false} -{} - -Window::Window(Provider provider) : - WindowContext(provider), - p_width {0}, - p_height {0}, - p_posX {0}, - p_posY {0}, - p_title {}, - p_state {State::Hidden}, - p_style {Style::Unknown}, - p_parent {nullptr}, - p_monitor {nullptr}, - p_isActive {true}, - p_isResizing {false} -{} - -Window::~Window() = default; - -void Window::init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor) -{ - p_width = width; - p_height = height; - p_posX = x; - p_posY = y; - - p_title = title; - p_state = State::Hidden; - p_style = style; - - p_parent = parent; - p_monitor = monitor; -} - -void Window::init(const std::string& title, Style style, Window* parent, Monitor* monitor) -{ - init(title, style, monitor->originX(), monitor->originY(), monitor->width(), monitor->height(), parent, monitor); -} - -void Window::state(State state) -{ - p_state = state; -} - -void Window::close() -{ - state(State::Closed); -} - -void Window::restore() -{ - State prevState {p_state}; - init(p_title, p_style, p_posX, p_posY, p_width, p_height, p_parent, p_monitor); - state(prevState); -} - -bool Window::isOpen() const -{ - return p_state != State::Closed; -} - -bool Window::isActive() const -{ - return p_isActive; -} - -void Window::size(int width, int height) -{ - resizeCallback(width, height); -} - -void Window::position(int x, int y) -{ - moveCallback(x, y); -} - -void Window::title(const std::string& title) -{ - p_title = title; -} - -void Window::style(Style style) -{ - p_style = style; -} - -void Window::resizeCallback(int width, int height) -{ - p_width = width; - p_height = height; -} - -void Window::moveCallback(int x, int y) -{ - p_posX = x; - p_posY = y; -} - -} diff --git a/source/hpr/window_system/window.hpp b/source/hpr/window_system/window.hpp deleted file mode 100644 index d52d2b0..0000000 --- a/source/hpr/window_system/window.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "window_context.hpp" -#include "monitor.hpp" - - -namespace hpr::gpu -{ - -class Window : public WindowContext -{ - -public: - - enum class State - { - Unknown, - Visible, - Hidden, - Maximized, - Minimized, - Closed, - }; - - enum class Style - { - Unknown, - Windowed, - Fullscreen, - Popup - }; - -protected: - - int p_width; - int p_height; - int p_posX; - int p_posY; - std::string p_title; - - State p_state; - Style p_style; - Window* p_parent; - Monitor* p_monitor; - - bool p_isActive; - bool p_isResizing; - -public: - - Window(); - - Window(Provider provider); - - virtual - ~Window(); - - // Member functions - - virtual - void init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor); - - virtual - void init(const std::string& title, Style style, Window* parent, Monitor* monitor); - - virtual - void state(State state); - - virtual - void close(); - - virtual - void restore(); - - virtual - bool isOpen() const; - - virtual - bool isActive() const; - - virtual - void size(int width, int height); - - virtual - int width() const - { - return p_width; - } - - virtual - int height() const - { - return p_height; - } - - virtual - void position(int x, int y); - - virtual - int posX() const - { - return p_posX; - } - - virtual - int posY() const - { - return p_posY; - } - - virtual - void title(const std::string& title); - - virtual - void style(Style style); - - void resizeCallback(int width, int height); - - void moveCallback(int x, int y); - -}; - -} \ No newline at end of file diff --git a/source/hpr/window_system/window_context.hpp b/source/hpr/window_system/window_context.hpp deleted file mode 100644 index 08f1a0a..0000000 --- a/source/hpr/window_system/window_context.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - - -namespace hpr::gpu -{ - -class WindowContext -{ - -public: - - enum class Provider - { - Unknown, - GLFW - }; - -private: - - Provider p_provider; - -public: - - inline - WindowContext() : - p_provider {Provider::Unknown} - {} - - inline - WindowContext(Provider provider) : - p_provider {provider} - {} - - virtual - ~WindowContext() = default; - - bool checkCompability(const WindowContext* ctx) const - { - return (ctx != nullptr) ? ctx->p_provider == p_provider : true; - } - -}; - -} diff --git a/source/hpr/window_system/window_system.cpp b/source/hpr/window_system/window_system.cpp deleted file mode 100644 index 73281fd..0000000 --- a/source/hpr/window_system/window_system.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "window_system.hpp" -#include "glfw/window_system.hpp" - - -namespace hpr::gpu -{ - -WindowSystem::WindowSystem() : - WindowContext {Provider::Unknown} -{} - -WindowSystem::WindowSystem(Provider provider) : - WindowContext {provider} -{} - -WindowSystem::~WindowSystem() = default; - -WindowSystem* WindowSystem::create(Provider provider) -{ - if (provider == Provider::Unknown) - throw std::invalid_argument("Cannot create window system from 'Unknown' provider"); - - if (provider == Provider::GLFW) - return new glfw::WindowSystem; - else - throw std::invalid_argument("Unsupported window system"); -} - -void WindowSystem::destroy(WindowSystem*& ws) -{ - delete ws; - ws = nullptr; -} - -Window* WindowSystem::window(int index) -{ - return p_windows[index]; -} - -void WindowSystem::closeWindow(Window* window) -{ - window->close(); -} - -void WindowSystem::destroyWindow(Window* window) -{ - for (auto n = 0; n < p_windows.size(); ++n) - if (p_windows[n] == window) - p_windows.remove(n); - window->close(); - window = nullptr; -} - -Monitor* WindowSystem::monitor(int index) -{ - return p_monitors[index]; -} - -void WindowSystem::destroyMonitor(Monitor* monitor) -{ - for (auto n = 0; n < p_monitors.size(); ++n) - if (p_monitors[n] == monitor) - p_monitors.remove(n); -} -} diff --git a/source/hpr/window_system/window_system.hpp b/source/hpr/window_system/window_system.hpp deleted file mode 100644 index 946cbd8..0000000 --- a/source/hpr/window_system/window_system.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "../containers/array.hpp" -#include "window.hpp" -#include "monitor.hpp" - -#include - - -namespace hpr::gpu -{ - -class WindowSystem : public WindowContext -{ - -protected: - - darray p_windows; - darray p_monitors; - -protected: - - WindowSystem(); - - WindowSystem(Provider provider); - - virtual - ~WindowSystem(); - -public: - - // Global functions - - static - WindowSystem* create(Provider provider); - - static - void destroy(WindowSystem*& ws); - - // Window interface - - virtual - Window* newWindow() = 0; - - Window* window(int index); - - void closeWindow(Window* window); - - void destroyWindow(Window* window); - - // Monitor interface - - //virtual - //void newMonitor(Monitor** monitor) = 0; - - Monitor* monitor(int index); - - void destroyMonitor(Monitor* monitor); - -}; - -} \ No newline at end of file