0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / samples / qt / AndroidQt / src / AndroidQt.cxx
CommitLineData
80eb9670 1// Copyright (c) 2014 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
41ea50ac 14#if defined(_WIN32)
15 #include <windows.h>
16#endif
17
18#include "AndroidQt.h"
19#include "AndroidQt_UserInteractionParameters.h"
20#include "AndroidQt_Window.h"
80eb9670 21
22#include <AIS_Shape.hxx>
23#include <BRepTools.hxx>
24#include <BRep_Builder.hxx>
41ea50ac 25#include <Message.hxx>
26#include <Message_Messenger.hxx>
80eb9670 27#include <OpenGl_GraphicDriver.hxx>
28#include <Quantity_Color.hxx>
29#include <Standard_ErrorHandler.hxx>
30#include <TopoDS.hxx>
31#include <TopoDS_Face.hxx>
32#include <TopoDS_Shape.hxx>
33#include <UnitsAPI.hxx>
41ea50ac 34#include <WNT_Window.hxx>
80eb9670 35
36#include <EGL/egl.h>
55a40de8 37
38#include <Standard_WarningsDisable.hxx>
80eb9670 39#include <QFileInfo>
55a40de8 40#include <Standard_WarningsRestore.hxx>
80eb9670 41
42// =======================================================================
43// function : AndroidQt
44// purpose :
45// =======================================================================
46AndroidQt::AndroidQt()
47: myFitAllAction (false)
48{
41ea50ac 49 connect (this, SIGNAL (windowChanged (QQuickWindow*)), this, SLOT (handleWindowChanged (QQuickWindow*)));
80eb9670 50
51 // set shaders location variable
52 QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared";
53 qputenv ("CSF_ShadersDirectory", aDataRoot + "/Shaders");
54}
55
56// =======================================================================
57// function : ReadShapeFromFile
58// purpose :
59// =======================================================================
60bool AndroidQt::ReadShapeFromFile (QString theFilePath)
61{
62 QUrl aFileUrl (theFilePath);
63 QString aFilePath = theFilePath;
64 if (aFileUrl.isLocalFile())
65 {
66 aFilePath = QUrl (theFilePath).toLocalFile();
67 }
68
69 if (!QFile (aFilePath).exists())
70 {
71 return false;
72 }
73
74 TopoDS_Shape aShape;
75 BRep_Builder aBuildTool;
76 try
77 {
78 OCC_CATCH_SIGNALS
79
80 if (!BRepTools::Read (aShape, aFilePath.toStdString().c_str(), aBuildTool))
81 {
82 return false;
83 }
84
85 if (!myContext.IsNull())
86 {
87 myContext->EraseAll (Standard_False);
88
89 Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
90 aShapePrs->SetColor (Quantity_Color(1.0, 0.73, 0.2, Quantity_TOC_RGB));
91
92 myContext->Display (aShapePrs, Standard_False);
93 myContext->SetDisplayMode (aShapePrs, AIS_Shaded, Standard_False);
94 }
95
96 myMutex.lock();
97 myFitAllAction = true;
98 myMutex.unlock();
99
100 if (window())
101 {
102 window()->update();
103 }
104 }
105 catch (Standard_Failure)
106 {
107 return false;
108 }
109
110 return true;
111}
112
113// =======================================================================
114// function : InitTouch
115// purpose :
116// =======================================================================
117void AndroidQt::InitTouch (const double theX,
118 const double theY)
119{
120 myMutex.lock();
121 myTouchPoint.SetStarts (theX, theY);
122 myMutex.unlock();
123}
124
125// =======================================================================
126// function : UpdateTouch
127// purpose :
128// =======================================================================
129void AndroidQt::UpdateTouch (const double theX,
130 const double theY)
131{
132 myMutex.lock();
133 myTouchPoint.SetEnds (theX, theY);
134 myMutex.unlock();
135
136 if (window())
137 window()->update();
138}
139
140// =======================================================================
141// function : handleWindowChanged
142// purpose :
143// =======================================================================
144void AndroidQt::handleWindowChanged (QQuickWindow* theWin)
145{
146 if (theWin == NULL)
147 {
148 return;
149 }
150
41ea50ac 151 connect (theWin, SIGNAL (beforeSynchronizing()), this, SLOT (sync()), Qt::DirectConnection);
80eb9670 152
153 theWin->setClearBeforeRendering (false);
154}
155
156// =======================================================================
157// function : sync
158// purpose :
159// =======================================================================
160void AndroidQt::sync()
161{
162 myViewportSize = window()->size() * window()->devicePixelRatio();
163
41ea50ac 164 Graphic3d_Vec2i aWinTopLeft (window()->x(), window()->y());
165 Graphic3d_Vec2i aWinSize (myViewportSize.width(), myViewportSize.height());
166 const bool isChangedLeft = (myWinTopLeft.x() != aWinTopLeft.x());
167 const bool isChangedTop = (myWinTopLeft.y() != aWinTopLeft.y());
168 myWinTopLeft = aWinTopLeft;
169
80eb9670 170 if (myViewer.IsNull())
171 {
41ea50ac 172 initViewer (Aspect_Drawable (window()->winId()));
173 connect (window(), SIGNAL (beforeRendering()), this, SLOT (paint()), Qt::DirectConnection);
80eb9670 174 }
175 else
176 {
177 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
41ea50ac 178 #ifdef __ANDROID__
80eb9670 179 if (aDriver->getRawGlContext() != eglGetCurrentContext())
180 {
41ea50ac 181 initViewer (Aspect_Drawable (window()->winId()));
80eb9670 182 }
183 else
41ea50ac 184 #endif
80eb9670 185 {
41ea50ac 186 #ifdef __ANDROID__
187 Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast(myView->Window());
80eb9670 188 aWindow->SetSize (myViewportSize.width(), myViewportSize.height());
189 //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
190
191 EGLContext anEglContext = eglGetCurrentContext();
81a2800c 192 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
41ea50ac 193 #else
194 if (aWinSize.x() != myWinSize.x()
195 || aWinSize.y() != myWinSize.y())
196 {
197 myView->MustBeResized();
198 myView->Invalidate();
199 }
200 else if (isChangedTop)
201 {
202 myView->MustBeResized();
203 }
204 else if (isChangedLeft)
205 {
206 myView->MustBeResized();
207 }
208 #endif
80eb9670 209 }
210 }
41ea50ac 211 myWinSize = aWinSize;
80eb9670 212}
213
214// =======================================================================
215// function : paint
216// purpose :
217// =======================================================================
218void AndroidQt::paint()
219{
220 myMutex.lock();
221
41ea50ac 222 if (Abs (myTouchPoint.DevX()) + Abs (myTouchPoint.DevY()) > 1)
80eb9670 223 {
55a40de8 224 myView->StartRotation ((Standard_Integer)myTouchPoint.X().first, (Standard_Integer)myTouchPoint.Y().first);
225 myView->Rotation ((Standard_Integer)myTouchPoint.X().second, (Standard_Integer)myTouchPoint.Y().second);
80eb9670 226
227 myTouchPoint.ClearDev();
228 }
229
230 if (myFitAllAction)
231 {
232 myView->FitAll();
233 myFitAllAction = false;
234 }
235
236 myMutex.unlock();
237
238 myView->Redraw();
239}
240
241// =======================================================================
242// function : initViewer
243// purpose :
244// =======================================================================
41ea50ac 245bool AndroidQt::initViewer (Aspect_Drawable theWin)
80eb9670 246{
80eb9670 247 int aWidth = 0, aHeight = 0;
41ea50ac 248 Handle(Aspect_DisplayConnection) aDisplayConnection;
249#ifdef __ANDROID__
250 EGLint aCfgId = 0;
80eb9670 251 EGLDisplay anEglDisplay = eglGetCurrentDisplay();
252 EGLContext anEglContext = eglGetCurrentContext();
253 EGLSurface anEglSurf = eglGetCurrentSurface (EGL_DRAW);
254
255 if (anEglDisplay == EGL_NO_DISPLAY
256 || anEglContext == EGL_NO_CONTEXT
257 || anEglSurf == EGL_NO_SURFACE)
258 {
259 release();
260 return false;
261 }
262
263 eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH, &aWidth);
264 eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT, &aHeight);
265 eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
266
267 const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
268 EGLint aNbConfigs = 0;
269 void* anEglConfig = NULL;
270
271 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
272 {
41ea50ac 273 Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations", Message_Fail);
80eb9670 274 release();
275 return false;
276 }
277
278 if (!myViewer.IsNull())
279 {
280 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
281 Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
282 if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
283 {
41ea50ac 284 Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized", Message_Fail);
80eb9670 285 release();
286 return false;
287 }
288
289 aWindow->SetSize (aWidth, aHeight);
81a2800c 290 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
80eb9670 291 }
292
293 Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
41ea50ac 294#elif defined(_WIN32)
295 HWND aWinHandle = (HWND)theWin;
296 HDC aWindowDC = wglGetCurrentDC();
297 HGLRC aRendCtx = wglGetCurrentContext();
298 if (aWinHandle == NULL
299 || aWindowDC == NULL
300 || aRendCtx == NULL)
301 {
302 Message::DefaultMessenger()->Send ("Error: No active WGL context!", Message_Fail);
303 release();
304 return false;
305 }
306
307 RECT aRect;
308 ::GetClientRect (aWinHandle, &aRect);
309 aWidth = aRect.right - aRect.left;
310 aHeight = aRect.bottom - aRect.top;
311 myWinSize.x() = aWidth;
312 myWinSize.y() = aHeight;
313 if (!myViewer.IsNull())
314 {
315 Handle(WNT_Window) aWindow = new WNT_Window (aWinHandle);
316 myView->SetWindow (aWindow, (Aspect_RenderingContext)aRendCtx);
317 return true;
318 }
319 Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (aDisplayConnection, Standard_False);
320#endif
321
80eb9670 322 aDriver->ChangeOptions().buffersNoSwap = Standard_True;
323 //aDriver->ChangeOptions().glslWarnings = Standard_True; // for GLSL shaders debug
324
41ea50ac 325#ifdef __ANDROID__
80eb9670 326 if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
327 {
41ea50ac 328 Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized", Message_Fail);
80eb9670 329 release();
330 return false;
331 }
41ea50ac 332#endif
80eb9670 333
334 // create viewer
6a24c6de 335 myViewer = new V3d_Viewer (aDriver);
336 myViewer->SetDefaultBackgroundColor (AndroidQt_UserInteractionParameters::BgColor.Name());
80eb9670 337 myViewer->SetDefaultLights();
338 myViewer->SetLightOn();
339
340 // create AIS context
341 myContext = new AIS_InteractiveContext (myViewer);
b2857a7e 342 myContext->SetDisplayMode (AIS_Shaded, false);
80eb9670 343
41ea50ac 344#ifdef __ANDROID__
80eb9670 345 Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight);
41ea50ac 346#elif defined(_WIN32)
347 Handle(WNT_Window) aWindow = new WNT_Window (aWinHandle);
348#endif
349
80eb9670 350 myView = myViewer->CreateView();
41ea50ac 351 myView->SetImmediateUpdate (Standard_False);
80eb9670 352
41ea50ac 353#ifdef __ANDROID__
81a2800c 354 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
41ea50ac 355#else
356 myView->SetWindow (aWindow, (Aspect_RenderingContext )aRendCtx);
357#endif
80eb9670 358 myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
359
360 return true;
361}
362
363// =======================================================================
364// function : release
365// purpose :
366// =======================================================================
367void AndroidQt::release()
368{
369 myContext.Nullify();
370 myView.Nullify();
371 myViewer.Nullify();
372}