mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01: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() {
|
||||
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} tabletScreenID - The UUID of the tablet's screen 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} homeButtonUnhighlightMaterialID - The UUID of the material entity use to unhighlight the entity
|
||||
* @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 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 {
|
||||
Q_OBJECT
|
||||
|
@ -71,6 +73,8 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID)
|
||||
Q_PROPERTY(QUuid homeButtonHighlightMaterialID READ getCurrentHomeButtonHighlightMaterialID WRITE setCurrentHomeButtonHighlightMaterialID)
|
||||
Q_PROPERTY(QUuid homeButtonUnhighlightMaterialID READ getCurrentHomeButtonUnhighlightMaterialID WRITE setCurrentHomeButtonUnhighlightMaterialID)
|
||||
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
|
||||
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -385,6 +389,9 @@ public:
|
|||
void setCurrentHomeButtonUnhighlightMaterialID(QUuid homeButtonUnhighlightMaterialID) { _homeButtonUnhighlightMaterialID = homeButtonUnhighlightMaterialID; }
|
||||
QUuid getCurrentHomeButtonUnhighlightMaterialID() { return _homeButtonUnhighlightMaterialID; }
|
||||
|
||||
QVariant getPlayAreaRect();
|
||||
QVector<glm::vec3> getSensorPositions();
|
||||
|
||||
private:
|
||||
bool _showTablet { false };
|
||||
bool _tabletContextualMode { false };
|
||||
|
|
|
@ -112,6 +112,9 @@ public:
|
|||
virtual bool suppressKeyboard() { return false; }
|
||||
virtual void unsuppressKeyboard() {};
|
||||
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 {
|
||||
|
|
|
@ -552,6 +552,14 @@ glm::vec2 vec2FromVariant(const QVariant &object) {
|
|||
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 obj = engine->newObject();
|
||||
obj.setProperty("x", rect.x());
|
||||
|
@ -568,22 +576,6 @@ void qRectFromScriptValue(const QScriptValue &object, QRect& rect) {
|
|||
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) {
|
||||
QVariantMap obj;
|
||||
obj["x"] = rect.x();
|
||||
|
@ -615,6 +607,61 @@ QRect qRectFromVariant(const QVariant& object) {
|
|||
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) {
|
||||
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);
|
||||
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
|
||||
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
||||
|
|
|
@ -167,3 +167,53 @@ void OculusBaseDisplayPlugin::updatePresentPose() {
|
|||
_currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
||||
_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;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||
|
||||
QRectF getPlayAreaRect() override;
|
||||
QVector<glm::vec3> getSensorPositions() override;
|
||||
|
||||
protected:
|
||||
void customizeContext() override;
|
||||
|
|
|
@ -765,3 +765,36 @@ QString OpenVrDisplayPlugin::getPreferredAudioOutDevice() const {
|
|||
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 getPreferredAudioOutDevice() const override;
|
||||
|
||||
QRectF getPlayAreaRect() override;
|
||||
|
||||
protected:
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
|
|
Loading…
Reference in a new issue