Aspect_DisplayConnection now provides constructor wrapping existing X Display connection.
--- /dev/null
+cmake_minimum_required(VERSION 3.2)
+
+project(glfw-occt-demo)
+
+set(CMAKE_CXX_STANDARD 11)
+set(APP_VERSION_MAJOR 1)
+set(APP_VERSION_MINOR 0)
+set(APP_TARGET glfwocct)
+
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
+file(GLOB SOURCES
+ *.h
+ *.cpp
+)
+source_group ("Headers" FILES
+ GlfwOcctView.h
+ GlfwOcctWindow.h)
+source_group ("Sources" FILES
+ GlfwOcctView.cpp
+ GlfwOcctWindow.cpp
+ main.cpp)
+
+# OpenGL
+find_package(OpenGL REQUIRED)
+
+# Open CASCADE Technology
+find_package(OpenCASCADE REQUIRED NO_DEFAULT_PATH)
+if (OpenCASCADE_FOUND)
+ message (STATUS "Using OpenCASCADE from \"${OpenCASCADE_DIR}\"" )
+ INCLUDE_DIRECTORIES(${OpenCASCADE_INCLUDE_DIR})
+ LINK_DIRECTORIES(${OpenCASCADE_LIBRARY_DIR})
+else()
+ message (WARNING "Could not find OpenCASCADE, please set OpenCASCADE_DIR variable." )
+ set (OCCT_LIBRARY_DIR)
+ set (OCCT_BIN_DIR)
+endif()
+
+SET(OpenCASCADE_LIBS
+ TKernel
+ TKService
+ TKV3d
+ TKOpenGl
+ TKBRep
+ TKGeomBase
+ TKGeomAlgo
+ TKG3d
+ TKG2d
+ TKTopAlgo
+ TKPrim
+)
+
+# glfw
+find_package(glfw3 REQUIRED)
+if (glfw3_FOUND)
+ message (STATUS "Using glfw3 ${glfw3_VERSION}" )
+ INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS})
+ LINK_DIRECTORIES(${GLFW_LIBRARY_DIRS})
+else()
+ message (STATUS "glfw3 is not found." )
+endif()
+
+add_executable(${APP_TARGET} ${SOURCES})
+target_link_libraries(
+ ${APP_TARGET}
+ ${OpenCASCADE_LIBS}
+ glfw
+ ${OPENGL_LIBRARIES}
+)
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// 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
+
+#include "GlfwOcctView.h"
+
+#include <AIS_Shape.hxx>
+#include <Aspect_Handle.hxx>
+#include <Aspect_DisplayConnection.hxx>
+#include <BRepPrimAPI_MakeBox.hxx>
+#include <BRepPrimAPI_MakeCone.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+
+#include <iostream>
+
+#include <GLFW/glfw3.h>
+
+// ================================================================
+// Function : GlfwOcctView
+// Purpose :
+// ================================================================
+GlfwOcctView::GlfwOcctView()
+: myCurAction3d (CurAction3d_Nothing),
+ myToRedraw (true)
+{
+}
+
+// ================================================================
+// Function : ~GlfwOcctView
+// Purpose :
+// ================================================================
+GlfwOcctView::~GlfwOcctView()
+{
+}
+
+// ================================================================
+// Function : toView
+// Purpose :
+// ================================================================
+GlfwOcctView* GlfwOcctView::toView (GLFWwindow* theWin)
+{
+ return static_cast<GlfwOcctView*>(glfwGetWindowUserPointer (theWin));
+}
+
+// ================================================================
+// Function : errorCallback
+// Purpose :
+// ================================================================
+void GlfwOcctView::errorCallback (int theError, const char* theDescription)
+{
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error") + theError + ": " + theDescription, Message_Fail);
+}
+
+// ================================================================
+// Function : run
+// Purpose :
+// ================================================================
+void GlfwOcctView::run()
+{
+ initWindow (800, 600, "glfw occt");
+ initViewer();
+ initDemoScene();
+ if (myView.IsNull())
+ {
+ return;
+ }
+
+ myView->MustBeResized();
+ myOcctWindow->Map();
+ mainloop();
+ cleanup();
+}
+
+// ================================================================
+// Function : initWindow
+// Purpose :
+// ================================================================
+void GlfwOcctView::initWindow (int theWidth, int theHeight, const char* theTitle)
+{
+ glfwSetErrorCallback (GlfwOcctView::errorCallback);
+ glfwInit();
+ const bool toAskCoreProfile = true;
+ if (toAskCoreProfile)
+ {
+ glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3);
+#if defined (__APPLE__)
+ glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+#endif
+ glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ }
+ myOcctWindow = new GlfwOcctWindow (theWidth, theHeight, theTitle);
+ glfwSetWindowUserPointer (myOcctWindow->getGlfwWindow(), this);
+ // window callback
+ glfwSetWindowSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onResizeCallback);
+ glfwSetFramebufferSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onFBResizeCallback);
+ // mouse callback
+ glfwSetScrollCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseScrollCallback);
+ glfwSetMouseButtonCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseButtonCallback);
+ glfwSetCursorPosCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseMoveCallback);
+}
+
+// ================================================================
+// Function : initViewer
+// Purpose :
+// ================================================================
+void GlfwOcctView::initViewer()
+{
+ if (myOcctWindow.IsNull()
+ || myOcctWindow->getGlfwWindow() == nullptr)
+ {
+ return;
+ }
+
+ Handle(OpenGl_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver (myOcctWindow->GetDisplay(), false);
+ Handle(V3d_Viewer) aViewer = new V3d_Viewer (aGraphicDriver);
+ aViewer->SetDefaultLights();
+ aViewer->SetLightOn();
+ aViewer->SetDefaultTypeOfView (V3d_PERSPECTIVE);
+ aViewer->ActivateGrid (Aspect_GT_Rectangular, Aspect_GDM_Lines);
+ myView = aViewer->CreateView();
+ myView->SetImmediateUpdate (false);
+ myView->SetWindow (myOcctWindow, myOcctWindow->NativeGlContext());
+ myView->ChangeRenderingParams().ToShowStats = true;
+ myContext = new AIS_InteractiveContext (aViewer);
+}
+
+// ================================================================
+// Function : initDemoScene
+// Purpose :
+// ================================================================
+void GlfwOcctView::initDemoScene()
+{
+ if (myContext.IsNull())
+ {
+ return;
+ }
+
+ myView->TriedronDisplay (Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_WIREFRAME);
+
+ gp_Ax2 anAxis;
+ anAxis.SetLocation (gp_Pnt (0.0, 0.0, 0.0));
+ Handle(AIS_Shape) aBox = new AIS_Shape (BRepPrimAPI_MakeBox (anAxis, 50, 50, 50).Shape());
+ myContext->Display (aBox, AIS_Shaded, 0, false);
+ anAxis.SetLocation (gp_Pnt (25.0, 125.0, 0.0));
+ Handle(AIS_Shape) aCone = new AIS_Shape (BRepPrimAPI_MakeCone (anAxis, 25, 0, 50).Shape());
+ myContext->Display (aCone, AIS_Shaded, 0, false);
+
+ TCollection_AsciiString aGlInfo;
+ {
+ TColStd_IndexedDataMapOfStringString aRendInfo;
+ myView->DiagnosticInformation (aRendInfo, Graphic3d_DiagnosticInfo_Basic);
+ for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aRendInfo); aValueIter.More(); aValueIter.Next())
+ {
+ if (!aGlInfo.IsEmpty()) { aGlInfo += "\n"; }
+ aGlInfo += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value();
+ }
+ }
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OpenGL info:\n") + aGlInfo, Message_Info);
+}
+
+// ================================================================
+// Function : mainloop
+// Purpose :
+// ================================================================
+void GlfwOcctView::mainloop()
+{
+ while (!glfwWindowShouldClose (myOcctWindow->getGlfwWindow()))
+ {
+ // glfwPollEvents() for continuous rendering (immediate return if there are no new events)
+ // and glfwWaitEvents() for rendering on demand (something actually happened in the viewer)
+ //glfwPollEvents();
+ glfwWaitEvents();
+ if (!myView.IsNull())
+ {
+ if (myView->IsInvalidated())
+ {
+ myView->Redraw();
+ }
+ else if (myToRedraw)
+ {
+ myView->RedrawImmediate();
+ }
+ myToRedraw = false;
+ }
+ }
+}
+
+// ================================================================
+// Function : cleanup
+// Purpose :
+// ================================================================
+void GlfwOcctView::cleanup()
+{
+ if (!myView.IsNull())
+ {
+ myView->Remove();
+ }
+ if (!myOcctWindow.IsNull())
+ {
+ myOcctWindow->Close();
+ }
+ glfwTerminate();
+}
+
+// ================================================================
+// Function : onResize
+// Purpose :
+// ================================================================
+void GlfwOcctView::onResize (int theWidth, int theHeight)
+{
+ if (theWidth != 0
+ && theHeight != 0
+ && !myView.IsNull())
+ {
+ myView->Window()->DoResize();
+ myView->MustBeResized();
+ myView->Invalidate();
+ myView->Redraw();
+ //myToRedraw = true;
+ }
+}
+
+// ================================================================
+// Function : onMouseScroll
+// Purpose :
+// ================================================================
+void GlfwOcctView::onMouseScroll (double theOffsetX, double theOffsetY)
+{
+ if (myView.IsNull()) { return; }
+
+ const Graphic3d_Vec2i aPos = myOcctWindow->CursorPosition();
+ myView->StartZoomAtPoint (aPos.x(), aPos.y());
+ myView->ZoomAtPoint (0, 0, int(theOffsetY * 4.0), int(theOffsetY * 4.0));
+ myView->Invalidate();
+ myToRedraw = true;
+}
+
+// ================================================================
+// Function : onMouseButton
+// Purpose :
+// ================================================================
+void GlfwOcctView::onMouseButton (int theButton, int theAction, int theMods)
+{
+ if (myView.IsNull()) { return; }
+
+ const Graphic3d_Vec2i aPos = myOcctWindow->CursorPosition();
+ if (theAction != GLFW_PRESS)
+ {
+ myCurAction3d = CurAction3d_Nothing;
+ return;
+ }
+
+ myMouseMin = aPos;
+ myMouseMax = aPos;
+ switch (theButton)
+ {
+ case GLFW_MOUSE_BUTTON_RIGHT:
+ {
+ myCurAction3d = CurAction3d_DynamicRoation;
+ myView->StartRotation (aPos.x(), aPos.y());
+ break;
+ }
+ case GLFW_MOUSE_BUTTON_MIDDLE:
+ {
+ myCurAction3d = CurAction3d_DynamicPanning;
+ break;
+ }
+ }
+}
+
+// ================================================================
+// Function : onMouseMove
+// Purpose :
+// ================================================================
+void GlfwOcctView::onMouseMove (int thePosX, int thePosY)
+{
+ if (myView.IsNull()) { return; }
+
+ switch (myCurAction3d)
+ {
+ case CurAction3d_DynamicRoation:
+ {
+ myView->Rotation (thePosX, thePosY);
+ myView->Invalidate();
+ myToRedraw = true;
+ break;
+ }
+ case CurAction3d_DynamicPanning:
+ {
+ myView->Pan (thePosX - myMouseMax.x(), -(thePosY - myMouseMax.y()));
+ myView->Invalidate();
+ myToRedraw = true;
+ myMouseMax.SetValues (thePosX, thePosY);
+ break;
+ }
+ default:
+ {
+ myContext->MoveTo (thePosX, thePosY, myView, false);
+ myToRedraw = true;
+ break;
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// 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
+
+#ifndef _GlfwOcctView_Header
+#define _GlfwOcctView_Header
+
+#include "GlfwOcctWindow.h"
+
+#include <AIS_InteractiveContext.hxx>
+#include <V3d_View.hxx>
+
+//! Sample class creating 3D Viewer within GLFW window.
+class GlfwOcctView
+{
+public:
+ enum CurAction3d
+ {
+ CurAction3d_Nothing,
+ CurAction3d_DynamicZooming,
+ CurAction3d_DynamicPanning,
+ CurAction3d_DynamicRoation
+ };
+
+public:
+ //! Default constructor.
+ GlfwOcctView();
+
+ //! Destructor.
+ ~GlfwOcctView();
+
+ //! Main application entry point.
+ void run();
+
+private:
+
+ //! Create GLFW window.
+ void initWindow (int theWidth, int theHeight, const char* theTitle);
+
+ //! Create 3D Viewer.
+ void initViewer();
+
+ //! Fill 3D Viewer with a DEMO items.
+ void initDemoScene();
+
+ //! Application event loop.
+ void mainloop();
+
+ //! Clean up before .
+ void cleanup();
+
+//! @name GLWF callbacks
+private:
+ //! Window resize event.
+ void onResize (int theWidth, int theHeight);
+
+ //! Mouse scroll event.
+ void onMouseScroll (double theOffsetX, double theOffsetY);
+
+ //! Mouse click event.
+ void onMouseButton (int theButton, int theAction, int theMods);
+
+ //! Mouse move event.
+ void onMouseMove (int thePosX, int thePosY);
+
+//! @name GLWF callbacks (static functions)
+private:
+
+ //! GLFW callback redirecting messages into Message::DefaultMessenger().
+ static void errorCallback (int theError, const char* theDescription);
+
+ //! Wrapper for glfwGetWindowUserPointer() returning this class instance.
+ static GlfwOcctView* toView (GLFWwindow* theWin);
+
+ //! Window resize callback.
+ static void onResizeCallback (GLFWwindow* theWin, int theWidth, int theHeight)
+ { toView(theWin)->onResize (theWidth, theHeight); }
+
+ //! Frame-buffer resize callback.
+ static void onFBResizeCallback (GLFWwindow* theWin, int theWidth, int theHeight)
+ { toView(theWin)->onResize (theWidth, theHeight); }
+
+ //! Mouse scroll callback.
+ static void onMouseScrollCallback (GLFWwindow* theWin, double theOffsetX, double theOffsetY)
+ { toView(theWin)->onMouseScroll (theOffsetX, theOffsetY); }
+
+ //! Mouse click callback.
+ static void onMouseButtonCallback (GLFWwindow* theWin, int theButton, int theAction, int theMods)
+ { toView(theWin)->onMouseButton (theButton, theAction, theMods); }
+
+ //! Mouse move callback.
+ static void onMouseMoveCallback (GLFWwindow* theWin, double thePosX, double thePosY)
+ { toView(theWin)->onMouseMove ((int )thePosX, (int )thePosY); }
+
+private:
+
+ Handle(GlfwOcctWindow) myOcctWindow;
+ Handle(V3d_View) myView;
+ Handle(AIS_InteractiveContext) myContext;
+
+ CurAction3d myCurAction3d;
+ Graphic3d_Vec2i myMouseMin;
+ Graphic3d_Vec2i myMouseMax;
+ bool myToRedraw;
+
+};
+
+#endif // _GlfwOcctView_Header
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// 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
+
+#include "GlfwOcctWindow.h"
+
+#if defined (__APPLE__)
+ #undef Handle // avoid name collisions in macOS headers
+ #define GLFW_EXPOSE_NATIVE_COCOA
+ #define GLFW_EXPOSE_NATIVE_NSGL
+#elif defined (_WIN32)
+ #define GLFW_EXPOSE_NATIVE_WIN32
+ #define GLFW_EXPOSE_NATIVE_WGL
+#else
+ #define GLFW_EXPOSE_NATIVE_X11
+ #define GLFW_EXPOSE_NATIVE_GLX
+#endif
+#include <GLFW/glfw3.h>
+#include <GLFW/glfw3native.h>
+
+// ================================================================
+// Function : GlfwOcctWindow
+// Purpose :
+// ================================================================
+GlfwOcctWindow::GlfwOcctWindow (int theWidth, int theHeight, const TCollection_AsciiString& theTitle)
+: myGlfwWindow (glfwCreateWindow (theWidth, theHeight, theTitle.ToCString(), NULL, NULL)),
+ myXLeft (0),
+ myYTop (0),
+ myXRight (0),
+ myYBottom(0)
+{
+ if (myGlfwWindow != nullptr)
+ {
+ int aWidth = 0, aHeight = 0;
+ glfwGetWindowPos (myGlfwWindow, &myXLeft, &myYTop);
+ glfwGetWindowSize(myGlfwWindow, &aWidth, &aHeight);
+ myXRight = myXLeft + aWidth;
+ myYBottom = myYTop + aHeight;
+
+ #if !defined(_WIN32) && !defined(__APPLE__)
+ myDisplay = new Aspect_DisplayConnection (glfwGetX11Display());
+ #endif
+ }
+}
+
+// ================================================================
+// Function : Close
+// Purpose :
+// ================================================================
+void GlfwOcctWindow::Close()
+{
+ if (myGlfwWindow != nullptr)
+ {
+ glfwDestroyWindow (myGlfwWindow);
+ myGlfwWindow = nullptr;
+ }
+}
+
+// ================================================================
+// Function : NativeHandle
+// Purpose :
+// ================================================================
+Aspect_Drawable GlfwOcctWindow::NativeHandle() const
+{
+#if defined (__APPLE__)
+ return (Aspect_Drawable)glfwGetCocoaWindow (myGlfwWindow);
+#elif defined (_WIN32)
+ return (Aspect_Drawable)glfwGetWin32Window (myGlfwWindow);
+#else
+ return (Aspect_Drawable)glfwGetX11Window (myGlfwWindow);
+#endif
+}
+
+// ================================================================
+// Function : NativeGlContext
+// Purpose :
+// ================================================================
+Aspect_RenderingContext GlfwOcctWindow::NativeGlContext() const
+{
+#if defined (__APPLE__)
+ return (NSOpenGLContext*)glfwGetNSGLContext (myGlfwWindow);
+#elif defined (_WIN32)
+ return glfwGetWGLContext (myGlfwWindow);
+#else
+ return glfwGetGLXContext (myGlfwWindow);
+#endif
+}
+
+// ================================================================
+// Function : IsMapped
+// Purpose :
+// ================================================================
+Standard_Boolean GlfwOcctWindow::IsMapped() const
+{
+ return glfwGetWindowAttrib (myGlfwWindow, GLFW_VISIBLE) != 0;
+}
+
+// ================================================================
+// Function : Map
+// Purpose :
+// ================================================================
+void GlfwOcctWindow::Map() const
+{
+ glfwShowWindow (myGlfwWindow);
+}
+
+// ================================================================
+// Function : Unmap
+// Purpose :
+// ================================================================
+void GlfwOcctWindow::Unmap() const
+{
+ glfwHideWindow (myGlfwWindow);
+}
+
+// ================================================================
+// Function : DoResize
+// Purpose :
+// ================================================================
+Aspect_TypeOfResize GlfwOcctWindow::DoResize() const
+{
+ if (glfwGetWindowAttrib (myGlfwWindow, GLFW_VISIBLE) == 1)
+ {
+ int anXPos = 0, anYPos = 0, aWidth = 0, aHeight = 0;
+ glfwGetWindowPos (myGlfwWindow, &anXPos, &anYPos);
+ glfwGetWindowSize(myGlfwWindow, &aWidth, &aHeight);
+ *const_cast<Standard_Integer*>(&myXLeft ) = anXPos;
+ *const_cast<Standard_Integer*>(&myXRight ) = anXPos + aWidth;
+ *const_cast<Standard_Integer*>(&myYTop ) = anYPos;
+ *const_cast<Standard_Integer*>(&myYBottom) = anYPos + aHeight;
+ }
+ return Aspect_TOR_UNKNOWN;
+}
+
+// ================================================================
+// Function : CursorPosition
+// Purpose :
+// ================================================================
+Graphic3d_Vec2i GlfwOcctWindow::CursorPosition() const
+{
+ Graphic3d_Vec2d aPos;
+ glfwGetCursorPos (myGlfwWindow, &aPos.x(), &aPos.y());
+ return Graphic3d_Vec2i ((int )aPos.x(), (int )aPos.y());
+}
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// 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
+
+#ifndef _GlfwOcctWindow_Header
+#define _GlfwOcctWindow_Header
+
+#include <Aspect_DisplayConnection.hxx>
+#include <Aspect_RenderingContext.hxx>
+#include <Aspect_Window.hxx>
+#include <Graphic3d_Vec.hxx>
+#include <TCollection_AsciiString.hxx>
+
+struct GLFWwindow;
+
+//! GLFWwindow wrapper implementing Aspect_Window interface.
+class GlfwOcctWindow : public Aspect_Window
+{
+ DEFINE_STANDARD_RTTI_INLINE(GlfwOcctWindow, Aspect_Window)
+public:
+ //! Main constructor.
+ GlfwOcctWindow (int theWidth, int theHeight, const TCollection_AsciiString& theTitle);
+
+ //! Close the window.
+ virtual ~GlfwOcctWindow() { Close(); }
+
+ //! Close the window.
+ void Close();
+
+ //! Return X Display connection.
+ const Handle(Aspect_DisplayConnection)& GetDisplay() const { return myDisplay; }
+
+ //! Return GLFW window.
+ GLFWwindow* getGlfwWindow() { return myGlfwWindow; }
+
+ //! Return native OpenGL context.
+ Aspect_RenderingContext NativeGlContext() const;
+
+ //! Return cursor position.
+ Graphic3d_Vec2i CursorPosition() const;
+
+public:
+
+ //! Returns native Window handle
+ virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE;
+
+ //! Returns parent of native Window handle.
+ virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE { return 0; }
+
+ //! Applies the resizing to the window <me>
+ virtual Aspect_TypeOfResize DoResize() const Standard_OVERRIDE;
+
+ //! Returns True if the window <me> is opened and False if the window is closed.
+ virtual Standard_Boolean IsMapped() const Standard_OVERRIDE;
+
+ //! Apply the mapping change to the window <me> and returns TRUE if the window is mapped at screen.
+ virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; }
+
+ //! Opens the window <me>.
+ virtual void Map() const Standard_OVERRIDE;
+
+ //! Closes the window <me>.
+ virtual void Unmap() const Standard_OVERRIDE;
+
+ virtual void Position (Standard_Integer& theX1, Standard_Integer& theY1,
+ Standard_Integer& theX2, Standard_Integer& theY2) const Standard_OVERRIDE
+ {
+ theX1 = myXLeft;
+ theX2 = myXRight;
+ theY1 = myYTop;
+ theY2 = myYBottom;
+ }
+
+ //! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions.
+ virtual Standard_Real Ratio() const Standard_OVERRIDE
+ {
+ return Standard_Real (myXRight - myXLeft) / Standard_Real (myYBottom - myYTop);
+ }
+
+ //! Return window size.
+ virtual void Size (Standard_Integer& theWidth, Standard_Integer& theHeight) const Standard_OVERRIDE
+ {
+ theWidth = myXRight - myXLeft;
+ theHeight = myYBottom - myYTop;
+ }
+
+ virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; }
+
+protected:
+ Handle(Aspect_DisplayConnection) myDisplay;
+ GLFWwindow* myGlfwWindow;
+ Standard_Integer myXLeft;
+ Standard_Integer myYTop;
+ Standard_Integer myXRight;
+ Standard_Integer myYBottom;
+};
+
+#endif // _GlfwOcctWindow_Header
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// 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
+
+#include "GlfwOcctView.h"
+
+int main (int, char**)
+{
+ GlfwOcctView anApp;
+ try
+ {
+ anApp.run();
+ }
+ catch (const std::runtime_error& theError)
+ {
+ std::cerr << theError.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return 0;
+}
--- /dev/null
+A sample demonstrating usage of OCCT 3D Viewer within a window created using GLFW.
+
+Platforms: Windows, macOS, Linux
+Required: glfw
Aspect_DisplayConnection::Aspect_DisplayConnection()
{
#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+ myDisplay = NULL;
+ myIsOwnDisplay = false;
OSD_Environment anEnv ("DISPLAY");
myDisplayName = anEnv.Value();
- Init();
+ Init (NULL);
#endif
}
Aspect_DisplayConnection::~Aspect_DisplayConnection()
{
#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
- if (myDisplay != NULL)
+ if (myDisplay != NULL
+ && myIsOwnDisplay)
{
XCloseDisplay (myDisplay);
}
// purpose :
// =======================================================================
Aspect_DisplayConnection::Aspect_DisplayConnection (const TCollection_AsciiString& theDisplayName)
+: myDisplay (NULL),
+ myIsOwnDisplay (false)
{
myDisplayName = theDisplayName;
- Init();
+ Init (NULL);
}
// =======================================================================
-// function : GetDisplay
-// purpose :
-// =======================================================================
-Display* Aspect_DisplayConnection::GetDisplay()
-{
- return myDisplay;
-}
-
-// =======================================================================
-// function : GetDisplayName
+// function : Aspect_DisplayConnection
// purpose :
// =======================================================================
-TCollection_AsciiString Aspect_DisplayConnection::GetDisplayName()
+Aspect_DisplayConnection::Aspect_DisplayConnection (Display* theDisplay)
+: myDisplay (NULL),
+ myIsOwnDisplay (false)
{
- return myDisplayName;
+ Init (theDisplay);
}
// =======================================================================
// function : Init
// purpose :
// =======================================================================
-void Aspect_DisplayConnection::Init()
+void Aspect_DisplayConnection::Init (Display* theDisplay)
{
- myDisplay = XOpenDisplay (myDisplayName.ToCString());
- myAtoms.Bind (Aspect_XA_DELETE_WINDOW, XInternAtom(myDisplay, "WM_DELETE_WINDOW", False));
-
+ if (myDisplay != NULL
+ && myIsOwnDisplay)
+ {
+ XCloseDisplay (myDisplay);
+ }
+ myIsOwnDisplay = false;
+ myAtoms.Clear();
+
+ myDisplay = theDisplay != NULL ? theDisplay : XOpenDisplay (myDisplayName.ToCString());
if (myDisplay == NULL)
{
TCollection_AsciiString aMessage;
aMessage += myDisplayName + "\"";
throw Aspect_DisplayConnectionDefinitionError(aMessage.ToCString());
}
+ else
+ {
+ myIsOwnDisplay = theDisplay == NULL;
+ myAtoms.Bind (Aspect_XA_DELETE_WINDOW, XInternAtom(myDisplay, "WM_DELETE_WINDOW", False));
+ }
}
// =======================================================================
//! screen_number - Specifies the screen to be used on that server. Optional variable.
Aspect_DisplayConnection (const TCollection_AsciiString& theDisplayName);
+ //! Constructor wrapping existing Display instance.
+ //! WARNING! it is a responsibility of application to keep this pointer
+ //! valid while Aspect_DisplayConnection is alive and to close Display when it is no more needed.
+ Aspect_DisplayConnection (Display* theDisplay);
+
//! @return pointer to Display structure that serves as the connection to the X server.
- Display* GetDisplay();
-
+ Display* GetDisplay() { return myDisplay; }
+
+ //! @return TRUE if X Display has been allocated by this class
+ Standard_Boolean IsOwnDisplay() const { return myIsOwnDisplay; }
+
//! @return identifier(atom) for custom named property associated with windows that use current connection to X server.
Atom GetAtom (const Aspect_XAtom theAtom) const;
//! @return display name for this connection.
- TCollection_AsciiString GetDisplayName();
-
-private:
+ const TCollection_AsciiString& GetDisplayName() { return myDisplayName; }
- //! Open connection with display specified in myDisplayName class field.
- void Init();
+ //! Open connection with display specified in myDisplayName class field
+ //! or takes theDisplay parameter when it is not NULL.
+ //! WARNING! When external Display is specified, it is a responsibility of application
+ //! to keep this pointer valid while Aspect_DisplayConnection is alive
+ //! and to close Display when it is no more needed.
+ //! @param theDisplay external pointer to allocated Display, or NULL if new connection should be created
+ void Init (Display* theDisplay);
private:
Display* myDisplay;
NCollection_DataMap<Aspect_XAtom, Atom> myAtoms;
TCollection_AsciiString myDisplayName;
+ Standard_Boolean myIsOwnDisplay;
#endif
private: