My friend and I are trying to communicate between C++ and Javascript. We want to render some spheres at a given position with WebGL embedded in a C++/Qt (version 5.6) application.
To do that, we use a QWebView
which reads a HTML file with all the JS code for WebGL. This works well, we have a great high-level 3D renderer inside our application. The problem is that the position is known by the C++ and has to be shared to the JavaScript.
More precisely, the C++ knows the number of spheres we need to display and their position, and has to tell it to the Javascript side. What is the best way to do that?
Note : We tried to use Qt Canvas3D but it was too slow in comparison to the classic WebGL.
EDIT 1 - After the first try
I tried to do what you wrote and also read some examples (like this one) but I cannot make it work.
I created a subclass of QWebEngineView where I do all my initializations and put my datas.
.h :
#ifndef WEBGLVIEW_H
#define WEBGLVIEW_H
#include <QObject>
#include <QtWebEngineWidgets>
#include <QtWebChannel/QtWebChannel>
class WebGLView : public QWebEngineView
{
Q_OBJECT
Q_INVOKABLE int getNumber();
Q_PROPERTY(int num READ getNumber)
public:
WebGLView(QWidget *parent = 0);
private :
QWebChannel* m_channel;
};
#endif // WEBGLVIEW_H
.cpp :
#include "WebGLView.h"
#include <QCoreApplication>
#include <QUrl>
#include <QDebug>
WebGLView::WebGLView(QWidget *parent) :
QWebEngineView(parent)
{
// Set up the communications channel
//C++ to Java test
m_channel = new QWebChannel(this);
this->page()->setWebChannel(m_channel);
m_channel->registerObject(QString("test"),this);
QString path = QCoreApplication::applicationDirPath() + "/test6.html";
this->setUrl(QUrl::fromLocalFile(path));
}
int WebGLView::getNumber()
{
qDebug() << "getNumber";
return 10;
}
At the beginning of the JS :
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
...
var JSobject;
if (typeof qt != 'undefined') {new QWebChannel(qt.webChannelTransport, function(channel) {
JSobject = channel.objects.test;
} );
When I want to access the value :
if (typeof widget !== 'undefined') {
var nspherefromc = JSobject.getNumber;
} else {var nspherefromc = 50;}
When I run it :
- getNumber is called once, and it seems that it comes after a call to QWebChannel
- I have warning : Property 'num'' of object 'WebGLView' has no notify signal and is not constant, value updates in HTML will be broken!
- nspherefromc is the number of spheres that will be displayed. 50 are displayed, not 10.
Any ideas ?
EDIT 2 - Second try
I still cannot make it work. I tried to add a new variable named more to see if a function is called or a if statement is entered :
var more = 0;
if (typeof qt != 'undefined') {
new QWebChannel(qt.webChannelTransport, function(channel) {
JSobject = channel.objects.test;
more = 1000;
}
);
}
I still have :
if (typeof JSobject !== 'undefined') {
nspherefromc = JSobject.num;
}
else {nspherefromc = 50;}
...
var spheresNum = nspherefromc + more;//Number of Spheres
When running it, I only have 50 spheres. The function in the QWebChannel is not called. I'm I suppose to call it myself ? And when ? I also tried the more debug in the if(typeof qt != 'undefined') sttement and I got 1050 spheres.
EDIT 3 - With a HTML Debugger
function init() {
var JSobject;
var nspherefromc = 0;
if (typeof qt !== 'undefined') {
new QWebChannel(qt.webChannelTransport, function(channel) {
JSobject = channel.objects.test;
console.log(JSobject); //-> returns the object, I can access the functions and everything
nspherefromc = JSobject.num;
console.log("in the function " + nspherefromc); //prints 5000, what i sent from C++
more = 1000;
}
);
console.log(JSobject); // prints undefined
}
console.log(JSobject); // prints undefined
if (typeof JSobject !== 'undefined') {
console.log("Yeaaaah"); //Not reached
nspherefromc = JSobject.num;
nspherefromc + 1;
}
...
console.log("when loading " + nspherefromc + " (more is = to " + more); // nsphere = 0 , more = 0
var spheresNum = nspherefromc + more;
Which means that outside of the function I cannot reach the JSobject anymore. Do you know why ?
EDIT - In the end The openGL is already initialized when the data from the C++ is received. Therefore, the number of spheres displayed is not the one the C++ asked.