diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..c04e4f3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,292 @@ +--- +Language: Cpp +AccessModifierOffset: 0 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: true + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionDeclarations: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AllowShortNamespacesOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AttributeMacros: + - __capability +BinPackArguments: true +BinPackLongBracedList: true +BinPackParameters: BinPack +BitFieldColonSpacing: Both +BracedInitializerIndentWidth: -1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: None +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTemplateCloser: false +BreakBeforeTernaryOperators: true +BreakBinaryOperations: Never +BreakConstructorInitializers: BeforeColon +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +BreakTemplateDeclarations: MultiLine +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +EnumTrailingComma: Leave +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +KeepFormFeed: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MainIncludeChar: Quote +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakBeforeMemberAccess: 150 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: Always +RemoveBracesLLVM: false +RemoveEmptyLinesInUnwrappedLines: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TableGenBreakInsideDAGArg: DontBreak +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +WrapNamespaceBodyWithEmptyLines: Leave +... + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a9bd51..ab60944 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,11 +47,6 @@ jobs: brew install googletest - - name: Install Windows Dependencies - if: runner.os == 'Windows' - uses: GuillaumeFalourd/setup-windows10-sdk-action@v2.4 - - - uses: lukka/get-cmake@latest - name: Prepare Vulkan SDK diff --git a/.gitignore b/.gitignore index e430a49..ca2cfd7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +1,24 @@ -/.vs -/Debug -/x64 -*.sln -*.vcx* -/imgui -/packages -/Cadera -shaders/compile.bat -/.obsidian -*.spv -*.gfxr -*.ini -imgui.ini - +# Visual Studio +*.code-workspace .vscode/ -*.spv +*.pdb + +# Documentation Files doc/Doxyfile doc/html -*.code-workspace doc/visuals/**/media/ doc/visuals/**/__pycache__/ *.drawio -*.pdb -vcpkg_installed/ -src/ux/imnodes/ -shaders/frag.spv -shaders/gridvert.spv -shaders/vert.spv + +# Compiled Shaders +*.spv + +# Config for Local File Paths +config.hpp # Build Install Directories build/ -install/ \ No newline at end of file +install/ + +# Dear ImGui +imgui.ini \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index ab164c6..398e633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,10 @@ cmake_minimum_required(VERSION 3.5) project(Cadera VERSION 0.1.2) # GoogleTest requires at least C++14 -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") enable_testing() @@ -13,19 +15,13 @@ enable_testing() #========================================= # Targets #========================================= -add_executable(CaderaApp src/Cadera.cpp - src/Selection.cpp +add_executable(CaderaApp src/cadera.cpp + src/selection.cpp src/callbacks.cpp - src/Model.cpp - src/Main.cpp - + src/main.cpp ) -add_subdirectory(src/render) -add_subdirectory(src/sketch) -add_subdirectory(src/ux) - set_target_properties(CaderaApp PROPERTIES OUTPUT_NAME CaderaApp EXPORT_NAME CaderaApp @@ -36,71 +32,63 @@ target_compile_definitions(CaderaApp PUBLIC) #========================================= # Precompiled Headers / Include Directories #========================================= -target_precompile_headers(CaderaApp PRIVATE src/pch.hpp) + +add_library(pch_interface INTERFACE) +target_precompile_headers(pch_interface INTERFACE src/pch.hpp) +target_include_directories(pch_interface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/) + + target_include_directories(CaderaApp PRIVATE src/) -#include_directories(${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-windows/include/) +add_subdirectory(src/render) +add_subdirectory(src/sketch) +add_subdirectory(src/text) +add_subdirectory(src/ux) + #========================================= # Libraries #========================================= + find_package(Vulkan REQUIRED) -target_link_libraries(CaderaApp PRIVATE Vulkan::Vulkan) +target_link_libraries(pch_interface INTERFACE Vulkan::Vulkan) find_package(glfw3 CONFIG REQUIRED) -target_link_libraries(CaderaApp PRIVATE glfw) +target_link_libraries(pch_interface INTERFACE glfw) find_package(imgui CONFIG REQUIRED) -target_link_libraries(CaderaApp PRIVATE imgui::imgui) +target_link_libraries(pch_interface INTERFACE imgui::imgui) find_package(glm CONFIG REQUIRED) -target_link_libraries(CaderaApp PRIVATE glm::glm) +target_link_libraries(pch_interface INTERFACE glm::glm) find_package(Stb REQUIRED) -target_include_directories(CaderaApp PRIVATE ${Stb_INCLUDE_DIR}) +target_include_directories(pch_interface INTERFACE ${Stb_INCLUDE_DIR}) + +target_link_libraries(CaderaApp PRIVATE sketchlib) +target_link_libraries(CaderaApp PRIVATE textlib) + +# Precompiled Headers +target_link_libraries(CaderaApp PUBLIC pch_interface) #========================================= # Textures/Shaders #========================================= -# Copy textures/*.png to build directory -## Make textures/ directory -add_custom_command( - TARGET CaderaApp POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/textures/ - ) - -## Gather list of all .png files in /shaders/ -file(GLOB TextureFiles ${CMAKE_SOURCE_DIR}/textures/*.png - ${CMAKE_SOURCE_DIR}/textures/*.csv) - -foreach(TextureFile ${TextureFiles}) - add_custom_command(TARGET CaderaApp POST_BUILD - COMMAND ${CMAKE_COMMAND} -E - copy ${TextureFile} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/textures/) -endforeach() - - -# Copy shaders/*.spv to build directory -## Make shaders/ directory -add_custom_command( - TARGET CaderaApp POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/shaders/ - ) - -## Gather list of all .spv files in /shaders/ -file(GLOB ShaderFiles ${CMAKE_SOURCE_DIR}/shaders/*.spv) - -foreach(ShaderFile ${ShaderFiles}) - add_custom_command(TARGET CaderaApp POST_BUILD - COMMAND ${CMAKE_COMMAND} -E - copy ${ShaderFile} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/shaders/) -endforeach() +get_filename_component(VERT_SHADER_FILE_PATH ${CMAKE_SOURCE_DIR}/shaders/vert.spv ABSOLUTE) +get_filename_component(FRAG_SHADER_FILE_PATH ${CMAKE_SOURCE_DIR}/shaders/frag.spv ABSOLUTE) +get_filename_component(GRID_VERTEX_SHADER_FILE_PATH ${CMAKE_SOURCE_DIR}/shaders/gridvert.spv ABSOLUTE) +get_filename_component(TEXT_VERTEX_SHADER_FILE_PATH ${CMAKE_SOURCE_DIR}/shaders/textvert.spv ABSOLUTE) +get_filename_component(TEXT_FRAGMENT_SHADER_FILE_PATH ${CMAKE_SOURCE_DIR}/shaders/textfrag.spv ABSOLUTE) + +get_filename_component(ARIAL_FONT_TEXTURE_FILE_PATH ${CMAKE_SOURCE_DIR}/textures/arial.png ABSOLUTE) +get_filename_component(ARIAL_FONT_COORDINATES_FILE_PATH ${CMAKE_SOURCE_DIR}/textures/arial.csv ABSOLUTE) + +configure_file(${CMAKE_SOURCE_DIR}/src/config.hpp.in ${CMAKE_SOURCE_DIR}/src/config.hpp) + # Compile Shaders diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..8779e72 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright 2025 Austin Schuberth + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. \ No newline at end of file diff --git a/shaders/compile_shaders.sh b/shaders/compile_shaders.sh index f865697..5a0fb36 100644 --- a/shaders/compile_shaders.sh +++ b/shaders/compile_shaders.sh @@ -1,6 +1,6 @@ $VULKAN_SDK/bin/glslangValidator -V $1/vertex.vert -o $1/vert.spv -$VULKAN_SDK/bin/glslangValidator -V $1/gridvertex.vert -o $1/gridvert.spv $VULKAN_SDK/bin/glslangValidator -V $1/fragment.frag -o $1/frag.spv +$VULKAN_SDK/bin/glslangValidator -V $1/gridvertex.vert -o $1/gridvert.spv $VULKAN_SDK/bin/glslangValidator -V $1/text.vert -o $1/textvert.spv $VULKAN_SDK/bin/glslangValidator -V $1/text.frag -o $1/textfrag.spv diff --git a/src/Cadera.hpp b/src/Cadera.hpp deleted file mode 100644 index 55a6a6a..0000000 --- a/src/Cadera.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "ux/gui.hpp" - - - - - -namespace CADERA_APP_NAMESPACE { - - /// @brief Flags that can be toggled in a bitset to trigger events - enum CaderaFlags { - - - /// Will trigger deletion of the currently selected object - cadera_delete, - /// Number of flags to be used in the creation of the bitset - cadera_num_flags - }; - -/** - * @brief Cadera - * @author Austin Schuberth - * @page Cadera - * - */ - class Cadera { - - private: - - void initCallbacks(); - - std::map Models; - - int modelIdCounter; - - public: - - CADRender Render; - sketch::Sketch Sketch; - - std::bitset flags; - - Cadera(); - - ~Cadera(); - - void SketchEvents(); - - void updateSelectionPoints(std::vector ids); - - void run(); - - void mainLoop(); - }; - -} \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp deleted file mode 100644 index cf07ac7..0000000 --- a/src/Main.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "pch.hpp" -#include "Cadera.hpp" - - - -VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE - - -/// @brief main function -/// @return 0 -int main() { - - - cad::Cadera App; - - try { - App.run(); - - } - catch (const std::exception & err) { - std::cerr << err.what() << std::endl; - } - - - return 0; -} \ No newline at end of file diff --git a/src/Model.cpp b/src/Model.cpp deleted file mode 100644 index 2f732d8..0000000 --- a/src/Model.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "pch.hpp" -#include "Model.hpp" - -namespace CADERA_APP_NAMESPACE { - - Model::Model() { - - } - - - Model::Model(int id) { - mId = id; - } - - void Model::setId(int id) { - - mId = id; - - } - - int Model::getId() { - return mId; - } - - void Model::setType(ModelType type) { - - mType = type; - } - - ModelType Model::getType() { - - return mType; - } - - std::vector Model::getGridLine() - { - return std::vector(); - } - - std::vector Model::getGridAxii() - { - return std::vector(); - } - - std::vector Model::getRelationTexts() - { - return std::vector(); - } - - std::vector Model::getVertices() { - - return std::vector(); - } - - std::vector Model::getVertices(std::vector& colors) - { - return std::vector(); - } - -} \ No newline at end of file diff --git a/src/Model.hpp b/src/Model.hpp deleted file mode 100644 index 58556eb..0000000 --- a/src/Model.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include "render/TextRender.hpp" -#include "render/grid.hpp" - -namespace CADERA_APP_NAMESPACE { - - enum ModelType { - cad_sketch, - cad_layout, - cad_part, - cad_assembly, - cad_drawing - }; - - class Model { - - int mId; - ModelType mType; - - public: - - Model(); - Model(int id); - - void setId(int id); - - int getId(); - - void setType(ModelType type); - - ModelType getType(); - - std::map Notes; - - virtual std::vector getGridLine(); - virtual std::vector getGridAxii(); - - virtual std::vector getRelationTexts(); - - virtual std::vector getVertices(); - virtual std::vector getVertices(std::vector& colors); - - - - }; - -} - diff --git a/src/Selection.cpp b/src/Selection.cpp deleted file mode 100644 index 9d5575a..0000000 --- a/src/Selection.cpp +++ /dev/null @@ -1,327 +0,0 @@ -#include "pch.hpp" -#include "Selection.hpp" - -namespace CADERA_APP_NAMESPACE { -namespace sel { - - float calcRatioToPlane(glm::vec3 currentRay, glm::vec3 cameraToPlaneDist, glm::vec3 planeOrigin, - glm::vec3 planeNormal) { - - float ratio; - - glm::vec3 rayProjToPlaneNormalDist; - glm::vec3 cameraToNormalPlaneDist; - - cameraToNormalPlaneDist = (glm::dot(cameraToPlaneDist, planeNormal) * planeNormal); - rayProjToPlaneNormalDist = (glm::dot(currentRay, planeNormal) * planeNormal); - - ratio = std::fabs(glm::length(cameraToNormalPlaneDist) / glm::length(rayProjToPlaneNormalDist)); - - return ratio; - - } - - glm::vec3 calcPOnPlane(glm::vec3 currentRay, glm::vec3 origin, glm::vec3 normal, glm::vec3 pos) { - - glm::vec3 cameraToPlaneDist; - float ratio; - glm::vec3 vecCamToPOnPlane; - glm::vec3 POnPlaneCoord; - - - cameraToPlaneDist = { pos.x - origin.x, pos.y - origin.y, pos.z - origin.z }; - - ratio = calcRatioToPlane(currentRay, cameraToPlaneDist, origin, normal); - - - vecCamToPOnPlane = ratio * currentRay; - POnPlaneCoord = cameraToPlaneDist + vecCamToPOnPlane + origin; - - return POnPlaneCoord; - - } - - glm::vec2 normalizeToVulkanCoords(glm::vec2 screenCoords, uint32_t surfaceWidth, uint32_t surfaceHeight) { - glm::vec2 normCoords; - - normCoords.x = 2.0f * screenCoords.x / static_cast(surfaceWidth) - 1.0; - normCoords.y = 2.0f * screenCoords.y / static_cast(surfaceHeight) - 1.0; - - return normCoords; - } - - glm::vec4 clipToEyeSpace(glm::vec4 clipCoords, glm::mat4 projMat) { - glm::vec4 eyeCoords; - glm::mat4 inverseProjection; - - inverseProjection = glm::inverse(projMat); - eyeCoords = inverseProjection * clipCoords; - eyeCoords.z = -1.0f; - eyeCoords.w = 0.0f; - - - return eyeCoords; - } - - glm::vec3 toWorldCoord(glm::vec4 eyeCoords, glm::mat4 viewMat) { - glm::vec3 mouseRay; - glm::vec4 rayWorld; - glm::mat4 inverseView; - - inverseView = glm::inverse(viewMat); - rayWorld = inverseView * eyeCoords; - mouseRay = { rayWorld.x, rayWorld.y, rayWorld.z }; - mouseRay = glm::normalize(mouseRay); - - - return mouseRay; - } - - glm::vec3 calcCurrentRay(float x, float y, glm::mat4 viewMat, glm::mat4 projMat, uint32_t width, uint32_t height) { - glm::vec2 screenCoords; - glm::vec2 normCoords; - glm::vec4 clipCoords; - glm::vec4 eyeCoords; - - glm::vec3 currentRay; - - screenCoords = { x, y }; - - normCoords = normalizeToVulkanCoords(screenCoords, width, height); - clipCoords = { normCoords.x, normCoords.y, -1.0f, 1.0f }; - eyeCoords = clipToEyeSpace(clipCoords, projMat); - - currentRay = toWorldCoord(eyeCoords, viewMat); - - return currentRay; - } - - - Selector::Selector() { - - point = { 0.0f, 0.0f, 0.0f }; - - flags.set(select_first_click); - - } - - void Selector::setActiveSketch(sketch::Sketch* pSketch) { - - pActiveSketch = pSketch; - - } - - void Selector::select(glm::vec3 mouseRay, glm::vec3 origin, glm::vec3 normal, glm::vec3 pos, glm::vec3 cross, bool isOrtho) { - - - - if (isOrtho) { - glm::vec3 up = glm::cross(cross, normal); - - glm::vec3 x = mouseRay.x * cross; - glm::vec3 y = mouseRay.y * up; - - glm::vec3 posOnPlane = origin + ( up + cross) * pos; - point = posOnPlane + x + y; - } - else { - point = calcPOnPlane(mouseRay, origin, normal, pos); - } - - } - - int Selector::selectPoint(glm::vec3 pointToAdd, std::map &points, float skScale) { - - std::vector sortedIndices; - double sensitivity = skScale / 800.0f; - - for (const auto& point : points) { - glm::vec3 pointVec; - double length; - - pointVec = pointToAdd - point.second.pos; - - - length = glm::length2(pointVec); - - if (length < sensitivity) { - return point.first; - } - } - - return -1; - } - - void Selector::update(std::map points) { - - selectedPoints.clear(); - - for (const auto &point : points) { - - selectedPoints[point.first] = point.second; - } - } - - int Selector::add(glm::vec3 pointToAdd, std::map& points, float skScale) { - - // Clear selected points if CTRL isn't pressed - if (!flags.test(select_isCTRL)) { - selectedPoints.clear(); - setFlags(); - } - - pointJustAdded = false; - - int selectedPointId = selectPoint(pointToAdd, points, skScale); - - // If a point is selected - if (selectedPointId >= 0) { - - // If not in selectedPoints, add it, else remove it - if (selectedPoints.find(selectedPointId) == selectedPoints.end()) { - - selectedPoints[selectedPointId] = points[selectedPointId]; - setFlags(); - - pointJustAdded = true; - - return selectedPointId; - - } - - } - - // If not CTRL and selectedPointId < 0 - if (!flags.test(select_isCTRL)) { - - selectedPoints.clear(); - setFlags(); - - } - - return selectedPointId; - - } - - int Selector::remove(glm::vec3 pointToRemove, std::map &points, float skScale) - { - if(!flags.test(select_isCTRL)) - return -1; - - if (pointJustAdded) - return -1; - - int selectedPointId = selectPoint(pointToRemove, points, skScale); - - - if (selectedPointId >= 0) { - - selectedPoints.erase(selectedPointId); - setFlags(); - - return selectedPointId; - - } - - - return -1; - } - - bool Selector::existingPoint(glm::vec3 point) { - - if (pActiveSketch == nullptr) - throw std::runtime_error("Selection.existingPoint(): pActiveSketch is not set!"); - - int16_t pointSketchId = -1; - - // If there are points in sketch - if (pActiveSketch->Points.size() > 0) { - - if (pActiveSketch->mCamDistance == nullptr) - throw std::runtime_error("Selection.existingPoint(): pActiveSketch->mCamDistance is nullptr!"); - - pointSketchId = sel::Selector::selectPoint(point, pActiveSketch->Points, *pActiveSketch->mCamDistance); - - // Point already exists - if (pointSketchId >= 0) { - - if (&pActiveSketch->Points[pointSketchId] == nullptr) - throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); - - return true; - - } - else { - return false; - } - } - - // No points in sketch - return false; - } - - void Selector::setFlags() { - - if (selectedPoints.size() == 1) { - - flags.set(select_single_point); - - flags.reset(select_double_point); - flags.reset(select_multi_point); - - } - else if (selectedPoints.size() == 2) { - - flags.set(select_double_point); - - flags.reset(select_single_point); - flags.reset(select_multi_point); - - } - else if (selectedPoints.size() >= 3) { - - flags.set(select_multi_point); - - flags.reset(select_single_point); - flags.reset(select_double_point); - - } - else { - - flags.reset(select_single_point); - flags.reset(select_double_point); - flags.reset(select_multi_point); - - } - - - } - - void Selector::clear() { - selectedPoints.clear(); - } - - std::vector Selector::getVertices() { - - std::vector vertices; - - for (const auto& p : selectedPoints) { - vertices.push_back(p.second.pos); - } - - return vertices; - } - - std::vector Selector::getSelectedPointIds() { - - std::vector ids; - - for (auto& P : selectedPoints) { - ids.push_back(P.second.getId()); - } - - return ids; - } - -} -} \ No newline at end of file diff --git a/src/Selection.hpp b/src/Selection.hpp deleted file mode 100644 index 308dc4e..0000000 --- a/src/Selection.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once -#include "sketch/SketchSolver.hpp" - - -namespace CADERA_APP_NAMESPACE { -namespace sel { - float calcRatioToPlane(glm::vec3 currentRay, glm::vec3 cameraToPlaneDist, glm::vec3 planeOrigin, - glm::vec3 planeNormal); - - glm::vec3 calcPOnPlane(glm::vec3 currentRay, glm::vec3 origin, glm::vec3 normal, glm::vec3 pos); - - glm::vec2 normalizeToVulkanCoords(glm::vec2 screenCoords, uint32_t surfaceWidth, uint32_t surfaceHeight); - - glm::vec4 clipToEyeSpace(glm::vec4 clipCoords, glm::mat4 projMat); - - glm::vec3 toWorldCoord(glm::vec4 eyeCoords, glm::mat4 viewMat); - - glm::vec3 calcCurrentRay(float x, float y, glm::mat4 viewMat, glm::mat4 projMat, uint32_t width, - uint32_t height); - - - enum SelectionFlags { - select_toggle, // Used in callbacks to toggle selection - select_isCTRL, // Is CTRL pressed down - select_single_point, - select_double_point, - select_multi_point, - select_first_click, - select_number_flags // Number of flags for bitset - }; - - class Selector { - - sketch::Sketch *pActiveSketch = nullptr; - - public: - - std::bitset flags; - - glm::vec3 point; - - bool pointJustAdded; - - std::map selectedPoints; - - Selector(); - - void setActiveSketch(sketch::Sketch* pSketch); - - void select(glm::vec3 mouseRay, glm::vec3 origin, glm::vec3 normal, glm::vec3 pos, glm::vec3 cross, bool isOrtho); - - static int selectPoint(glm::vec3 pointToAdd, std::map &points, float skScale); - - void update(std::map points); - - int add(glm::vec3 pointToAdd, std::map &points, float skScale); - - int remove(glm::vec3 pointToRemove, std::map &points, float skScale); - - bool existingPoint(glm::vec3 point); - - void setFlags(); - - void clear(); - - std::vector getVertices(); - - std::vector getSelectedPointIds(); - - }; -} -} \ No newline at end of file diff --git a/src/Cadera.cpp b/src/cadera.cpp similarity index 82% rename from src/Cadera.cpp rename to src/cadera.cpp index e6c6189..c5d8f1b 100644 --- a/src/Cadera.cpp +++ b/src/cadera.cpp @@ -1,4 +1,4 @@ -#include "Cadera.hpp" +#include "cadera.hpp" #include "pch.hpp" namespace CADERA_APP_NAMESPACE { @@ -68,14 +68,14 @@ void Cadera::SketchEvents() { } if (Sketch.flags.test(sketch::skt_event_tool_deactivated)) { - Render.deleteBuffer(BUF_SKETCH_POINT_TOOL); + Render.deleteBuffer(BufferName::sketch_point_tool); Sketch.flags.reset(sketch::skt_event_tool_deactivated); } } void Cadera::run() { - Render.setBGColor(glm::vec4(0.1f, 0.1f, 0.1f, 0.1f)); + Render.setBGColor(glm::vec4(0.3f, 0.3f, 0.3f, 0.1f)); Render.Cam.flags.set(cam::ortho); Render.setup(); @@ -86,6 +86,19 @@ void Cadera::run() { Render.SktSolver.setActiveSketch(&Sketch); + + // Mouse Commands + // TODO: Determine better way to handle commands + sketchAddPointCmd.setSketch(&Sketch); + sketchAddPointCmd.setSelector(&Render.Sel); + sketchAddPointCmd.setCamera(&Render.Cam); + + cameraZoomCmd.setCamera(&Render.Cam); + + Render.mouse.setScrollMouseSlot(&cameraZoomCmd); + Render.mouse.setLeftMouseSlot(&sketchAddPointCmd); + + mainLoop(); } @@ -112,4 +125,5 @@ void Cadera::mainLoop() { } } -} // namespace CADERA_APP_NAMESPACE \ No newline at end of file + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/cadera.hpp b/src/cadera.hpp new file mode 100644 index 0000000..7e714fe --- /dev/null +++ b/src/cadera.hpp @@ -0,0 +1,52 @@ +#pragma once +#include "ux/gui.hpp" + +namespace CADERA_APP_NAMESPACE { + +/// @brief Flags that can be toggled in a bitset to trigger events +enum CaderaFlags { + + /// Will trigger deletion of the currently selected object + cadera_delete, + /// Number of flags to be used in the creation of the bitset + cadera_num_flags +}; + +/** + * @brief Cadera + * @author Austin Schuberth + * @page Cadera + * + */ +class Cadera { + +private: + void initCallbacks(); + + std::map Models; + + int modelIdCounter; + +public: + // TODO: Restructure + command::SketchAddPointCommand sketchAddPointCmd; + command::CameraZoomCommand cameraZoomCmd; + //------------- + + CADRender Render; + sketch::Sketch Sketch; + + std::bitset flags; + + Cadera(); + + ~Cadera(); + + void SketchEvents(); + + void run(); + + void mainLoop(); +}; + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/callbacks.cpp b/src/callbacks.cpp index 3bfcc59..c797cd9 100644 --- a/src/callbacks.cpp +++ b/src/callbacks.cpp @@ -1,179 +1,149 @@ -#include "pch.hpp" #include "callbacks.hpp" -#include "Cadera.hpp" +#include "cadera.hpp" +#include "pch.hpp" -void sketch_mode_callbacks(cad::Cadera *app, int &button, int &action, int &mods); +void sketch_mode_callbacks(cad::Cadera *app, int &button, int &action, + int &mods); void sketch_select_addPoint(cad::Cadera *app); void sketch_select_removePoint(cad::Cadera *app); -void sketch_add_point(cad::Cadera *app); +void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods) { -void sketch_move_point(cad::Cadera *app); + auto app = reinterpret_cast( + glfwGetWindowUserPointer(window)); -void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { + ImGuiIO &io = ImGui::GetIO(); - auto app = reinterpret_cast (glfwGetWindowUserPointer(window)); + // (2) ONLY forward mouse data to your underlying app/game. + if (!io.WantCaptureMouse) { - ImGuiIO& io = ImGui::GetIO(); - + if (app->Sketch.flags.test(CADERA_APP_NAMESPACE::sketch::skt_active)) { - // (2) ONLY forward mouse data to your underlying app/game. - if (!io.WantCaptureMouse) { + sketch_mode_callbacks(app, button, action, mods); + } - - if (app->Sketch.flags.test(CADERA_APP_NAMESPACE::sketch::skt_active)) { - - sketch_mode_callbacks(app, button, action, mods); - - } - - - - + if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) { - if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) { + app->Render.Cam.flags.set(cad::cam::pan); + app->Render.Cam.flags.set(cad::cam::mouseFirstPressed); + } - app->Render.Cam.flags.set(cad::cam::pan); - app->Render.Cam.flags.set(cad::cam::mouseFirstPressed); - - } + if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) { - if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) { + app->Render.Cam.flags.reset(cad::cam::pan); + } + } - app->Render.Cam.flags.reset(cad::cam::pan); + if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) { + } - } - } + if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) { + } +} - - if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) { - - } +void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { - if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) { - - } + auto app = reinterpret_cast( + glfwGetWindowUserPointer(window)); + if (!ImGui::IsWindowHovered(ImGuiHoveredFlags_::ImGuiHoveredFlags_AnyWindow)) { + app->Render.mouse.scroll(yoffset); + } } -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { +void framebuffer_resize_callback(GLFWwindow *window, int width, int height) { - auto app = reinterpret_cast (glfwGetWindowUserPointer(window)); - - if (!ImGui::IsWindowHovered(ImGuiHoveredFlags_::ImGuiHoveredFlags_AnyWindow)) - app->Render.Cam.zoom(yoffset); - + auto app = reinterpret_cast( + glfwGetWindowUserPointer(window)); + app->Render.frameBufferResized = true; } -void framebuffer_resize_callback(GLFWwindow* window, int width, int height) { +void key_callback(GLFWwindow *window, int key, int scancode, int action, + int mods) { - auto app = reinterpret_cast (glfwGetWindowUserPointer(window)); + auto app = reinterpret_cast( + glfwGetWindowUserPointer(window)); + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { + app->Sketch.deactivateTools(); + } - app->Render.frameBufferResized = true; + if (key == GLFW_KEY_DELETE && action == GLFW_PRESS) { + app->flags.set(CADERA_APP_NAMESPACE::cadera_delete); + } -} + if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_PRESS) { + app->Render.Sel.flags.set(CADERA_APP_NAMESPACE::sel::select_isCTRL); + } -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { - - auto app = reinterpret_cast (glfwGetWindowUserPointer(window)); + if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_RELEASE) { + app->Render.Sel.flags.reset(CADERA_APP_NAMESPACE::sel::select_isCTRL); + } +} - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { - app->Sketch.deactivateTools(); - - } +void cursor_position_callback(GLFWwindow *window, double xpos, double ypos) {} - if (key == GLFW_KEY_DELETE && action == GLFW_PRESS) { - app->flags.set(CADERA_APP_NAMESPACE::cadera_delete); - } +void sketch_mode_callbacks(cad::Cadera *app, int &button, int &action, + int &mods) { - if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_PRESS) { - app->Render.Sel.flags.set(CADERA_APP_NAMESPACE::sel::select_isCTRL); - } + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { + if (app->Sketch.flags.test(CADERA_APP_NAMESPACE::sketch::skt_tool_active)) { + + app->Render.mouse.leftMouseClick(); - if (key == GLFW_KEY_LEFT_CONTROL && action == GLFW_RELEASE) { - app->Render.Sel.flags.reset(CADERA_APP_NAMESPACE::sel::select_isCTRL); - } + app->Render.flags.set(CADERA_APP_NAMESPACE::render_update_sketch); + } + else { -} + sketch_select_addPoint(app); + app->Sketch.flags.set(cad::sketch::skt_move_points); + } -void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { + } else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { -} + if (!app->Sketch.flags.test( + CADERA_APP_NAMESPACE::sketch::skt_tool_active)) { + if (!app->Sketch.flags.test(cad::sketch::skt_points_have_moved)) + sketch_select_removePoint(app); -void sketch_mode_callbacks(cad::Cadera *app, int &button, int &action, int &mods) { - - if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { - if (app->Sketch.flags.test(CADERA_APP_NAMESPACE::sketch::skt_tool_active)) - sketch_add_point(app); - else { - - sketch_select_addPoint(app); - app->Sketch.flags.set(cad::sketch::skt_move_points); - - } - - - } else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { - - if (!app->Sketch.flags.test(CADERA_APP_NAMESPACE::sketch::skt_tool_active)) { - - if (!app->Sketch.flags.test(cad::sketch::skt_points_have_moved)) - sketch_select_removePoint(app); - - app->Render.Sel.flags.set(cad::sel::select_first_click); - app->Sketch.flags.reset(cad::sketch::skt_move_points); - app->Sketch.flags.reset(cad::sketch::skt_points_have_moved); - } - } + app->Render.Sel.flags.set(cad::sel::select_first_click); + app->Sketch.flags.reset(cad::sketch::skt_move_points); + app->Sketch.flags.reset(cad::sketch::skt_points_have_moved); + } + } } void sketch_select_addPoint(cad::Cadera *app) { - app->Render.Sel.select(app->Render.Cam.mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), - app->Render.Cam.cameraVec, app->Render.Cam.pos, app->Render.Cam.cross, - app->Render.Cam.flags.test(cad::cam::ortho)); + app->Render.Sel.select(app->Render.Cam.mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), + app->Render.Cam.cameraVec, app->Render.Cam.pos, + app->Render.Cam.cross, + app->Render.Cam.flags.test(cad::cam::ortho)); - int id = app->Render.Sel.add(app->Render.Sel.point, app->Sketch.Points, app->Render.Cam.camDistance); + int id = app->Render.Sel.add(app->Render.Sel.point, app->Sketch.Points, + app->Render.Cam.camDistance); - if (id >= 0 || app->Render.Sel.selectedPoints.empty()) { - app->Render.flags.set(cad::render_update_sketch); - } + if (id >= 0 || app->Render.Sel.selectedPoints.empty()) { + app->Render.flags.set(cad::render_update_sketch); + } } void sketch_select_removePoint(cad::Cadera *app) { - app->Render.Sel.select(app->Render.Cam.mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), - app->Render.Cam.cameraVec, app->Render.Cam.pos, - app->Render.Cam.cross, - app->Render.Cam.flags.test(cad::cam::ortho)); - - int id = app->Render.Sel.remove(app->Render.Sel.point, app->Sketch.Points, - app->Render.Cam.camDistance); - - - if (id >= 0 || app->Render.Sel.selectedPoints.empty()) { - app->Render.flags.set(cad::render_update_sketch); - } + app->Render.Sel.select(app->Render.Cam.mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), + app->Render.Cam.cameraVec, app->Render.Cam.pos, + app->Render.Cam.cross, + app->Render.Cam.flags.test(cad::cam::ortho)); -} - - - -void sketch_add_point(cad::Cadera *app) { - - app->Render.Sel.select(app->Render.Cam.mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), - app->Render.Cam.cameraVec, app->Render.Cam.pos, app->Render.Cam.cross, - app->Render.Cam.flags.test(cad::cam::ortho)); - - if (!app->Render.Sel.existingPoint(app->Render.Sel.point)) - app->Sketch.add(app->Render.Sel.point); - - app->Render.flags.set(CADERA_APP_NAMESPACE::render_update_sketch); - -} + int id = app->Render.Sel.remove(app->Render.Sel.point, app->Sketch.Points, + app->Render.Cam.camDistance); + if (id >= 0 || app->Render.Sel.selectedPoints.empty()) { + app->Render.flags.set(cad::render_update_sketch); + } +} \ No newline at end of file diff --git a/src/callbacks.hpp b/src/callbacks.hpp index dc56358..a16ace4 100644 --- a/src/callbacks.hpp +++ b/src/callbacks.hpp @@ -1,13 +1,14 @@ #pragma once -//#include "gui.hpp" +// #include "gui.hpp" -void mouse_button_callback(GLFWwindow* window, int button, int action, int mods); +void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods); -void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); +void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); -void framebuffer_resize_callback(GLFWwindow* window, int width, int height); +void framebuffer_resize_callback(GLFWwindow *window, int width, int height); -void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); - -void cursor_position_callback(GLFWwindow* window, double xpos, double ypos); +void key_callback(GLFWwindow *window, int key, int scancode, int action, + int mods); +void cursor_position_callback(GLFWwindow *window, double xpos, double ypos); diff --git a/src/config.hpp.in b/src/config.hpp.in new file mode 100644 index 0000000..7d5eb40 --- /dev/null +++ b/src/config.hpp.in @@ -0,0 +1,16 @@ +#pragma once + +namespace CADERA_APP_NAMESPACE { +namespace config { + +static constexpr auto vertex_shader_file_path = "@VERT_SHADER_FILE_PATH@"; +static constexpr auto fragment_shader_file_path = "@FRAG_SHADER_FILE_PATH@"; +static constexpr auto grid_vertex_shader_file_path = "@GRID_VERTEX_SHADER_FILE_PATH@"; +static constexpr auto text_vertex_shader_file_path = "@TEXT_VERTEX_SHADER_FILE_PATH@"; +static constexpr auto text_fragment_shader_file_path = "@TEXT_FRAGMENT_SHADER_FILE_PATH@"; + +static constexpr auto arial_font_texture_file_path = "@ARIAL_FONT_TEXTURE_FILE_PATH@"; +static constexpr auto arial_font_coordinates_file_path = "@ARIAL_FONT_COORDINATES_FILE_PATH@"; + +} +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..497f44f --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,20 @@ +#include "cadera.hpp" +#include "pch.hpp" + +VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE + +/// @brief main function +/// @return 0 +int main() { + + cad::Cadera App; + + try { + App.run(); + + } catch (const std::exception &err) { + std::cerr << err.what() << std::endl; + } + + return 0; +} diff --git a/src/pch.cpp b/src/pch.cpp deleted file mode 100644 index 7f3196a..0000000 --- a/src/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.hpp" \ No newline at end of file diff --git a/src/pch.hpp b/src/pch.hpp index de40e23..f9a9e8d 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -1,8 +1,10 @@ #pragma once +// STL #include #include #include +#include #include #include #include @@ -10,32 +12,40 @@ #include #include +// Project Namespaces #define CADERA_APP_NAMESPACE cad -#define GLM_ENABLE_EXPERIMENTAL -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#define GLFW_INCLUDE_VULKAN -#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 -#define IMGUI_DEFINE_MATH_OPERATORS -// Windows MINGW64 gcc +// Windows MINGW64 gcc/MSVC #ifdef _DEBUG #define CADERA_DEBUG #endif -// Linux gcc +// Linux gcc clang #ifndef NDEBUG #define CADERA_DEBUG #endif +// Vulkan +#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #include +// GLM +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_FORCE_RADIANS +#define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include +// GLFW3 +#define GLFW_INCLUDE_VULKAN #include "GLFW/glfw3.h" +// Dear ImGui +#define IMGUI_DEFINE_MATH_OPERATORS #include #include #include #include + +// Project Includes +#include "config.hpp" \ No newline at end of file diff --git a/src/render/CADRender.hpp b/src/render/CADRender.hpp deleted file mode 100644 index 202adfb..0000000 --- a/src/render/CADRender.hpp +++ /dev/null @@ -1,438 +0,0 @@ -#pragma once - -#include "callbacks.hpp" -#include "Camera.hpp" - - - - - - - -namespace CADERA_APP_NAMESPACE { - - - struct SwapChainSupportDetails { - vk::SurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector presentModes; - }; - - struct QueueFamilyIndices { - int graphicsFamily = -1; - int presentFamily = -1; - - bool isComplete() { - return graphicsFamily >= 0 && presentFamily >= 0; - } - - bool isDifferent() { - return graphicsFamily != presentFamily; - } - }; - - - - struct ubo { - glm::mat4 model; - glm::mat4 view; - glm::mat4 proj; - }; - - - struct Buffer { - - - vk::Buffer mBuffer; - vk::DeviceMemory mMemory; - vk::DeviceSize mDeviceSize; - uint32_t mPointSize; - bool isEmpty = true; - - }; - - - enum RenderFlags { - render_update_sketch, - render_num_flags - }; - - class CADRender { - - private: - std::vector validationLayers = { - "VK_LAYER_LUNARG_standard_validation" - }; - - std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - vk::DescriptorPool mGuiDescriptorPool; - VkAllocationCallbacks* mGuiAllocator; - - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; - PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = 0; - PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTag = 0; - PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = 0; - PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = 0; - PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = 0; - PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = 0; - - struct { - - vk::Pipeline SketchPoint; - vk::Pipeline SketchLine; - vk::Pipeline SketchGrid; - - } Pipelines; - - - - public: - - - - // GLFW - GLFWwindow* mMainWindow; - - - - // Main Vulkan Objects - vk::Instance mInstance; - vk::PhysicalDevice mPhysicalDevice; - vk::Device mDevice; - vk::RenderPass mRenderPass; - - // Secondary Vulkan Objects - - // mInstance - vk::detail::DynamicLoader dl; - vk::detail::DispatchLoaderDynamic dldy; - VkDebugUtilsMessengerEXT mDebug; - vk::ApplicationInfo mAppInfo; - bool enableValidationLayers; - vk::DebugUtilsMessengerEXT mCallback; - vk::SurfaceKHR mSurface; - - - // Physical mDevice - QueueFamilyIndices mIndices; - - // Logical mDevice - vk::Queue mGraphicsQueue; - vk::Queue mPresentQueue; - - // Swapchain - int mWidth = 750; - int mHeight = 750; - - bool frameBufferResized; - - std::vector mImages; - std::vector mImageViews; - vk::Format mFormat; - vk::Extent2D mExtent; - - vk::Image depthImage; - vk::DeviceMemory depthImageMemory; - vk::ImageView depthImageView; - - vk::SwapchainKHR mSwapchain; - - // Pipeline - vk::PipelineCache mPipelineCache; - - vk::PipelineLayout mPipelineLayout; - - vk::Pipeline mTextPipeline; - - // Buffers - vk::CommandPool mCommandPool; - std::vector mCommandBuffers; - std::vector mFramebuffers; - - std::vector mUniformBuffers; - std::vector mUniformBufferMemories; - - vk::DescriptorPool mDescriptorPool; - std::vector mDescriptorSets; - - std::map mBuffers; - - // Textures - vk::Image mTextureImage; - vk::DeviceMemory mTextureMemory; - vk::ImageView mTextureImageView; - vk::Sampler mTextureSampler; - - - // Sync Objects - std::vector mImageAvailableSemaphores; - std::vector mRenderFinishedSemaphores; - std::vector mInFlightFences; - size_t mCurrentFrame = 0; - - // Options - glm::vec4 bgColor; - - - - vk::DescriptorSetLayout mDescriptorSetLayout; - - - std::bitset flags; - - ubo u; - - cam::Camera Cam; - - sel::Selector Sel; - - sketch::SketchSolver SktSolver; - - txt::TextRender TxtRend; - - // Imgui - - ImGui_ImplVulkanH_Window mImguiWindowData; - VkSurfaceKHR mImguiSurface; - - - void setup(); - - - //------------------------------------------- - - - // Functions - - void setBGColor(glm::vec4 color); - - // GLFW - - void createWindow(); - - // Instance - - void createInstance(); - - void createSurface(); - - // Physical Device - - void pickPhysicalDevice(); - - SwapChainSupportDetails querySwapChainSupport(const vk::PhysicalDevice &device); - - QueueFamilyIndices findQueueFamilies(vk::PhysicalDevice device, VkSurfaceKHR surface); - - bool isDeviceSuitable(vk::PhysicalDevice device); - - bool checkDeviceExtensionSupport(vk::PhysicalDevice device); - - // Logical mDevice - void createLogicalDevice(); - - // Swapchain - bool checkFormat(vk::Format Format); - - - vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats); - - vk::PresentModeKHR chooseSwapPresentMode(const std::vector availablePresentModes); - - vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities); - - void createSwapChain(); - - void recreateSwapchain(); - - void createImageViews(); - - vk::ImageView createImageView(vk::Image image, vk::Format format, vk::ImageAspectFlags aspectFlags); - - vk::Format findSupportedFormat(vk::PhysicalDevice const &PhysicalDevice, const std::vector &candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features); - - vk::Format findDepthFormat(vk::PhysicalDevice const &PhysicalDevice); - - void createRenderPass(); - - void createDescriptorSetLayout(); - - void createPipelineLayout(); - - std::vector readFile(const std::string filename); - - vk::ShaderModule createShaderModule(const std::vector &code); - - void loadFonts(); - - void createTextPipeline(); - - void createCommandPool(); - - uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties); - - void createImage(vk::PhysicalDevice const &PhysicalDevice, vk::Device const &Device, uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Image &image, vk::DeviceMemory &imageMemory); - - void createDepthResources(); - - void createBuffer(vk::DeviceSize &size, const vk::BufferUsageFlags &usage, const vk::MemoryPropertyFlags &properties, vk::Buffer &buffer, vk::DeviceMemory &bufferMemory); - - vk::CommandBuffer beginSingleTimeCommands(const vk::CommandBufferLevel &level, const vk::CommandBufferInheritanceInfo &inheritance); - - void endSingleTimeCommands(vk::CommandBuffer &commandBuffer); - - void transitionImageLayout(vk::Image &image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout); - - void copyBufferToImage(vk::Buffer &buffer, vk::Image &image, uint32_t width, uint32_t height); - - void createTextureImage(); - - void createTextureImageView(); - - void createTextureSampler(); - - void createFramebuffers(); - - void createUniformBuffer(); - - void createDescriptorPool(); - - void createDescriptorSets(); - - void allocCommandBuffers(); - - void createSyncObjects(); - - void initImgui(); - - void createSketchPointPipeline(); - - void createSketchLinePipeline(); - - void createSketchGridPipeline(); - - void preparePipelines(); - - void copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize size); - - void deleteBuffer(uint32_t id); - - void createCommandBuffers(); - - void updateUniformBuffer(uint32_t currentImage); - - void drawFrame(); - - template - inline void createDeviceBuffer(uint32_t id, std::vector const& points, vk::BufferUsageFlagBits const& flag) { - - vk::Buffer stagingBuffer; - vk::DeviceMemory stagingBufferMemory; - - mBuffers[id].mPointSize = static_cast(points.size()); - mBuffers[id].mDeviceSize = sizeof(points[0]) * points.size(); - - createBuffer(mBuffers[id].mDeviceSize, vk::BufferUsageFlagBits::eTransferSrc, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, - stagingBuffer, stagingBufferMemory); - - vk::MemoryMapFlags memMapFlags; - - void* data; - data = mDevice.mapMemory(stagingBufferMemory, 0, mBuffers[id].mDeviceSize, memMapFlags); - memcpy(data, points.data(), (size_t)mBuffers[id].mDeviceSize); - mDevice.unmapMemory(stagingBufferMemory); - - createBuffer(mBuffers[id].mDeviceSize, vk::BufferUsageFlagBits::eTransferDst | flag, - vk::MemoryPropertyFlagBits::eDeviceLocal, - mBuffers[id].mBuffer, mBuffers[id].mMemory); - - - copyBuffer(stagingBuffer, mBuffers[id].mBuffer, mBuffers[id].mDeviceSize); - - mDevice.destroyBuffer(stagingBuffer); - mDevice.freeMemory(stagingBufferMemory); - - mBuffers[id].isEmpty = false; - - }; - - - - - - - template - inline void updateBuffer(uint32_t id, std::vector const& points, vk::BufferUsageFlagBits const& flag) { - if (mBuffers[id].isEmpty) { - createDeviceBuffer(id, points, flag); - } - else { - deleteBuffer(id); - createDeviceBuffer(id, points, flag); - } - } - - - - void destroyPipelines(); - - void cleanupSwapchain(); - - // Cleanup - void cleanup(); - - - - //------------------------------- - - // void initImgui(); - - // void imguiRun(); - - /* void createSketchPointPipeline(); - void createSketchLinePipeline(); - - void createSketchGridPipeline(); - - void preparePipelines(); - - void destroyPipelines(); - - void createDescriptorPool(); - - void createDescriptorSets(); - - void createCommandBuffers(); - - void updateUniformBuffer(uint32_t currentImage); - */ - void destroy(); - - void runCamera(); - - void render(Model &M); - - void renderSketchGrid(Model &S); - - void renderSketchNotes(Model &S); - - void renderSketchPoints(Model &S); - - void renderSketchPointTool(); - - //void runCamera(); - - //void render(Model &M); - - //void renderSketchNotes(Model& S); - - //void renderSketchPoints(Model &S); - - }; -} - diff --git a/src/render/CMakeLists.txt b/src/render/CMakeLists.txt index 69de1e9..33cc8b1 100644 --- a/src/render/CMakeLists.txt +++ b/src/render/CMakeLists.txt @@ -1,11 +1,5 @@ cmake_minimum_required(VERSION 3.5) - - -target_sources(CaderaApp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/CADRender.cpp - ${CMAKE_CURRENT_LIST_DIR}/Camera.cpp - ${CMAKE_CURRENT_LIST_DIR}/RenderUtil.cpp - ${CMAKE_CURRENT_LIST_DIR}/TextRender.cpp - ${CMAKE_CURRENT_LIST_DIR}/grid.cpp - ) - +target_sources(CaderaApp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/cadrender.cpp + ${CMAKE_CURRENT_LIST_DIR}/camera.cpp + ) \ No newline at end of file diff --git a/src/render/Camera.cpp b/src/render/Camera.cpp deleted file mode 100644 index 1044878..0000000 --- a/src/render/Camera.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "pch.hpp" -#include "Camera.hpp" - -namespace CADERA_APP_NAMESPACE { - -namespace cam { - - - Camera::Camera() - { - pos = { 0.0f, 0.0f, 20.0f }; - focus = { 0.0f, 0.0f, 0.0f }; - cameraVec = { 0.0f, 0.0f, -1.0f }; - xpos = 0.0; - ypos = 0.0; - mouseRay = { 0.0f, 0.0f, 0.0f }; - left = -10.0f; - camDistance = 0.0f; - - up = {0.0f, 1.0f, 0.0f}; - - cross = glm::cross(cameraVec, up); - - } - - - void Camera::setXYView() { - - pos = { 0.0f, 0.0f, 20.0f }; - focus = { 0.0f, 0.0f, 0.0f }; - cameraVec = { 0.0f, 0.0f, -1.0f }; - - up = {0.0f, 1.0f, 0.0f}; - cross = glm::cross(cameraVec, up); - - } - - void Camera::setYZView() { - - pos = { 20.0f, 0.0f, 0.0f }; - focus = { 0.0f, 0.0f, 0.0f }; - cameraVec = { -1.0f, 0.0f, 0.0f }; - - up = {0.0f, 0.0f, 1.0f}; - cross = glm::cross(cameraVec, up); - - } - - void Camera::setZXView() { - - pos = { 0.0f, 20.0f, 0.0f }; - focus = { 0.0f, 0.0f, 0.0f }; - cameraVec = { 0.0f, -1.0f, 0.0f }; - - up = {1.0f, 0.0f, 0.0f}; - cross = glm::cross(cameraVec, up); - - } - - - - void Camera::update() { - - camDistance = glm::length(pos - focus); - - } - - void Camera::zoom(float yoffset) { - - if (flags.test(ortho)) { - - if (yoffset > 0 && left < -1.02) { - left += 1.0f; - } - else if (yoffset < 0) { - left -= 1.0f; - } - } - else { - - glm::vec3 normalPos = {0.0f, pos.y, pos.z}; - - if (yoffset > 0) { - pos -= 1.0f * glm::normalize(cameraVec); - } - else if (yoffset < 0 && glm::length2(pos - focus) > 1.02f) { - pos += 1.0f * glm::normalize(cameraVec); - } - } - - } - - void Camera::updateMouseRay(float x, float y, glm::mat4 modelMat, glm::mat4 viewMat, glm::mat4 projMat, uint32_t width, - uint32_t height) { - - if (flags.test(ortho)) { - mouseRay = glm::unProject(glm::vec3(x, y, 0.0f), modelMat, projMat, - glm::vec4(0.0f, 0.0f, width, height)); - } - else { - mouseRay = sel::calcCurrentRay(x, y, viewMat, projMat, width, height); - } - - } - - /** - * @brief - * - * @param origin Origin point of the plane. - * This is used for calulating the point on the plane for projection view - * - * @param planeNormal The normal vector of the plane to pan on - */ - void Camera::pan(glm::vec3 origin, glm::vec3 planeNormal) { - - - static glm::vec3 prevMouseRay = mouseRay; - glm::vec3 p1, p2, diff; - - if (flags.test(mouseFirstPressed)) { - - prevMouseRay = mouseRay; - flags.reset(mouseFirstPressed); - - } - - if (flags.test(ortho)) { - - diff = mouseRay - prevMouseRay; - - - - pos -= diff.y * up; - pos -= diff.x * cross; - focus -= diff.y * up; - focus -= diff.x * cross; - - } - else { - - p1 = sel::calcPOnPlane(prevMouseRay, origin, planeNormal, pos); - p2 = sel::calcPOnPlane(mouseRay, origin, planeNormal, pos); - - diff = p2 - p1; - - pos -= diff; - focus -= diff; - } - - prevMouseRay = mouseRay; - - } - - -} -} - diff --git a/src/render/Camera.hpp b/src/render/Camera.hpp deleted file mode 100644 index eac835c..0000000 --- a/src/render/Camera.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once -#include "Selection.hpp" - -namespace CADERA_APP_NAMESPACE { - -namespace cam { - - enum CameraFlags { - /// Toggle orthographics projection - ortho, - /// Used for resetting functions such as pan() on first mouse click - mouseFirstPressed, - /// Toggle the camera pan() function - pan, - /// Bitset size - camera_number_flags - }; - - /** - * @brief - * - * - */ - class Camera { - - public: - - Camera(); - - std::bitset flags; - - /// Position of the camera in 3D space - glm::vec3 pos; - /// Focus point of the camera in 3D space - glm::vec3 focus; - /// The vector going from pos to focus - glm::vec3 cameraVec; - /// The length of the cameraVec vector - float camDistance; - - /// Up direction of Camera - glm::vec3 up; - - /// Direction to move Camera to the side, for panning - glm::vec3 cross; - - // Ortho view - float left; - - - // For mouse input and selection - glm::vec3 mouseRay; - - // For obtaining mouse position on screen - double xpos; - double ypos; - - void setXYView(); - - void setYZView(); - - void setZXView(); - - void update(); - - /** - * @brief - * - * @param yoffset - */ - void zoom(float yoffset); - - void updateMouseRay(float x, float y, glm::mat4 modelMat, glm::mat4 viewMat, glm::mat4 projMat, uint32_t width, - uint32_t height); - - void pan(glm::vec3 origin, glm::vec3 planeNormal); - - - }; - -} -} diff --git a/src/render/RenderUtil.cpp b/src/render/RenderUtil.cpp deleted file mode 100644 index 8fb029d..0000000 --- a/src/render/RenderUtil.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "pch.hpp" -#include "RenderUtil.hpp" \ No newline at end of file diff --git a/src/render/RenderUtil.hpp b/src/render/RenderUtil.hpp deleted file mode 100644 index b792235..0000000 --- a/src/render/RenderUtil.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - - - - -namespace CADERA_APP_NAMESPACE { - - const uint32_t BUF_SKETCH_GRID_LINE = 1; - const uint32_t BUF_SKETCH_GRID_AXII = 2; - const uint32_t BUF_SKETCH_POINTS = 3; - const uint32_t BUF_SELECTION_POINTS = 4; - const uint32_t BUF_TEXT_VERTICES = 5; - const uint32_t BUF_TEXT_INDICES = 6; - const uint32_t BUF_SKETCH_POINT_TOOL = 7; - - - struct Vertex { - glm::vec3 pos; - glm::vec3 col; - - }; - - -} - diff --git a/src/render/TextRender.cpp b/src/render/TextRender.cpp deleted file mode 100644 index e3cdbab..0000000 --- a/src/render/TextRender.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "pch.hpp" -#include "TextRender.hpp" - -void coutVec3(glm::vec3 v) { - std::cout << "x: " << v.x << " "; - std::cout << "y: " << v.y << " "; - std::cout << "z: " << v.z << " " << std::endl; -} - -namespace CADERA_APP_NAMESPACE { -namespace txt { - - TextRender::TextRender() { - mFontSize = 100.0; - mAtlasSize = 2864.0f; - - mCursorPos = { 0.0f, 0.0f, 0.0f }; - mCursorDirX = { 0.0f, 0.0f, 1.0f }; - mCursorDirY = { 0.0f, 1.0f, 0.0f }; - - textCounter = 0; - } - - TextRender::~TextRender() - { - } - - void TextRender::setFontSize(float s) { - - mFontSize = s; - } - - void TextRender::loadFont(std::string filePath) { - - Characters.clear(); - - std::ifstream fontAtlasCsv; - - std::string row, cell, value; - - - fontAtlasCsv.open(filePath); - - while (std::getline(fontAtlasCsv, row)) { - - - std::stringstream ss(row); - - Character C; - - std::vector values; - - while (ss.good()) { - std::getline(ss, cell, ','); - - values.push_back(std::stof(cell)); - - } - - C.xAdvance = values[1]; - C.x = values[2]; - C.y = values[5]; - C.width = (values[4] - values[2]); - C.height = (values[5] - values[3]); - C.textureCoords.x = values[6] / mAtlasSize; - C.textureCoords.z = values[8] / mAtlasSize; - C.textureCoords.y = 1.0f - values[7] / mAtlasSize; - C.textureCoords.w = 1.0f - values[9] / mAtlasSize; - - - Characters[(int)values[0]] = C; - - - - } - - - } - - void TextRender::setCursorPos(glm::vec3 pos) { - - mCursorPos = pos; - - } - - void TextRender::setPlane(glm::vec3 xDir, glm::vec3 yDir) { - - mCursorDirX = xDir; - mCursorDirY = yDir; - - } - - void TextRender::addText(Text T) { - - mTexts[textCounter] = T; - textCounter++; - - } - - void TextRender::addText(std::vector Ts) { - - for (const auto& T : Ts) { - - mTexts[textCounter] = T; - textCounter++; - - } - - } - - void TextRender::clearTexts() { - mTexts.clear(); - } - - std::vector TextRender::generateQuads() { - - numChars = 0; - - std::vector vertices; - - for (const auto& T : mTexts) { - - setCursorPos(T.second.cursorPos); - setPlane(glm::normalize(T.second.cursorDirX), glm::normalize(T.second.cursorDirY)); - - for (const auto& c : T.second.text) { - - - - glm::vec3 p0, p1, p2, p3; - - - // Character Atlas Values - glm::vec3 width, height, xAdvance, xBear, yBear; - - glm::vec2 A, B, C, D; - - // Change to vectors in the plane - xBear = T.second.textSize * Characters[c].x * mCursorDirX + T.second.offset.x * mCursorDirX; - yBear = T.second.textSize * Characters[c].y * mCursorDirY + T.second.offset.y * mCursorDirY; - width = T.second.textSize * Characters[c].width * mCursorDirX; - height = T.second.textSize * Characters[c].height * mCursorDirY; - xAdvance = T.second.textSize * Characters[c].xAdvance * mCursorDirX; - - - // If Space, just advance the cursor and move on - if (c == 32) { - - mCursorPos += xAdvance; - continue; - } - - - - // Texture Coordinates - A = { Characters[c].textureCoords.x , Characters[c].textureCoords.w }; - B = { Characters[c].textureCoords.x , Characters[c].textureCoords.y }; - C = { Characters[c].textureCoords.z , Characters[c].textureCoords.y }; - D = { Characters[c].textureCoords.z , Characters[c].textureCoords.w }; - - - // Construct the 4 points of the Quad - p0 = mCursorPos + xBear + yBear; - p1 = p0 - height; - p2 = p1 + width; - p3 = p2 + height; - - // Generate Vertices - Vertex V1 = { p0, T.second.textColor, T.second.backgroundColor, A }; - Vertex V2 = { p1, T.second.textColor, T.second.backgroundColor, B }; - Vertex V3 = { p2, T.second.textColor, T.second.backgroundColor, C }; - Vertex V4 = { p3, T.second.textColor, T.second.backgroundColor, D }; - - - - - vertices.push_back(V1); - vertices.push_back(V2); - vertices.push_back(V3); - vertices.push_back(V4); - - // Advance the text cursor to the next position - mCursorPos += xAdvance; - - numChars++; - - - - } - - - } - - return vertices; - - } - - std::vector TextRender::generateIndices() { - - std::vector indices; - - for (int i = 0; i < numChars; i++) { - indices.push_back(i * 4 + 0); - indices.push_back(i * 4 + 1); - indices.push_back(i * 4 + 2); - indices.push_back(i * 4 + 2); - indices.push_back(i * 4 + 3); - indices.push_back(i * 4 + 0); - - } - return indices; - - } - - -} -} diff --git a/src/render/TextRender.hpp b/src/render/TextRender.hpp deleted file mode 100644 index d5aced1..0000000 --- a/src/render/TextRender.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - - - - - - - -namespace CADERA_APP_NAMESPACE { -namespace txt { - - struct Text { - std::string text; - float textSize = 1.0f; - glm::vec3 textColor; - glm::vec3 backgroundColor; - glm::vec3 cursorPos; - glm::vec3 cursorDirX; - glm::vec3 cursorDirY; - glm::vec2 offset = {0.0f, 0.0f}; - - }; - - struct Vertex { - - glm::vec3 pos; - glm::vec3 textColor; - glm::vec3 backgroundColor; - glm::vec2 texCoord; - - }; - - struct Character { - float width; - float height; - float x; - float y; - float xAdvance; - glm::vec4 textureCoords; - - }; - - class TextRender { - - public: - TextRender(); - ~TextRender(); - - void setFontSize(float s); - - void loadFont(std::string filePath); - - void setCursorPos(glm::vec3 pos); - void setPlane(glm::vec3 xDir, glm::vec3 yDir); - - void addText(Text T); - void addText(std::vector Ts); - void clearTexts(); - - std::vector generateQuads(); - std::vector generateIndices(); - - private: - - std::map Characters; - - std::map mTexts; - - glm::vec3 mCursorPos; - glm::vec3 mCursorDirX; - glm::vec3 mCursorDirY; - - float mFontSize; - float mAtlasSize; - - int numChars; - int textCounter; - - }; -} -} - diff --git a/src/render/CADRender.cpp b/src/render/cadrender.cpp similarity index 92% rename from src/render/CADRender.cpp rename to src/render/cadrender.cpp index 6cfa87f..f2bd37c 100644 --- a/src/render/CADRender.cpp +++ b/src/render/cadrender.cpp @@ -1,4 +1,4 @@ -#include "CADRender.hpp" +#include "cadrender.hpp" #include "pch.hpp" #define STB_IMAGE_IMPLEMENTATION @@ -48,7 +48,7 @@ void CADRender::setup() { createSyncObjects(); } -void CADRender::setBGColor(glm::vec4 color) { bgColor = color; } +void CADRender::setBGColor(glm::vec4 color) { mRenderColors.bgColor = color; } void CADRender::createWindow() { glfwInit(); @@ -91,6 +91,8 @@ void CADRender::createInstance() { vk::Result result = vk::createInstance(&createInfo, nullptr, &mInstance); VULKAN_HPP_DEFAULT_DISPATCHER.init(mInstance); + + } void CADRender::createSurface() { @@ -402,7 +404,13 @@ vk::ImageView CADRender::createImageView(vk::Image image, vk::Format format, vk::ImageView imageView; - mDevice.createImageView(&createInfo, nullptr, &imageView); + vk::Result result{}; + + result = mDevice.createImageView(&createInfo, nullptr, &imageView); + + if (result != vk::Result::eSuccess) + throw("Failed to create ImageView"); + return imageView; } @@ -502,6 +510,7 @@ void CADRender::createRenderPass() { if (mDevice.createRenderPass(&renderPassInfo, nullptr, &mRenderPass) != vk::Result::eSuccess) throw std::runtime_error("failed to create render pass!"); + } void CADRender::createDescriptorSetLayout() { @@ -574,126 +583,25 @@ vk::ShaderModule CADRender::createShaderModule(const std::vector &code) { void CADRender::loadFonts() { TxtRend.setFontSize(100.0f); - TxtRend.loadFont("textures/test.csv"); + TxtRend.loadFont(config::arial_font_coordinates_file_path); } -void CADRender::createTextPipeline() { - - vk::VertexInputBindingDescription BindingDescription( - 0, sizeof(txt::Vertex), vk::VertexInputRate::eVertex); - - std::vector BindingDescriptions = { - BindingDescription}; - - std::vector AttributeDescriptions(4); - - AttributeDescriptions[0].binding = 0; - AttributeDescriptions[0].location = 0; - AttributeDescriptions[0].format = vk::Format::eR32G32B32Sfloat; - AttributeDescriptions[0].offset = offsetof(txt::Vertex, pos); - - AttributeDescriptions[1].binding = 0; - AttributeDescriptions[1].location = 1; - AttributeDescriptions[1].format = vk::Format::eR32G32B32Sfloat; - AttributeDescriptions[1].offset = offsetof(txt::Vertex, textColor); - - AttributeDescriptions[2].binding = 0; - AttributeDescriptions[2].location = 2; - AttributeDescriptions[2].format = vk::Format::eR32G32B32Sfloat; - AttributeDescriptions[2].offset = offsetof(txt::Vertex, backgroundColor); - - AttributeDescriptions[3].binding = 0; - AttributeDescriptions[3].location = 3; - AttributeDescriptions[3].format = vk::Format::eR32G32Sfloat; - AttributeDescriptions[3].offset = offsetof(txt::Vertex, texCoord); - - vk::PipelineVertexInputStateCreateInfo VertexInputInfo( - {}, static_cast(BindingDescriptions.size()), - BindingDescriptions.data(), - static_cast(AttributeDescriptions.size()), - AttributeDescriptions.data()); - - auto vertShaderCode = readFile("shaders/textvert.spv"); - auto fragShaderCode = readFile("shaders/textfrag.spv"); - - vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); - vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); - - vk::PipelineShaderStageCreateInfo VertShaderInfo( - {}, vk::ShaderStageFlagBits::eVertex, vertShaderModule, "main"); - vk::PipelineShaderStageCreateInfo FragShaderInfo( - {}, vk::ShaderStageFlagBits::eFragment, fragShaderModule, "main"); - - vk::PipelineShaderStageCreateInfo ShaderStages[] = {VertShaderInfo, - FragShaderInfo}; - - vk::PipelineInputAssemblyStateCreateInfo InputAssemblyInfo( - {}, vk::PrimitiveTopology::eTriangleList, VK_FALSE); - - vk::PipelineRasterizationStateCreateInfo RasterizerInfo( - {}, VK_FALSE, VK_FALSE, vk::PolygonMode::eFill, - vk::CullModeFlagBits::eNone, vk::FrontFace::eCounterClockwise, VK_FALSE); - - vk::Viewport ViewPort(0.0f, 0.0f, static_cast(mExtent.width), - static_cast(mExtent.height), 0.0f, 1.0f); - - vk::Rect2D Scissor({0, 0}, mExtent); - - vk::PipelineViewportStateCreateInfo ViewportInfo({}, 1, &ViewPort, 1, - &Scissor); - - vk::PipelineMultisampleStateCreateInfo MultisampleInfo( - {}, vk::SampleCountFlagBits::e1, VK_FALSE, 1.0f, nullptr, VK_FALSE, - VK_FALSE); - - vk::PipelineColorBlendAttachmentState ColorBlendAttachment( - VK_TRUE, vk::BlendFactor::eSrcAlpha, vk::BlendFactor::eOneMinusSrcAlpha, - vk::BlendOp::eAdd, vk::BlendFactor::eOne, vk::BlendFactor::eZero, - vk::BlendOp::eAdd, - vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | - vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); - - vk::PipelineColorBlendStateCreateInfo ColorBlendingInfo( - {}, VK_FALSE, vk::LogicOp::eCopy, 1, &ColorBlendAttachment, - {0.0f, 0.0f, 0.0f, 0.0f}); - - vk::PipelineDepthStencilStateCreateInfo depthStencilInfo( - {}, VK_TRUE, VK_TRUE, vk::CompareOp::eLess, VK_TRUE, VK_FALSE, {}, {}, - 0.0f, 1.0f); - - vk::GraphicsPipelineCreateInfo PipelineCreateInfo; - - PipelineCreateInfo.stageCount = 2; - PipelineCreateInfo.pStages = ShaderStages; - PipelineCreateInfo.pVertexInputState = &VertexInputInfo; - PipelineCreateInfo.pInputAssemblyState = &InputAssemblyInfo; - PipelineCreateInfo.pViewportState = &ViewportInfo; - PipelineCreateInfo.pRasterizationState = &RasterizerInfo; - PipelineCreateInfo.pMultisampleState = &MultisampleInfo; - PipelineCreateInfo.pDepthStencilState = &depthStencilInfo; - PipelineCreateInfo.pColorBlendState = &ColorBlendingInfo; - - PipelineCreateInfo.renderPass = mRenderPass; - PipelineCreateInfo.subpass = 0; - - PipelineCreateInfo.basePipelineIndex = -1; - PipelineCreateInfo.layout = mPipelineLayout; - - mTextPipeline = static_cast( - mDevice - .createGraphicsPipeline(mPipelineCache, PipelineCreateInfo, nullptr) - .value); - - mDevice.destroyShaderModule(vertShaderModule, nullptr); - mDevice.destroyShaderModule(fragShaderModule, nullptr); -} void CADRender::createCommandPool() { vk::CommandPoolCreateInfo commandPoolInfo( vk::CommandPoolCreateFlagBits::eTransient, mIndices.graphicsFamily); - mDevice.createCommandPool(&commandPoolInfo, nullptr, &mCommandPool); + + vk::Result result{}; + + result = mDevice.createCommandPool(&commandPoolInfo, nullptr, &mCommandPool); + + if (result != vk::Result::eSuccess) { + throw("Command Pool was not created!\n"); + } + + } uint32_t CADRender::findMemoryType(uint32_t typeFilter, @@ -868,7 +776,7 @@ void CADRender::createTextureImage() { int texWidth, texHeight, texChannels; - stbi_uc *pixels = stbi_load("textures/test.png", &texWidth, &texHeight, + stbi_uc *pixels = stbi_load(config::arial_font_texture_file_path, &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); vk::DeviceSize imageSize = (uint64_t)texWidth * (uint64_t)texHeight * 4; @@ -942,7 +850,14 @@ void CADRender::createFramebuffers() { {}, mRenderPass, static_cast(attachments.size()), attachments.data(), mExtent.width, mExtent.height, 1); - mDevice.createFramebuffer(&FramebufferInfo, nullptr, &mFramebuffers[i]); + + vk::Result result{}; + + result = mDevice.createFramebuffer(&FramebufferInfo, nullptr, &mFramebuffers[i]); + + if (result != vk::Result::eSuccess) + throw("Framebuffer was not created!\n"); + } } @@ -1145,8 +1060,8 @@ void CADRender::createSketchPointPipeline() { static_cast(AttributeDescriptions.size()), AttributeDescriptions.data()); - auto vertShaderCode = readFile("shaders/vert.spv"); - auto fragShaderCode = readFile("shaders/frag.spv"); + auto vertShaderCode = readFile(config::vertex_shader_file_path); + auto fragShaderCode = readFile(config::fragment_shader_file_path); vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); @@ -1245,8 +1160,8 @@ void CADRender::createSketchLinePipeline() { static_cast(AttributeDescriptions.size()), AttributeDescriptions.data()); - auto vertShaderCode = readFile("shaders/vert.spv"); - auto fragShaderCode = readFile("shaders/frag.spv"); + auto vertShaderCode = readFile(config::vertex_shader_file_path); + auto fragShaderCode = readFile(config::fragment_shader_file_path); vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); @@ -1369,8 +1284,8 @@ void CADRender::createSketchGridPipeline() { static_cast(AttributeDescriptions.size()), AttributeDescriptions.data()); - auto vertShaderCode = readFile("shaders/gridvert.spv"); - auto fragShaderCode = readFile("shaders/frag.spv"); + auto vertShaderCode = readFile(config::grid_vertex_shader_file_path); + auto fragShaderCode = readFile(config::fragment_shader_file_path); vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); @@ -1443,6 +1358,117 @@ void CADRender::createSketchGridPipeline() { mDevice.destroyShaderModule(fragShaderModule, nullptr); } +void CADRender::createTextPipeline() { + + vk::VertexInputBindingDescription BindingDescription( + 0, sizeof(txt::Vertex), vk::VertexInputRate::eVertex); + + std::vector BindingDescriptions = { + BindingDescription}; + + std::vector AttributeDescriptions(4); + + AttributeDescriptions[0].binding = 0; + AttributeDescriptions[0].location = 0; + AttributeDescriptions[0].format = vk::Format::eR32G32B32Sfloat; + AttributeDescriptions[0].offset = offsetof(txt::Vertex, pos); + + AttributeDescriptions[1].binding = 0; + AttributeDescriptions[1].location = 1; + AttributeDescriptions[1].format = vk::Format::eR32G32B32Sfloat; + AttributeDescriptions[1].offset = offsetof(txt::Vertex, textColor); + + AttributeDescriptions[2].binding = 0; + AttributeDescriptions[2].location = 2; + AttributeDescriptions[2].format = vk::Format::eR32G32B32Sfloat; + AttributeDescriptions[2].offset = offsetof(txt::Vertex, backgroundColor); + + AttributeDescriptions[3].binding = 0; + AttributeDescriptions[3].location = 3; + AttributeDescriptions[3].format = vk::Format::eR32G32Sfloat; + AttributeDescriptions[3].offset = offsetof(txt::Vertex, texCoord); + + vk::PipelineVertexInputStateCreateInfo VertexInputInfo( + {}, static_cast(BindingDescriptions.size()), + BindingDescriptions.data(), + static_cast(AttributeDescriptions.size()), + AttributeDescriptions.data()); + + auto vertShaderCode = readFile(config::text_vertex_shader_file_path); + auto fragShaderCode = readFile(config::text_fragment_shader_file_path); + + vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); + vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); + + vk::PipelineShaderStageCreateInfo VertShaderInfo( + {}, vk::ShaderStageFlagBits::eVertex, vertShaderModule, "main"); + vk::PipelineShaderStageCreateInfo FragShaderInfo( + {}, vk::ShaderStageFlagBits::eFragment, fragShaderModule, "main"); + + vk::PipelineShaderStageCreateInfo ShaderStages[] = {VertShaderInfo, + FragShaderInfo}; + + vk::PipelineInputAssemblyStateCreateInfo InputAssemblyInfo( + {}, vk::PrimitiveTopology::eTriangleList, VK_FALSE); + + vk::PipelineRasterizationStateCreateInfo RasterizerInfo( + {}, VK_FALSE, VK_FALSE, vk::PolygonMode::eFill, + vk::CullModeFlagBits::eNone, vk::FrontFace::eCounterClockwise, VK_FALSE); + + vk::Viewport ViewPort(0.0f, 0.0f, static_cast(mExtent.width), + static_cast(mExtent.height), 0.0f, 1.0f); + + vk::Rect2D Scissor({0, 0}, mExtent); + + vk::PipelineViewportStateCreateInfo ViewportInfo({}, 1, &ViewPort, 1, + &Scissor); + + vk::PipelineMultisampleStateCreateInfo MultisampleInfo( + {}, vk::SampleCountFlagBits::e1, VK_FALSE, 1.0f, nullptr, VK_FALSE, + VK_FALSE); + + vk::PipelineColorBlendAttachmentState ColorBlendAttachment( + VK_TRUE, vk::BlendFactor::eSrcAlpha, vk::BlendFactor::eOneMinusSrcAlpha, + vk::BlendOp::eAdd, vk::BlendFactor::eOne, vk::BlendFactor::eZero, + vk::BlendOp::eAdd, + vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); + + vk::PipelineColorBlendStateCreateInfo ColorBlendingInfo( + {}, VK_FALSE, vk::LogicOp::eCopy, 1, &ColorBlendAttachment, + {0.0f, 0.0f, 0.0f, 0.0f}); + + vk::PipelineDepthStencilStateCreateInfo depthStencilInfo( + {}, VK_TRUE, VK_TRUE, vk::CompareOp::eLess, VK_TRUE, VK_FALSE, {}, {}, + 0.0f, 1.0f); + + vk::GraphicsPipelineCreateInfo PipelineCreateInfo; + + PipelineCreateInfo.stageCount = 2; + PipelineCreateInfo.pStages = ShaderStages; + PipelineCreateInfo.pVertexInputState = &VertexInputInfo; + PipelineCreateInfo.pInputAssemblyState = &InputAssemblyInfo; + PipelineCreateInfo.pViewportState = &ViewportInfo; + PipelineCreateInfo.pRasterizationState = &RasterizerInfo; + PipelineCreateInfo.pMultisampleState = &MultisampleInfo; + PipelineCreateInfo.pDepthStencilState = &depthStencilInfo; + PipelineCreateInfo.pColorBlendState = &ColorBlendingInfo; + + PipelineCreateInfo.renderPass = mRenderPass; + PipelineCreateInfo.subpass = 0; + + PipelineCreateInfo.basePipelineIndex = -1; + PipelineCreateInfo.layout = mPipelineLayout; + + mTextPipeline = static_cast( + mDevice + .createGraphicsPipeline(mPipelineCache, PipelineCreateInfo, nullptr) + .value); + + mDevice.destroyShaderModule(vertShaderModule, nullptr); + mDevice.destroyShaderModule(fragShaderModule, nullptr); +} + void CADRender::preparePipelines() { createTextPipeline(); @@ -1465,7 +1491,7 @@ void CADRender::copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, endSingleTimeCommands(commandBuffer); } -void CADRender::deleteBuffer(uint32_t id) { +void CADRender::deleteBuffer(BufferName id) { mBuffers[id].isEmpty = true; mDevice.destroyBuffer(mBuffers[id].mBuffer); @@ -1485,7 +1511,11 @@ void CADRender::createCommandBuffers() { vk::Rect2D renderArea({0, 0}, {mExtent.width, mExtent.height}); - std::array color = {bgColor.x, bgColor.y, bgColor.z, bgColor.w}; + std::array color = {mRenderColors.bgColor.x, + mRenderColors.bgColor.y, + mRenderColors.bgColor.z, + mRenderColors.bgColor.w}; + std::array clearValues{}; clearValues[0].setColor(color); @@ -1506,57 +1536,58 @@ void CADRender::createCommandBuffers() { &mDescriptorSets[i], 0, nullptr); // Selection Points - if (!mBuffers[BUF_SELECTION_POINTS].isEmpty) { + if (!mBuffers[BufferName::selection_points].isEmpty) { mCommandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, Pipelines.SketchPoint); mCommandBuffers[i].bindVertexBuffers( - 0, 1, &mBuffers[BUF_SELECTION_POINTS].mBuffer, offsets); - mCommandBuffers[i].draw(mBuffers[BUF_SELECTION_POINTS].mPointSize, 1, 0, - 0); + 0, 1, &mBuffers[BufferName::selection_points].mBuffer, offsets); + mCommandBuffers[i].draw(mBuffers[BufferName::selection_points].mPointSize, + 1, 0, 0); } // Sketch Points - if (!mBuffers[BUF_SKETCH_POINTS].isEmpty) { + if (!mBuffers[BufferName::sketch_points].isEmpty) { mCommandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, Pipelines.SketchPoint); mCommandBuffers[i].bindVertexBuffers( - 0, 1, &mBuffers[BUF_SKETCH_POINTS].mBuffer, offsets); - mCommandBuffers[i].draw(mBuffers[BUF_SKETCH_POINTS].mPointSize + 2, 1, 0, - 0); + 0, 1, &mBuffers[BufferName::sketch_points].mBuffer, offsets); + mCommandBuffers[i].draw( + mBuffers[BufferName::sketch_points].mPointSize + 2, 1, 0, 0); } // Sketch Tools - if (!mBuffers[BUF_SKETCH_POINT_TOOL].isEmpty) { + if (!mBuffers[BufferName::sketch_point_tool].isEmpty) { mCommandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, Pipelines.SketchPoint); mCommandBuffers[i].bindVertexBuffers( - 0, 1, &mBuffers[BUF_SKETCH_POINT_TOOL].mBuffer, offsets); - mCommandBuffers[i].draw(mBuffers[BUF_SKETCH_POINT_TOOL].mPointSize, 1, 0, - 0); + 0, 1, &mBuffers[BufferName::sketch_point_tool].mBuffer, offsets); + mCommandBuffers[i].draw( + mBuffers[BufferName::sketch_point_tool].mPointSize, 1, 0, 0); } // Grid - if (!mBuffers[BUF_SKETCH_GRID_LINE].isEmpty) { + if (!mBuffers[BufferName::sketch_grid_line].isEmpty) { mCommandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, Pipelines.SketchGrid); mCommandBuffers[i].bindVertexBuffers( - 0, 1, &mBuffers[BUF_SKETCH_GRID_LINE].mBuffer, offsets); + 0, 1, &mBuffers[BufferName::sketch_grid_line].mBuffer, offsets); mCommandBuffers[i].bindVertexBuffers( - 1, 1, &mBuffers[BUF_SKETCH_GRID_AXII].mBuffer, offsets); - mCommandBuffers[i].draw(2, mBuffers[BUF_SKETCH_GRID_AXII].mPointSize, 0, - 0); + 1, 1, &mBuffers[BufferName::sketch_grid_axii].mBuffer, offsets); + mCommandBuffers[i].draw( + 2, mBuffers[BufferName::sketch_grid_axii].mPointSize, 0, 0); } // Text - if (!mBuffers[BUF_TEXT_VERTICES].isEmpty) { + if (!mBuffers[BufferName::text_vertices].isEmpty) { mCommandBuffers[i].bindPipeline(vk::PipelineBindPoint::eGraphics, mTextPipeline); mCommandBuffers[i].bindVertexBuffers( - 0, 1, &mBuffers[BUF_TEXT_VERTICES].mBuffer, offsets); - mCommandBuffers[i].bindIndexBuffer(mBuffers[BUF_TEXT_INDICES].mBuffer, 0, - vk::IndexType::eUint32); - mCommandBuffers[i].drawIndexed(mBuffers[BUF_TEXT_INDICES].mPointSize, 1, - 0, 0, 0); + 0, 1, &mBuffers[BufferName::text_vertices].mBuffer, offsets); + mCommandBuffers[i].bindIndexBuffer( + mBuffers[BufferName::text_indices].mBuffer, 0, + vk::IndexType::eUint32); + mCommandBuffers[i].drawIndexed( + mBuffers[BufferName::text_indices].mPointSize, 1, 0, 0, 0); } ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), mCommandBuffers[i]); @@ -1600,13 +1631,19 @@ void CADRender::updateUniformBuffer(uint32_t currentImage) { void CADRender::drawFrame() { - mDevice.waitForFences(mInFlightFences[mCurrentFrame], VK_TRUE, UINT64_MAX); + vk::Result result{}; + + result = mDevice.waitForFences(mInFlightFences[mCurrentFrame], VK_TRUE, UINT64_MAX); + + if (result != vk::Result::eSuccess) + throw("waitForFences failed! \n"); + uint32_t imageIndex = 0; vk::Fence F; - vk::Result result = mDevice.acquireNextImageKHR( + result = mDevice.acquireNextImageKHR( mSwapchain, UINT64_MAX, mImageAvailableSemaphores[mCurrentFrame], F, &imageIndex); @@ -1702,8 +1739,6 @@ void CADRender::cleanup() { } } - mDevice.destroyDescriptorPool(mDescriptorPool); - for (auto &framebuffer : mFramebuffers) { mDevice.destroyFramebuffer(framebuffer, nullptr); } @@ -1712,6 +1747,10 @@ void CADRender::cleanup() { mDevice.destroyBuffer(Buffer); } + for (auto &memory : mUniformBufferMemories) { + mDevice.freeMemory(memory); + } + mDevice.destroySampler(mTextureSampler); mDevice.destroyImageView(mTextureImageView); mDevice.destroyImage(mTextureImage); @@ -1722,7 +1761,8 @@ void CADRender::cleanup() { mDevice.destroyImageView(depthImageView); mDevice.destroyCommandPool(mCommandPool); - + mDevice.destroyDescriptorPool(mGuiDescriptorPool); + mDevice.destroyDescriptorPool(mDescriptorPool); mDevice.destroyPipelineLayout(mPipelineLayout, nullptr); mDevice.destroyDescriptorSetLayout(mDescriptorSetLayout, nullptr); mDevice.destroy(mRenderPass, nullptr); @@ -1734,6 +1774,7 @@ void CADRender::cleanup() { mDevice.destroySwapchainKHR(mSwapchain, nullptr); vkDestroyDevice(mDevice, nullptr); + vkDestroySurfaceKHR(mInstance, mImguiSurface, nullptr); vkDestroySurfaceKHR(mInstance, mSurface, nullptr); vkDestroyInstance(mInstance, nullptr); @@ -1778,18 +1819,28 @@ void CADRender::render(Model &M) { void CADRender::renderSketchGrid(Model &S) { std::vector axii; - std::vector line; + std::vector line; + + std::vector Vertices; axii = S.getGridAxii(); line = S.getGridLine(); - if (!axii.empty() && !line.empty()) { - updateBuffer(BUF_SKETCH_GRID_LINE, line, + + // Convert vector of glm::vec3 to vector of Vertex + for (const auto &point : line) { + + Vertex V = {point, {0.0f, 0.0f, 0.0f}}; + Vertices.push_back(V); + } + + if (!axii.empty() && !Vertices.empty()) { + updateBuffer(BufferName::sketch_grid_line, Vertices, vk::BufferUsageFlagBits::eVertexBuffer); - updateBuffer(BUF_SKETCH_GRID_AXII, axii, + updateBuffer(BufferName::sketch_grid_axii, axii, vk::BufferUsageFlagBits::eVertexBuffer); } else { - deleteBuffer(BUF_SKETCH_GRID_LINE); - deleteBuffer(BUF_SKETCH_GRID_AXII); + deleteBuffer(BufferName::sketch_grid_line); + deleteBuffer(BufferName::sketch_grid_axii); } } @@ -1809,17 +1860,17 @@ void CADRender::renderSketchNotes(Model &S) { TxtRend.addText(T); } - std::vector txtVertices = TxtRend.generateQuads(); + std::vector txtVertices = TxtRend.generateQuads(mRenderColors.bgColor); std::vector txtIndices = TxtRend.generateIndices(); if (!txtVertices.empty()) { - updateBuffer(BUF_TEXT_VERTICES, txtVertices, + updateBuffer(BufferName::text_vertices, txtVertices, vk::BufferUsageFlagBits::eVertexBuffer); - updateBuffer(BUF_TEXT_INDICES, txtIndices, + updateBuffer(BufferName::text_indices, txtIndices, vk::BufferUsageFlagBits::eIndexBuffer); - } else if (!mBuffers[BUF_TEXT_VERTICES].isEmpty) { - deleteBuffer(BUF_TEXT_VERTICES); - deleteBuffer(BUF_TEXT_INDICES); + } else if (!mBuffers[BufferName::text_vertices].isEmpty) { + deleteBuffer(BufferName::text_vertices); + deleteBuffer(BufferName::text_indices); } } @@ -1834,7 +1885,7 @@ void CADRender::renderSketchPoints(Model &S) { if (!selPointVertices.empty()) { for (const auto &v : selPointVertices) { - Vertices.push_back({v, {0.0f, 1.0f, 0.0f}}); + Vertices.push_back({v, {mRenderColors.selPointColor.x, mRenderColors.selPointColor.y, mRenderColors.selPointColor.z}}); } } @@ -1846,10 +1897,10 @@ void CADRender::renderSketchPoints(Model &S) { } if (!Vertices.empty()) { - updateBuffer(BUF_SKETCH_POINTS, Vertices, + updateBuffer(BufferName::sketch_points, Vertices, vk::BufferUsageFlagBits::eVertexBuffer); - } else if (!mBuffers[BUF_SKETCH_POINTS].isEmpty) { - deleteBuffer(BUF_SKETCH_POINTS); + } else if (!mBuffers[BufferName::sketch_points].isEmpty) { + deleteBuffer(BufferName::sketch_points); } } @@ -1881,10 +1932,10 @@ void CADRender::renderSketchPointTool() { } if (!Vertices.empty()) { - updateBuffer(BUF_SKETCH_POINT_TOOL, Vertices, + updateBuffer(BufferName::sketch_point_tool, Vertices, vk::BufferUsageFlagBits::eVertexBuffer); - } else if (!mBuffers[BUF_SKETCH_POINT_TOOL].isEmpty) { - deleteBuffer(BUF_SKETCH_POINT_TOOL); + } else if (!mBuffers[BufferName::sketch_point_tool].isEmpty) { + deleteBuffer(BufferName::sketch_point_tool); } } diff --git a/src/render/cadrender.hpp b/src/render/cadrender.hpp new file mode 100644 index 0000000..cfe8da5 --- /dev/null +++ b/src/render/cadrender.hpp @@ -0,0 +1,416 @@ +#pragma once + +#include "ux/command/mouse.hpp" +#include "callbacks.hpp" + +namespace CADERA_APP_NAMESPACE { + +struct Vertex { + glm::vec3 pos; + glm::vec3 col; +}; + +enum class BufferName { + + sketch_grid_line = 0, + sketch_grid_axii = 1, + sketch_points = 2, + selection_points = 3, + text_vertices = 4, + text_indices = 5, + sketch_point_tool = 6, +}; + +struct SwapChainSupportDetails { + vk::SurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector presentModes; +}; + +struct QueueFamilyIndices { + int graphicsFamily = -1; + int presentFamily = -1; + + bool isComplete() { return graphicsFamily >= 0 && presentFamily >= 0; } + + bool isDifferent() { return graphicsFamily != presentFamily; } +}; + +struct ubo { + glm::mat4 model; + glm::mat4 view; + glm::mat4 proj; +}; + +struct Buffer { + + vk::Buffer mBuffer; + vk::DeviceMemory mMemory; + vk::DeviceSize mDeviceSize; + uint32_t mPointSize; + bool isEmpty = true; +}; + +enum RenderFlags { render_update_sketch, render_num_flags }; + +struct RendorColors { + glm::vec4 bgColor = {0.0f, 0.0f, 0.0f, 1.0f}; + glm::vec4 selPointColor = {0.0f, 1.0f, 0.0f, 1.0f}; + glm::vec4 sketchPointColor = {1.0f, 1.0f, 1.0f, 1.0f}; + glm::vec4 sketchLineColor = {1.0f, 1.0f, 1.0f, 1.0f}; + glm::vec4 sketchGridColor = {0.5f, 0.5f, 0.5f, 1.0f}; +}; + + +class CADRender { + +private: + std::vector validationLayers = { + "VK_LAYER_LUNARG_standard_validation"}; + + std::vector deviceExtensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + + vk::DescriptorPool mGuiDescriptorPool; + VkAllocationCallbacks *mGuiAllocator; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = 0; + PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTag = 0; + PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = 0; + PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = 0; + PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = 0; + PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = 0; + + struct { + + vk::Pipeline SketchPoint; + vk::Pipeline SketchLine; + vk::Pipeline SketchGrid; + + } Pipelines; + + + + +public: + // Restructure + + command::Mouse mouse; + + // GLFW + GLFWwindow *mMainWindow; + + // Main Vulkan Objects + vk::Instance mInstance; + vk::PhysicalDevice mPhysicalDevice; + vk::Device mDevice; + vk::RenderPass mRenderPass; + + // Secondary Vulkan Objects + + // mInstance + vk::detail::DynamicLoader dl; + vk::detail::DispatchLoaderDynamic dldy; + VkDebugUtilsMessengerEXT mDebug; + vk::ApplicationInfo mAppInfo; + bool enableValidationLayers; + vk::DebugUtilsMessengerEXT mCallback; + vk::SurfaceKHR mSurface; + + // Physical mDevice + QueueFamilyIndices mIndices; + + // Logical mDevice + vk::Queue mGraphicsQueue; + vk::Queue mPresentQueue; + + // Swapchain + int mWidth = 750; + int mHeight = 750; + + bool frameBufferResized; + + std::vector mImages; + std::vector mImageViews; + vk::Format mFormat; + vk::Extent2D mExtent; + + vk::Image depthImage; + vk::DeviceMemory depthImageMemory; + vk::ImageView depthImageView; + + vk::SwapchainKHR mSwapchain; + + // Pipeline + vk::PipelineCache mPipelineCache; + + vk::PipelineLayout mPipelineLayout; + + vk::Pipeline mTextPipeline; + + // Buffers + vk::CommandPool mCommandPool; + std::vector mCommandBuffers; + std::vector mFramebuffers; + + std::vector mUniformBuffers; + std::vector mUniformBufferMemories; + + vk::DescriptorPool mDescriptorPool; + std::vector mDescriptorSets; + + std::map mBuffers; + + // Textures + vk::Image mTextureImage; + vk::DeviceMemory mTextureMemory; + vk::ImageView mTextureImageView; + vk::Sampler mTextureSampler; + + // Sync Objects + std::vector mImageAvailableSemaphores; + std::vector mRenderFinishedSemaphores; + std::vector mInFlightFences; + size_t mCurrentFrame = 0; + + // Options + + vk::DescriptorSetLayout mDescriptorSetLayout; + + std::bitset flags; + + ubo u; + + cam::Camera Cam; + + sel::Selector Sel; + + sketch::SketchSolver SktSolver; + + txt::TextRender TxtRend; + + // Imgui + + ImGui_ImplVulkanH_Window mImguiWindowData; + VkSurfaceKHR mImguiSurface; + + RendorColors mRenderColors; + + void setup(); + + //------------------------------------------- + + // Functions + + void setBGColor(glm::vec4 color); + + // GLFW + + void createWindow(); + + // Instance + + void createInstance(); + + void createSurface(); + + // Physical Device + + void pickPhysicalDevice(); + + SwapChainSupportDetails + querySwapChainSupport(const vk::PhysicalDevice &device); + + QueueFamilyIndices findQueueFamilies(vk::PhysicalDevice device, + VkSurfaceKHR surface); + + bool isDeviceSuitable(vk::PhysicalDevice device); + + bool checkDeviceExtensionSupport(vk::PhysicalDevice device); + + // Logical mDevice + void createLogicalDevice(); + + // Swapchain + bool checkFormat(vk::Format Format); + + vk::SurfaceFormatKHR chooseSwapSurfaceFormat( + const std::vector &availableFormats); + + vk::PresentModeKHR chooseSwapPresentMode( + const std::vector availablePresentModes); + + vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities); + + void createSwapChain(); + + void recreateSwapchain(); + + void createImageViews(); + + vk::ImageView createImageView(vk::Image image, vk::Format format, + vk::ImageAspectFlags aspectFlags); + + vk::Format findSupportedFormat(vk::PhysicalDevice const &PhysicalDevice, + const std::vector &candidates, + vk::ImageTiling tiling, + vk::FormatFeatureFlags features); + + vk::Format findDepthFormat(vk::PhysicalDevice const &PhysicalDevice); + + void createRenderPass(); + + void createDescriptorSetLayout(); + + void createPipelineLayout(); + + std::vector readFile(const std::string filename); + + vk::ShaderModule createShaderModule(const std::vector &code); + + void loadFonts(); + + void createTextPipeline(); + + void createCommandPool(); + + uint32_t findMemoryType(uint32_t typeFilter, + vk::MemoryPropertyFlags properties); + + void createImage(vk::PhysicalDevice const &PhysicalDevice, + vk::Device const &Device, uint32_t width, uint32_t height, + vk::Format format, vk::ImageTiling tiling, + vk::ImageUsageFlags usage, + vk::MemoryPropertyFlags properties, vk::Image &image, + vk::DeviceMemory &imageMemory); + + void createDepthResources(); + + void createBuffer(vk::DeviceSize &size, const vk::BufferUsageFlags &usage, + const vk::MemoryPropertyFlags &properties, + vk::Buffer &buffer, vk::DeviceMemory &bufferMemory); + + vk::CommandBuffer + beginSingleTimeCommands(const vk::CommandBufferLevel &level, + const vk::CommandBufferInheritanceInfo &inheritance); + + void endSingleTimeCommands(vk::CommandBuffer &commandBuffer); + + void transitionImageLayout(vk::Image &image, vk::Format format, + vk::ImageLayout oldLayout, + vk::ImageLayout newLayout); + + void copyBufferToImage(vk::Buffer &buffer, vk::Image &image, uint32_t width, + uint32_t height); + + void createTextureImage(); + + void createTextureImageView(); + + void createTextureSampler(); + + void createFramebuffers(); + + void createUniformBuffer(); + + void createDescriptorPool(); + + void createDescriptorSets(); + + void allocCommandBuffers(); + + void createSyncObjects(); + + void initImgui(); + + void createSketchPointPipeline(); + + void createSketchLinePipeline(); + + void createSketchGridPipeline(); + + void preparePipelines(); + + void copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, + vk::DeviceSize size); + + void deleteBuffer(BufferName id); + + void createCommandBuffers(); + + void updateUniformBuffer(uint32_t currentImage); + + void drawFrame(); + + template + inline void createDeviceBuffer(BufferName id, std::vector const &points, + vk::BufferUsageFlagBits const &flag) { + + vk::Buffer stagingBuffer; + vk::DeviceMemory stagingBufferMemory; + + mBuffers[id].mPointSize = static_cast(points.size()); + mBuffers[id].mDeviceSize = sizeof(points[0]) * points.size(); + + createBuffer(mBuffers[id].mDeviceSize, + vk::BufferUsageFlagBits::eTransferSrc, + vk::MemoryPropertyFlagBits::eHostVisible | + vk::MemoryPropertyFlagBits::eHostCoherent, + stagingBuffer, stagingBufferMemory); + + vk::MemoryMapFlags memMapFlags; + + void *data; + data = mDevice.mapMemory(stagingBufferMemory, 0, mBuffers[id].mDeviceSize, + memMapFlags); + memcpy(data, points.data(), (size_t)mBuffers[id].mDeviceSize); + mDevice.unmapMemory(stagingBufferMemory); + + createBuffer(mBuffers[id].mDeviceSize, + vk::BufferUsageFlagBits::eTransferDst | flag, + vk::MemoryPropertyFlagBits::eDeviceLocal, mBuffers[id].mBuffer, + mBuffers[id].mMemory); + + copyBuffer(stagingBuffer, mBuffers[id].mBuffer, mBuffers[id].mDeviceSize); + + mDevice.destroyBuffer(stagingBuffer); + mDevice.freeMemory(stagingBufferMemory); + + mBuffers[id].isEmpty = false; + }; + + template + inline void updateBuffer(BufferName id, std::vector const &points, + vk::BufferUsageFlagBits const &flag) { + if (mBuffers[id].isEmpty) { + createDeviceBuffer(id, points, flag); + } else { + deleteBuffer(id); + createDeviceBuffer(id, points, flag); + } + } + + void destroyPipelines(); + + void cleanupSwapchain(); + + // Cleanup + void cleanup(); + + void destroy(); + + void runCamera(); + + void render(Model &M); + + void renderSketchGrid(Model &S); + + void renderSketchNotes(Model &S); + + void renderSketchPoints(Model &S); + + void renderSketchPointTool(); +}; +} // namespace CADERA_APP_NAMESPACE diff --git a/src/render/camera.cpp b/src/render/camera.cpp new file mode 100644 index 0000000..f3b430b --- /dev/null +++ b/src/render/camera.cpp @@ -0,0 +1,131 @@ +#include "camera.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace cam { + +Camera::Camera() { + pos = {0.0f, 0.0f, 20.0f}; + focus = {0.0f, 0.0f, 0.0f}; + cameraVec = {0.0f, 0.0f, -1.0f}; + xpos = 0.0; + ypos = 0.0; + mouseRay = {0.0f, 0.0f, 0.0f}; + left = -10.0f; + camDistance = 0.0f; + + up = {0.0f, 1.0f, 0.0f}; + + cross = glm::cross(cameraVec, up); +} + +void Camera::setXYView() { + + pos = {0.0f, 0.0f, 20.0f}; + focus = {0.0f, 0.0f, 0.0f}; + cameraVec = {0.0f, 0.0f, -1.0f}; + + up = {0.0f, 1.0f, 0.0f}; + cross = glm::cross(cameraVec, up); +} + +void Camera::setYZView() { + + pos = {20.0f, 0.0f, 0.0f}; + focus = {0.0f, 0.0f, 0.0f}; + cameraVec = {-1.0f, 0.0f, 0.0f}; + + up = {0.0f, 0.0f, 1.0f}; + cross = glm::cross(cameraVec, up); +} + +void Camera::setZXView() { + + pos = {0.0f, 20.0f, 0.0f}; + focus = {0.0f, 0.0f, 0.0f}; + cameraVec = {0.0f, -1.0f, 0.0f}; + + up = {1.0f, 0.0f, 0.0f}; + cross = glm::cross(cameraVec, up); +} + +void Camera::update() { camDistance = glm::length(pos - focus); } + +void Camera::zoom(float yoffset) { + + if (flags.test(ortho)) { + + if (yoffset > 0 && left < -1.02) { + left += 1.0f; + } else if (yoffset < 0) { + left -= 1.0f; + } + } else { + + glm::vec3 normalPos = {0.0f, pos.y, pos.z}; + + if (yoffset > 0) { + pos -= 1.0f * glm::normalize(cameraVec); + } else if (yoffset < 0 && glm::length2(pos - focus) > 1.02f) { + pos += 1.0f * glm::normalize(cameraVec); + } + } +} + +void Camera::updateMouseRay(float x, float y, glm::mat4 modelMat, + glm::mat4 viewMat, glm::mat4 projMat, + uint32_t width, uint32_t height) { + + if (flags.test(ortho)) { + mouseRay = glm::unProject(glm::vec3(x, y, 0.0f), modelMat, projMat, + glm::vec4(0.0f, 0.0f, width, height)); + } else { + mouseRay = sel::calcCurrentRay(x, y, viewMat, projMat, width, height); + } +} + +/** + * @brief + * + * @param origin Origin point of the plane. + * This is used for calulating the point on the plane for projection view + * + * @param planeNormal The normal vector of the plane to pan on + */ +void Camera::pan(glm::vec3 origin, glm::vec3 planeNormal) { + + static glm::vec3 prevMouseRay = mouseRay; + glm::vec3 p1, p2, diff; + + if (flags.test(mouseFirstPressed)) { + + prevMouseRay = mouseRay; + flags.reset(mouseFirstPressed); + } + + if (flags.test(ortho)) { + + diff = mouseRay - prevMouseRay; + + pos -= diff.y * up; + pos -= diff.x * cross; + focus -= diff.y * up; + focus -= diff.x * cross; + + } else { + + p1 = sel::calcPOnPlane(prevMouseRay, origin, planeNormal, pos); + p2 = sel::calcPOnPlane(mouseRay, origin, planeNormal, pos); + + diff = p2 - p1; + + pos -= diff; + focus -= diff; + } + + prevMouseRay = mouseRay; +} + +} // namespace cam +} // namespace CADERA_APP_NAMESPACE diff --git a/src/render/camera.hpp b/src/render/camera.hpp new file mode 100644 index 0000000..978b066 --- /dev/null +++ b/src/render/camera.hpp @@ -0,0 +1,78 @@ +#pragma once +#include "selection.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace cam { + +enum CameraFlags { + /// Toggle orthographics projection + ortho, + /// Used for resetting functions such as pan() on first mouse click + mouseFirstPressed, + /// Toggle the camera pan() function + pan, + /// Bitset size + camera_number_flags +}; + +/** + * @brief + * + * + */ +class Camera { + +public: + Camera(); + + std::bitset flags; + + /// Position of the camera in 3D space + glm::vec3 pos; + /// Focus point of the camera in 3D space + glm::vec3 focus; + /// The vector going from pos to focus + glm::vec3 cameraVec; + /// The length of the cameraVec vector + float camDistance; + + /// Up direction of Camera + glm::vec3 up; + + /// Direction to move Camera to the side, for panning + glm::vec3 cross; + + // Ortho view + float left; + + // For mouse input and selection + glm::vec3 mouseRay; + + // For obtaining mouse position on screen + double xpos; + double ypos; + + void setXYView(); + + void setYZView(); + + void setZXView(); + + void update(); + + /** + * @brief + * + * @param yoffset + */ + void zoom(float yoffset); + + void updateMouseRay(float x, float y, glm::mat4 modelMat, glm::mat4 viewMat, + glm::mat4 projMat, uint32_t width, uint32_t height); + + void pan(glm::vec3 origin, glm::vec3 planeNormal); +}; + +} // namespace cam +} // namespace CADERA_APP_NAMESPACE diff --git a/src/render/grid.cpp b/src/render/grid.cpp deleted file mode 100644 index a8d0222..0000000 --- a/src/render/grid.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "pch.hpp" -#include "grid.hpp" - - -namespace CADERA_APP_NAMESPACE { - -Grid::Grid() { - - size = 10; - spacing = 1.0f; - - p1 = { {0.0f, -size, 0.0f}, {.0f, .0f, .0f} }; - p2 = { {0.0f, size, 0.0f}, {.0f, .0f, .0f} }; - - line = { p1, p2 }; - - gUp = {0.0f, 1.0f, 0.0f}; - gCross = {1.0f, 0.0f, 0.0f}; - gNormal = {0.0f, 0.0f, 1.0f}; -} - -void Grid::setGridOrientation(glm::vec3 normal, glm::vec3 up, glm::vec3 cross) { - gNormal = normal; - gUp = up; - gCross = cross; -} - -std::vector Grid::createGridInstanceAxii() { - - std::vector axii; - - - p1 = {(-size*spacing) * gUp, {.0f, .0f, .0f}};//{ {0.0f, -size * spacing, 0.0f}, {.0f, .0f, .0f} }; - p2 = {(size*spacing) * gUp, {.0f, .0f, .0f}};// { {0.0f, size * spacing, 0.0f}, {.0f, .0f, .0f} }; - - line = { p1, p2 }; - - float position = -size * spacing; - for (int i = 0; i < 2*size+1 ; i++) { - - GridRotationAxis axis = { - position*gCross, - gNormal, - {0.0f, 0.0f, 0.0f}, - 0.0f - }; - - - if (i == size) { - axis.color = {0.0f, 1.0f, 0.0f}; - } - - axii.push_back(axis); - - axis.angle = 90.0f; - - if (i == size) { - axis.color = {1.0f, 0.0f, 0.0f}; - } - - axii.push_back(axis); - - position += spacing; - } - - - return axii; - } - -} diff --git a/src/render/grid.hpp b/src/render/grid.hpp deleted file mode 100644 index fa3f1b8..0000000 --- a/src/render/grid.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include "render/RenderUtil.hpp" - -namespace CADERA_APP_NAMESPACE { - -struct GridRotationAxis { - glm::vec3 pos; - glm::vec3 axis; - glm::vec3 color; - float angle; -}; - - -class Grid { - - public: - - - Grid(); - - void setGridOrientation(glm::vec3 normal, glm::vec3 up, glm::vec3 cross); - - - - /// @brief To generate the values needed to instance each grid line from the base line - /// @return Vector to be used for rendering the instances - std::vector createGridInstanceAxii(); - - Vertex p1; - Vertex p2; - - glm::vec3 gNormal; - glm::vec3 gUp; - glm::vec3 gCross; - - /// @brief The container for rendering the base line - std::vector line; - - /// @brief The size of the grid. The number of times the grid gets incremented. - int32_t size; - - /// @brief The spacing between each line in the grid - float spacing; - - -}; -} \ No newline at end of file diff --git a/src/selection.cpp b/src/selection.cpp new file mode 100644 index 0000000..2392e2b --- /dev/null +++ b/src/selection.cpp @@ -0,0 +1,310 @@ +#include "selection.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sel { + +float calcRatioToPlane(glm::vec3 currentRay, glm::vec3 cameraToPlaneDist, + glm::vec3 planeOrigin, glm::vec3 planeNormal) { + + float ratio; + + glm::vec3 rayProjToPlaneNormalDist; + glm::vec3 cameraToNormalPlaneDist; + + cameraToNormalPlaneDist = + (glm::dot(cameraToPlaneDist, planeNormal) * planeNormal); + rayProjToPlaneNormalDist = (glm::dot(currentRay, planeNormal) * planeNormal); + + ratio = std::fabs(glm::length(cameraToNormalPlaneDist) / + glm::length(rayProjToPlaneNormalDist)); + + return ratio; +} + +glm::vec3 calcPOnPlane(glm::vec3 currentRay, glm::vec3 origin, glm::vec3 normal, + glm::vec3 pos) { + + glm::vec3 cameraToPlaneDist; + float ratio; + glm::vec3 vecCamToPOnPlane; + glm::vec3 POnPlaneCoord; + + cameraToPlaneDist = {pos.x - origin.x, pos.y - origin.y, pos.z - origin.z}; + + ratio = calcRatioToPlane(currentRay, cameraToPlaneDist, origin, normal); + + vecCamToPOnPlane = ratio * currentRay; + POnPlaneCoord = cameraToPlaneDist + vecCamToPOnPlane + origin; + + return POnPlaneCoord; +} + +glm::vec2 normalizeToVulkanCoords(glm::vec2 screenCoords, uint32_t surfaceWidth, + uint32_t surfaceHeight) { + glm::vec2 normCoords; + + normCoords.x = 2.0f * screenCoords.x / static_cast(surfaceWidth) - 1.0f; + normCoords.y = + 2.0f * screenCoords.y / static_cast(surfaceHeight) - 1.0f; + + return normCoords; +} + +glm::vec4 clipToEyeSpace(glm::vec4 clipCoords, glm::mat4 projMat) { + glm::vec4 eyeCoords; + glm::mat4 inverseProjection; + + inverseProjection = glm::inverse(projMat); + eyeCoords = inverseProjection * clipCoords; + eyeCoords.z = -1.0f; + eyeCoords.w = 0.0f; + + return eyeCoords; +} + +glm::vec3 toWorldCoord(glm::vec4 eyeCoords, glm::mat4 viewMat) { + glm::vec3 mouseRay; + glm::vec4 rayWorld; + glm::mat4 inverseView; + + inverseView = glm::inverse(viewMat); + rayWorld = inverseView * eyeCoords; + mouseRay = {rayWorld.x, rayWorld.y, rayWorld.z}; + mouseRay = glm::normalize(mouseRay); + + return mouseRay; +} + +glm::vec3 calcCurrentRay(float x, float y, glm::mat4 viewMat, glm::mat4 projMat, + uint32_t width, uint32_t height) { + glm::vec2 screenCoords; + glm::vec2 normCoords; + glm::vec4 clipCoords; + glm::vec4 eyeCoords; + + glm::vec3 currentRay; + + screenCoords = {x, y}; + + normCoords = normalizeToVulkanCoords(screenCoords, width, height); + clipCoords = {normCoords.x, normCoords.y, -1.0f, 1.0f}; + eyeCoords = clipToEyeSpace(clipCoords, projMat); + + currentRay = toWorldCoord(eyeCoords, viewMat); + + return currentRay; +} + +Selector::Selector() { + + point = {0.0f, 0.0f, 0.0f}; + + flags.set(select_first_click); +} + +void Selector::setActiveSketch(sketch::Sketch *pSketch) { + + pActiveSketch = pSketch; +} + +void Selector::select(glm::vec3 mouseRay, glm::vec3 origin, glm::vec3 normal, + glm::vec3 pos, glm::vec3 cross, bool isOrtho) { + + if (isOrtho) { + glm::vec3 up = glm::cross(cross, normal); + + glm::vec3 x = mouseRay.x * cross; + glm::vec3 y = mouseRay.y * up; + + glm::vec3 posOnPlane = origin + (up + cross) * pos; + point = posOnPlane + x + y; + } else { + point = calcPOnPlane(mouseRay, origin, normal, pos); + } +} + +int Selector::selectPoint(glm::vec3 pointToAdd, std::map &points, + float skScale) { + + std::vector sortedIndices; + double sensitivity = skScale / 800.0f; + + for (const auto &point : points) { + glm::vec3 pointVec; + double length; + + pointVec = pointToAdd - point.second.pos; + + length = glm::length2(pointVec); + + if (length < sensitivity) { + return point.first; + } + } + + return -1; +} + +void Selector::update(std::map points) { + + selectedPoints.clear(); + + for (const auto &point : points) { + + selectedPoints[point.first] = point.second; + } +} + +int Selector::add(glm::vec3 pointToAdd, std::map &points, + float skScale) { + + // Clear selected points if CTRL isn't pressed + if (!flags.test(select_isCTRL)) { + selectedPoints.clear(); + setFlags(); + } + + pointJustAdded = false; + + int selectedPointId = selectPoint(pointToAdd, points, skScale); + + // If a point is selected + if (selectedPointId >= 0) { + + // If not in selectedPoints, add it, else remove it + if (selectedPoints.find(selectedPointId) == selectedPoints.end()) { + + selectedPoints[selectedPointId] = points[selectedPointId]; + setFlags(); + + pointJustAdded = true; + + return selectedPointId; + } + } + + // If not CTRL and selectedPointId < 0 + if (!flags.test(select_isCTRL)) { + + selectedPoints.clear(); + setFlags(); + } + + return selectedPointId; +} + +int Selector::remove(glm::vec3 pointToRemove, std::map &points, + float skScale) { + if (!flags.test(select_isCTRL)) + return -1; + + if (pointJustAdded) + return -1; + + int selectedPointId = selectPoint(pointToRemove, points, skScale); + + if (selectedPointId >= 0) { + + selectedPoints.erase(selectedPointId); + setFlags(); + + return selectedPointId; + } + + return -1; +} + +bool Selector::existingPoint(glm::vec3 point) { + + if (pActiveSketch == nullptr) + throw std::runtime_error( + "Selection.existingPoint(): pActiveSketch is not set!"); + + int16_t pointSketchId = -1; + + // If there are points in sketch + if (pActiveSketch->Points.size() > 0) { + + if (pActiveSketch->mCamDistance == nullptr) + throw std::runtime_error( + "Selection.existingPoint(): pActiveSketch->mCamDistance is nullptr!"); + + pointSketchId = sel::Selector::selectPoint(point, pActiveSketch->Points, + *pActiveSketch->mCamDistance); + + // Point already exists + if (pointSketchId >= 0) { + + if (&pActiveSketch->Points[pointSketchId] == nullptr) + throw std::runtime_error( + "Sketch.addPoint(): Funtion returned a nullptr!"); + + return true; + + } else { + return false; + } + } + + // No points in sketch + return false; +} + +void Selector::setFlags() { + + if (selectedPoints.size() == 1) { + + flags.set(select_single_point); + + flags.reset(select_double_point); + flags.reset(select_multi_point); + + } else if (selectedPoints.size() == 2) { + + flags.set(select_double_point); + + flags.reset(select_single_point); + flags.reset(select_multi_point); + + } else if (selectedPoints.size() >= 3) { + + flags.set(select_multi_point); + + flags.reset(select_single_point); + flags.reset(select_double_point); + + } else { + + flags.reset(select_single_point); + flags.reset(select_double_point); + flags.reset(select_multi_point); + } +} + +void Selector::clear() { selectedPoints.clear(); } + +std::vector Selector::getVertices() { + + std::vector vertices; + + for (const auto &p : selectedPoints) { + vertices.push_back(p.second.pos); + } + + return vertices; +} + +std::vector Selector::getSelectedPointIds() { + + std::vector ids; + + for (auto &P : selectedPoints) { + ids.push_back(P.second.getId()); + } + + return ids; +} + +} // namespace sel +} // namespace CADERA_APP_NAMESPACE diff --git a/src/selection.hpp b/src/selection.hpp new file mode 100644 index 0000000..5cbb04a --- /dev/null +++ b/src/selection.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "sketch/sketchsolver.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sel { +float calcRatioToPlane(glm::vec3 currentRay, glm::vec3 cameraToPlaneDist, + glm::vec3 planeOrigin, glm::vec3 planeNormal); + +glm::vec3 calcPOnPlane(glm::vec3 currentRay, glm::vec3 origin, glm::vec3 normal, + glm::vec3 pos); + +glm::vec2 normalizeToVulkanCoords(glm::vec2 screenCoords, uint32_t surfaceWidth, + uint32_t surfaceHeight); + +glm::vec4 clipToEyeSpace(glm::vec4 clipCoords, glm::mat4 projMat); + +glm::vec3 toWorldCoord(glm::vec4 eyeCoords, glm::mat4 viewMat); + +glm::vec3 calcCurrentRay(float x, float y, glm::mat4 viewMat, glm::mat4 projMat, + uint32_t width, uint32_t height); + +enum SelectionFlags { + select_toggle, // Used in callbacks to toggle selection + select_isCTRL, // Is CTRL pressed down + select_single_point, + select_double_point, + select_multi_point, + select_first_click, + select_number_flags // Number of flags for bitset +}; + +class Selector { + + sketch::Sketch *pActiveSketch = nullptr; + +public: + std::bitset flags; + + glm::vec3 point; + + bool pointJustAdded; + + std::map selectedPoints; + + Selector(); + + void setActiveSketch(sketch::Sketch *pSketch); + + void select(glm::vec3 mouseRay, glm::vec3 origin, glm::vec3 normal, + glm::vec3 pos, glm::vec3 cross, bool isOrtho); + + static int selectPoint(glm::vec3 pointToAdd, std::map &points, + float skScale); + + void update(std::map points); + + int add(glm::vec3 pointToAdd, std::map &points, float skScale); + + int remove(glm::vec3 pointToRemove, std::map &points, + float skScale); + + bool existingPoint(glm::vec3 point); + + void setFlags(); + + void clear(); + + std::vector getVertices(); + + std::vector getSelectedPointIds(); +}; +} // namespace sel +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/CMakeLists.txt b/src/sketch/CMakeLists.txt index 69ee428..9af35ab 100644 --- a/src/sketch/CMakeLists.txt +++ b/src/sketch/CMakeLists.txt @@ -2,11 +2,25 @@ cmake_minimum_required(VERSION 3.5) -target_sources(CaderaApp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Relation.cpp - ${CMAKE_CURRENT_LIST_DIR}/Feature.cpp - ${CMAKE_CURRENT_LIST_DIR}/Sketch.cpp - ${CMAKE_CURRENT_LIST_DIR}/Sketcher.cpp - ${CMAKE_CURRENT_LIST_DIR}/SketchSolver.cpp - ${CMAKE_CURRENT_LIST_DIR}/Point.cpp - ) + +add_library(sketchlib ${CMAKE_CURRENT_LIST_DIR}/relation.cpp + ${CMAKE_CURRENT_LIST_DIR}/feature.cpp + ${CMAKE_CURRENT_LIST_DIR}/sketch.cpp + ${CMAKE_CURRENT_LIST_DIR}/sketcher.cpp + ${CMAKE_CURRENT_LIST_DIR}/sketchsolver.cpp + ${CMAKE_CURRENT_LIST_DIR}/point.cpp + ${CMAKE_CURRENT_LIST_DIR}/model.cpp + ${CMAKE_CURRENT_LIST_DIR}/grid.cpp + ) + +target_include_directories(sketchlib PRIVATE ${CMAKE_CURRENT_LIST_DIR}/) +target_include_directories(sketchlib PRIVATE ${CMAKE_SOURCE_DIR}/src/text/) + +target_link_libraries(sketchlib PUBLIC pch_interface) + + +target_link_libraries(sketchlib PRIVATE textlib) + +find_package(glm CONFIG REQUIRED) +target_link_libraries(sketchlib PRIVATE glm::glm) \ No newline at end of file diff --git a/src/sketch/Feature.cpp b/src/sketch/Feature.cpp deleted file mode 100644 index 3f6ff9d..0000000 --- a/src/sketch/Feature.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.hpp" -#include "Feature.hpp" - -namespace CADERA_APP_NAMESPACE { - - Feature::Feature() { - mId = -1; - } - - Feature::Feature(int id) { - mId = id; - } - - void Feature::setId(int id) { - mId = id; - } - - int Feature::getId() { - return mId; - } - -} \ No newline at end of file diff --git a/src/sketch/Feature.hpp b/src/sketch/Feature.hpp deleted file mode 100644 index 817ffd3..0000000 --- a/src/sketch/Feature.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "Relation.hpp" - -namespace CADERA_APP_NAMESPACE { - - enum FeatureType { - feat_origin, - feat_point, - feat_edge, - feat_round, - feat_construction, - feat_note - }; - - - class Feature { - - int mId; - - - public: - - Feature(); - Feature(int i); - - FeatureType Type; - - - - - void setId(int i); - - int getId(); - - - - }; -} - diff --git a/src/sketch/Point.cpp b/src/sketch/Point.cpp deleted file mode 100644 index bab5711..0000000 --- a/src/sketch/Point.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "pch.hpp" -#include "Point.hpp" - -namespace CADERA_APP_NAMESPACE { - - Point::Point() { - noteId = -1; - } - - Point::Point(int id, glm::vec3 pos) { - - setId(id); - this->pos = pos; - - - } -} \ No newline at end of file diff --git a/src/sketch/Point.hpp b/src/sketch/Point.hpp deleted file mode 100644 index 1c59479..0000000 --- a/src/sketch/Point.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "Feature.hpp" - - -namespace CADERA_APP_NAMESPACE { - - class Point : public Feature { - - public: - - - glm::vec3 pos; - std::list relationIds; - int noteId; - - Point(); - Point(int id, glm::vec3 pos); - - inline void removeRelationId(int id) { - - std::list::iterator iter = relationIds.begin(); - - while (iter != relationIds.end()) { - - if (*iter == id) { - iter = relationIds.erase(iter); - } - else { - ++iter; - } - } - } - - }; -} \ No newline at end of file diff --git a/src/sketch/Relation.cpp b/src/sketch/Relation.cpp deleted file mode 100644 index 3755a19..0000000 --- a/src/sketch/Relation.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "pch.hpp" -#include "Relation.hpp" diff --git a/src/sketch/Relation.hpp b/src/sketch/Relation.hpp deleted file mode 100644 index c69932a..0000000 --- a/src/sketch/Relation.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - - -namespace CADERA_APP_NAMESPACE { - - enum RelationType { - rel_vertical, - rel_horizontal, - rel_coincident, - }; - - struct Relation { - - int mId; - std::list mFeatureIds; - RelationType mType; - - inline void removeId(int id) { - - std::list::iterator iter = mFeatureIds.begin(); - - while (iter != mFeatureIds.end()) { - - if (*iter == id) { - iter = mFeatureIds.erase(iter); - } - else { - ++iter; - } - } - - } - }; - -} diff --git a/src/sketch/Sketch.cpp b/src/sketch/Sketch.cpp deleted file mode 100644 index 75585c3..0000000 --- a/src/sketch/Sketch.cpp +++ /dev/null @@ -1,327 +0,0 @@ -#include "pch.hpp" -#include "Sketch.hpp" - - - -namespace CADERA_APP_NAMESPACE { -namespace sketch { - - Sketch::Sketch() { - - featureCounter = 1; - addOrigin(); - - - mCamDistance = nullptr; - } - - Sketch::Sketch(int i) { - - setId(i); - setType(cad_sketch); - featureCounter = 1; - - mCamDistance = nullptr; - } - - int Sketch::getFeatureCounter() { - - return featureCounter; - } - - void Sketch::setCameraDistance(float* camDistance) { - mCamDistance = camDistance; - } - - void Sketch::activatePointTool() { - deactivateTools(); - flags.set(skt_point_tool); - flags.set(skt_tool_active); - } - - void Sketch::activateNoteTool() { - deactivateTools(); - flags.set(skt_note_tool); - flags.set(skt_tool_active); - } - - void Sketch::deactivateTools() { - - flags.reset(skt_point_tool); - flags.reset(skt_note_tool); - flags.reset(skt_tool_active); - flags.set(skt_event_tool_deactivated); - - } - - void Sketch::add(glm::vec3 point) { - - if (flags.test(skt_point_tool)) { - addPoint(point); - } - - if (flags.test(skt_note_tool)) { - addNotePoint(point); - } - - - } - - void Sketch::addOrigin() { - - Point Origin; - - Origin.pos = { 0.0f, 0.0f, 0.0f }; - Origin.setId(0); - Origin.Type = feat_origin; - - Points[0] = Origin; - - } - - void Sketch::addRelation(const std::vector& ids, RelationType Type) { - - Relation newRelation; - - newRelation.mId = featureCounter; - - for (const auto& id : ids) { - newRelation.mFeatureIds.push_back(id); - - Points[id].relationIds.push_back(newRelation.mId); - } - - newRelation.mType = Type; - - mRelations[featureCounter] = newRelation; - - featureCounter++; - } - - void Sketch::deleteRelation(int id) { - - mRelations.erase(id); - - } - - void Sketch::clearRelations() { - - mRelations.clear(); - - } - - size_t Sketch::numRelations() { - - return mRelations.size(); - } - - Point* Sketch::addPoint(glm::vec3 point) { - - Point pointToAdd; - - pointToAdd.pos = point; - pointToAdd.setId(featureCounter); - pointToAdd.Type = feat_point; - - Points[featureCounter] = pointToAdd; - - if (&Points[featureCounter] == nullptr) - throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); - - featureCounter++; - - return &Points[featureCounter - 1]; - - } - - Point* Sketch::addConstructionPoint(glm::vec3 point) { - - Point pointToAdd; - - pointToAdd.pos = point; - pointToAdd.setId(featureCounter); - pointToAdd.Type = feat_construction; - - Points[featureCounter] = pointToAdd; - - if (&Points[featureCounter] == nullptr) - throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); - - featureCounter++; - - return &Points[featureCounter - 1]; - } - - Point* Sketch::addNotePoint(glm::vec3 point) { - - Point pointToAdd; - - pointToAdd.pos = point; - pointToAdd.setId(featureCounter); - pointToAdd.Type = feat_note; - pointToAdd.noteId = featureCounter + 1; - - Points[featureCounter] = pointToAdd; - - if (&Points[featureCounter] == nullptr) - throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); - - featureCounter++; - - txt::Text T; - - T.textSize = 1.0f; - T.cursorPos = point; - T.cursorDirX = { 1.0f, 0.0f, 0.0f }; - T.cursorDirY = { 0.0f, 1.0f, 0.0f }; - T.backgroundColor = { 0.1f, 0.1f, 0.1f }; - T.textColor = { 1.0f, 0.0f, 0.0f }; - T.text = noteText; - - Notes[featureCounter] = T; - - - featureCounter++; - - return &Points[featureCounter - 2]; - } - - void Sketch::movePoints(std::map ids, const glm::vec3 &POnPlane, const bool& isFirstClick) { - - - static glm::vec3 initPoint = POnPlane; - - - if (isFirstClick) - initPoint = POnPlane; - - glm::vec3 difference = POnPlane - initPoint; - - - if (glm::length2(difference) < .001) - return; - - for (const auto& id : ids) { - - if (id.first == 0) - continue; - - - - - Points[id.first].pos += difference; - - if (Points[id.first].Type == feat_note) { - - Notes[Points[id.first].noteId].cursorPos = Points[id.first].pos; - } - - } - - - - flags.set(skt_points_have_moved); - - initPoint = POnPlane; - } - - void Sketch::deletion(std::vector ids) { - - for (const auto& id : ids) { - - if (id == 0) - continue; - - if (Points[id].Type == feat_note && Points[id].noteId != -1) { - Notes.erase(Points[id].noteId); - } - - for (const auto& rId : Points[id].relationIds) { - mRelations[rId].removeId(id); - - if (mRelations[rId].mFeatureIds.size() == 1) { - - Points[*mRelations[rId].mFeatureIds.begin()].removeRelationId(rId); - mRelations.erase(rId); - } - - } - - Points.erase(id); - } - } - - std::vector Sketch::getGridLine() { - return mGrid.line; - } - - std::vector Sketch::getGridAxii() { - return mGrid.createGridInstanceAxii(); - } - - std::vector Sketch::getVertices(std::vector& colors) { - - std::vector vertices; - colors.clear(); - - for (const auto& p : Points) { - vertices.push_back(p.second.pos); - - if (p.second.Type == feat_point) { - colors.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); - } - else if (p.second.Type == feat_construction) { - colors.push_back(glm::vec3(1.0f, 1.0f, 0.0f)); - } - else if (p.second.Type == feat_note) { - colors.push_back(glm::vec3(1.0f, 0.8f, 0.0f)); - } - else if (p.second.Type == feat_origin) { - colors.push_back(glm::vec3(1.0f, 0.0f, 1.0f)); - } - } - - return vertices; - } - - std::vector Sketch::getRelationTexts() { - - std::vector Texts; - std::map pointRelCounter; - - for (const auto& R : mRelations) { - - for (const auto& id : R.second.mFeatureIds) { - txt::Text T; - - T.textSize = 0.3f; - T.backgroundColor = { 0.0f, 0.0f, 1.0f }; - T.textColor = { 1.0f, 1.0f, 1.0f }; - T.cursorDirX = { 0.0f, 0.0f, 1.0f }; - T.cursorDirY = { 0.0f, 1.0f, 0.0f }; - T.cursorPos = Points[id].pos; - T.offset = { 0.1f, 0.1f }; - T.offset.x += 0.3f * (float)pointRelCounter[id]; - - if (R.second.mType == rel_vertical) { - T.text = "|"; - } - else if (R.second.mType == rel_horizontal) { - T.text = "_"; - } - else if (R.second.mType == rel_coincident) { - T.text = "C"; - } - - Texts.push_back(T); - - pointRelCounter[id]++; - } - } - - return Texts; - - } - -} -} \ No newline at end of file diff --git a/src/sketch/Sketch.hpp b/src/sketch/Sketch.hpp deleted file mode 100644 index c469bc7..0000000 --- a/src/sketch/Sketch.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "Sketcher.hpp" - - -namespace CADERA_APP_NAMESPACE { -namespace sketch { - - // Returns a list with any elements in v2 that aren't in v1 - template - inline std::list getDifferenceVector(std::list v1, std::list v2) { - - std::list differenceVector; - - if (v1.empty()) - return v2; - - for (const auto& elem : v2) { - - bool isFound = std::find(v1.begin(), v1.end(), elem) != v1.end(); - - if (!isFound) { - - differenceVector.push_back(elem); - - } - - } - - return differenceVector; - - } - - class Sketch : public Model { - - int featureCounter; - - public: - - float* mCamDistance; - - Grid mGrid; - - std::map Points; - std::map mRelations; - - std::string noteText; - - Sketch(); - Sketch(int i); - - std::bitset flags; - - int getFeatureCounter(); - - void setCameraDistance(float* camDistance); - - void activatePointTool(); - - void activateNoteTool(); - - void deactivateTools(); - - void add(glm::vec3 point); - - void addOrigin(); - - void addRelation(const std::vector &ids, RelationType Type); - - void deleteRelation(int id); - - void clearRelations(); - - size_t numRelations(); - - Point* addPoint(glm::vec3 point); - - Point* addConstructionPoint(glm::vec3 point); - - Point* addNotePoint(glm::vec3 point); - - void movePoints(std::map ids, const glm::vec3 &POnPlane, const bool& isFirstClick); - - void deletion(std::vector ids); - - std::vector getGridLine(); - - std::vector getGridAxii(); - - std::vector getVertices(std::vector& colors); - - std::vector getRelationTexts(); - - - - }; - -} -} diff --git a/src/sketch/SketchSolver.cpp b/src/sketch/SketchSolver.cpp deleted file mode 100644 index 7a8d560..0000000 --- a/src/sketch/SketchSolver.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "pch.hpp" -#include "SketchSolver.hpp" - -void CADERA_APP_NAMESPACE::sketch::SketchSolver::setActiveSketch(Sketch* S) { - - pActiveSketch = S; - -} - - - -bool CADERA_APP_NAMESPACE::sketch::SketchSolver::checkNewRelation(const Relation& R) { - - std::list newRelationIds = R.mFeatureIds; - - // If relation doesn't involve any features, don't add relation - if (newRelationIds.size() == 0) - return false; - - - - for (const auto& id : newRelationIds) { - - // If point doesn't have any other relation, skip - if (pActiveSketch->Points[id].relationIds.size() == 0) { - continue; - } - - // Does the point already have relations to the other points in the new relation - std::list relatedPointIds = getRelatedPointIds(id); - - - - bool hasRelations = false; - - for (const auto& relPtId : relatedPointIds) { - - // Returns true if related point id is in the new relation ids; - hasRelations = std::find(newRelationIds.begin(), newRelationIds.end(), relPtId) != newRelationIds.end(); - - - if (hasRelations) - return false; - } - - } - - return true; -} - -bool CADERA_APP_NAMESPACE::sketch::SketchSolver::checkCommenRelationPts(const Relation& R) { - - std::list newRelationIds = R.mFeatureIds; - - size_t totalsize = 0; - - std::list allUniqueRelatedPtIds; - - for (const auto& id : newRelationIds) { - - std::list relatedPointIds = getRelatedPointIds(id); - - totalsize += relatedPointIds.size(); - - bool hasRelations = false; - - std::list UniqueIds = getDifferenceVector(allUniqueRelatedPtIds, relatedPointIds); - - for (const auto& relPtid : UniqueIds) { - - allUniqueRelatedPtIds.push_back(relPtid); - - } - } - - if (allUniqueRelatedPtIds.size() == totalsize) { - return true; - } - else { - return false; - } -} - - -// Returns a vector of the ids of points that have relations to the inputed point id -std::list CADERA_APP_NAMESPACE::sketch::SketchSolver::getRelatedPointIds(const int& PId) { - - if (pActiveSketch == nullptr) - throw std::runtime_error("SketchSolver: Active Sketch is nullptr!!!"); - - Point P = pActiveSketch->Points[PId]; - - std::list relatedPointIds; - - for (const auto& relId : P.relationIds) { - - std::list v = { PId }; - std::list featureIds = getDifferenceVector(v, pActiveSketch->mRelations[relId].mFeatureIds);; - - featureIds = getDifferenceVector(relatedPointIds, featureIds); - - for (const auto& featId :featureIds) { - - relatedPointIds.push_back(featId); - - } - - } - - return relatedPointIds; -} - -bool CADERA_APP_NAMESPACE::sketch::SketchSolver::addNewSketchRelation(const std::vector& ids, RelationType Type) { - - bool isSuccess = false; - - Relation NewRelation; - - for (const auto& id : ids) { - NewRelation.mFeatureIds.push_back(id); - } - - NewRelation.mType = Type; - - if (checkNewRelation(NewRelation) && checkCommenRelationPts(NewRelation)) - pActiveSketch->addRelation(ids, Type); - - - return isSuccess; -} diff --git a/src/sketch/SketchSolver.hpp b/src/sketch/SketchSolver.hpp deleted file mode 100644 index 686b323..0000000 --- a/src/sketch/SketchSolver.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include "Sketch.hpp" - -namespace CADERA_APP_NAMESPACE { - - - - - template - inline std::vector vectorSameElements(std::vector v1, std::vector v2) { - - std::vector SameElements; - - for (const auto& elem : v1) { - - bool isSame = std::find(v2.begin(), v2.end(), elem) != v2.end(); - - if (isSame) - SameElements.push_back(elem); - - } - - return SameElements; - } - -namespace sketch { - - - - class SketchSolver { - - public: - - void setActiveSketch(Sketch* S); - - bool checkNewRelation(const Relation& R); - - bool checkCommenRelationPts(const Relation& R); - - std::list getRelatedPointIds(const int& Pid); - - bool addNewSketchRelation(const std::vector& ids, RelationType Type); - - - - private: - - Sketch* pActiveSketch = nullptr; - - - }; - -} -} - diff --git a/src/sketch/Sketcher.cpp b/src/sketch/Sketcher.cpp deleted file mode 100644 index 18a7e91..0000000 --- a/src/sketch/Sketcher.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.hpp" -#include "Sketcher.hpp" - - -namespace CADERA_APP_NAMESPACE { -namespace sketch { - - Sketcher::Sketcher() { - - - } - - Sketcher::~Sketcher() { - - - } - - void Sketcher::add(glm::vec3 pointToAdd) { - - } -} -} \ No newline at end of file diff --git a/src/sketch/Sketcher.hpp b/src/sketch/Sketcher.hpp deleted file mode 100644 index ccff3d6..0000000 --- a/src/sketch/Sketcher.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "Point.hpp" -#include "Model.hpp" - - - -namespace CADERA_APP_NAMESPACE { -namespace sketch { - - enum SketchToolFlags { - skt_active, // Cadera is in sketch mode - skt_move_points, // Triggers the moving of points - skt_points_have_moved, // Stops deselection when points have moved - skt_tool_active, // Used to toggle adding of point to sketch in the callbacks - skt_point_tool, // Activate the point tool - skt_note_tool, // Activate the note tool - skt_event_tool_deactivated, // Stops the rendering of tool indicators - skt_num_flags // Number of flags for sketch flags bitset - }; - - class Sketcher { - - Sketcher(); - - ~Sketcher(); - - - - - std::bitset flags; - - void add(glm::vec3 pointToAdd); - - - - }; - -} -} - diff --git a/src/sketch/feature.cpp b/src/sketch/feature.cpp new file mode 100644 index 0000000..f79fe17 --- /dev/null +++ b/src/sketch/feature.cpp @@ -0,0 +1,14 @@ +#include "feature.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +Feature::Feature() { mId = -1; } + +Feature::Feature(int id) { mId = id; } + +void Feature::setId(int id) { mId = id; } + +int Feature::getId() { return mId; } + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/feature.hpp b/src/sketch/feature.hpp new file mode 100644 index 0000000..8a3b55f --- /dev/null +++ b/src/sketch/feature.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "relation.hpp" + +namespace CADERA_APP_NAMESPACE { + +enum FeatureType { + feat_origin, + feat_point, + feat_edge, + feat_round, + feat_construction, + feat_note +}; + +class Feature { + + int mId; + +public: + Feature(); + Feature(int i); + + FeatureType Type; + + void setId(int i); + + int getId(); +}; +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/grid.cpp b/src/sketch/grid.cpp new file mode 100644 index 0000000..1676088 --- /dev/null +++ b/src/sketch/grid.cpp @@ -0,0 +1,62 @@ +#include "grid.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +Grid::Grid() { + + size = 10; + spacing = 1.0f; + + p1 = {0.0f, -size, 0.0f}; + p2 = {0.0f, size, 0.0f}; + + line = {p1, p2}; + + gUp = {0.0f, 1.0f, 0.0f}; + gCross = {1.0f, 0.0f, 0.0f}; + gNormal = {0.0f, 0.0f, 1.0f}; +} + +void Grid::setGridOrientation(glm::vec3 normal, glm::vec3 up, glm::vec3 cross) { + gNormal = normal; + gUp = up; + gCross = cross; +} + +std::vector Grid::createGridInstanceAxii() { + + std::vector axii; + + p1 = (-size * spacing) * gUp; + p2 = (size * spacing) * gUp; + + line = {p1, p2}; + + float position = -size * spacing; + for (int i = 0; i < 2 * size + 1; i++) { + + GridRotationAxis axis = { + position * gCross, gNormal, {0.0f, 0.0f, 0.0f}, 0.0f}; + + if (i == size) { + axis.color = {0.0f, 1.0f, 0.0f}; + } + + axii.push_back(axis); + + axis.angle = 90.0f; + + if (i == size) { + axis.color = {1.0f, 0.0f, 0.0f}; + } + + axii.push_back(axis); + + position += spacing; + } + + return axii; +} + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/grid.hpp b/src/sketch/grid.hpp new file mode 100644 index 0000000..46bd391 --- /dev/null +++ b/src/sketch/grid.hpp @@ -0,0 +1,42 @@ +#pragma once + +namespace CADERA_APP_NAMESPACE { + +/// @brief The axis of rotation for the grid lines +struct GridRotationAxis { + glm::vec3 pos; + glm::vec3 axis; + glm::vec3 color; + float angle; +}; + +class Grid { + +public: + Grid(); + + void setGridOrientation(glm::vec3 normal, glm::vec3 up, glm::vec3 cross); + + /// @brief To generate the values needed to instance each grid line from the + /// base line + /// @return Vector to be used for rendering the instances + std::vector createGridInstanceAxii(); + + glm::vec3 p1; + glm::vec3 p2; + + glm::vec3 gNormal; + glm::vec3 gUp; + glm::vec3 gCross; + + /// @brief The container for rendering the base line + std::vector line; + + /// @brief The size of the grid. The number of times the grid gets + /// incremented. + int32_t size; + + /// @brief The spacing between each line in the grid + float spacing; +}; +} // namespace CADERA_APP_NAMESPACE \ No newline at end of file diff --git a/src/sketch/model.cpp b/src/sketch/model.cpp new file mode 100644 index 0000000..c1fb5eb --- /dev/null +++ b/src/sketch/model.cpp @@ -0,0 +1,34 @@ +#include "model.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +Model::Model() {} + +Model::Model(int id) { mId = id; } + +void Model::setId(int id) { mId = id; } + +int Model::getId() { return mId; } + +void Model::setType(ModelType type) { mType = type; } + +ModelType Model::getType() { return mType; } + +std::vector Model::getGridLine() { return std::vector(); } + +std::vector Model::getGridAxii() { + return std::vector(); +} + +std::vector Model::getRelationTexts() { + return std::vector(); +} + +std::vector Model::getVertices() { return std::vector(); } + +std::vector Model::getVertices(std::vector &colors) { + return std::vector(); +} + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/model.hpp b/src/sketch/model.hpp new file mode 100644 index 0000000..c196673 --- /dev/null +++ b/src/sketch/model.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "textrender.hpp" +#include "grid.hpp" + +namespace CADERA_APP_NAMESPACE { + +enum ModelType { cad_sketch, cad_layout, cad_part, cad_assembly, cad_drawing }; + +class Model { + + int mId; + ModelType mType; + +public: + Model(); + Model(int id); + + void setId(int id); + + int getId(); + + void setType(ModelType type); + + ModelType getType(); + + std::map Notes; + + virtual std::vector getGridLine(); + virtual std::vector getGridAxii(); + + virtual std::vector getRelationTexts(); + + virtual std::vector getVertices(); + virtual std::vector getVertices(std::vector &colors); +}; + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/pch.hpp b/src/sketch/pch.hpp deleted file mode 100644 index f4bef1f..0000000 --- a/src/sketch/pch.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/src/sketch/point.cpp b/src/sketch/point.cpp new file mode 100644 index 0000000..7f4d8bd --- /dev/null +++ b/src/sketch/point.cpp @@ -0,0 +1,13 @@ +#include "point.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +Point::Point() { noteId = -1; } + +Point::Point(int id, glm::vec3 pos) { + + setId(id); + this->pos = pos; +} +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/point.hpp b/src/sketch/point.hpp new file mode 100644 index 0000000..80fcf2a --- /dev/null +++ b/src/sketch/point.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "feature.hpp" + +namespace CADERA_APP_NAMESPACE { + +class Point : public Feature { + +public: + glm::vec3 pos; + std::list relationIds; + int noteId; + + Point(); + Point(int id, glm::vec3 pos); + + inline void removeRelationId(int id) { + + std::list::iterator iter = relationIds.begin(); + + while (iter != relationIds.end()) { + + if (*iter == id) { + iter = relationIds.erase(iter); + } else { + ++iter; + } + } + } +}; +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/relation.cpp b/src/sketch/relation.cpp new file mode 100644 index 0000000..2048c1d --- /dev/null +++ b/src/sketch/relation.cpp @@ -0,0 +1,2 @@ +#include "relation.hpp" +#include "pch.hpp" diff --git a/src/sketch/relation.hpp b/src/sketch/relation.hpp new file mode 100644 index 0000000..ae6e86d --- /dev/null +++ b/src/sketch/relation.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace CADERA_APP_NAMESPACE { + +enum RelationType { + rel_vertical, + rel_horizontal, + rel_coincident, +}; + +struct Relation { + + int mId; + std::list mFeatureIds; + RelationType mType; + + inline void removeId(int id) { + + std::list::iterator iter = mFeatureIds.begin(); + + while (iter != mFeatureIds.end()) { + + if (*iter == id) { + iter = mFeatureIds.erase(iter); + } else { + ++iter; + } + } + } +}; + +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/sketch.cpp b/src/sketch/sketch.cpp new file mode 100644 index 0000000..17c1315 --- /dev/null +++ b/src/sketch/sketch.cpp @@ -0,0 +1,285 @@ +#include "sketch.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sketch { + +Sketch::Sketch() { + + featureCounter = 1; + addOrigin(); + + mCamDistance = nullptr; +} + +Sketch::Sketch(int i) { + + setId(i); + setType(cad_sketch); + featureCounter = 1; + + mCamDistance = nullptr; +} + +int Sketch::getFeatureCounter() { return featureCounter; } + +void Sketch::setCameraDistance(float *camDistance) { + mCamDistance = camDistance; +} + +void Sketch::activatePointTool() { + deactivateTools(); + flags.set(skt_point_tool); + flags.set(skt_tool_active); +} + +void Sketch::activateNoteTool() { + deactivateTools(); + flags.set(skt_note_tool); + flags.set(skt_tool_active); +} + +void Sketch::deactivateTools() { + + flags.reset(skt_point_tool); + flags.reset(skt_note_tool); + flags.reset(skt_tool_active); + flags.set(skt_event_tool_deactivated); +} + +void Sketch::add(glm::vec3 point) { + + if (flags.test(skt_point_tool)) { + addPoint(point); + } + + if (flags.test(skt_note_tool)) { + addNotePoint(point); + } +} + +void Sketch::addOrigin() { + + Point Origin; + + Origin.pos = {0.0f, 0.0f, 0.0f}; + Origin.setId(0); + Origin.Type = feat_origin; + + Points[0] = Origin; +} + +void Sketch::addRelation(const std::vector &ids, RelationType Type) { + + Relation newRelation; + + newRelation.mId = featureCounter; + + for (const auto &id : ids) { + newRelation.mFeatureIds.push_back(id); + + Points[id].relationIds.push_back(newRelation.mId); + } + + newRelation.mType = Type; + + mRelations[featureCounter] = newRelation; + + featureCounter++; +} + +void Sketch::deleteRelation(int id) { mRelations.erase(id); } + +void Sketch::clearRelations() { mRelations.clear(); } + +size_t Sketch::numRelations() { return mRelations.size(); } + +Point *Sketch::addPoint(glm::vec3 point) { + + Point pointToAdd; + + pointToAdd.pos = point; + pointToAdd.setId(featureCounter); + pointToAdd.Type = feat_point; + + Points[featureCounter] = pointToAdd; + + if (&Points[featureCounter] == nullptr) + throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); + + featureCounter++; + + return &Points[featureCounter - 1]; +} + +Point *Sketch::addConstructionPoint(glm::vec3 point) { + + Point pointToAdd; + + pointToAdd.pos = point; + pointToAdd.setId(featureCounter); + pointToAdd.Type = feat_construction; + + Points[featureCounter] = pointToAdd; + + if (&Points[featureCounter] == nullptr) + throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); + + featureCounter++; + + return &Points[featureCounter - 1]; +} + +Point *Sketch::addNotePoint(glm::vec3 point) { + + Point pointToAdd; + + pointToAdd.pos = point; + pointToAdd.setId(featureCounter); + pointToAdd.Type = feat_note; + pointToAdd.noteId = featureCounter + 1; + + Points[featureCounter] = pointToAdd; + + if (&Points[featureCounter] == nullptr) + throw std::runtime_error("Sketch.addPoint(): Funtion returned a nullptr!"); + + featureCounter++; + + txt::Text T; + + T.textSize = 1.0f; + T.cursorPos = point; + T.cursorDirX = {1.0f, 0.0f, 0.0f}; + T.cursorDirY = {0.0f, 1.0f, 0.0f}; + T.textColor = {1.0f, 0.0f, 0.0f}; + T.text = noteText; + + Notes[featureCounter] = T; + + featureCounter++; + + return &Points[featureCounter - 2]; +} + +void Sketch::movePoints(std::map ids, const glm::vec3 &POnPlane, + const bool &isFirstClick) { + + static glm::vec3 initPoint = POnPlane; + + if (isFirstClick) + initPoint = POnPlane; + + glm::vec3 difference = POnPlane - initPoint; + + if (glm::length2(difference) < .001) + return; + + for (const auto &id : ids) { + + if (id.first == 0) + continue; + + Points[id.first].pos += difference; + + if (Points[id.first].Type == feat_note) { + + Notes[Points[id.first].noteId].cursorPos = Points[id.first].pos; + } + } + + flags.set(skt_points_have_moved); + + initPoint = POnPlane; +} + +void Sketch::deletion(std::vector ids) { + + for (const auto &id : ids) { + + if (id == 0) + continue; + + if (Points[id].Type == feat_note && Points[id].noteId != -1) { + Notes.erase(Points[id].noteId); + } + + for (const auto &rId : Points[id].relationIds) { + mRelations[rId].removeId(id); + + if (mRelations[rId].mFeatureIds.size() == 1) { + + Points[*mRelations[rId].mFeatureIds.begin()].removeRelationId(rId); + mRelations.erase(rId); + } + } + + Points.erase(id); + } +} + +std::vector Sketch::getGridLine() { return mGrid.line; } + +std::vector Sketch::getGridAxii() { + return mGrid.createGridInstanceAxii(); +} + +std::vector Sketch::getVertices(std::vector &colors) { + + std::vector vertices; + colors.clear(); + + for (const auto &p : Points) { + vertices.push_back(p.second.pos); + + if (p.second.Type == feat_point) { + colors.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); + } else if (p.second.Type == feat_construction) { + colors.push_back(glm::vec3(1.0f, 1.0f, 0.0f)); + } else if (p.second.Type == feat_note) { + colors.push_back(glm::vec3(1.0f, 0.8f, 0.0f)); + } else if (p.second.Type == feat_origin) { + colors.push_back(glm::vec3(1.0f, 0.0f, 1.0f)); + } + } + + return vertices; +} + +std::vector Sketch::getRelationTexts() { + + std::vector Texts; + std::map pointRelCounter; + + for (const auto &R : mRelations) { + + for (const auto &id : R.second.mFeatureIds) { + txt::Text T; + + T.textSize = 0.3f; + T.textColor = {1.0f, 1.0f, 1.0f}; + T.cursorDirX = {0.0f, 0.0f, 1.0f}; + T.cursorDirY = {0.0f, 1.0f, 0.0f}; + T.cursorPos = Points[id].pos; + T.offset = {0.1f, 0.1f}; + T.offset.x += 0.3f * (float)pointRelCounter[id]; + + if (R.second.mType == rel_vertical) { + T.text = "|"; + } else if (R.second.mType == rel_horizontal) { + T.text = "_"; + } else if (R.second.mType == rel_coincident) { + T.text = "C"; + } + + Texts.push_back(T); + + pointRelCounter[id]++; + } + } + + return Texts; +} + +} // namespace sketch +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/sketch.hpp b/src/sketch/sketch.hpp new file mode 100644 index 0000000..b656dde --- /dev/null +++ b/src/sketch/sketch.hpp @@ -0,0 +1,91 @@ +#pragma once +#include "sketcher.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sketch { + +// Returns a list with any elements in v2 that aren't in v1 +template +inline std::list getDifferenceVector(std::list v1, std::list v2) { + + std::list differenceVector; + + if (v1.empty()) + return v2; + + for (const auto &elem : v2) { + + bool isFound = std::find(v1.begin(), v1.end(), elem) != v1.end(); + + if (!isFound) { + + differenceVector.push_back(elem); + } + } + + return differenceVector; +} + +class Sketch : public Model { + + int featureCounter; + +public: + float *mCamDistance; + + Grid mGrid; + + std::map Points; + std::map mRelations; + + std::string noteText; + + Sketch(); + Sketch(int i); + + std::bitset flags; + + int getFeatureCounter(); + + void setCameraDistance(float *camDistance); + + void activatePointTool(); + + void activateNoteTool(); + + void deactivateTools(); + + void add(glm::vec3 point); + + void addOrigin(); + + void addRelation(const std::vector &ids, RelationType Type); + + void deleteRelation(int id); + + void clearRelations(); + + size_t numRelations(); + + Point *addPoint(glm::vec3 point); + + Point *addConstructionPoint(glm::vec3 point); + + Point *addNotePoint(glm::vec3 point); + + void movePoints(std::map ids, const glm::vec3 &POnPlane, + const bool &isFirstClick); + + void deletion(std::vector ids); + + std::vector getGridLine(); + + std::vector getGridAxii(); + + std::vector getVertices(std::vector &colors); + + std::vector getRelationTexts(); +}; + +} // namespace sketch +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/sketcher.cpp b/src/sketch/sketcher.cpp new file mode 100644 index 0000000..5c390f7 --- /dev/null +++ b/src/sketch/sketcher.cpp @@ -0,0 +1,13 @@ +#include "sketcher.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sketch { + +Sketcher::Sketcher() {} + +Sketcher::~Sketcher() {} + +void Sketcher::add(glm::vec3 pointToAdd) {} +} // namespace sketch +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/sketcher.hpp b/src/sketch/sketcher.hpp new file mode 100644 index 0000000..a27f4cb --- /dev/null +++ b/src/sketch/sketcher.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "model.hpp" +#include "point.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace sketch { + +enum SketchToolFlags { + skt_active, // Cadera is in sketch mode + skt_move_points, // Triggers the moving of points + skt_points_have_moved, // Stops deselection when points have moved + skt_tool_active, // Used to toggle adding of point to sketch in the callbacks + skt_point_tool, // Activate the point tool + skt_note_tool, // Activate the note tool + skt_event_tool_deactivated, // Stops the rendering of tool indicators + skt_num_flags // Number of flags for sketch flags bitset +}; + +class Sketcher { + + Sketcher(); + + ~Sketcher(); + + std::bitset flags; + + void add(glm::vec3 pointToAdd); +}; + +} // namespace sketch +} // namespace CADERA_APP_NAMESPACE diff --git a/src/sketch/sketchsolver.cpp b/src/sketch/sketchsolver.cpp new file mode 100644 index 0000000..e0e5013 --- /dev/null +++ b/src/sketch/sketchsolver.cpp @@ -0,0 +1,125 @@ +#include "sketchsolver.hpp" +#include "pch.hpp" + +void CADERA_APP_NAMESPACE::sketch::SketchSolver::setActiveSketch(Sketch *S) { + + pActiveSketch = S; +} + +bool CADERA_APP_NAMESPACE::sketch::SketchSolver::checkNewRelation( + const Relation &R) { + + std::list newRelationIds = R.mFeatureIds; + + // If relation doesn't involve any features, don't add relation + if (newRelationIds.size() == 0) + return false; + + for (const auto &id : newRelationIds) { + + // If point doesn't have any other relation, skip + if (pActiveSketch->Points[id].relationIds.size() == 0) { + continue; + } + + // Does the point already have relations to the other points in the new + // relation + std::list relatedPointIds = getRelatedPointIds(id); + + bool hasRelations = false; + + for (const auto &relPtId : relatedPointIds) { + + // Returns true if related point id is in the new relation ids; + hasRelations = std::find(newRelationIds.begin(), newRelationIds.end(), + relPtId) != newRelationIds.end(); + + if (hasRelations) + return false; + } + } + + return true; +} + +bool CADERA_APP_NAMESPACE::sketch::SketchSolver::checkCommenRelationPts( + const Relation &R) { + + std::list newRelationIds = R.mFeatureIds; + + size_t totalsize = 0; + + std::list allUniqueRelatedPtIds; + + for (const auto &id : newRelationIds) { + + std::list relatedPointIds = getRelatedPointIds(id); + + totalsize += relatedPointIds.size(); + + bool hasRelations = false; + + std::list UniqueIds = + getDifferenceVector(allUniqueRelatedPtIds, relatedPointIds); + + for (const auto &relPtid : UniqueIds) { + + allUniqueRelatedPtIds.push_back(relPtid); + } + } + + if (allUniqueRelatedPtIds.size() == totalsize) { + return true; + } else { + return false; + } +} + +// Returns a vector of the ids of points that have relations to the inputed +// point id +std::list +CADERA_APP_NAMESPACE::sketch::SketchSolver::getRelatedPointIds(const int &PId) { + + if (pActiveSketch == nullptr) + throw std::runtime_error("SketchSolver: Active Sketch is nullptr!!!"); + + Point P = pActiveSketch->Points[PId]; + + std::list relatedPointIds; + + for (const auto &relId : P.relationIds) { + + std::list v = {PId}; + std::list featureIds = + getDifferenceVector(v, pActiveSketch->mRelations[relId].mFeatureIds); + ; + + featureIds = getDifferenceVector(relatedPointIds, featureIds); + + for (const auto &featId : featureIds) { + + relatedPointIds.push_back(featId); + } + } + + return relatedPointIds; +} + +bool CADERA_APP_NAMESPACE::sketch::SketchSolver::addNewSketchRelation( + const std::vector &ids, RelationType Type) { + + bool isSuccess = false; + + Relation NewRelation; + + for (const auto &id : ids) { + NewRelation.mFeatureIds.push_back(id); + } + + NewRelation.mType = Type; + + if (checkNewRelation(NewRelation) && checkCommenRelationPts(NewRelation)) + pActiveSketch->addRelation(ids, Type); + + return isSuccess; +} diff --git a/src/sketch/sketchsolver.hpp b/src/sketch/sketchsolver.hpp new file mode 100644 index 0000000..753b009 --- /dev/null +++ b/src/sketch/sketchsolver.hpp @@ -0,0 +1,42 @@ +#pragma once +#include "sketch.hpp" + +namespace CADERA_APP_NAMESPACE { + +template +inline std::vector vectorSameElements(std::vector v1, std::vector v2) { + + std::vector SameElements; + + for (const auto &elem : v1) { + + bool isSame = std::find(v2.begin(), v2.end(), elem) != v2.end(); + + if (isSame) + SameElements.push_back(elem); + } + + return SameElements; +} + +namespace sketch { + +class SketchSolver { + +public: + void setActiveSketch(Sketch *S); + + bool checkNewRelation(const Relation &R); + + bool checkCommenRelationPts(const Relation &R); + + std::list getRelatedPointIds(const int &Pid); + + bool addNewSketchRelation(const std::vector &ids, RelationType Type); + +private: + Sketch *pActiveSketch = nullptr; +}; + +} // namespace sketch +} // namespace CADERA_APP_NAMESPACE diff --git a/src/text/CMakeLists.txt b/src/text/CMakeLists.txt new file mode 100644 index 0000000..b47401b --- /dev/null +++ b/src/text/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) + +add_library(textlib ${CMAKE_CURRENT_LIST_DIR}/textrender.cpp) + + +target_link_libraries(textlib PUBLIC pch_interface) + +target_include_directories(textlib PUBLIC ${CMAKE_CURRENT_LIST_DIR}/) \ No newline at end of file diff --git a/src/text/textrender.cpp b/src/text/textrender.cpp new file mode 100644 index 0000000..8402bfc --- /dev/null +++ b/src/text/textrender.cpp @@ -0,0 +1,177 @@ +#include "textrender.hpp" +#include "pch.hpp" + +void coutVec3(glm::vec3 v) { + std::cout << "x: " << v.x << " "; + std::cout << "y: " << v.y << " "; + std::cout << "z: " << v.z << " " << std::endl; +} + +namespace CADERA_APP_NAMESPACE { +namespace txt { + +TextRender::TextRender() { + mFontSize = 100.0; + mAtlasSize = 2864.0f; + + mCursorPos = {0.0f, 0.0f, 0.0f}; + mCursorDirX = {0.0f, 0.0f, 1.0f}; + mCursorDirY = {0.0f, 1.0f, 0.0f}; + + textCounter = 0; +} + +TextRender::~TextRender() {} + +void TextRender::setFontSize(float s) { mFontSize = s; } + +void TextRender::loadFont(std::string filePath) { + + Characters.clear(); + + std::ifstream fontAtlasCsv; + + std::string row, cell, value; + + fontAtlasCsv.open(filePath); + + while (std::getline(fontAtlasCsv, row)) { + + std::stringstream ss(row); + + Character C; + + std::vector values; + + while (ss.good()) { + std::getline(ss, cell, ','); + + values.push_back(std::stof(cell)); + } + + C.xAdvance = values[1]; + C.x = values[2]; + C.y = values[5]; + C.width = (values[4] - values[2]); + C.height = (values[5] - values[3]); + C.textureCoords.x = values[6] / mAtlasSize; + C.textureCoords.z = values[8] / mAtlasSize; + C.textureCoords.y = 1.0f - values[7] / mAtlasSize; + C.textureCoords.w = 1.0f - values[9] / mAtlasSize; + + Characters[(int)values[0]] = C; + } +} + +void TextRender::setCursorPos(glm::vec3 pos) { mCursorPos = pos; } + +void TextRender::setPlane(glm::vec3 xDir, glm::vec3 yDir) { + + mCursorDirX = xDir; + mCursorDirY = yDir; +} + +void TextRender::addText(Text T) { + + mTexts[textCounter] = T; + textCounter++; +} + +void TextRender::addText(std::vector Ts) { + + for (const auto &T : Ts) { + + mTexts[textCounter] = T; + textCounter++; + } +} + +void TextRender::clearTexts() { mTexts.clear(); } + +std::vector TextRender::generateQuads(const glm::vec3& bgColor) { + + numChars = 0; + + std::vector vertices; + + for (const auto &T : mTexts) { + + setCursorPos(T.second.cursorPos); + setPlane(glm::normalize(T.second.cursorDirX), + glm::normalize(T.second.cursorDirY)); + + for (const auto &c : T.second.text) { + + glm::vec3 p0, p1, p2, p3; + + // Character Atlas Values + glm::vec3 width, height, xAdvance, xBear, yBear; + + glm::vec2 A, B, C, D; + + // Change to vectors in the plane + xBear = T.second.textSize * Characters[c].x * mCursorDirX + + T.second.offset.x * mCursorDirX; + yBear = T.second.textSize * Characters[c].y * mCursorDirY + + T.second.offset.y * mCursorDirY; + width = T.second.textSize * Characters[c].width * mCursorDirX; + height = T.second.textSize * Characters[c].height * mCursorDirY; + xAdvance = T.second.textSize * Characters[c].xAdvance * mCursorDirX; + + // If Space, just advance the cursor and move on + if (c == 32) { + + mCursorPos += xAdvance; + continue; + } + + // Texture Coordinates + A = {Characters[c].textureCoords.x, Characters[c].textureCoords.w}; + B = {Characters[c].textureCoords.x, Characters[c].textureCoords.y}; + C = {Characters[c].textureCoords.z, Characters[c].textureCoords.y}; + D = {Characters[c].textureCoords.z, Characters[c].textureCoords.w}; + + // Construct the 4 points of the Quad + p0 = mCursorPos + xBear + yBear; + p1 = p0 - height; + p2 = p1 + width; + p3 = p2 + height; + + // Generate Vertices + Vertex V1 = {p0, T.second.textColor, bgColor, A}; + Vertex V2 = {p1, T.second.textColor, bgColor, B}; + Vertex V3 = {p2, T.second.textColor, bgColor, C}; + Vertex V4 = {p3, T.second.textColor, bgColor, D}; + + vertices.push_back(V1); + vertices.push_back(V2); + vertices.push_back(V3); + vertices.push_back(V4); + + // Advance the text cursor to the next position + mCursorPos += xAdvance; + + numChars++; + } + } + + return vertices; +} + +std::vector TextRender::generateIndices() { + + std::vector indices; + + for (int i = 0; i < numChars; i++) { + indices.push_back(i * 4 + 0); + indices.push_back(i * 4 + 1); + indices.push_back(i * 4 + 2); + indices.push_back(i * 4 + 2); + indices.push_back(i * 4 + 3); + indices.push_back(i * 4 + 0); + } + return indices; +} + +} // namespace txt +} // namespace CADERA_APP_NAMESPACE diff --git a/src/text/textrender.hpp b/src/text/textrender.hpp new file mode 100644 index 0000000..8421d7f --- /dev/null +++ b/src/text/textrender.hpp @@ -0,0 +1,68 @@ +#pragma once + +namespace CADERA_APP_NAMESPACE { +namespace txt { + +struct Text { + std::string text; + float textSize = 1.0f; + glm::vec3 textColor; + glm::vec3 cursorPos; + glm::vec3 cursorDirX; + glm::vec3 cursorDirY; + glm::vec2 offset = {0.0f, 0.0f}; +}; + +struct Vertex { + glm::vec3 pos; + glm::vec3 textColor; + glm::vec3 backgroundColor; + glm::vec2 texCoord; +}; + +struct Character { + float width; + float height; + float x; + float y; + float xAdvance; + glm::vec4 textureCoords; +}; + +class TextRender { + +public: + TextRender(); + ~TextRender(); + + void setFontSize(float s); + + void loadFont(std::string filePath); + + void setCursorPos(glm::vec3 pos); + void setPlane(glm::vec3 xDir, glm::vec3 yDir); + + void addText(Text T); + void addText(std::vector Ts); + void clearTexts(); + + std::vector generateQuads(const glm::vec3& bgColor); + std::vector generateIndices(); + +private: + std::map Characters; + + std::map mTexts; + + glm::vec3 mCursorPos; + glm::vec3 mCursorDirX; + glm::vec3 mCursorDirY; + + float mFontSize; + float mAtlasSize; + + int numChars; + int textCounter; +}; +} // namespace txt +} // namespace CADERA_APP_NAMESPACE diff --git a/src/ux/CMakeLists.txt b/src/ux/CMakeLists.txt index 42b9e81..621fc52 100644 --- a/src/ux/CMakeLists.txt +++ b/src/ux/CMakeLists.txt @@ -2,10 +2,12 @@ cmake_minimum_required(VERSION 3.5) target_sources(CaderaApp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/gui.cpp - ${CMAKE_CURRENT_LIST_DIR}/Nodes.cpp + ${CMAKE_CURRENT_LIST_DIR}/command/command.cpp + ${CMAKE_CURRENT_LIST_DIR}/command/mouse.cpp + ${CMAKE_CURRENT_LIST_DIR}/command/sketchcommands.cpp + ${CMAKE_CURRENT_LIST_DIR}/command/cameracommands.cpp ) -# target_sources(CaderaApp PRIVATE ${CMAKE_CURRENT_LIST_DIR}/imnodes/imnodes.cpp) \ No newline at end of file diff --git a/src/ux/Nodes.cpp b/src/ux/Nodes.cpp deleted file mode 100644 index afb7a6c..0000000 --- a/src/ux/Nodes.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "Nodes.hpp" - -void NodeTest::show() -{ - // ImNodes::CreateContext(); - // ImNodes::SetNodeGridSpacePos(1, ImVec2(200.0f, 200.0f)); - - // ImGui::Begin("simple node editor"); - - // ImNodes::BeginNodeEditor(); - // ImNodes::BeginNode(1); - - // ImNodes::BeginNodeTitleBar(); - // ImGui::TextUnformatted("Node 1"); - // ImNodes::EndNodeTitleBar(); - - // ImNodes::BeginInputAttribute(2); - // ImGui::Text("input"); - // ImNodes::EndInputAttribute(); - - // static float nodeValue = 0.0f; - - // ImGui::PushItemWidth(30.f); - // ImGui::InputFloat("Value", &nodeValue); - // ImGui::PopItemWidth(); - - // ImNodes::BeginOutputAttribute(3); - // ImGui::Indent(50); - // ImGui::Text("output"); - // ImNodes::EndOutputAttribute(); - - // ImNodes::EndNode(); - - - - // ImNodes::BeginNode(4); - - // ImNodes::BeginNodeTitleBar(); - // ImGui::TextUnformatted("Node 2"); - // ImNodes::EndNodeTitleBar(); - - // ImNodes::BeginInputAttribute(5); - // ImGui::Text("input"); - // ImNodes::EndInputAttribute(); - - // static float nodeValue2 = 0.0f; - - // ImGui::PushItemWidth(50.f); - // ImGui::InputFloat("Value", &nodeValue2); - // ImGui::PopItemWidth(); - - // ImNodes::BeginOutputAttribute(6); - // ImGui::Indent(40); - // ImGui::Text("output"); - // ImNodes::EndOutputAttribute(); - - // ImNodes::EndNode(); - - - // ImNodes::EndNodeEditor(); - - // ImGui::End(); - -} - - - diff --git a/src/ux/Nodes.hpp b/src/ux/Nodes.hpp deleted file mode 100644 index 331aae2..0000000 --- a/src/ux/Nodes.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -//#include "imnodes/imnodes_internal.h" - - -class NodeTest { -public: - void show(); - - -}; diff --git a/src/ux/command/cameracommands.cpp b/src/ux/command/cameracommands.cpp new file mode 100644 index 0000000..72a6c3a --- /dev/null +++ b/src/ux/command/cameracommands.cpp @@ -0,0 +1,26 @@ +#include "cameracommands.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + + + +CameraZoomCommand::CameraZoomCommand() : mCamera{nullptr} {} + + +void CameraZoomCommand::setCamera(cam::Camera *cam) { + mCamera = cam; +} + +void CameraZoomCommand::execute(double yoffset) { + if (mCamera) { + + mCamera->zoom(static_cast(yoffset)); + + } +} + +} +} \ No newline at end of file diff --git a/src/ux/command/cameracommands.hpp b/src/ux/command/cameracommands.hpp new file mode 100644 index 0000000..8a24680 --- /dev/null +++ b/src/ux/command/cameracommands.hpp @@ -0,0 +1,24 @@ +#pragma once +#include "sketchcommands.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + + +class CameraZoomCommand : public Command { +public: + + CameraZoomCommand(); + + void setCamera(cam::Camera* cam); + + void execute(double) override; + +private: + cam::Camera* mCamera; + +}; + +} +} \ No newline at end of file diff --git a/src/ux/command/command.cpp b/src/ux/command/command.cpp new file mode 100644 index 0000000..1580931 --- /dev/null +++ b/src/ux/command/command.cpp @@ -0,0 +1,16 @@ +#include "command.hpp" + +namespace CADERA_APP_NAMESPACE { +namespace command { + +Command::Command() {} + +Command::~Command() {} + +void Command::execute() { std::cout << "Command Executed!" << std::endl; } + +void Command::execute(double d) {}; + + +} // namespace action +} // namespace CADERA_APP_NAMESPACE diff --git a/src/ux/command/command.hpp b/src/ux/command/command.hpp new file mode 100644 index 0000000..66da265 --- /dev/null +++ b/src/ux/command/command.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "render/camera.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + + +class Command { + + + +public: + + + Command(); + ~Command(); + + virtual void execute(); + + virtual void execute(double); +}; +} // namespace action +} // namespace CADERA_APP_NAMESPACE \ No newline at end of file diff --git a/src/ux/command/mouse.cpp b/src/ux/command/mouse.cpp new file mode 100644 index 0000000..f3bc389 --- /dev/null +++ b/src/ux/command/mouse.cpp @@ -0,0 +1,49 @@ +#include "mouse.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + +Mouse::Mouse() : + mRightMouseSlot{nullptr}, + mMiddleMouseSlot{nullptr}, + mScrollMouseSlot{nullptr}, + mLeftMouseSlot{nullptr} {} + +void Mouse::setRightMouseSlot(Command *rightMouse) { + mRightMouseSlot = rightMouse; +} + +void Mouse::setMiddleMouseSlot(Command *middleMouse) { + mMiddleMouseSlot = middleMouse; +} + +void Mouse::setScrollMouseSlot(Command *scrollMouse) { + mScrollMouseSlot = scrollMouse; +} + +void Mouse::setLeftMouseSlot(Command *leftMouse) { + mLeftMouseSlot = leftMouse; +} + +void Mouse::rightMouseClick() { + if (mRightMouseSlot) + mRightMouseSlot->execute(); + +} + +void Mouse::scroll(double yOffset) { + if (mScrollMouseSlot) + mScrollMouseSlot->execute(yOffset); +} + + +void Mouse::leftMouseClick() { + if (mLeftMouseSlot) + mLeftMouseSlot->execute(); + +} + +} // namespace command +} \ No newline at end of file diff --git a/src/ux/command/mouse.hpp b/src/ux/command/mouse.hpp new file mode 100644 index 0000000..ceb9cb0 --- /dev/null +++ b/src/ux/command/mouse.hpp @@ -0,0 +1,33 @@ +#pragma once +#include "cameracommands.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + +class Mouse { +public: + + Mouse(); + + void setRightMouseSlot(Command* rightMouse); + void setMiddleMouseSlot(Command* middleMouse); + void setScrollMouseSlot(Command* scrollMouse); + void setLeftMouseSlot(Command* leftMouse); + + void rightMouseClick(); + void scroll(double yOffset); + void leftMouseClick(); + + +private: + + Command* mRightMouseSlot; + Command* mMiddleMouseSlot; + Command* mScrollMouseSlot; + Command* mLeftMouseSlot; + +}; + +} +} \ No newline at end of file diff --git a/src/ux/command/sketchcommands.cpp b/src/ux/command/sketchcommands.cpp new file mode 100644 index 0000000..7105e95 --- /dev/null +++ b/src/ux/command/sketchcommands.cpp @@ -0,0 +1,45 @@ +#include "sketchcommands.hpp" +#include "pch.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + + + +SketchAddPointCommand::SketchAddPointCommand() : mSketch{nullptr}, + mSelector{nullptr}, + mCamera{nullptr} + {} + +void SketchAddPointCommand::setSketch(sketch::Sketch *S) { + + mSketch = S; +} + +void SketchAddPointCommand::setSelector(sel::Selector *sel) { + mSelector = sel; +} + +void SketchAddPointCommand::setCamera(cam::Camera *cam) { + mCamera = cam; +} + +void SketchAddPointCommand::execute() { + if (mSketch && mSelector && mCamera) { + + mSelector->select(mCamera->mouseRay, glm::vec3(0.0f, 0.0f, 0.0f), + mCamera->cameraVec, mCamera->pos, + mCamera->cross, + mCamera->flags.test(cad::cam::ortho)); + + if (!mSelector->existingPoint(mSelector->point)) + mSketch->add(mSelector->point); + + + } +} + + +} +} \ No newline at end of file diff --git a/src/ux/command/sketchcommands.hpp b/src/ux/command/sketchcommands.hpp new file mode 100644 index 0000000..63add37 --- /dev/null +++ b/src/ux/command/sketchcommands.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "command.hpp" + +namespace CADERA_APP_NAMESPACE { + +namespace command { + + +class SketchAddPointCommand : public Command { +public: + + SketchAddPointCommand(); + + void setSketch(sketch::Sketch* S); + void setSelector(sel::Selector* sel); + void setCamera(cam::Camera* cam); + + void execute() override; + +private: + + sketch::Sketch* mSketch; + sel::Selector* mSelector; + cam::Camera* mCamera; + +}; + +} +} \ No newline at end of file diff --git a/src/ux/gui.cpp b/src/ux/gui.cpp index faf5baa..9098cde 100644 --- a/src/ux/gui.cpp +++ b/src/ux/gui.cpp @@ -1,518 +1,483 @@ -#include "../pch.hpp" #include "gui.hpp" +#include "../pch.hpp" namespace CADERA_APP_NAMESPACE { namespace gui { - +void imguiBegin() { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); +} - void imguiBegin() { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - } +void imguiEnd() { ImGui::Render(); } - void imguiEnd() { - ImGui::Render(); - } +void mainMenuBar() { + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { - void mainMenuBar() { - - if (ImGui::BeginMainMenuBar()) { - if (ImGui::BeginMenu("File")) { + ImGui::MenuItem("New"); + ImGui::MenuItem("Open"); + ImGui::MenuItem("Save"); + ImGui::MenuItem("Close"); - ImGui::MenuItem("New"); - ImGui::MenuItem("Open"); - ImGui::MenuItem("Save"); - ImGui::MenuItem("Close"); + ImGui::EndMenu(); + } - ImGui::EndMenu(); - } + if (ImGui::BeginMenu("Edit")) { - if (ImGui::BeginMenu("Edit")) { + ImGui::MenuItem("Undo"); - ImGui::MenuItem("Undo"); + ImGui::EndMenu(); + } - ImGui::EndMenu(); - } + if (ImGui::BeginMenu("View")) { - if (ImGui::BeginMenu("View")) { + ImGui::EndMenu(); + } - ImGui::EndMenu(); - } + if (ImGui::BeginMenu("Tools")) { - if (ImGui::BeginMenu("Tools")) { + ImGui::EndMenu(); + } - ImGui::EndMenu(); - } + if (ImGui::BeginMenu("Help")) { - if (ImGui::BeginMenu("Help")) { + ImGui::EndMenu(); + } - ImGui::EndMenu(); - } + ImGui::EndMainMenuBar(); + } +} - ImGui::EndMainMenuBar(); - } - } +void startMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + std::bitset &flags) { - void startMenu(sketch::Sketch& Sketch, CADRender& Render, sel::Selector& Sel, - std::bitset &flags) { + ImGui::Begin("Start Screen"); - ImGui::Begin("Start Screen"); + static int modelTypeInt; + ImGui::RadioButton("Sketch", &modelTypeInt, 0); + ImGui::SameLine(); + ImGui::RadioButton("Part", &modelTypeInt, 1); - + if (modelTypeInt == 0) { - static int modelTypeInt; - ImGui::RadioButton("Sketch", &modelTypeInt, 0); ImGui::SameLine(); - ImGui::RadioButton("Part", &modelTypeInt, 1); + ImGui::Text("Sketch Plane:"); - if (modelTypeInt == 0) { - - ImGui::Text("Sketch Plane:"); + static int sketchViewInt; + ImGui::RadioButton("XY", &sketchViewInt, 0); + ImGui::SameLine(); + ImGui::RadioButton("ZX", &sketchViewInt, 1); + ImGui::SameLine(); + ImGui::RadioButton("YZ", &sketchViewInt, 2); - static int sketchViewInt; - ImGui::RadioButton("XY", &sketchViewInt, 0); ImGui::SameLine(); - ImGui::RadioButton("ZX", &sketchViewInt, 1); ImGui::SameLine(); - ImGui::RadioButton("YZ", &sketchViewInt, 2); + if (ImGui::Button("New Sketch")) { - if (ImGui::Button("New Sketch")) { - - flags.set(gui_sketch_menu); - - if (sketchViewInt == 0) { - Render.Cam.setXYView(); - Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, Render.Cam.cross); - } - else if (sketchViewInt == 1) { - Render.Cam.setZXView(); - Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, Render.Cam.cross); - } - else { - Render.Cam.setYZView(); - Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, Render.Cam.cross); - } + flags.set(gui_sketch_menu); - Sketch.flags.set(sketch::skt_active); - Sketch.setType(cad_sketch); - Sketch.setCameraDistance(&Render.Cam.camDistance); - Sel.setActiveSketch(&Sketch); + if (sketchViewInt == 0) { + Render.Cam.setXYView(); + Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, + Render.Cam.cross); + } else if (sketchViewInt == 1) { + Render.Cam.setZXView(); + Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, + Render.Cam.cross); + } else { + Render.Cam.setYZView(); + Sketch.mGrid.setGridOrientation(Render.Cam.cameraVec, Render.Cam.up, + Render.Cam.cross); + } - Render.flags.set(render_update_sketch); + Sketch.flags.set(sketch::skt_active); + Sketch.setType(cad_sketch); + Sketch.setCameraDistance(&Render.Cam.camDistance); + Sel.setActiveSketch(&Sketch); - flags.reset(gui_start_menu); - } - } + Render.flags.set(render_update_sketch); - ImGui::End(); + flags.reset(gui_start_menu); + } + } - } + ImGui::End(); +} - void sketchMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags) { +void sketchMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + std::bitset &flags) { - ImGui::SetNextWindowPos({ 0, 20 }); - ImGui::SetNextWindowSize({ 300.0f, - static_cast(Render.mExtent.height - 20) }); + ImGui::SetNextWindowPos({0, 20}); + ImGui::SetNextWindowSize( + {300.0f, static_cast(Render.mExtent.height - 20)}); - ImGui::Begin("Sketching"); + ImGui::Begin("Sketching"); #ifdef CADERA_DEBUG - static bool demoCheck = false; - ImGui::Checkbox("Demo Window", &demoCheck); - - - if (demoCheck) ImGui::ShowDemoWindow(); + static bool demoCheck = false; + ImGui::Checkbox("Demo Window", &demoCheck); - static bool debugCheck = true; - ImGui::Checkbox("Debug Window", &debugCheck); + if (demoCheck) + ImGui::ShowDemoWindow(); + static bool debugCheck = true; + ImGui::Checkbox("Debug Window", &debugCheck); - if (debugCheck) showDebugWindow(Sketch, Render, Sel, flags); - + if (debugCheck) + showDebugWindow(Sketch, Render, Sel, flags); #endif - if (ImGui::Button("Node Editor")) { - - flags.set(gui_sketch_node_editor); - } - - if (ImGui::Button("Grid Options")) { - - flags.set(gui_sketch_grid_menu); - } + if (ImGui::Button("Grid Options")) { - if (ImGui::Button("Point")) { + flags.set(gui_sketch_grid_menu); + } - Sketch.activatePointTool(); + if (ImGui::Button("Point")) { - } + Sketch.activatePointTool(); + } - if (ImGui::Button("Note")) { + if (ImGui::Button("Note")) { - Sketch.activateNoteTool(); - - } + Sketch.activateNoteTool(); + } - if (Sketch.flags.test(sketch::skt_note_tool)) { - + if (Sketch.flags.test(sketch::skt_note_tool)) { - static ImGuiInputTextFlags flags = {}; - - ImGui::InputTextMultiline("Note Text", &Sketch.noteText ); - } + static ImGuiInputTextFlags flags = {}; - if (ImGui::CollapsingHeader("Relations", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::InputTextMultiline("Note Text", &Sketch.noteText); + } - if (Sel.flags.test(sel::select_double_point) || Sel.flags.test(sel::select_multi_point)) { + if (ImGui::CollapsingHeader("Relations", ImGuiTreeNodeFlags_DefaultOpen)) { - if (ImGui::Button("Vertical")) { - - bool success = Render.SktSolver.addNewSketchRelation(Sel.getSelectedPointIds(), cad::rel_vertical); - - if (success) - Render.flags.set(render_update_sketch); - - } + if (Sel.flags.test(sel::select_double_point) || + Sel.flags.test(sel::select_multi_point)) { - if (ImGui::Button("Horizontal")) { - - bool success = Render.SktSolver.addNewSketchRelation(Sel.getSelectedPointIds(), cad::rel_horizontal); + if (ImGui::Button("Vertical")) { - if (success) - Render.flags.set(render_update_sketch); + bool success = Render.SktSolver.addNewSketchRelation( + Sel.getSelectedPointIds(), cad::rel_vertical); - } + if (success) + Render.flags.set(render_update_sketch); + } - if (ImGui::Button("Coincident")) { + if (ImGui::Button("Horizontal")) { - bool success = Render.SktSolver.addNewSketchRelation(Sel.getSelectedPointIds(), cad::rel_coincident); + bool success = Render.SktSolver.addNewSketchRelation( + Sel.getSelectedPointIds(), cad::rel_horizontal); - if (success) - Render.flags.set(render_update_sketch); + if (success) + Render.flags.set(render_update_sketch); + } - } + if (ImGui::Button("Coincident")) { - if (ImGui::Button("Clear")) { + bool success = Render.SktSolver.addNewSketchRelation( + Sel.getSelectedPointIds(), cad::rel_coincident); - Sketch.clearRelations(); + if (success) + Render.flags.set(render_update_sketch); + } - Render.flags.set(render_update_sketch); + if (ImGui::Button("Clear")) { - } + Sketch.clearRelations(); - } + Render.flags.set(render_update_sketch); + } + } + } - } + ImGui::End(); +} +void gridMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + std::bitset &flags) { - ImGui::End(); + ImGui::SetNextWindowPos({320, 20}); + ImGui::SetNextWindowSize({300.0f, 300.0f}); - } + ImGui::Begin("Grid Options Menu"); - void gridMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags) { + ImGui::InputInt("Grid Size", &Sketch.mGrid.size); + ImGui::InputFloat("Grid Spacing", &Sketch.mGrid.spacing); - ImGui::SetNextWindowPos({ 320, 20 }); - ImGui::SetNextWindowSize({ 300.0f, 300.0f }); + // Prevent too large of a grid from freezing program + if (Sketch.mGrid.size > 10000) + Sketch.mGrid.size = 10000; - ImGui::Begin("Grid Options Menu"); + // Limit size of grid to protect from undefined behavior + if (Sketch.mGrid.spacing > 10000) + Sketch.mGrid.spacing = 10000; - ImGui::InputInt("Grid Size", &Sketch.mGrid.size); - ImGui::InputFloat("Grid Spacing", &Sketch.mGrid.spacing); + if (ImGui::Button("OK")) { + Render.flags.set(render_update_sketch); + flags.reset(gui_sketch_grid_menu); + } - if (ImGui::Button("OK")) { - Render.flags.set(render_update_sketch); - flags.reset(gui_sketch_grid_menu); - } + ImGui::End(); +} - ImGui::End(); +void showDebugWindow(sketch::Sketch &Sketch, CADRender &Render, + sel::Selector &Sel, + std::bitset &flags) { - } + ImGui::Begin("Debugging"); - void nodeMenu() { - - NodeTest N; + if (ImGui::CollapsingHeader("Render", ImGuiTreeNodeFlags_None)) { + // Copy of selection point color to check for changes + glm::vec4 selPointColor = Render.mRenderColors.selPointColor; - N.show(); + ImGui::ColorPicker4("Background Color", (float *)&Render.mRenderColors.bgColor); + ImGui::ColorPicker4("Selection Point Color", + (float *)&Render.mRenderColors.selPointColor); + ImGui::ColorPicker4("Sketch Point Color", + (float *)&Render.mRenderColors.sketchPointColor); + ImGui::ColorPicker4("Sketch Line Color", + (float *)&Render.mRenderColors.sketchLineColor); + ImGui::ColorPicker4("Sketch Grid Color", + (float *)&Render.mRenderColors.sketchGridColor); - + // Update rendering if selection point color has changed + if (selPointColor != Render.mRenderColors.selPointColor) { + Render.flags.set(render_update_sketch); + std::cout << "Selection Point Color has changed!" << std::endl; } + } - void showDebugWindow(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags) { - - - ImGui::Begin("Debugging"); + if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_None)) { + static bool orthoCheck = true; + ImGui::Checkbox("Orthogonal", &orthoCheck); - if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_None)) - { + if (orthoCheck && !Render.Cam.flags.test(cam::ortho)) { - static bool orthoCheck = true; - ImGui::Checkbox("Orthogonal", &orthoCheck); + Render.Cam.flags.set(cam::ortho); + } else if (!orthoCheck && Render.Cam.flags.test(cam::ortho)) { - if (orthoCheck && !Render.Cam.flags.test(cam::ortho)) { - - Render.Cam.flags.set(cam::ortho); - - } - else if (!orthoCheck && Render.Cam.flags.test(cam::ortho)) { - - Render.Cam.flags.reset(cam::ortho); - - } + Render.Cam.flags.reset(cam::ortho); + } - if (ImGui::Button("Set XY View")) { - Render.Cam.setXYView(); - } - if (ImGui::Button("Set ZX View")) { - Render.Cam.setZXView(); - } - if (ImGui::Button("Set YZ View")) { - Render.Cam.setYZView(); - } - + if (ImGui::Button("Set XY View")) { + Render.Cam.setXYView(); + } + if (ImGui::Button("Set ZX View")) { + Render.Cam.setZXView(); + } + if (ImGui::Button("Set YZ View")) { + Render.Cam.setYZView(); + } - ImGui::Text("Left: %f", Render.Cam.left); + ImGui::Text("Left: %f", Render.Cam.left); - ImGui::NewLine(); + ImGui::NewLine(); - ImGui::Text("Position"); - ImGui::Text("x: %f", Render.Cam.pos.x); - ImGui::Text("y: %f", Render.Cam.pos.y); - ImGui::Text("z: %f", Render.Cam.pos.z); + ImGui::Text("Position"); + ImGui::Text("x: %f", Render.Cam.pos.x); + ImGui::Text("y: %f", Render.Cam.pos.y); + ImGui::Text("z: %f", Render.Cam.pos.z); - ImGui::NewLine(); - - ImGui::Text("Focus"); - ImGui::Text("x: %f", Render.Cam.focus.x); - ImGui::Text("y: %f", Render.Cam.focus.y); - ImGui::Text("z: %f", Render.Cam.focus.z); - - ImGui::NewLine(); - - ImGui::Text("Mouse Ray"); - ImGui::Text("x: %f", Render.Cam.mouseRay.x); - ImGui::Text("y: %f", Render.Cam.mouseRay.y); - ImGui::Text("z: %f", Render.Cam.mouseRay.z); - - ImGui::NewLine(); - - ImGui::Text("Camera Distance"); - ImGui::Text("Distance: %f", Render.Cam.camDistance); - - ImGui::NewLine(); - - ImGui::Text("Up"); - ImGui::Text("x: %f", Render.Cam.up.x); - ImGui::Text("y: %f", Render.Cam.up.y); - ImGui::Text("z: %f", Render.Cam.up.z); + ImGui::NewLine(); - ImGui::NewLine(); + ImGui::Text("Focus"); + ImGui::Text("x: %f", Render.Cam.focus.x); + ImGui::Text("y: %f", Render.Cam.focus.y); + ImGui::Text("z: %f", Render.Cam.focus.z); - ImGui::Text("Cross"); - ImGui::Text("x: %f", Render.Cam.cross.x); - ImGui::Text("y: %f", Render.Cam.cross.y); - ImGui::Text("z: %f", Render.Cam.cross.z); - - } + ImGui::NewLine(); - if (ImGui::CollapsingHeader("Selection", ImGuiTreeNodeFlags_None)) { + ImGui::Text("Mouse Ray"); + ImGui::Text("x: %f", Render.Cam.mouseRay.x); + ImGui::Text("y: %f", Render.Cam.mouseRay.y); + ImGui::Text("z: %f", Render.Cam.mouseRay.z); - ImGui::Text("Selection Flags"); - ImGui::Text("First Click: %d", Render.Sel.flags.test(sel::select_first_click)); - ImGui::Text("Single Point: %d", Render.Sel.flags.test(sel::select_single_point)); - ImGui::Text("Double Point: %d", Render.Sel.flags.test(sel::select_double_point)); - ImGui::Text("Multi Point: %d", Render.Sel.flags.test(sel::select_multi_point)); + ImGui::NewLine(); - ImGui::NewLine(); + ImGui::Text("Camera Distance"); + ImGui::Text("Distance: %f", Render.Cam.camDistance); - ImGui::Text("Selection Point"); - ImGui::Text("x: %f", Sel.point.x); - ImGui::Text("y: %f", Sel.point.y); - ImGui::Text("z: %f", Sel.point.z); + ImGui::NewLine(); - ImGui::NewLine(); + ImGui::Text("Up"); + ImGui::Text("x: %f", Render.Cam.up.x); + ImGui::Text("y: %f", Render.Cam.up.y); + ImGui::Text("z: %f", Render.Cam.up.z); - ImGui::Text("Selected Points"); - for (const auto& p : Sel.selectedPoints) { - ImGui::Text("Selected Point: %d", p.first); - ImGui::Text("x: %f", p.second.pos.x); - ImGui::Text("y: %f", p.second.pos.y); - ImGui::Text("z: %f", p.second.pos.z); - ImGui::NewLine(); - } + ImGui::NewLine(); - } + ImGui::Text("Cross"); + ImGui::Text("x: %f", Render.Cam.cross.x); + ImGui::Text("y: %f", Render.Cam.cross.y); + ImGui::Text("z: %f", Render.Cam.cross.z); + } - if (ImGui::CollapsingHeader("Sketch", ImGuiTreeNodeFlags_DefaultOpen)) { - - ImGui::Text("Sketch Tools:"); + if (ImGui::CollapsingHeader("Selection", ImGuiTreeNodeFlags_None)) { - ImGui::Text("FeatureCounter: %d", Sketch.getFeatureCounter()); - - ImGui::Text("Camera Distance"); - ImGui::Text("Distance: %f", *Sketch.mCamDistance); - - ImGui::NewLine(); - - - static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | - ImGuiTableFlags_Reorderable | - ImGuiTableFlags_Hideable | - ImGuiTableFlags_RowBg; - - - if (ImGui::BeginTable("Sketch Flags Debug", 2, flags)) - { - - ImGui::TableSetupColumn("Flag Name"); - ImGui::TableSetupColumn("Status"); - ImGui::TableHeadersRow(); - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("Sketch Active"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%d", Sketch.flags.test(sketch::skt_active)); - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("Sketch Points Have Moved"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%d", Sketch.flags.test(sketch::skt_points_have_moved)); - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("Tool Active"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%d", Sketch.flags.test(sketch::skt_tool_active)); + ImGui::Text("Selection Flags"); + ImGui::Text("First Click: %d", + Render.Sel.flags.test(sel::select_first_click)); + ImGui::Text("Single Point: %d", + Render.Sel.flags.test(sel::select_single_point)); + ImGui::Text("Double Point: %d", + Render.Sel.flags.test(sel::select_double_point)); + ImGui::Text("Multi Point: %d", + Render.Sel.flags.test(sel::select_multi_point)); - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("Point Tool Active"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%d", Sketch.flags.test(sketch::skt_point_tool)); + ImGui::NewLine(); - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("Note Tool Active"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%d", Sketch.flags.test(sketch::skt_note_tool)); + ImGui::Text("Selection Point"); + ImGui::Text("x: %f", Sel.point.x); + ImGui::Text("y: %f", Sel.point.y); + ImGui::Text("z: %f", Sel.point.z); - - + ImGui::NewLine(); - ImGui::EndTable(); - } + ImGui::Text("Selected Points"); + for (const auto &p : Sel.selectedPoints) { + ImGui::Text("Selected Point: %d", p.first); + ImGui::Text("x: %f", p.second.pos.x); + ImGui::Text("y: %f", p.second.pos.y); + ImGui::Text("z: %f", p.second.pos.z); + ImGui::NewLine(); + } + } + if (ImGui::CollapsingHeader("Sketch", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Text("Sketch Tools:"); - for (auto& rel : Sketch.mRelations) { + ImGui::Text("FeatureCounter: %d", Sketch.getFeatureCounter()); - if (rel.second.mId == 0) - continue; + ImGui::Text("Camera Distance"); + ImGui::Text("Distance: %f", *Sketch.mCamDistance); - if (rel.second.mType == cad::rel_vertical) - ImGui::Text("Relation: Vertical"); - if (rel.second.mType == cad::rel_horizontal) - ImGui::Text("Relation: Horizontal"); - if (rel.second.mType == cad::rel_coincident) - ImGui::Text("Relation: Coincident"); + ImGui::NewLine(); + static ImGuiTableFlags flags = + ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | + ImGuiTableFlags_Hideable | ImGuiTableFlags_RowBg; - ImGui::Text("Id: %d", rel.second.mId); + if (ImGui::BeginTable("Sketch Flags Debug", 2, flags)) { - ImGui::Text("Features:"); - for (const auto& id : rel.second.mFeatureIds) { - ImGui::Text("%d", id); - } - - } + ImGui::TableSetupColumn("Flag Name"); + ImGui::TableSetupColumn("Status"); + ImGui::TableHeadersRow(); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Sketch Active"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%d", Sketch.flags.test(sketch::skt_active)); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Sketch Points Have Moved"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%d", Sketch.flags.test(sketch::skt_points_have_moved)); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Tool Active"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%d", Sketch.flags.test(sketch::skt_tool_active)); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Point Tool Active"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%d", Sketch.flags.test(sketch::skt_point_tool)); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Note Tool Active"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%d", Sketch.flags.test(sketch::skt_note_tool)); + ImGui::EndTable(); + } - - // Sketch Points - + for (auto &rel : Sketch.mRelations) { - if (ImGui::BeginTable("Sketch Points Debug", 4, flags)) - { + if (rel.second.mId == 0) + continue; - ImGui::TableSetupColumn("Id"); - ImGui::TableSetupColumn("x"); - ImGui::TableSetupColumn("y"); - ImGui::TableSetupColumn("z"); - ImGui::TableHeadersRow(); - - - for (const auto &point : Sketch.Points) - { - - ImGui::TableNextRow(); - - ImGui::TableSetColumnIndex(0); - ImGui::Text("%d", point.first); + if (rel.second.mType == cad::rel_vertical) + ImGui::Text("Relation: Vertical"); + if (rel.second.mType == cad::rel_horizontal) + ImGui::Text("Relation: Horizontal"); + if (rel.second.mType == cad::rel_coincident) + ImGui::Text("Relation: Coincident"); - ImGui::TableSetColumnIndex(1); - ImGui::Text("%f", point.second.pos.x); + ImGui::Text("Id: %d", rel.second.mId); - ImGui::TableSetColumnIndex(2); - ImGui::Text("%f", point.second.pos.y); + ImGui::Text("Features:"); + for (const auto &id : rel.second.mFeatureIds) { + ImGui::Text("%d", id); + } + } - ImGui::TableSetColumnIndex(3); - ImGui::Text("%f", point.second.pos.z); - - - } + // Sketch Points - ImGui::EndTable(); - } + if (ImGui::BeginTable("Sketch Points Debug", 4, flags)) { - ImGui::NewLine(); + ImGui::TableSetupColumn("Id"); + ImGui::TableSetupColumn("x"); + ImGui::TableSetupColumn("y"); + ImGui::TableSetupColumn("z"); + ImGui::TableHeadersRow(); - - } + for (const auto &point : Sketch.Points) { - ImGui::End(); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("%d", point.first); - } + ImGui::TableSetColumnIndex(1); + ImGui::Text("%f", point.second.pos.x); - void imguiRun(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel) { + ImGui::TableSetColumnIndex(2); + ImGui::Text("%f", point.second.pos.y); - static std::bitset flags(gui_start_menu + 1); - + ImGui::TableSetColumnIndex(3); + ImGui::Text("%f", point.second.pos.z); + } + ImGui::EndTable(); + } - // Cadera imgui begin, not part of Dear Imgui - imguiBegin(); + ImGui::NewLine(); + } - mainMenuBar(); - - if (flags.test(gui_start_menu)) startMenu(Sketch, Render, Sel, flags); - if (flags.test(gui_sketch_menu)) sketchMenu(Sketch, Render, Sel, flags); - if (flags.test(gui_sketch_grid_menu)) gridMenu(Sketch, Render, Sel, flags); - if (flags.test(gui_sketch_node_editor)) nodeMenu(); + ImGui::End(); +} - +void imguiRun(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel) { + static std::bitset flags(gui_start_menu + 1); - // Cadera imgui end, not part of Dear Imgui - imguiEnd(); + // Cadera imgui begin, not part of Dear Imgui + imguiBegin(); + mainMenuBar(); - } + if (flags.test(gui_start_menu)) + startMenu(Sketch, Render, Sel, flags); + if (flags.test(gui_sketch_menu)) + sketchMenu(Sketch, Render, Sel, flags); + if (flags.test(gui_sketch_grid_menu)) + gridMenu(Sketch, Render, Sel, flags); + // Cadera imgui end, not part of Dear Imgui + imguiEnd(); } -} \ No newline at end of file + +} // namespace gui +} // namespace CADERA_APP_NAMESPACE \ No newline at end of file diff --git a/src/ux/gui.hpp b/src/ux/gui.hpp index 3efbc0c..8e0eae3 100644 --- a/src/ux/gui.hpp +++ b/src/ux/gui.hpp @@ -1,40 +1,40 @@ #pragma once -#include "../render/CADRender.hpp" -#include "Nodes.hpp" +#include "../render/cadrender.hpp" namespace CADERA_APP_NAMESPACE { namespace gui { - enum GUIFlags { - gui_start_menu, - gui_sketch_menu, - gui_sketch_grid_menu, - gui_sketch_node_editor, - gui_num_flags - }; +enum GUIFlags { + gui_start_menu, + gui_sketch_menu, + gui_sketch_grid_menu, + gui_num_flags +}; - void imguiRun(sketch::Sketch &Sketch, CADRender &Render, sel::Selector& Sel); +void imguiRun(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel + ); - void imguiBegin(); +void imguiBegin(); - void imguiEnd(); +void imguiEnd(); - void mainMenuBar(); +void mainMenuBar(); - void startMenu(sketch::Sketch& Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags); +void startMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + std::bitset &flags); - void sketchMenu(sketch::Sketch& Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags); - - void gridMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags); +void sketchMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + std::bitset &flags); - void nodeMenu(); - - void showDebugWindow(sketch::Sketch& Sketch, CADRender &Render, sel::Selector &Sel, - std::bitset &flags); +void gridMenu(sketch::Sketch &Sketch, CADRender &Render, sel::Selector &Sel, + + std::bitset &flags); -} -} \ No newline at end of file +void showDebugWindow(sketch::Sketch &Sketch, CADRender &Render, + sel::Selector &Sel, + std::bitset &flags); + + +} // namespace gui +} // namespace CADERA_APP_NAMESPACE \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f4e1090..12119e3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,7 @@ include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE ) @@ -14,49 +15,44 @@ FetchContent_MakeAvailable(googletest) include(CTest) - find_package(GTest REQUIRED) -add_executable(GTest_Cadera test_sketch.cpp - test_camera.cpp -) +# Test_Camera +# add_executable(Test_Cadera_Camera test_camera.cpp) +# target_include_directories(Test_Cadera_Camera PRIVATE ${CMAKE_SOURCE_DIR}/src) + +# target_link_libraries(Test_Cadera_Camera INTERFACE pch_interface) + +# target_include_directories(Test_Cadera_Camera PRIVATE ${GTEST_INCLUDE_DIRS} ) +# target_link_libraries(Test_Cadera_Camera PRIVATE ${GTEST_BOTH_LIBRARIES}) + + + +# Test_Sketch +add_executable(Test_Cadera_Sketch test_sketch.cpp) +target_include_directories(Test_Cadera_Sketch PRIVATE ${CMAKE_SOURCE_DIR}/src) + + +target_link_libraries(Test_Cadera_Sketch PRIVATE sketchlib) +target_link_libraries(Test_Cadera_Sketch INTERFACE pch_interface) + +target_include_directories(Test_Cadera_Sketch PRIVATE ${GTEST_INCLUDE_DIRS} ) +target_link_libraries(Test_Cadera_Sketch PRIVATE ${GTEST_BOTH_LIBRARIES}) + + +# Test_Text +add_executable(Test_Cadera_Text test_text.cpp) +target_include_directories(Test_Cadera_Text PRIVATE ${CMAKE_SOURCE_DIR}/src) + +target_link_libraries(Test_Cadera_Text PRIVATE textlib) +target_link_libraries(Test_Cadera_Text INTERFACE pch_interface) +target_include_directories(Test_Cadera_Text PRIVATE ${GTEST_INCLUDE_DIRS} ) +target_link_libraries(Test_Cadera_Text PRIVATE ${GTEST_BOTH_LIBRARIES}) -target_precompile_headers(GTest_Cadera PRIVATE pch.hpp) -target_include_directories(GTest_Cadera PRIVATE ${CMAKE_SOURCE_DIR}/src) - -target_sources(GTest_Cadera PRIVATE ../src/sketch/Relation.cpp - ../src/sketch/Feature.cpp - ../src/sketch/Point.cpp - ../src/sketch/Sketcher.cpp - ../src/sketch/Sketch.cpp - ../src/sketch/SketchSolver.cpp - ../src/render/grid.cpp - ../src/render/RenderUtil.cpp - ../src/render/CADRender.cpp - ../src/render/TextRender.cpp - ../src/render/Camera.cpp - ../src/Selection.cpp - ../src/Model.cpp - ../src/callbacks.cpp - ../src/Cadera.cpp - ../src/ux/gui.cpp - ../src/ux/Nodes.cpp - # ../src/ux/imnodes/imnodes.cpp - ) - - -target_include_directories( GTest_Cadera PRIVATE ${GTEST_INCLUDE_DIRS} ) -target_link_libraries(GTest_Cadera PRIVATE ${GTEST_BOTH_LIBRARIES}) -target_link_libraries(GTest_Cadera PRIVATE glm::glm) -find_package(Vulkan REQUIRED) -target_link_libraries(GTest_Cadera PRIVATE Vulkan::Vulkan) -target_link_libraries(GTest_Cadera PRIVATE glfw) -target_include_directories(GTest_Cadera PRIVATE ${Stb_INCLUDE_DIR}) -find_package(imgui CONFIG REQUIRED) -target_link_libraries(GTest_Cadera PRIVATE imgui::imgui) include(GoogleTest) -gtest_discover_tests(GTest_Cadera) +gtest_discover_tests(Test_Cadera_Sketch) +gtest_discover_tests(Test_Cadera_Text) diff --git a/test/pch.hpp b/test/pch.hpp deleted file mode 100644 index 7f0b13b..0000000 --- a/test/pch.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CADERA_APP_NAMESPACE cad -#define GLM_ENABLE_EXPERIMENTAL -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#define GLFW_INCLUDE_VULKAN -#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 -#define IMGUI_DEFINE_MATH_OPERATORS - - -#ifdef _DEBUG -#define CADERA_DEBUG -#endif - -#include - -#include -#include - -#include "GLFW/glfw3.h" - -#include -#include -#include -#include - diff --git a/test/test_camera.cpp b/test/test_camera.cpp index 1cd5a07..e76e2ba 100644 --- a/test/test_camera.cpp +++ b/test/test_camera.cpp @@ -1,5 +1,5 @@ #include -#include +#include VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE diff --git a/test/test_sketch.cpp b/test/test_sketch.cpp index fbd6de7..fb8bdb6 100644 --- a/test/test_sketch.cpp +++ b/test/test_sketch.cpp @@ -1,25 +1,20 @@ #include -#include - +#include // @brief Test if id of Point without an input id is -1 TEST(Sketch, Point_Id_Basic) { + CADERA_APP_NAMESPACE::Point P; - CADERA_APP_NAMESPACE::Point P; - - EXPECT_EQ(P.getId(), -1); - - + EXPECT_EQ(P.getId(), -1); } // @brief Test if id of Point is set to the initialized value TEST(Sketch, Point_Id_Set) { - glm::vec3 v = {0.0f, 0.0f, 0.0f}; - - CADERA_APP_NAMESPACE::Point P(3, v); + glm::vec3 v = {0.0f, 0.0f, 0.0f}; - EXPECT_EQ(P.getId(), 3); + CADERA_APP_NAMESPACE::Point P(3, v); + EXPECT_EQ(P.getId(), 3); } diff --git a/test/test_text.cpp b/test/test_text.cpp new file mode 100644 index 0000000..2803939 --- /dev/null +++ b/test/test_text.cpp @@ -0,0 +1,5 @@ +#include +#include + +// @brief Test if id of Point without an input id is -1 +TEST(Text, Text) { EXPECT_EQ(1, 1); } \ No newline at end of file diff --git a/textures/test.csv b/textures/arial.csv similarity index 100% rename from textures/test.csv rename to textures/arial.csv diff --git a/textures/test.png b/textures/arial.png similarity index 100% rename from textures/test.png rename to textures/arial.png diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index 1ca18cd..619e3db 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -1,9 +1,4 @@ { - "default-registry": { - "kind": "git", - "baseline": "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1", - "repository": "https://github.com/microsoft/vcpkg" - }, "registries": [ { "kind": "artifact", diff --git a/vcpkg.json b/vcpkg.json index 2c5433d..788f75c 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,5 +11,6 @@ }, "stb", "vulkan" - ] + ], + "builtin-baseline": "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1" }