Utilize the rest of the device data, remove unused radius and other

logic, apply MSAA for edge/text smoothing, prep for monitor wrap logic
This commit is contained in:
wheaney 2025-07-29 13:03:49 -07:00
parent 07ccbe12cc
commit 4093123332
5 changed files with 33 additions and 50 deletions

View File

@ -202,6 +202,10 @@ QColor BreezyDesktopEffect::backgroundColor() const {
return QColor(Qt::black);
}
bool BreezyDesktopEffect::imuResetState() const {
return m_imuResetState;
}
QList<QQuaternion> BreezyDesktopEffect::imuRotations() const {
return m_imuRotations;
}
@ -310,14 +314,7 @@ void BreezyDesktopEffect::updateImuRotation() {
float imuData[4 * DataView::IMU_QUAT_ENTRIES]; // 4 quaternion-sized rows
memcpy(imuData, data + DataView::IMU_QUAT_DATA[DataView::OFFSET_INDEX], sizeof(imuData));
const bool imuResetState = (imuData[0] == 0.0f && imuData[1] == 0.0f && imuData[2] == 0.0f && imuData[3] == 1.0f);
if (imuResetState) {
if (isRunning()) {
qCCritical(KWIN_XR) << "\t\t\tBreezy - deactivate due to reset state";
deactivate();
}
return;
}
m_imuResetState = (imuData[0] == 0.0f && imuData[1] == 0.0f && imuData[2] == 0.0f && imuData[3] == 1.0f);
// convert NWU to EUS by passing root.rotation values: -y, z, -x
QQuaternion quatT0(imuData[3], -imuData[1], imuData[2], -imuData[0]);
@ -326,7 +323,9 @@ void BreezyDesktopEffect::updateImuRotation() {
QQuaternion quatT1(imuData[imuDataOffset + 3], -imuData[imuDataOffset + 1], imuData[imuDataOffset + 2], -imuData[imuDataOffset + 0]);
imuDataOffset += DataView::IMU_QUAT_ENTRIES;
// skip the 3rd quaternion
imuDataOffset += DataView::IMU_QUAT_ENTRIES;
// set imuRotations to the last two rotations, leave out the elapsed time
m_imuRotations.clear();
@ -335,7 +334,6 @@ void BreezyDesktopEffect::updateImuRotation() {
// 4th row isn't actually a quaternion, it contains the timestamps for each of the 3 quaternions
// elapsed time between T0 and T1 is: imuData[0] - imuData[1]
imuDataOffset += DataView::IMU_QUAT_ENTRIES;
m_imuTimeElapsedMs = static_cast<quint32>(imuData[imuDataOffset + 0] - imuData[imuDataOffset + 1]);
m_imuTimestamp = imuDateMs;

View File

@ -18,6 +18,7 @@ namespace KWin
Q_PROPERTY(qreal distanceFactor READ distanceFactor NOTIFY distanceFactorChanged)
Q_PROPERTY(BackgroundMode backgroundMode READ backgroundMode NOTIFY backgroundModeChanged)
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged)
Q_PROPERTY(bool imuResetState READ imuResetState NOTIFY imuRotationsChanged)
Q_PROPERTY(QList<QQuaternion> imuRotations READ imuRotations NOTIFY imuRotationsChanged)
Q_PROPERTY(quint32 imuTimeElapsedMs READ imuTimeElapsedMs NOTIFY imuRotationsChanged)
Q_PROPERTY(quint64 imuTimestamp READ imuTimestamp NOTIFY imuRotationsChanged)
@ -52,6 +53,7 @@ namespace KWin
QString cursorImageSource() const;
QPointF cursorPos() const;
bool imuResetState() const;
QList<qreal> lookAheadConfig() const;
QList<quint32> displayResolution() const;
qreal diagonalFOV() const;
@ -99,6 +101,7 @@ namespace KWin
QList<ElectricBorder> m_touchBorderActivate;
QString m_cursorImageSource;
bool m_imuResetState;
QList<QQuaternion> m_imuRotations;
quint32 m_imuTimeElapsedMs;
quint64 m_imuTimestamp;

View File

@ -16,10 +16,15 @@ Node {
"Rokid Air"
]
required property real viewportFOVHorizontal
required property real viewportWidth
required property real viewportHeight
property real distance: viewportWidth / (2 * Math.tan(Math.PI * viewportFOVHorizontal / 360))
property real viewportDiagonalFOV: effect.diagonalFOV
property var viewportResolution: effect.displayResolution
property real viewportHorizontalFOV: {
const aspectRatio = viewportResolution[0] / viewportResolution[1];
return viewportDiagonalFOV * aspectRatio / Math.sqrt(aspectRatio * aspectRatio + 1);
}
property real viewportCenterRadius: {
return viewportResolution[0] / (2 * Math.tan(Math.PI * viewportHorizontalFOV / 360))
}
property var screens: KWinComponents.Workspace.screens
// .filter(function(screen) {
// return supportedModels.includes(screen.model);
@ -36,7 +41,7 @@ Node {
xMax = Math.max(xMax, geometry.x + geometry.width);
}
return (xMin + xMax) / 2 - (viewportWidth / 2);
return (xMin + xMax) / 2 - (viewportResolution[0] / 2);
}
// y value for placing the viewport in the middle of all screens
@ -50,7 +55,7 @@ Node {
yMax = Math.max(yMax, geometry.y + geometry.height);
}
return (yMin + yMax) / 2 - (viewportHeight / 2);
return (yMin + yMax) / 2 - (viewportResolution[1] / 2);
}
Repeater3D {
@ -60,24 +65,26 @@ Node {
property real screenRotation: {
const geometry = screen.geometry;
const rot = (viewportFOVHorizontal / viewportWidth) * (geometry.x - screensXMid);
console.log(`\t\t\tBreezy - screenRotation ${geometry.x} ${geometry.width} ${rot}`);
const rot = (viewportHorizontalFOV / viewportResolution[0]) * (geometry.x - screensXMid);
return -rot;
}
property vector3d screenScale: {
const geometry = screen.geometry;
// apparently the default model unit size is 100x100, so we scale it up to the screen size
return Qt.vector3d(geometry.width / 100, geometry.height / 100, 1);
}
scale: screenScale
eulerRotation.y: screenRotation
position: {
console.log(`\t\t\tBreezy - position ${distance} ${screenRotation}`);
position: {
// rotate about the Y (up) axis, to create a horizontal movement
const transform = Qt.matrix4x4();
transform.rotate(screenRotation, Qt.vector3d(0, 1, 0));
const position = Qt.vector3d(0, 0, -distance);
return transform.times(position).minus(position);
// camera looks along the negative Z axis
return transform.times(Qt.vector3d(0, 0, -viewportCenterRadius));
}
}
}

View File

@ -6,7 +6,6 @@ Item {
required property Camera camera
property real radius: 2000
property var imuRotations: effect.imuRotations
property int imuTimeElapsedMs: effect.imuTimeElapsedMs
property double imuTimestamp: effect.imuTimestamp
@ -22,12 +21,6 @@ Item {
implicitHeight: parent.height
function updateCamera(rotation) {
const theta = 90 * Math.PI / 180;
const phi = 0.0;
camera.position = Qt.vector3d(radius * Math.sin(phi) * Math.sin(theta),
radius * Math.cos(theta),
radius * Math.cos(phi) * Math.sin(theta));
camera.eulerRotation = rotation;
}
@ -62,10 +55,8 @@ Item {
function updateFOV() {
const aspectRatio = displayResolution[0] / displayResolution[1];
camera.fieldOfView = 2 * Math.atan(Math.tan(diagonalFOV * Math.PI / 360) / Math.sqrt(1 + aspectRatio * aspectRatio)) * 180 / Math.PI;
radius = 0.5 * displayResolution[1] / Math.tan(camera.fieldOfView * Math.PI / 360);
}
onRadiusChanged: updateCamera(camera.eulerRotation);
onDisplayResolutionChanged: updateFOV();
onDiagonalFOVChanged: updateFOV();

View File

@ -23,39 +23,23 @@ Item {
View3D {
id: view
anchors.fill: parent
environment: SceneEnvironment {
antialiasingMode: SceneEnvironment.MSAA
}
PerspectiveCamera {
id: camera
fieldOfView: 22.55
frustumCullingEnabled: false
}
BreezyDesktop {
id: breezyDesktop
viewportFOVHorizontal: 40.09
viewportWidth: 1920
viewportHeight: 1080
}
CameraController {
id: cameraController
anchors.fill: parent
camera: camera
radius: 0.5 * breezyDesktop.viewportHeight / Math.tan(camera.fieldOfView * Math.PI / 360)
Behavior on rotation {
enabled: !cameraController.busy && root.animationEnabled
QuaternionAnimation {
id: rotationAnimation
duration: effect.animationDuration
easing.type: Easing.OutCubic
}
}
Behavior on radius {
NumberAnimation {
duration: effect.animationDuration
easing.type: Easing.OutCubic
}
}
}
}