mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
293 lines
8.5 KiB
C++
293 lines
8.5 KiB
C++
// 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 <AndroidQt_Window.h>
|
|
#include <AndroidQt.h>
|
|
#include <AndroidQt_UserInteractionParameters.h>
|
|
|
|
#include <AIS_Shape.hxx>
|
|
#include <BRepTools.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <OpenGl_GraphicDriver.hxx>
|
|
#include <Quantity_Color.hxx>
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <UnitsAPI.hxx>
|
|
|
|
#include <EGL/egl.h>
|
|
#include <QFileInfo>
|
|
|
|
// =======================================================================
|
|
// 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, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// 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, NULL, NULL);
|
|
}
|
|
|
|
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, TCollection_ExtendedString("Viewer").ToExtString(), "", 1000.0,
|
|
V3d_XposYnegZpos, AndroidQt_UserInteractionParameters::BgColor.Name(), V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
|
|
Standard_True, Standard_False);
|
|
myViewer->SetDefaultLights();
|
|
myViewer->SetLightOn();
|
|
|
|
// create AIS context
|
|
myContext = new AIS_InteractiveContext (myViewer);
|
|
myContext->SetDisplayMode (AIS_Shaded);
|
|
|
|
Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight);
|
|
myView = myViewer->CreateView();
|
|
|
|
myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL);
|
|
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();
|
|
}
|