Have a Question ?
Ask about our products, services, or latest research. Let's discuss how we can help you solve your problem.
Tuesday, December 04, 2018
Autodesk FORGE Viewer Integration in Native Applications Using Qt
By
Santosh Kawtikwar, Swapnil Kakde
Have you used the Autodesk FORGE Viewer before? If you have, you must be amazed by its ability to render model data in a browser. For those, who do not know about Autodesk FORGE viewer, let us introduce it in brief.
It is a WebGL-based, JavaScript library for 3D and 2D model rendering. 3D and 2D model data may come from applications, such as AutoCAD, Fusion 360, Revit, and many more. Simple!! Right?? And how to use this viewer in a browser? Well, you need access token and URN (Unique resource name) of the file. You can follow this link for the basic application set up.
The Need
Fine. how about viewing these models in the native applications? You may say ok but why? Suppose you have Windows or Android application in which you want to present your product (which is surely a 3D model). Many times, you may think about providing a high definition image of the product, but 3D model really adds a great value for customer experience. So the need is “ you want to render 3D model in a native application”. Next question is how we are going get this feature? Can we do something like this?
  1. Create a native application using C++ and Qt
  2. Insert a webpage containing the Autodesk FORGE Viewer inside it
  3. Set up some interface for communication between a native application and the Autodesk FORGE web application
Ok, these steps sound good. Let’s try this. We will create windows desktop application with Qt. You can follow these Qt installation steps. Now let's create a Qt project in visual studio. Make sure you add WebEngine, WebEngine Widgets, and Web Channel modules in your project.
Qt Project
In CPP code, use QWebEngineView class which provides a widget that is used to view and edit web documents. In it, we will load the Autodesk FORGE Viewer.
QWebEngineView *view = new QWebEngineView();
QGridLayout* baseLayout = new QGridLayout(this);
baseLayout->addWidget(view, 0, 0);
ui.centralWidget->setLayout(baseLayout);
view->load(QUrl("http://192.168.1.30:8080/basic_viewer.html"));
view->show();
You can design UI like below: In this, you can split the application window in two main widgets i.e left side navigation widget and main widget which will contain the Autodesk FORGE Viewer.
Qt project with Autodesk FORGE viewer
Autodesk FORGE Web App
To initialize Autodesk viewing service use below snippet:
var viewer;
    var options = {
        env: 'AutodeskProduction',
        accessToken: ''
    };
    var documentId = 'urn:'; //model urn
    Autodesk.Viewing.Initializer(options, function onInitialized(){
        Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
    });
After loading document successfully, proceed with viewer initialization:
var viewerDiv = document.getElementById('MyViewerDiv');
    viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
    viewer.start(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
Here is how the Autodesk FORGE Viewer with 3D model looks like:
Autodesk FORGE web app
CPP(Qt) And JS(Web Application) Intercommunication
There is a communication mechanism, which works as a bridge between the C++ world to the JavaScript world. It provides a way in which C++ code can call JavaScript functions and vice versa. Not only function calling but also, we can pass the variables from one side to another. These scenarios can be divided into two parts:
Part I
Qt (CPP) app invokes Autodesk FORGE (Js) web app functions:
This is very easy and straightforward way as compared to JavaScript to CPP. In this case, you need to use runJavaScript() function to run JavaScript on a page loaded by QWebEngineView. And pass JavaScript function call as a parameter.
runJavaScript()
Runs the JavaScript code contained in scriptSource. For example,
view->page()->runJavaScript("forgeViewer.SetView('front')");
Here forgeViewer is viewer object, SetView() is a function defined in JavaScript code and ‘front’ is function parameter
Part II
Autodesk FORGE (Js) web app invokes Qt (Cpp) app functions:
In this scenario, we must use QtWebChannel class which enables peer-to-peer communication between a server and a client. In Cpp code, you should have a class which is derived from QObject and it should contain Q_OBJECT macro that declares its own signals and slots.
Let's say that class name is MyWebChannel which contains a slot as below:
class MyWebChannel: public QObject
{
    Q_OBJECT
public:
    MyWebChannel();
    ~MyWebChannel();

    public slots:
   	 void ActivateUI();             	 
};
[Important Step] Now register an object of this class with QWebChannel object, to get access to the properties, signals and public methods of the object on the remote clients.
QWebChannel* qWebChannel = new QWebChannel();
MyWebChannel* webChannelObj = new MyWebChannel();
qWebChannel->registerObject("mainWindow", webChannelObj);
view->page()->setWebChannel(qWebChannel);
To create an instance of QWebChannel on the client side, we need to add qwebchannel.js file. To communicate with a QWebChannel or WebChannel, a client must use and set up the Javascript API provided by qwebchannel.js. Then instantiate a QWebChannel object and pass it a transport object and a callback function, which will be invoked once the initialization of the channel finishes and published objects become available.
new QWebChannel(qt.webChannelTransport, function (channel) {
	mainWindowObj = channel.objects.mainwindow;	
});
Now we can call CPP functions from Javascript as follows:
mainWindowObj.ActivateUI();
Data passing between Cpp and Js Functions
As I mentioned above, we can pass data in between and this can also be divided into two parts:
Part I
Data passing from CPP to JS
view->page()->runJavaScript("forgeViewer.SetView('back')");
view->page()->runJavaScript("forgeViewer.SetSelectedBodyColor(' "+ colorName +" ',' "+ mSelectedDbId +" ')");
});
Part II
Data passing from JS to CPP
mainWindowObj .ShowModelTreeView(JSON.stringify(treeObj));
Output
In this demo application we have created a native application using Cpp and Qt. Which on startup loads hosted Autodesk FORGE viewer. In the left navigation panel, we get three options like:
  1. The Autodesk FORGE views (You can change view i.e top, bottom, left, right)
  2. Model tree (which shows a listing of model parts, also on selection of particular body, that body gets highlighted in viewer)
  3. Properties of a selected body
Real beauty is that you can do all above options from native application. Isn't it iteresting?
About authors
Swapnil Kakde
Swapnil is a Member of Technical Staff at Center for Computational Technology Pvt. Ltd. (CCTech). Skilled in C++, C# Rest API, Web development technologies and Amazon web services (AWS). He has experience in client interaction and software development life cycle(SDLC). He enjoys reading about technology, science, sports, economy, politics etc. In free time he likes to play badminton and volleyball. He is good at creating and maintaining healthy relationships. He also loves to travel and explore new places. He holds a B.E in Information technology from the University of Pune.
Santosh Kawtikwar
Santosh is a member of technical staff at Center for Computational Technology Pvt. Ltd. with a demonstrated history of working in the computer software - IT industry. He has worked as a software developer in simulationHub. Santosh is skilled in AWS Cloud services, C#, C++, and JavaScript. He keeps himself socially and technologically aware. He is a food lover and loves travelling on vacation and reading books in free time.
Comments