// Copyright (c) 2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ======================================================================= // function : AndroidQt // purpose : // ======================================================================= AndroidQt::AndroidQt() : myFitAllAction (false) { connect (this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); // set shaders location variable QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared"; qputenv ("CSF_ShadersDirectory", aDataRoot + "/Shaders"); } // ======================================================================= // function : ReadShapeFromFile // purpose : // ======================================================================= bool AndroidQt::ReadShapeFromFile (QString theFilePath) { QUrl aFileUrl (theFilePath); QString aFilePath = theFilePath; if (aFileUrl.isLocalFile()) { aFilePath = QUrl (theFilePath).toLocalFile(); } if (!QFile (aFilePath).exists()) { return false; } TopoDS_Shape aShape; BRep_Builder aBuildTool; try { OCC_CATCH_SIGNALS if (!BRepTools::Read (aShape, aFilePath.toStdString().c_str(), aBuildTool)) { return false; } if (!myContext.IsNull()) { myContext->EraseAll (Standard_False); Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape); aShapePrs->SetColor (Quantity_Color(1.0, 0.73, 0.2, Quantity_TOC_RGB)); myContext->Display (aShapePrs, Standard_False); myContext->SetDisplayMode (aShapePrs, AIS_Shaded, Standard_False); } myMutex.lock(); myFitAllAction = true; myMutex.unlock(); if (window()) { window()->update(); } } catch (Standard_Failure) { return false; } return true; } // ======================================================================= // function : InitTouch // purpose : // ======================================================================= void AndroidQt::InitTouch (const double theX, const double theY) { myMutex.lock(); myTouchPoint.SetStarts (theX, theY); myMutex.unlock(); } // ======================================================================= // function : UpdateTouch // purpose : // ======================================================================= void AndroidQt::UpdateTouch (const double theX, const double theY) { myMutex.lock(); myTouchPoint.SetEnds (theX, theY); myMutex.unlock(); if (window()) window()->update(); } // ======================================================================= // function : handleWindowChanged // purpose : // ======================================================================= void AndroidQt::handleWindowChanged (QQuickWindow* theWin) { if (theWin == NULL) { return; } connect(theWin, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection); theWin->setClearBeforeRendering (false); } // ======================================================================= // function : sync // purpose : // ======================================================================= void AndroidQt::sync() { myViewportSize = window()->size() * window()->devicePixelRatio(); if (myViewer.IsNull()) { initViewer(); connect (window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); } else { Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver()); if (aDriver->getRawGlContext() != eglGetCurrentContext()) { initViewer(); } else { Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window()); aWindow->SetSize (myViewportSize.width(), myViewportSize.height()); //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed EGLContext anEglContext = eglGetCurrentContext(); myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext); } } } // ======================================================================= // function : paint // purpose : // ======================================================================= void AndroidQt::paint() { myMutex.lock(); if (Abs(myTouchPoint.DevX()) + Abs(myTouchPoint.DevY()) > 1) { myView->StartRotation (myTouchPoint.X().first, myTouchPoint.Y().first); myView->Rotation (myTouchPoint.X().second, myTouchPoint.Y().second); myTouchPoint.ClearDev(); } if (myFitAllAction) { myView->FitAll(); myFitAllAction = false; } myMutex.unlock(); myView->Redraw(); } // ======================================================================= // function : initViewer // purpose : // ======================================================================= bool AndroidQt::initViewer() { EGLint aCfgId = 0; int aWidth = 0, aHeight = 0; EGLDisplay anEglDisplay = eglGetCurrentDisplay(); EGLContext anEglContext = eglGetCurrentContext(); EGLSurface anEglSurf = eglGetCurrentSurface (EGL_DRAW); if (anEglDisplay == EGL_NO_DISPLAY || anEglContext == EGL_NO_CONTEXT || anEglSurf == EGL_NO_SURFACE) { release(); return false; } eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH, &aWidth); eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT, &aHeight); eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId); const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE }; EGLint aNbConfigs = 0; void* anEglConfig = NULL; if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE) { release(); return false; } if (!myViewer.IsNull()) { Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver()); Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window()); if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig)) { release(); return false; } aWindow->SetSize (aWidth, aHeight); myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext); } Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False); aDriver->ChangeOptions().buffersNoSwap = Standard_True; //aDriver->ChangeOptions().glslWarnings = Standard_True; // for GLSL shaders debug if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig)) { release(); return false; } // create viewer myViewer = new V3d_Viewer (aDriver); myViewer->SetDefaultBackgroundColor (AndroidQt_UserInteractionParameters::BgColor.Name()); myViewer->SetDefaultLights(); myViewer->SetLightOn(); // create AIS context myContext = new AIS_InteractiveContext (myViewer); myContext->SetDisplayMode (AIS_Shaded, false); Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight); myView = myViewer->CreateView(); myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext); myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER); return true; } // ======================================================================= // function : release // purpose : // ======================================================================= void AndroidQt::release() { myContext.Nullify(); myView.Nullify(); myViewer.Nullify(); }