mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 15:09:24 +02:00
Add HMD play area to API; Oculus and Vive
This commit is contained in:
parent
cf12124b34
commit
41c4ecd465
9 changed files with 177 additions and 19 deletions
|
@ -201,3 +201,12 @@ bool HMDScriptingInterface::isKeyboardVisible() {
|
||||||
void HMDScriptingInterface::centerUI() {
|
void HMDScriptingInterface::centerUI() {
|
||||||
QMetaObject::invokeMethod(qApp, "centerUI", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(qApp, "centerUI", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant HMDScriptingInterface::getPlayAreaRect() {
|
||||||
|
auto rect = qApp->getActiveDisplayPlugin()->getPlayAreaRect();
|
||||||
|
return qRectFToVariant(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::vec3> HMDScriptingInterface::getSensorPositions() {
|
||||||
|
return qApp->getActiveDisplayPlugin()->getSensorPositions();
|
||||||
|
}
|
||||||
|
|
|
@ -56,8 +56,10 @@ class QScriptEngine;
|
||||||
* @property {Uuid} tabletID - The UUID of the tablet body model overlay.
|
* @property {Uuid} tabletID - The UUID of the tablet body model overlay.
|
||||||
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay.
|
* @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay.
|
||||||
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay.
|
* @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay.
|
||||||
* @property {Uuid} homeButtonHighlightMaterialID - The UUID of the material entity used to highlight tablet button
|
* @property {Uuid} homeButtonHighlightMaterialID - The UUID of the material entity used to highlight tablet button.
|
||||||
* @property {Uuid} homeButtonUnhighlightMaterialID - The UUID of the material entity use to unhighlight the entity
|
* @property {Uuid} homeButtonUnhighlightMaterialID - The UUID of the material entity use to unhighlight the tablet button.
|
||||||
|
* @property {Rect} playArea=0,0,0,0 - The size and position of the HMD play area in sensor coordinates. <em>Read-only.</em>
|
||||||
|
* @property {Vec3[]} sensorPositions=[]] - The positions of the VR system sensors in sensor coordinates. <em>Read-only.</em>
|
||||||
*/
|
*/
|
||||||
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -71,6 +73,8 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
||||||
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
|
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
|
||||||
Q_PROPERTY(QUuid homeButtonHighlightMaterialID READ getCurrentHomeButtonHighlightMaterialID WRITE setCurrentHomeButtonHighlightMaterialID)
|
Q_PROPERTY(QUuid homeButtonHighlightMaterialID READ getCurrentHomeButtonHighlightMaterialID WRITE setCurrentHomeButtonHighlightMaterialID)
|
||||||
Q_PROPERTY(QUuid homeButtonUnhighlightMaterialID READ getCurrentHomeButtonUnhighlightMaterialID WRITE setCurrentHomeButtonUnhighlightMaterialID)
|
Q_PROPERTY(QUuid homeButtonUnhighlightMaterialID READ getCurrentHomeButtonUnhighlightMaterialID WRITE setCurrentHomeButtonUnhighlightMaterialID)
|
||||||
|
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
|
||||||
|
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -385,6 +389,9 @@ public:
|
||||||
void setCurrentHomeButtonUnhighlightMaterialID(QUuid homeButtonUnhighlightMaterialID) { _homeButtonUnhighlightMaterialID = homeButtonUnhighlightMaterialID; }
|
void setCurrentHomeButtonUnhighlightMaterialID(QUuid homeButtonUnhighlightMaterialID) { _homeButtonUnhighlightMaterialID = homeButtonUnhighlightMaterialID; }
|
||||||
QUuid getCurrentHomeButtonUnhighlightMaterialID() { return _homeButtonUnhighlightMaterialID; }
|
QUuid getCurrentHomeButtonUnhighlightMaterialID() { return _homeButtonUnhighlightMaterialID; }
|
||||||
|
|
||||||
|
QVariant getPlayAreaRect();
|
||||||
|
QVector<glm::vec3> getSensorPositions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _showTablet { false };
|
bool _showTablet { false };
|
||||||
bool _tabletContextualMode { false };
|
bool _tabletContextualMode { false };
|
||||||
|
|
|
@ -112,6 +112,9 @@ public:
|
||||||
virtual bool suppressKeyboard() { return false; }
|
virtual bool suppressKeyboard() { return false; }
|
||||||
virtual void unsuppressKeyboard() {};
|
virtual void unsuppressKeyboard() {};
|
||||||
virtual bool isKeyboardVisible() { return false; }
|
virtual bool isKeyboardVisible() { return false; }
|
||||||
|
|
||||||
|
virtual QRectF getPlayAreaRect() { return QRectF(); }
|
||||||
|
virtual QVector<glm::vec3> getSensorPositions() { return QVector<glm::vec3>(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisplayPlugin : public Plugin, public HmdDisplay {
|
class DisplayPlugin : public Plugin, public HmdDisplay {
|
||||||
|
|
|
@ -552,6 +552,14 @@ glm::vec2 vec2FromVariant(const QVariant &object) {
|
||||||
return vec2FromVariant(object, valid);
|
return vec2FromVariant(object, valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Defines a rectangular portion of an image or screen, or similar.
|
||||||
|
* @typedef {object} Rect
|
||||||
|
* @property {number} x - Left, x-coordinate value.
|
||||||
|
* @property {number} y - Top, y-coordinate value.
|
||||||
|
* @property {number} width - Width of the rectangle.
|
||||||
|
* @property {number} height - Height of the rectangle.
|
||||||
|
*/
|
||||||
QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect) {
|
QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("x", rect.x());
|
obj.setProperty("x", rect.x());
|
||||||
|
@ -568,22 +576,6 @@ void qRectFromScriptValue(const QScriptValue &object, QRect& rect) {
|
||||||
rect.setHeight(object.property("height").toVariant().toInt());
|
rect.setHeight(object.property("height").toVariant().toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) {
|
|
||||||
QScriptValue obj = engine->newObject();
|
|
||||||
obj.setProperty("red", color.red);
|
|
||||||
obj.setProperty("green", color.green);
|
|
||||||
obj.setProperty("blue", color.blue);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**jsdoc
|
|
||||||
* Defines a rectangular portion of an image or screen.
|
|
||||||
* @typedef {object} Rect
|
|
||||||
* @property {number} x - Integer left, x-coordinate value.
|
|
||||||
* @property {number} y - Integer top, y-coordinate value.
|
|
||||||
* @property {number} width - Integer width of the rectangle.
|
|
||||||
* @property {number} height - Integer height of the rectangle.
|
|
||||||
*/
|
|
||||||
QVariant qRectToVariant(const QRect& rect) {
|
QVariant qRectToVariant(const QRect& rect) {
|
||||||
QVariantMap obj;
|
QVariantMap obj;
|
||||||
obj["x"] = rect.x();
|
obj["x"] = rect.x();
|
||||||
|
@ -615,6 +607,61 @@ QRect qRectFromVariant(const QVariant& object) {
|
||||||
return qRectFromVariant(object, valid);
|
return qRectFromVariant(object, valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue qRectFToScriptValue(QScriptEngine* engine, const QRectF& rect) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
obj.setProperty("x", rect.x());
|
||||||
|
obj.setProperty("y", rect.y());
|
||||||
|
obj.setProperty("width", rect.width());
|
||||||
|
obj.setProperty("height", rect.height());
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qRectFFromScriptValue(const QScriptValue &object, QRectF& rect) {
|
||||||
|
rect.setX(object.property("x").toVariant().toFloat());
|
||||||
|
rect.setY(object.property("y").toVariant().toFloat());
|
||||||
|
rect.setWidth(object.property("width").toVariant().toFloat());
|
||||||
|
rect.setHeight(object.property("height").toVariant().toFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant qRectFToVariant(const QRectF& rect) {
|
||||||
|
QVariantMap obj;
|
||||||
|
obj["x"] = rect.x();
|
||||||
|
obj["y"] = rect.y();
|
||||||
|
obj["width"] = rect.width();
|
||||||
|
obj["height"] = rect.height();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF qRectFFromVariant(const QVariant& objectVar, bool& valid) {
|
||||||
|
QVariantMap object = objectVar.toMap();
|
||||||
|
QRectF rect;
|
||||||
|
valid = false;
|
||||||
|
rect.setX(object["x"].toFloat(&valid));
|
||||||
|
if (valid) {
|
||||||
|
rect.setY(object["y"].toFloat(&valid));
|
||||||
|
}
|
||||||
|
if (valid) {
|
||||||
|
rect.setWidth(object["width"].toFloat(&valid));
|
||||||
|
}
|
||||||
|
if (valid) {
|
||||||
|
rect.setHeight(object["height"].toFloat(&valid));
|
||||||
|
}
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF qRectFFromVariant(const QVariant& object) {
|
||||||
|
bool valid;
|
||||||
|
return qRectFFromVariant(object, valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
obj.setProperty("red", color.red);
|
||||||
|
obj.setProperty("green", color.green);
|
||||||
|
obj.setProperty("blue", color.blue);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
void xColorFromScriptValue(const QScriptValue &object, xColor& color) {
|
void xColorFromScriptValue(const QScriptValue &object, xColor& color) {
|
||||||
if (!object.isValid()) {
|
if (!object.isValid()) {
|
||||||
|
|
|
@ -97,7 +97,11 @@ void qRectFromScriptValue(const QScriptValue& object, QRect& rect);
|
||||||
QRect qRectFromVariant(const QVariant& object, bool& isValid);
|
QRect qRectFromVariant(const QVariant& object, bool& isValid);
|
||||||
QRect qRectFromVariant(const QVariant& object);
|
QRect qRectFromVariant(const QVariant& object);
|
||||||
QVariant qRectToVariant(const QRect& rect);
|
QVariant qRectToVariant(const QRect& rect);
|
||||||
|
QScriptValue qRectFToScriptValue(QScriptEngine* engine, const QRectF& rect);
|
||||||
|
void qRectFFromScriptValue(const QScriptValue& object, QRectF& rect);
|
||||||
|
QRectF qRectFFromVariant(const QVariant& object, bool& isValid);
|
||||||
|
QRectF qRectFFromVariant(const QVariant& object);
|
||||||
|
QVariant qRectFToVariant(const QRectF& rect);
|
||||||
|
|
||||||
// xColor
|
// xColor
|
||||||
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
||||||
|
|
|
@ -167,3 +167,53 @@ void OculusBaseDisplayPlugin::updatePresentPose() {
|
||||||
_currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
_currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
||||||
_currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
|
_currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF OculusBaseDisplayPlugin::getPlayAreaRect() {
|
||||||
|
if (!_session) {
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
int floorPointsCount = 0;
|
||||||
|
auto result = ovr_GetBoundaryGeometry(_session, ovrBoundary_PlayArea, nullptr, &floorPointsCount);
|
||||||
|
if (!OVR_SUCCESS(result) || floorPointsCount != 4) {
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto floorPoints = new ovrVector3f[floorPointsCount];
|
||||||
|
result = ovr_GetBoundaryGeometry(_session, ovrBoundary_PlayArea, floorPoints, nullptr);
|
||||||
|
if (!OVR_SUCCESS(result)) {
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto minXZ = ovr::toGlm(floorPoints[0]);
|
||||||
|
auto maxXZ = minXZ;
|
||||||
|
for (int i = 1; i < floorPointsCount; i++) {
|
||||||
|
auto point = ovr::toGlm(floorPoints[i]);
|
||||||
|
minXZ.x = std::min(minXZ.x, point.x);
|
||||||
|
minXZ.z = std::min(minXZ.z, point.z);
|
||||||
|
maxXZ.x = std::max(maxXZ.x, point.x);
|
||||||
|
maxXZ.z = std::max(maxXZ.z, point.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 center = glm::vec2((minXZ.x + maxXZ.x) / 2, (minXZ.z + maxXZ.z) / 2);
|
||||||
|
glm::vec2 dimensions = glm::vec2(maxXZ.x - minXZ.x, maxXZ.z - minXZ.z);
|
||||||
|
|
||||||
|
return QRectF(center.x, center.y, dimensions.x, dimensions.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::vec3> OculusBaseDisplayPlugin::getSensorPositions() {
|
||||||
|
if (!_session) {
|
||||||
|
return QVector<glm::vec3>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::vec3> result;
|
||||||
|
auto numTrackers = ovr_GetTrackerCount(_session);
|
||||||
|
for (uint i = 0; i < numTrackers; i++) {
|
||||||
|
auto trackerPose = ovr_GetTrackerPose(_session, i);
|
||||||
|
if (trackerPose.TrackerFlags & ovrTracker_PoseTracked) {
|
||||||
|
result.append(ovr::toGlm(trackerPose.Pose.Position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ public:
|
||||||
void resetSensors() override final;
|
void resetSensors() override final;
|
||||||
bool beginFrameRender(uint32_t frameIndex) override;
|
bool beginFrameRender(uint32_t frameIndex) override;
|
||||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||||
|
|
||||||
|
QRectF getPlayAreaRect() override;
|
||||||
|
QVector<glm::vec3> getSensorPositions() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
|
|
|
@ -765,3 +765,36 @@ QString OpenVrDisplayPlugin::getPreferredAudioOutDevice() const {
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF OpenVrDisplayPlugin::getPlayAreaRect() {
|
||||||
|
auto chaperone = vr::VRChaperone();
|
||||||
|
if (!chaperone) {
|
||||||
|
qWarning() << "No chaperone";
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chaperone->GetCalibrationState() >= vr::ChaperoneCalibrationState_Error) {
|
||||||
|
qWarning() << "Chaperone status =" << chaperone->GetCalibrationState();
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
vr::HmdQuad_t rect;
|
||||||
|
if (!chaperone->GetPlayAreaRect(&rect)) {
|
||||||
|
qWarning() << "Chaperone rect not obtained";
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto minXZ = transformPoint(_sensorResetMat, toGlm(rect.vCorners[0]));
|
||||||
|
auto maxXZ = minXZ;
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
auto point = transformPoint(_sensorResetMat, toGlm(rect.vCorners[i]));
|
||||||
|
minXZ.x = std::min(minXZ.x, point.x);
|
||||||
|
minXZ.z = std::min(minXZ.z, point.z);
|
||||||
|
maxXZ.x = std::max(maxXZ.x, point.x);
|
||||||
|
maxXZ.z = std::max(maxXZ.z, point.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 center = glm::vec2((minXZ.x + maxXZ.x) / 2, (minXZ.z + maxXZ.z) / 2);
|
||||||
|
glm::vec2 dimensions = glm::vec2(maxXZ.x - minXZ.x, maxXZ.z - minXZ.z);
|
||||||
|
|
||||||
|
return QRectF(center.x, center.y, dimensions.x, dimensions.y);
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
QString getPreferredAudioInDevice() const override;
|
QString getPreferredAudioInDevice() const override;
|
||||||
QString getPreferredAudioOutDevice() const override;
|
QString getPreferredAudioOutDevice() const override;
|
||||||
|
|
||||||
|
QRectF getPlayAreaRect() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool internalActivate() override;
|
bool internalActivate() override;
|
||||||
void internalDeactivate() override;
|
void internalDeactivate() override;
|
||||||
|
|
Loading…
Reference in a new issue