0025180: Visualization - Homogeneous transformation API in TKV3d
[occt.git] / samples / qt / AndroidQt / 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
14#include <AndroidQt_Window.h>
15#include <AndroidQt.h>
16#include <AndroidQt_UserInteractionParameters.h>
17
18#include <AIS_Shape.hxx>
19#include <BRepTools.hxx>
20#include <BRep_Builder.hxx>
21#include <OpenGl_GraphicDriver.hxx>
22#include <Quantity_Color.hxx>
23#include <Standard_ErrorHandler.hxx>
24#include <TopoDS.hxx>
25#include <TopoDS_Face.hxx>
26#include <TopoDS_Shape.hxx>
27#include <UnitsAPI.hxx>
28
29#include <EGL/egl.h>
30#include <QFileInfo>
31
32// =======================================================================
33// function : AndroidQt
34// purpose :
35// =======================================================================
36AndroidQt::AndroidQt()
37: myFitAllAction (false)
38{
39 connect (this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
40
41 // set shaders location variable
42 QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared";
43 qputenv ("CSF_ShadersDirectory", aDataRoot + "/Shaders");
44}
45
46// =======================================================================
47// function : ReadShapeFromFile
48// purpose :
49// =======================================================================
50bool AndroidQt::ReadShapeFromFile (QString theFilePath)
51{
52 QUrl aFileUrl (theFilePath);
53 QString aFilePath = theFilePath;
54 if (aFileUrl.isLocalFile())
55 {
56 aFilePath = QUrl (theFilePath).toLocalFile();
57 }
58
59 if (!QFile (aFilePath).exists())
60 {
61 return false;
62 }
63
64 TopoDS_Shape aShape;
65 BRep_Builder aBuildTool;
66 try
67 {
68 OCC_CATCH_SIGNALS
69
70 if (!BRepTools::Read (aShape, aFilePath.toStdString().c_str(), aBuildTool))
71 {
72 return false;
73 }
74
75 if (!myContext.IsNull())
76 {
77 myContext->EraseAll (Standard_False);
78
79 Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
80 aShapePrs->SetColor (Quantity_Color(1.0, 0.73, 0.2, Quantity_TOC_RGB));
81
82 myContext->Display (aShapePrs, Standard_False);
83 myContext->SetDisplayMode (aShapePrs, AIS_Shaded, Standard_False);
84 }
85
86 myMutex.lock();
87 myFitAllAction = true;
88 myMutex.unlock();
89
90 if (window())
91 {
92 window()->update();
93 }
94 }
95 catch (Standard_Failure)
96 {
97 return false;
98 }
99
100 return true;
101}
102
103// =======================================================================
104// function : InitTouch
105// purpose :
106// =======================================================================
107void AndroidQt::InitTouch (const double theX,
108 const double theY)
109{
110 myMutex.lock();
111 myTouchPoint.SetStarts (theX, theY);
112 myMutex.unlock();
113}
114
115// =======================================================================
116// function : UpdateTouch
117// purpose :
118// =======================================================================
119void AndroidQt::UpdateTouch (const double theX,
120 const double theY)
121{
122 myMutex.lock();
123 myTouchPoint.SetEnds (theX, theY);
124 myMutex.unlock();
125
126 if (window())
127 window()->update();
128}
129
130// =======================================================================
131// function : handleWindowChanged
132// purpose :
133// =======================================================================
134void AndroidQt::handleWindowChanged (QQuickWindow* theWin)
135{
136 if (theWin == NULL)
137 {
138 return;
139 }
140
141 connect(theWin, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
142
143 theWin->setClearBeforeRendering (false);
144}
145
146// =======================================================================
147// function : sync
148// purpose :
149// =======================================================================
150void AndroidQt::sync()
151{
152 myViewportSize = window()->size() * window()->devicePixelRatio();
153
154 if (myViewer.IsNull())
155 {
156 initViewer();
157 connect (window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
158 }
159 else
160 {
161 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
162 if (aDriver->getRawGlContext() != eglGetCurrentContext())
163 {
164 initViewer();
165 }
166 else
167 {
168 Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
169 aWindow->SetSize (myViewportSize.width(), myViewportSize.height());
170 //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
171
172 EGLContext anEglContext = eglGetCurrentContext();
173 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
174 }
175 }
176}
177
178// =======================================================================
179// function : paint
180// purpose :
181// =======================================================================
182void AndroidQt::paint()
183{
184 myMutex.lock();
185
186 if (Abs(myTouchPoint.DevX()) + Abs(myTouchPoint.DevY()) > 1)
187 {
188 myView->StartRotation (myTouchPoint.X().first, myTouchPoint.Y().first);
189 myView->Rotation (myTouchPoint.X().second, myTouchPoint.Y().second);
190
191 myTouchPoint.ClearDev();
192 }
193
194 if (myFitAllAction)
195 {
196 myView->FitAll();
197 myFitAllAction = false;
198 }
199
200 myMutex.unlock();
201
202 myView->Redraw();
203}
204
205// =======================================================================
206// function : initViewer
207// purpose :
208// =======================================================================
209bool AndroidQt::initViewer()
210{
211 EGLint aCfgId = 0;
212 int aWidth = 0, aHeight = 0;
213 EGLDisplay anEglDisplay = eglGetCurrentDisplay();
214 EGLContext anEglContext = eglGetCurrentContext();
215 EGLSurface anEglSurf = eglGetCurrentSurface (EGL_DRAW);
216
217 if (anEglDisplay == EGL_NO_DISPLAY
218 || anEglContext == EGL_NO_CONTEXT
219 || anEglSurf == EGL_NO_SURFACE)
220 {
221 release();
222 return false;
223 }
224
225 eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH, &aWidth);
226 eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT, &aHeight);
227 eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId);
228
229 const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE };
230 EGLint aNbConfigs = 0;
231 void* anEglConfig = NULL;
232
233 if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
234 {
235 release();
236 return false;
237 }
238
239 if (!myViewer.IsNull())
240 {
241 Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
242 Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
243 if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
244 {
245 release();
246 return false;
247 }
248
249 aWindow->SetSize (aWidth, aHeight);
250 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
251 }
252
253 Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
254 aDriver->ChangeOptions().buffersNoSwap = Standard_True;
255 //aDriver->ChangeOptions().glslWarnings = Standard_True; // for GLSL shaders debug
256
257 if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
258 {
259 release();
260 return false;
261 }
262
263 // create viewer
264 myViewer = new V3d_Viewer (aDriver, TCollection_ExtendedString("Viewer").ToExtString(), "", 1000.0,
265 V3d_XposYnegZpos, AndroidQt_UserInteractionParameters::BgColor.Name(), V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
266 Standard_True, Standard_False);
267 myViewer->SetDefaultLights();
268 myViewer->SetLightOn();
269
270 // create AIS context
271 myContext = new AIS_InteractiveContext (myViewer);
272 myContext->SetDisplayMode (AIS_Shaded);
273
274 Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight);
275 myView = myViewer->CreateView();
276
277 myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
278 myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
279
280 return true;
281}
282
283// =======================================================================
284// function : release
285// purpose :
286// =======================================================================
287void AndroidQt::release()
288{
289 myContext.Nullify();
290 myView.Nullify();
291 myViewer.Nullify();
292}