Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions examples/labs/orientation/README
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
This example demonstrates rendering the PS Move controller orientation in 3D using Qt5/Qt6 + modern Qt3D.

This application expects that the PS Move API has been
build in "build/" in the root source folder.
Requirements

After you have built the PS Move API in this way, you can
use "qmake" to generate a Makefile and then "make" to build
the application.
Qt 5.15+ or Qt 6.x with these modules:

Additional requirements:
Core, Gui, Widgets

This requires Qt 4.8.2 + Qt3D 1.0.
3DCore, 3DRender, 3DInput, 3DLogic, 3DExtras

Optional: OpenCV 4 if you want to show tracker camera frames.

Building

From the orientation/ directory:

```
qmake
make -j
```

Running
```
./orientation
```

Notes

- This example has been ported from the old Qt 4.8 + Qt3D 1.0 API (QGLView, QGLTeapot) to modern Qt3D.

- The rendered object is a torus (QTorusMesh) by default, but you can switch to a sphere, cube, or a custom mesh.

- The camera frame preview (cvShowImage) is disabled by default. To enable, replace it with OpenCV4 cv::imshow.
16 changes: 7 additions & 9 deletions examples/labs/orientation/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

/**
/**
* PS Move API - An interface for the PS Move Motion Controller
* Copyright (c) 2012 Thomas Perl <m@thp.io>
* All rights reserved.
Expand Down Expand Up @@ -27,26 +26,25 @@
* POSSIBILITY OF SUCH DAMAGE.
**/


#include <QtGui>
#include <QApplication>
#include "orientationview.h"
#include "orientation.h"

int main(int argc, char **argv)
{
QApplication app(argc, argv);
OrientationView view;

OrientationView view; // QWidget that embeds a Qt3D window
Orientation orientation;
orientation.start();

QObject::connect(&orientation,
SIGNAL(orientation(qreal,qreal,qreal,qreal,qreal,qreal,qreal)),
&view,
SLOT(orientation(qreal,qreal,qreal,qreal,qreal,qreal,qreal)));
&Orientation::orientation, // new function-pointer syntax
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good change, but the comment is more for explaining the PR and not the code:

Suggested change
&Orientation::orientation, // new function-pointer syntax
&Orientation::orientation,

&view,
&OrientationView::orientation);

view.resize(900, 700);
view.show();

return app.exec();
}

110 changes: 55 additions & 55 deletions examples/labs/orientation/orientation.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

/**
/**
* PS Move API - An interface for the PS Move Motion Controller
* Copyright (c) 2012 Thomas Perl <m@thp.io>
* All rights reserved.
Expand Down Expand Up @@ -27,10 +26,11 @@
* POSSIBILITY OF SUCH DAMAGE.
**/

#ifndef ORIENTATION_H
#define ORIENTATION_H
Comment on lines +29 to +30
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are at it, might as well change it to #pragma once at the top (same for orientationview.h).


#include <QApplication>
#include <QThread>
#include "qglscenenode.h"

#include <unistd.h>
#include <stdio.h>
Expand All @@ -42,70 +42,70 @@
#include "psmove_tracker.h"
#include "psmove_tracker_opencv.h"

extern "C" {
void cvShowImage(const char *, void*);
};

class Orientation : public QThread
{
Q_OBJECT
signals:
void orientation(qreal a, qreal b, qreal c, qreal d,
qreal scale, qreal x, qreal y);

public:
Orientation() : QThread() {}

void run() override
{
PSMove *move = psmove_connect();
int quit = 0;
float q0, q1, q2, q3;

if (move == NULL) {
fprintf(stderr, "Could not connect to controller.\n");
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this also use the function pointer style syntax?

template <typename Functor, typename FunctorReturnType>
bool QMetaObject::invokeMethod(QObject *context, Functor function,
    Qt::ConnectionType type = Qt::AutoConnection,
    FunctorReturnType *ret = nullptr);

Invokes the function in the event loop of context. function can be a functor or a pointer to a member function. Returns true if the function could be invoked. Returns false if there is no such function or the parameters did not match. The return value of the function call is placed in ret.

https://doc.qt.io/archives/qt-5.15/qmetaobject.html#invokeMethod-4

return;
}

signals:
void orientation(qreal a, qreal b, qreal c, qreal d,
qreal scale, qreal x, qreal y);

public:
Orientation() : QThread() {}

void run()
{
PSMove *move = psmove_connect();
int quit = 0;
float q0, q1, q2, q3;

if (move == NULL) {
fprintf(stderr, "Could not connect to controller.\n");
QApplication::quit();
}

PSMoveTracker *tracker = psmove_tracker_new();

while (psmove_tracker_enable(tracker, move) != Tracker_CALIBRATED) {
// Retry calibration until it works
}

psmove_enable_orientation(move, true);

while (!quit) {
while (psmove_poll(move)) {
if (psmove_get_buttons(move) & Btn_PS) {
quit = 1;
break;
}
PSMoveTracker *tracker = psmove_tracker_new();

if (psmove_get_buttons(move) & Btn_MOVE) {
psmove_reset_orientation(move);
}
while (psmove_tracker_enable(tracker, move) != Tracker_CALIBRATED) {
// retry until calibrated
}

psmove_get_orientation(move, &q0, &q1, &q2, &q3);
psmove_enable_orientation(move, true);

float x, y, radius;
psmove_tracker_get_position(tracker, move, &x, &y, &radius);
emit this->orientation(q0, q1, q2, q3,
1.-((qreal)radius/150.),
1.-((qreal)x/640.)*2.,
1.-((qreal)y/480.)*2.);
while (!quit) {
while (psmove_poll(move)) {
if (psmove_get_buttons(move) & Btn_PS) {
quit = 1;
break;
}
if (psmove_get_buttons(move) & Btn_MOVE) {
psmove_reset_orientation(move);
}

psmove_get_orientation(move, &q0, &q1, &q2, &q3);

psmove_tracker_update_image(tracker);
psmove_tracker_update(tracker, NULL);
float x, y, radius;
psmove_tracker_get_position(tracker, move, &x, &y, &radius);

cvShowImage("asdf", psmove_tracker_opencv_get_frame(tracker));
emit orientation(q0, q1, q2, q3,
1. - (qreal)radius / 150.,
1. - ((qreal)x / 640.) * 2.,
1. - ((qreal)y / 480.) * 2.);
}

psmove_tracker_free(tracker);
psmove_disconnect(move);
QApplication::quit();
psmove_tracker_update_image(tracker);
psmove_tracker_update(tracker, NULL);

// Legacy C API display removed. If you want it back:
// cv::Mat frame = cv::cvarrToMat((IplImage*)psmove_tracker_opencv_get_frame(tracker));
// cv::imshow("tracker", frame);
// cv::waitKey(1);
}

psmove_tracker_free(tracker);
psmove_disconnect(move);
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, this can possibly use a function pointer/Functor instead of a C string "quit".

}
};

#endif // ORIENTATION_H
36 changes: 26 additions & 10 deletions examples/labs/orientation/orientation.pro
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@

TEMPLATE = app
DEPENDPATH += .
INCLUDEPATH += .

CONFIG += qt3d
TARGET = orientation

SOURCES += main.cpp
CONFIG += c++17
QT += core gui widgets 3dcore 3drender 3dinput 3dextras 3dlogic

SOURCES += orientationview.cpp
HEADERS += orientationview.h
# Sources / headers
SOURCES += \
main.cpp \
orientationview.cpp

HEADERS += orientation.h
HEADERS += \
orientationview.h \
orientation.h

# PS Move include/lib layout as before
DEPENDPATH += .
INCLUDEPATH += .
DEPENDPATH += ../../../include
INCLUDEPATH += ../../../include

LIBS += -L../../../build/ -lpsmoveapi -lpsmoveapi_tracker -lopencv_highgui
# NEW: where your psmove landed
INCLUDEPATH += /usr/local/include
# Sometimes headers live in a nested folder, add this too if needed:
INCLUDEPATH += /usr/local/include/psmoveapi
Comment on lines +22 to +25
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is a good idea, we have the headers above and link against a local build. The headers in /usr/local might very well be a different version. Remove this...


# Link PS Move and tracker
LIBS += -L../../../build/ -lpsmoveapi -lpsmoveapi_tracker

# Optional: OpenCV (comment out if not available)
CONFIG += link_pkgconfig
PKGCONFIG += opencv4
Comment on lines +31 to +32
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently isn't used by the code, so can be commented out by default?


# On some distros you might need pthread explicitly
unix:LIBS += -lpthread
Loading