The relationship between C ++ and Javascript for WebGL

My friend and I are trying to establish a connection between C ++ and Javascript. We want to display some spheres at a given position using WebGL built into the C ++ / Qt application (version 5.6).

To do this, we use QWebView , which reads an HTML file with all the JS code for WebGL. This works well, we have great high-level 3D rendering inside our application. The problem is that the position is known in C ++ and should be split into JavaScript .

More precisely, C ++ knows the number of areas we need to display, and their position, and I have to tell this to the side of Javascript. What is the best way to do this?

Note. We tried to use Qt Canvas3D, but it was too slow compared to classic WebGL.

EDIT 1 - after the first attempt

I tried to do what you wrote and also read some examples (like one ), but I can't get it to work.

I created a subclass of QWebEngineView, where I perform all my initializations and set my data.

.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 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 ran it:

  • getNumber is called once and it seems to come after a call to QWebChannel
  • I have a warning: the 'num' property of the 'WebGLView' object has no notification signal and is not constant, updating the values ​​in HTML will be broken!
  • nspherefromc - the number of spheres to be displayed. 50, not 10.

Any ideas?

EDIT 2 - second attempt

I still can't get it to work. I tried adding a new variable called more to see if the function was called or the if statement was 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 working with him, I have only 50 areas. Function in QWebChannel is not called. Perhaps I should call it myself? And when? I also tried more debugging in the if line (typeof qt! = 'Undefined'), and I got 1050 spheres.

EDIT 3 - With 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; 

This means that outside the function I can no longer get to the JSobject. Do you know, why?

EDIT - at the end of OpenGL is already initialized when receiving data from C ++. Therefore, the number of displayed spheres does not match C ++ requests.

+3
source share
1 answer

In Qt5.6, if you want to make part of C ++ and JavaScript for communication, the only way to do this is to use QWebChannel on QWebEngineView . You do this in the .cpp file:

 m_pView = new QWebEngineView(this); QWebChannel * channel = new QWebChannel(page); m_pView->page()->setWebChannel(channel); channel->registerObject(QString("TheNameOfTheObjectUsed"), this); 

Here you simply say that you registered an object called TheNameOfTheObjectUsed , which will be available on the JS side. Now this is part of the code to use on the JS side:

 new QWebChannel(qt.webChannelTransport, function (channel) { // now you retrieve your object var JSobject = channel.objects.TheNameOfTheObjectUsed; }); 

And in your case, you want to get the number of spheres, some positions, etc. So you need to have a method on the C ++ side that returns a string, integer, long ... This is what it looks on the C ++ side in .h :

 Q_INVOKABLE int getNumberOfSpheres(); Q_PROPERTY(int NumberOfSpheres READ getNumberOfSpheres); 

And now you get the number of such spheres on the JS side:

 var nbSpheres = JSobject.NumberOfSpheres; 

This is a very simple explanation, and I recommend that you watch this video , which was very useful to me. In addition, you can read more about the JavaScript API provided by QWebChannel, as well as the QWebChannel documentation;

Hope this helps!


After editing 1

In your .h you need to add (or change):

 int m_pNumber; Q_PROPERTY(int num READ getNumber WRITE setNumber NOTIFY numChanged) Q_INVOKABLE void setNumber(int number); // add this function to the cpp file as well //add a signal for NOTIFY signals: void numChanged(); public slots: void numHasChanged(); 

In your constructor in .cpp:

 connect(this, SIGNAL(numChanged()), this, SLOT(numHasChanged())); 

And in cpp itself:

 void WebGLView::setNumber(int number) { m_pNumber = number; emit numChanged(); } int WebGLView::getNumber() { return m_pNumber; } void WebGLView::numHasChanged() { // do anything here } 

And very important as a JS side:

First, be careful, you copied some code without checking it, so I think you meant:

 if (typeof JSobject !== 'undefined') 

instead

 if (typeof widget !== 'undefined') 

And then:

 var nspherefromc = JSobject.num; // this is ok var nspherefromc = JSobject.getNumber; // this is NOT ok 

Now, when you change the num variable in JS, a signal ( numChanged ) will be emitted and you can get the value in the corresponding slot using getNumber() .

+2
source

Source: https://habr.com/ru/post/1247528/


All Articles