├── readme.md ├── .gitignore ├── LICENSE ├── main.cpp ├── CMakeLists.txt ├── GlfwOcctView.h ├── GlfwOcctWindow.h ├── GlfwOcctWindow.cpp └── GlfwOcctView.cpp /readme.md: -------------------------------------------------------------------------------- 1 | A sample demonstrating usage of OCCT 3D Viewer within a window created using GLFW. 2 | 3 | Platforms: Windows, macOS, Linux 4 | Required: glfw, occt 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 caad.xyz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 OPEN CASCADE SAS 2 | // 3 | // This file is part of the examples of the Open CASCADE Technology software library. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21 | 22 | #include "GlfwOcctView.h" 23 | 24 | int main (int, char**) 25 | { 26 | GlfwOcctView anApp; 27 | try 28 | { 29 | anApp.run(); 30 | } 31 | catch (const std::runtime_error& theError) 32 | { 33 | std::cerr << theError.what() << std::endl; 34 | return EXIT_FAILURE; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(glfw-occt-demo) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(APP_VERSION_MAJOR 1) 7 | set(APP_VERSION_MINOR 0) 8 | set(APP_TARGET glfwocct) 9 | 10 | INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) 11 | file(GLOB SOURCES 12 | *.h 13 | *.cpp 14 | ) 15 | source_group ("Headers" FILES 16 | GlfwOcctView.h 17 | GlfwOcctWindow.h) 18 | source_group ("Sources" FILES 19 | GlfwOcctView.cpp 20 | GlfwOcctWindow.cpp 21 | main.cpp) 22 | 23 | # OpenGL 24 | find_package(OpenGL REQUIRED) 25 | 26 | # Open CASCADE Technology 27 | # set(OpenCASCADE_DIR "/usr/local/opt/occt/lib/cmake/opencascade") 28 | 29 | find_package(OpenCASCADE REQUIRED NO_DEFAULT_PATH) 30 | if (OpenCASCADE_FOUND) 31 | message (STATUS "Using OpenCASCADE from \"${OpenCASCADE_DIR}\"" ) 32 | INCLUDE_DIRECTORIES(${OpenCASCADE_INCLUDE_DIR}) 33 | LINK_DIRECTORIES(${OpenCASCADE_LIBRARY_DIR}) 34 | else() 35 | message (WARNING "Could not find OpenCASCADE, please set OpenCASCADE_DIR variable." ) 36 | set (OCCT_LIBRARY_DIR) 37 | set (OCCT_BIN_DIR) 38 | endif() 39 | 40 | SET(OpenCASCADE_LIBS 41 | TKernel 42 | TKService 43 | TKV3d 44 | TKOpenGl 45 | TKBRep 46 | TKGeomBase 47 | TKGeomAlgo 48 | TKG3d 49 | TKG2d 50 | TKTopAlgo 51 | TKPrim 52 | ) 53 | 54 | # glfw 55 | find_package(glfw3 REQUIRED) 56 | if (glfw3_FOUND) 57 | message (STATUS "Using glfw3 ${glfw3_VERSION}" ) 58 | INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS}) 59 | LINK_DIRECTORIES(${GLFW_LIBRARY_DIRS}) 60 | else() 61 | message (STATUS "glfw3 is not found." ) 62 | endif() 63 | 64 | add_executable(${APP_TARGET} ${SOURCES}) 65 | target_link_libraries( 66 | ${APP_TARGET} 67 | ${OpenCASCADE_LIBS} 68 | glfw 69 | ${OPENGL_LIBRARIES} 70 | ) 71 | -------------------------------------------------------------------------------- /GlfwOcctView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 OPEN CASCADE SAS 2 | // 3 | // This file is part of the examples of the Open CASCADE Technology software library. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21 | 22 | #ifndef _GlfwOcctView_Header 23 | #define _GlfwOcctView_Header 24 | 25 | #include "GlfwOcctWindow.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | //! Sample class creating 3D Viewer within GLFW window. 32 | class GlfwOcctView : protected AIS_ViewController 33 | { 34 | public: 35 | //! Default constructor. 36 | GlfwOcctView(); 37 | 38 | //! Destructor. 39 | ~GlfwOcctView(); 40 | 41 | //! Main application entry point. 42 | void run(); 43 | 44 | private: 45 | 46 | //! Create GLFW window. 47 | void initWindow (int theWidth, int theHeight, const char* theTitle); 48 | 49 | //! Create 3D Viewer. 50 | void initViewer(); 51 | 52 | //! Fill 3D Viewer with a DEMO items. 53 | void initDemoScene(); 54 | 55 | //! Application event loop. 56 | void mainloop(); 57 | 58 | //! Clean up before . 59 | void cleanup(); 60 | 61 | //! @name GLWF callbacks 62 | private: 63 | //! Window resize event. 64 | void onResize (int theWidth, int theHeight); 65 | 66 | //! Mouse scroll event. 67 | void onMouseScroll (double theOffsetX, double theOffsetY); 68 | 69 | //! Mouse click event. 70 | void onMouseButton (int theButton, int theAction, int theMods); 71 | 72 | //! Mouse move event. 73 | void onMouseMove (int thePosX, int thePosY); 74 | 75 | //! @name GLWF callbacks (static functions) 76 | private: 77 | 78 | //! GLFW callback redirecting messages into Message::DefaultMessenger(). 79 | static void errorCallback (int theError, const char* theDescription); 80 | 81 | //! Wrapper for glfwGetWindowUserPointer() returning this class instance. 82 | static GlfwOcctView* toView (GLFWwindow* theWin); 83 | 84 | //! Window resize callback. 85 | static void onResizeCallback (GLFWwindow* theWin, int theWidth, int theHeight) 86 | { toView(theWin)->onResize (theWidth, theHeight); } 87 | 88 | //! Frame-buffer resize callback. 89 | static void onFBResizeCallback (GLFWwindow* theWin, int theWidth, int theHeight) 90 | { toView(theWin)->onResize (theWidth, theHeight); } 91 | 92 | //! Mouse scroll callback. 93 | static void onMouseScrollCallback (GLFWwindow* theWin, double theOffsetX, double theOffsetY) 94 | { toView(theWin)->onMouseScroll (theOffsetX, theOffsetY); } 95 | 96 | //! Mouse click callback. 97 | static void onMouseButtonCallback (GLFWwindow* theWin, int theButton, int theAction, int theMods) 98 | { toView(theWin)->onMouseButton (theButton, theAction, theMods); } 99 | 100 | //! Mouse move callback. 101 | static void onMouseMoveCallback (GLFWwindow* theWin, double thePosX, double thePosY) 102 | { toView(theWin)->onMouseMove ((int )thePosX, (int )thePosY); } 103 | 104 | private: 105 | 106 | Handle(GlfwOcctWindow) myOcctWindow; 107 | Handle(V3d_View) myView; 108 | Handle(AIS_InteractiveContext) myContext; 109 | 110 | }; 111 | 112 | #endif // _GlfwOcctView_Header 113 | -------------------------------------------------------------------------------- /GlfwOcctWindow.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 OPEN CASCADE SAS 2 | // 3 | // This file is part of the examples of the Open CASCADE Technology software library. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21 | 22 | #ifndef _GlfwOcctWindow_Header 23 | #define _GlfwOcctWindow_Header 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | struct GLFWwindow; 32 | 33 | //! GLFWwindow wrapper implementing Aspect_Window interface. 34 | class GlfwOcctWindow : public Aspect_Window 35 | { 36 | DEFINE_STANDARD_RTTI_INLINE(GlfwOcctWindow, Aspect_Window) 37 | public: 38 | //! Main constructor. 39 | GlfwOcctWindow (int theWidth, int theHeight, const TCollection_AsciiString& theTitle); 40 | 41 | //! Close the window. 42 | virtual ~GlfwOcctWindow() { Close(); } 43 | 44 | //! Close the window. 45 | void Close(); 46 | 47 | //! Return X Display connection. 48 | const Handle(Aspect_DisplayConnection)& GetDisplay() const { return myDisplay; } 49 | 50 | //! Return GLFW window. 51 | GLFWwindow* getGlfwWindow() { return myGlfwWindow; } 52 | 53 | //! Return native OpenGL context. 54 | Aspect_RenderingContext NativeGlContext() const; 55 | 56 | //! Return cursor position. 57 | Graphic3d_Vec2i CursorPosition() const; 58 | 59 | public: 60 | 61 | //! Returns native Window handle 62 | virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE; 63 | 64 | //! Returns parent of native Window handle. 65 | virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE { return 0; } 66 | 67 | //! Applies the resizing to the window 68 | virtual Aspect_TypeOfResize DoResize() Standard_OVERRIDE; 69 | 70 | //! Returns True if the window is opened and False if the window is closed. 71 | virtual Standard_Boolean IsMapped() const Standard_OVERRIDE; 72 | 73 | //! Apply the mapping change to the window and returns TRUE if the window is mapped at screen. 74 | virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; } 75 | 76 | //! Opens the window . 77 | virtual void Map() const Standard_OVERRIDE; 78 | 79 | //! Closes the window . 80 | virtual void Unmap() const Standard_OVERRIDE; 81 | 82 | virtual void Position (Standard_Integer& theX1, Standard_Integer& theY1, 83 | Standard_Integer& theX2, Standard_Integer& theY2) const Standard_OVERRIDE 84 | { 85 | theX1 = myXLeft; 86 | theX2 = myXRight; 87 | theY1 = myYTop; 88 | theY2 = myYBottom; 89 | } 90 | 91 | //! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions. 92 | virtual Standard_Real Ratio() const Standard_OVERRIDE 93 | { 94 | return Standard_Real (myXRight - myXLeft) / Standard_Real (myYBottom - myYTop); 95 | } 96 | 97 | //! Return window size. 98 | virtual void Size (Standard_Integer& theWidth, Standard_Integer& theHeight) const Standard_OVERRIDE 99 | { 100 | theWidth = myXRight - myXLeft; 101 | theHeight = myYBottom - myYTop; 102 | } 103 | 104 | virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; } 105 | 106 | protected: 107 | Handle(Aspect_DisplayConnection) myDisplay; 108 | GLFWwindow* myGlfwWindow; 109 | Standard_Integer myXLeft; 110 | Standard_Integer myYTop; 111 | Standard_Integer myXRight; 112 | Standard_Integer myYBottom; 113 | }; 114 | 115 | #endif // _GlfwOcctWindow_Header 116 | -------------------------------------------------------------------------------- /GlfwOcctWindow.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 OPEN CASCADE SAS 2 | // 3 | // This file is part of the examples of the Open CASCADE Technology software library. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21 | 22 | #include "GlfwOcctWindow.h" 23 | 24 | #if defined (__APPLE__) 25 | #undef Handle // avoid name collisions in macOS headers 26 | #define GLFW_EXPOSE_NATIVE_COCOA 27 | #define GLFW_EXPOSE_NATIVE_NSGL 28 | #elif defined (_WIN32) 29 | #define GLFW_EXPOSE_NATIVE_WIN32 30 | #define GLFW_EXPOSE_NATIVE_WGL 31 | #else 32 | #define GLFW_EXPOSE_NATIVE_X11 33 | #define GLFW_EXPOSE_NATIVE_GLX 34 | #endif 35 | #include 36 | #include 37 | 38 | // ================================================================ 39 | // Function : GlfwOcctWindow 40 | // Purpose : 41 | // ================================================================ 42 | GlfwOcctWindow::GlfwOcctWindow (int theWidth, int theHeight, const TCollection_AsciiString& theTitle) 43 | : myGlfwWindow (glfwCreateWindow (theWidth, theHeight, theTitle.ToCString(), NULL, NULL)), 44 | myXLeft (0), 45 | myYTop (0), 46 | myXRight (0), 47 | myYBottom(0) 48 | { 49 | if (myGlfwWindow != nullptr) 50 | { 51 | int aWidth = 0, aHeight = 0; 52 | glfwGetWindowPos (myGlfwWindow, &myXLeft, &myYTop); 53 | glfwGetWindowSize(myGlfwWindow, &aWidth, &aHeight); 54 | myXRight = myXLeft + aWidth; 55 | myYBottom = myYTop + aHeight; 56 | 57 | #if !defined(_WIN32) && !defined(__APPLE__) 58 | myDisplay = new Aspect_DisplayConnection ((Aspect_XDisplay* )glfwGetX11Display()); 59 | #endif 60 | } 61 | } 62 | 63 | // ================================================================ 64 | // Function : Close 65 | // Purpose : 66 | // ================================================================ 67 | void GlfwOcctWindow::Close() 68 | { 69 | if (myGlfwWindow != nullptr) 70 | { 71 | glfwDestroyWindow (myGlfwWindow); 72 | myGlfwWindow = nullptr; 73 | } 74 | } 75 | 76 | // ================================================================ 77 | // Function : NativeHandle 78 | // Purpose : 79 | // ================================================================ 80 | Aspect_Drawable GlfwOcctWindow::NativeHandle() const 81 | { 82 | #if defined (__APPLE__) 83 | return (Aspect_Drawable)glfwGetCocoaWindow (myGlfwWindow); 84 | #elif defined (_WIN32) 85 | return (Aspect_Drawable)glfwGetWin32Window (myGlfwWindow); 86 | #else 87 | return (Aspect_Drawable)glfwGetX11Window (myGlfwWindow); 88 | #endif 89 | } 90 | 91 | // ================================================================ 92 | // Function : NativeGlContext 93 | // Purpose : 94 | // ================================================================ 95 | Aspect_RenderingContext GlfwOcctWindow::NativeGlContext() const 96 | { 97 | #if defined (__APPLE__) 98 | return (NSOpenGLContext*)glfwGetNSGLContext (myGlfwWindow); 99 | #elif defined (_WIN32) 100 | return glfwGetWGLContext (myGlfwWindow); 101 | #else 102 | return glfwGetGLXContext (myGlfwWindow); 103 | #endif 104 | } 105 | 106 | // ================================================================ 107 | // Function : IsMapped 108 | // Purpose : 109 | // ================================================================ 110 | Standard_Boolean GlfwOcctWindow::IsMapped() const 111 | { 112 | return glfwGetWindowAttrib (myGlfwWindow, GLFW_VISIBLE) != 0; 113 | } 114 | 115 | // ================================================================ 116 | // Function : Map 117 | // Purpose : 118 | // ================================================================ 119 | void GlfwOcctWindow::Map() const 120 | { 121 | glfwShowWindow (myGlfwWindow); 122 | } 123 | 124 | // ================================================================ 125 | // Function : Unmap 126 | // Purpose : 127 | // ================================================================ 128 | void GlfwOcctWindow::Unmap() const 129 | { 130 | glfwHideWindow (myGlfwWindow); 131 | } 132 | 133 | // ================================================================ 134 | // Function : DoResize 135 | // Purpose : 136 | // ================================================================ 137 | Aspect_TypeOfResize GlfwOcctWindow::DoResize() 138 | { 139 | if (glfwGetWindowAttrib (myGlfwWindow, GLFW_VISIBLE) == 1) 140 | { 141 | int anXPos = 0, anYPos = 0, aWidth = 0, aHeight = 0; 142 | glfwGetWindowPos (myGlfwWindow, &anXPos, &anYPos); 143 | glfwGetWindowSize(myGlfwWindow, &aWidth, &aHeight); 144 | myXLeft = anXPos; 145 | myXRight = anXPos + aWidth; 146 | myYTop = anYPos; 147 | myYBottom = anYPos + aHeight; 148 | } 149 | return Aspect_TOR_UNKNOWN; 150 | } 151 | 152 | // ================================================================ 153 | // Function : CursorPosition 154 | // Purpose : 155 | // ================================================================ 156 | Graphic3d_Vec2i GlfwOcctWindow::CursorPosition() const 157 | { 158 | Graphic3d_Vec2d aPos; 159 | glfwGetCursorPos (myGlfwWindow, &aPos.x(), &aPos.y()); 160 | return Graphic3d_Vec2i ((int )aPos.x(), (int )aPos.y()); 161 | } 162 | -------------------------------------------------------------------------------- /GlfwOcctView.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 OPEN CASCADE SAS 2 | // 3 | // This file is part of the examples of the Open CASCADE Technology software library. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21 | 22 | #include "GlfwOcctView.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include 37 | 38 | namespace 39 | { 40 | //! Convert GLFW mouse button into Aspect_VKeyMouse. 41 | static Aspect_VKeyMouse mouseButtonFromGlfw (int theButton) 42 | { 43 | switch (theButton) 44 | { 45 | case GLFW_MOUSE_BUTTON_LEFT: return Aspect_VKeyMouse_LeftButton; 46 | case GLFW_MOUSE_BUTTON_RIGHT: return Aspect_VKeyMouse_RightButton; 47 | case GLFW_MOUSE_BUTTON_MIDDLE: return Aspect_VKeyMouse_MiddleButton; 48 | } 49 | return Aspect_VKeyMouse_NONE; 50 | } 51 | 52 | //! Convert GLFW key modifiers into Aspect_VKeyFlags. 53 | static Aspect_VKeyFlags keyFlagsFromGlfw (int theFlags) 54 | { 55 | Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE; 56 | if ((theFlags & GLFW_MOD_SHIFT) != 0) 57 | { 58 | aFlags |= Aspect_VKeyFlags_SHIFT; 59 | } 60 | if ((theFlags & GLFW_MOD_CONTROL) != 0) 61 | { 62 | aFlags |= Aspect_VKeyFlags_CTRL; 63 | } 64 | if ((theFlags & GLFW_MOD_ALT) != 0) 65 | { 66 | aFlags |= Aspect_VKeyFlags_ALT; 67 | } 68 | if ((theFlags & GLFW_MOD_SUPER) != 0) 69 | { 70 | aFlags |= Aspect_VKeyFlags_META; 71 | } 72 | return aFlags; 73 | } 74 | } 75 | 76 | // ================================================================ 77 | // Function : GlfwOcctView 78 | // Purpose : 79 | // ================================================================ 80 | GlfwOcctView::GlfwOcctView() 81 | { 82 | } 83 | 84 | // ================================================================ 85 | // Function : ~GlfwOcctView 86 | // Purpose : 87 | // ================================================================ 88 | GlfwOcctView::~GlfwOcctView() 89 | { 90 | } 91 | 92 | // ================================================================ 93 | // Function : toView 94 | // Purpose : 95 | // ================================================================ 96 | GlfwOcctView* GlfwOcctView::toView (GLFWwindow* theWin) 97 | { 98 | return static_cast(glfwGetWindowUserPointer (theWin)); 99 | } 100 | 101 | // ================================================================ 102 | // Function : errorCallback 103 | // Purpose : 104 | // ================================================================ 105 | void GlfwOcctView::errorCallback (int theError, const char* theDescription) 106 | { 107 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error") + theError + ": " + theDescription, Message_Fail); 108 | } 109 | 110 | // ================================================================ 111 | // Function : run 112 | // Purpose : 113 | // ================================================================ 114 | void GlfwOcctView::run() 115 | { 116 | initWindow (800, 600, "glfw occt"); 117 | initViewer(); 118 | initDemoScene(); 119 | if (myView.IsNull()) 120 | { 121 | return; 122 | } 123 | 124 | myView->MustBeResized(); 125 | myOcctWindow->Map(); 126 | mainloop(); 127 | cleanup(); 128 | } 129 | 130 | // ================================================================ 131 | // Function : initWindow 132 | // Purpose : 133 | // ================================================================ 134 | void GlfwOcctView::initWindow (int theWidth, int theHeight, const char* theTitle) 135 | { 136 | glfwSetErrorCallback (GlfwOcctView::errorCallback); 137 | glfwInit(); 138 | const bool toAskCoreProfile = true; 139 | if (toAskCoreProfile) 140 | { 141 | glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); 142 | glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3); 143 | #if defined (__APPLE__) 144 | glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 145 | #endif 146 | glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 147 | } 148 | myOcctWindow = new GlfwOcctWindow (theWidth, theHeight, theTitle); 149 | glfwSetWindowUserPointer (myOcctWindow->getGlfwWindow(), this); 150 | // window callback 151 | glfwSetWindowSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onResizeCallback); 152 | glfwSetFramebufferSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onFBResizeCallback); 153 | // mouse callback 154 | glfwSetScrollCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseScrollCallback); 155 | glfwSetMouseButtonCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseButtonCallback); 156 | glfwSetCursorPosCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseMoveCallback); 157 | } 158 | 159 | // ================================================================ 160 | // Function : initViewer 161 | // Purpose : 162 | // ================================================================ 163 | void GlfwOcctView::initViewer() 164 | { 165 | if (myOcctWindow.IsNull() 166 | || myOcctWindow->getGlfwWindow() == nullptr) 167 | { 168 | return; 169 | } 170 | 171 | Handle(OpenGl_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver (myOcctWindow->GetDisplay(), false); 172 | Handle(V3d_Viewer) aViewer = new V3d_Viewer (aGraphicDriver); 173 | aViewer->SetDefaultLights(); 174 | aViewer->SetLightOn(); 175 | aViewer->SetDefaultTypeOfView (V3d_PERSPECTIVE); 176 | aViewer->ActivateGrid (Aspect_GT_Rectangular, Aspect_GDM_Lines); 177 | myView = aViewer->CreateView(); 178 | myView->SetImmediateUpdate (false); 179 | myView->SetWindow (myOcctWindow, myOcctWindow->NativeGlContext()); 180 | myView->ChangeRenderingParams().ToShowStats = true; 181 | myContext = new AIS_InteractiveContext (aViewer); 182 | } 183 | 184 | // ================================================================ 185 | // Function : initDemoScene 186 | // Purpose : 187 | // ================================================================ 188 | void GlfwOcctView::initDemoScene() 189 | { 190 | if (myContext.IsNull()) 191 | { 192 | return; 193 | } 194 | 195 | myView->TriedronDisplay (Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_WIREFRAME); 196 | 197 | gp_Ax2 anAxis; 198 | anAxis.SetLocation (gp_Pnt (0.0, 0.0, 0.0)); 199 | Handle(AIS_Shape) aBox = new AIS_Shape (BRepPrimAPI_MakeBox (anAxis, 50, 50, 50).Shape()); 200 | myContext->Display (aBox, AIS_Shaded, 0, false); 201 | anAxis.SetLocation (gp_Pnt (25.0, 125.0, 0.0)); 202 | Handle(AIS_Shape) aCone = new AIS_Shape (BRepPrimAPI_MakeCone (anAxis, 25, 0, 50).Shape()); 203 | myContext->Display (aCone, AIS_Shaded, 0, false); 204 | 205 | TCollection_AsciiString aGlInfo; 206 | { 207 | TColStd_IndexedDataMapOfStringString aRendInfo; 208 | myView->DiagnosticInformation (aRendInfo, Graphic3d_DiagnosticInfo_Basic); 209 | for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aRendInfo); aValueIter.More(); aValueIter.Next()) 210 | { 211 | if (!aGlInfo.IsEmpty()) { aGlInfo += "\n"; } 212 | aGlInfo += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value(); 213 | } 214 | } 215 | Message::DefaultMessenger()->Send (TCollection_AsciiString("OpenGL info:\n") + aGlInfo, Message_Info); 216 | } 217 | 218 | // ================================================================ 219 | // Function : mainloop 220 | // Purpose : 221 | // ================================================================ 222 | void GlfwOcctView::mainloop() 223 | { 224 | while (!glfwWindowShouldClose (myOcctWindow->getGlfwWindow())) 225 | { 226 | // glfwPollEvents() for continuous rendering (immediate return if there are no new events) 227 | // and glfwWaitEvents() for rendering on demand (something actually happened in the viewer) 228 | //glfwPollEvents(); 229 | glfwWaitEvents(); 230 | if (!myView.IsNull()) 231 | { 232 | FlushViewEvents (myContext, myView, true); 233 | } 234 | } 235 | } 236 | 237 | // ================================================================ 238 | // Function : cleanup 239 | // Purpose : 240 | // ================================================================ 241 | void GlfwOcctView::cleanup() 242 | { 243 | if (!myView.IsNull()) 244 | { 245 | myView->Remove(); 246 | } 247 | if (!myOcctWindow.IsNull()) 248 | { 249 | myOcctWindow->Close(); 250 | } 251 | glfwTerminate(); 252 | } 253 | 254 | // ================================================================ 255 | // Function : onResize 256 | // Purpose : 257 | // ================================================================ 258 | void GlfwOcctView::onResize (int theWidth, int theHeight) 259 | { 260 | if (theWidth != 0 261 | && theHeight != 0 262 | && !myView.IsNull()) 263 | { 264 | myView->Window()->DoResize(); 265 | myView->MustBeResized(); 266 | myView->Invalidate(); 267 | myView->Redraw(); 268 | } 269 | } 270 | 271 | // ================================================================ 272 | // Function : onMouseScroll 273 | // Purpose : 274 | // ================================================================ 275 | void GlfwOcctView::onMouseScroll (double theOffsetX, double theOffsetY) 276 | { 277 | if (!myView.IsNull()) 278 | { 279 | UpdateZoom (Aspect_ScrollDelta (myOcctWindow->CursorPosition(), int(theOffsetY * 8.0))); 280 | } 281 | } 282 | 283 | // ================================================================ 284 | // Function : onMouseButton 285 | // Purpose : 286 | // ================================================================ 287 | void GlfwOcctView::onMouseButton (int theButton, int theAction, int theMods) 288 | { 289 | if (myView.IsNull()) { return; } 290 | 291 | const Graphic3d_Vec2i aPos = myOcctWindow->CursorPosition(); 292 | if (theAction == GLFW_PRESS) 293 | { 294 | PressMouseButton (aPos, mouseButtonFromGlfw (theButton), keyFlagsFromGlfw (theMods), false); 295 | } 296 | else 297 | { 298 | ReleaseMouseButton (aPos, mouseButtonFromGlfw (theButton), keyFlagsFromGlfw (theMods), false); 299 | } 300 | } 301 | 302 | // ================================================================ 303 | // Function : onMouseMove 304 | // Purpose : 305 | // ================================================================ 306 | void GlfwOcctView::onMouseMove (int thePosX, int thePosY) 307 | { 308 | const Graphic3d_Vec2i aNewPos (thePosX, thePosY); 309 | if (!myView.IsNull()) 310 | { 311 | UpdateMousePosition (aNewPos, PressedMouseButtons(), LastMouseFlags(), false); 312 | } 313 | } 314 | --------------------------------------------------------------------------------