1 // Copyright (c) 2019 OPEN CASCADE SAS
3 // This file is part of the examples of the Open CASCADE Technology software library.
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:
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
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
22 #include "GlfwOcctView.h"
24 #include <AIS_Shape.hxx>
25 #include <Aspect_Handle.hxx>
26 #include <Aspect_DisplayConnection.hxx>
27 #include <BRepPrimAPI_MakeBox.hxx>
28 #include <BRepPrimAPI_MakeCone.hxx>
29 #include <Message.hxx>
30 #include <Message_Messenger.hxx>
31 #include <OpenGl_GraphicDriver.hxx>
32 #include <TopAbs_ShapeEnum.hxx>
36 #include <GLFW/glfw3.h>
38 // ================================================================
39 // Function : GlfwOcctView
41 // ================================================================
42 GlfwOcctView::GlfwOcctView()
43 : myCurAction3d (CurAction3d_Nothing),
48 // ================================================================
49 // Function : ~GlfwOcctView
51 // ================================================================
52 GlfwOcctView::~GlfwOcctView()
56 // ================================================================
59 // ================================================================
60 GlfwOcctView* GlfwOcctView::toView (GLFWwindow* theWin)
62 return static_cast<GlfwOcctView*>(glfwGetWindowUserPointer (theWin));
65 // ================================================================
66 // Function : errorCallback
68 // ================================================================
69 void GlfwOcctView::errorCallback (int theError, const char* theDescription)
71 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error") + theError + ": " + theDescription, Message_Fail);
74 // ================================================================
77 // ================================================================
78 void GlfwOcctView::run()
80 initWindow (800, 600, "glfw occt");
88 myView->MustBeResized();
94 // ================================================================
95 // Function : initWindow
97 // ================================================================
98 void GlfwOcctView::initWindow (int theWidth, int theHeight, const char* theTitle)
100 glfwSetErrorCallback (GlfwOcctView::errorCallback);
102 const bool toAskCoreProfile = true;
103 if (toAskCoreProfile)
105 glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
106 glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 3);
107 #if defined (__APPLE__)
108 glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
110 glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
112 myOcctWindow = new GlfwOcctWindow (theWidth, theHeight, theTitle);
113 glfwSetWindowUserPointer (myOcctWindow->getGlfwWindow(), this);
115 glfwSetWindowSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onResizeCallback);
116 glfwSetFramebufferSizeCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onFBResizeCallback);
118 glfwSetScrollCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseScrollCallback);
119 glfwSetMouseButtonCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseButtonCallback);
120 glfwSetCursorPosCallback (myOcctWindow->getGlfwWindow(), GlfwOcctView::onMouseMoveCallback);
123 // ================================================================
124 // Function : initViewer
126 // ================================================================
127 void GlfwOcctView::initViewer()
129 if (myOcctWindow.IsNull()
130 || myOcctWindow->getGlfwWindow() == nullptr)
135 Handle(OpenGl_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver (myOcctWindow->GetDisplay(), false);
136 Handle(V3d_Viewer) aViewer = new V3d_Viewer (aGraphicDriver);
137 aViewer->SetDefaultLights();
138 aViewer->SetLightOn();
139 aViewer->SetDefaultTypeOfView (V3d_PERSPECTIVE);
140 aViewer->ActivateGrid (Aspect_GT_Rectangular, Aspect_GDM_Lines);
141 myView = aViewer->CreateView();
142 myView->SetImmediateUpdate (false);
143 myView->SetWindow (myOcctWindow, myOcctWindow->NativeGlContext());
144 myView->ChangeRenderingParams().ToShowStats = true;
145 myContext = new AIS_InteractiveContext (aViewer);
148 // ================================================================
149 // Function : initDemoScene
151 // ================================================================
152 void GlfwOcctView::initDemoScene()
154 if (myContext.IsNull())
159 myView->TriedronDisplay (Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_WIREFRAME);
162 anAxis.SetLocation (gp_Pnt (0.0, 0.0, 0.0));
163 Handle(AIS_Shape) aBox = new AIS_Shape (BRepPrimAPI_MakeBox (anAxis, 50, 50, 50).Shape());
164 myContext->Display (aBox, AIS_Shaded, 0, false);
165 anAxis.SetLocation (gp_Pnt (25.0, 125.0, 0.0));
166 Handle(AIS_Shape) aCone = new AIS_Shape (BRepPrimAPI_MakeCone (anAxis, 25, 0, 50).Shape());
167 myContext->Display (aCone, AIS_Shaded, 0, false);
169 TCollection_AsciiString aGlInfo;
171 TColStd_IndexedDataMapOfStringString aRendInfo;
172 myView->DiagnosticInformation (aRendInfo, Graphic3d_DiagnosticInfo_Basic);
173 for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aRendInfo); aValueIter.More(); aValueIter.Next())
175 if (!aGlInfo.IsEmpty()) { aGlInfo += "\n"; }
176 aGlInfo += TCollection_AsciiString(" ") + aValueIter.Key() + ": " + aValueIter.Value();
179 Message::DefaultMessenger()->Send (TCollection_AsciiString("OpenGL info:\n") + aGlInfo, Message_Info);
182 // ================================================================
183 // Function : mainloop
185 // ================================================================
186 void GlfwOcctView::mainloop()
188 while (!glfwWindowShouldClose (myOcctWindow->getGlfwWindow()))
190 // glfwPollEvents() for continuous rendering (immediate return if there are no new events)
191 // and glfwWaitEvents() for rendering on demand (something actually happened in the viewer)
194 if (!myView.IsNull())
196 if (myView->IsInvalidated())
202 myView->RedrawImmediate();
209 // ================================================================
210 // Function : cleanup
212 // ================================================================
213 void GlfwOcctView::cleanup()
215 if (!myView.IsNull())
219 if (!myOcctWindow.IsNull())
221 myOcctWindow->Close();
226 // ================================================================
227 // Function : onResize
229 // ================================================================
230 void GlfwOcctView::onResize (int theWidth, int theHeight)
236 myView->Window()->DoResize();
237 myView->MustBeResized();
238 myView->Invalidate();
244 // ================================================================
245 // Function : onMouseScroll
247 // ================================================================
248 void GlfwOcctView::onMouseScroll (double theOffsetX, double theOffsetY)
250 if (myView.IsNull()) { return; }
252 const Graphic3d_Vec2i aPos = myOcctWindow->CursorPosition();
253 myView->StartZoomAtPoint (aPos.x(), aPos.y());
254 myView->ZoomAtPoint (0, 0, int(theOffsetY * 4.0), int(theOffsetY * 4.0));
255 myView->Invalidate();
259 // ================================================================
260 // Function : onMouseButton
262 // ================================================================
263 void GlfwOcctView::onMouseButton (int theButton, int theAction, int theMods)
265 if (myView.IsNull()) { return; }
267 const Graphic3d_Vec2i aPos = myOcctWindow->CursorPosition();
268 if (theAction != GLFW_PRESS)
270 myCurAction3d = CurAction3d_Nothing;
278 case GLFW_MOUSE_BUTTON_RIGHT:
280 myCurAction3d = CurAction3d_DynamicRoation;
281 myView->StartRotation (aPos.x(), aPos.y());
284 case GLFW_MOUSE_BUTTON_MIDDLE:
286 myCurAction3d = CurAction3d_DynamicPanning;
292 // ================================================================
293 // Function : onMouseMove
295 // ================================================================
296 void GlfwOcctView::onMouseMove (int thePosX, int thePosY)
298 if (myView.IsNull()) { return; }
300 switch (myCurAction3d)
302 case CurAction3d_DynamicRoation:
304 myView->Rotation (thePosX, thePosY);
305 myView->Invalidate();
309 case CurAction3d_DynamicPanning:
311 myView->Pan (thePosX - myMouseMax.x(), -(thePosY - myMouseMax.y()));
312 myView->Invalidate();
314 myMouseMax.SetValues (thePosX, thePosY);
319 myContext->MoveTo (thePosX, thePosY, myView, false);