Replace custom RotationData with QGraphicsRotation

This commit is contained in:
Martin Gräßlin 2012-05-27 19:28:02 +02:00
parent a394fade64
commit 966047ccd2
10 changed files with 120 additions and 150 deletions

View file

@ -461,8 +461,6 @@ void CoverSwitchEffect::paintScene(EffectWindow* frontWindow, const EffectWindow
int width = area.width();
int leftWindowCount = leftWindows.count();
int rightWindowCount = rightWindows.count();
RotationData rot;
rot.axis = RotationData::YAxis;
// Problem during animation: a window which is painted after another window
@ -701,8 +699,7 @@ void CoverSwitchEffect::paintWindowCover(EffectWindow* w, bool reflectedWindow,
}
}
data.zTranslate *= timeLine.currentValue();
if (data.rotation)
data.rotation->angle *= timeLine.currentValue();
data.rotation.setAngle(data.rotation.angle() * timeLine.currentValue());
}
}
if (stop) {
@ -732,8 +729,7 @@ void CoverSwitchEffect::paintWindowCover(EffectWindow* w, bool reflectedWindow,
}
}
data.zTranslate *= (1.0 - timeLine.currentValue());
if (data.rotation)
data.rotation->angle *= (1.0 - timeLine.currentValue());
data.rotation.setAngle(data.rotation.angle() * (1.0 - timeLine.currentValue()));
}
}
@ -788,7 +784,6 @@ void CoverSwitchEffect::paintFrontWindow(EffectWindow* frontWindow, int width, i
if (rightWindows == 0) {
rightWindows = 1;
}
RotationData rot; // this has to survive the if (animation) context as it's used as pointer - bug #297757
if (animation) {
float distance = 0.0;
if (direction == Right) {
@ -796,10 +791,9 @@ void CoverSwitchEffect::paintFrontWindow(EffectWindow* frontWindow, int width, i
distance = -frontWindow->geometry().width() * 0.5f + area.width() * 0.5f +
(((float)displayWidth() * 0.5 * scaleFactor) - (float)area.width() * 0.5f) / rightWindows;
data.xTranslate += distance * timeLine.currentValue();
rot.axis = RotationData::YAxis;
rot.angle = -angle * timeLine.currentValue();
rot.xRotationPoint = frontWindow->geometry().width();
data.rotation = &rot;
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(-angle * timeLine.currentValue());
data.rotation.setOrigin(QVector3D(frontWindow->geometry().width(), 0.0, 0.0));
} else {
// move to left
distance = frontWindow->geometry().width() * 0.5f - area.width() * 0.5f +
@ -808,10 +802,8 @@ void CoverSwitchEffect::paintFrontWindow(EffectWindow* frontWindow, int width, i
if (specialHandlingForward)
factor = 2.0;
data.xTranslate += distance * timeLine.currentValue() * factor;
rot.axis = RotationData::YAxis;
rot.angle = angle * timeLine.currentValue();
rot.xRotationPoint = 0.0;
data.rotation = &rot;
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(angle * timeLine.currentValue());
}
}
if (specialHandlingForward) {
@ -838,26 +830,20 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
// handling for additional window from other side
// has to appear on this side after half of the time
if (animation && timeLine.currentValue() >= 0.5 && additionalWindow != NULL) {
RotationData rot;
rot.axis = RotationData::YAxis;
rot.angle = angle;
rot.angle = angle * rotateFactor;
WindowPaintData data(additionalWindow);
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(angle * rotateFactor);
if (left) {
data.xTranslate += -xTranslate - additionalWindow->geometry().x();
rot.xRotationPoint = 0.0;
}
else {
data.xTranslate += xTranslate + area.width() -
additionalWindow->geometry().x() - additionalWindow->geometry().width();
rot.xRotationPoint = additionalWindow->geometry().width();
data.rotation.setOrigin(QVector3D(additionalWindow->geometry().width(), 0.0, 0.0));
}
data.rotation = &rot;
data.opacity *= (timeLine.currentValue() - 0.5) * 2.0;
paintWindowCover(additionalWindow, reflectedWindows, data);
}
RotationData rot;
rot.axis = RotationData::YAxis;
// normal behaviour
for (int i = 0; i < windows.count(); i++) {
window = windows.at(i);
@ -865,7 +851,8 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
continue;
}
WindowPaintData data(window);
rot.angle = angle;
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(angle);
if (left)
data.xTranslate += -xTranslate + xTranslate * i / windowCount - window->geometry().x();
else
@ -876,7 +863,7 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
// right most window on left side -> move to front
// have to move one window distance plus half the difference between the window and the desktop size
data.xTranslate += (xTranslate / windowCount + (width - window->geometry().width()) * 0.5f) * timeLine.currentValue();
rot.angle = (angle - angle * timeLine.currentValue());
data.rotation.setAngle(angle - angle * timeLine.currentValue());
}
// right most window does not have to be moved
else if (!left && (i == 0)); // do nothing
@ -888,7 +875,7 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
if ((i == windowCount - 1) && !left) {
// left most window on right side -> move to front
data.xTranslate -= (xTranslate / windowCount + (width - window->geometry().width()) * 0.5f) * timeLine.currentValue();
rot.angle = (angle - angle * timeLine.currentValue());
data.rotation.setAngle(angle - angle * timeLine.currentValue());
}
// left most window does not have to be moved
else if (i == 0 && left); // do nothing
@ -898,12 +885,9 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
}
}
}
if (left)
rot.xRotationPoint = 0.0;
else
rot.xRotationPoint = window->geometry().width();
rot.angle *= rotateFactor;
data.rotation = &rot;
if (!left)
data.rotation.setOrigin(QVector3D(window->geometry().width(), 0.0, 0.0));
data.rotation.setAngle(data.rotation.angle() * rotateFactor);
// make window most to edge transparent if animation
if (animation && i == 0 && ((direction == Left && left) || (direction == Right && !left))) {
// only for the first half of the animation

View file

@ -37,6 +37,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QKeyEvent>
#include <QtConcurrentRun>
#include <QVector2D>
#include <QVector3D>
#include <math.h>
@ -743,12 +744,9 @@ void CubeEffect::paintCube(int mask, QRegion region, ScreenPaintData& data)
painting_desktop = effects->numberOfDesktops();
}
ScreenPaintData newData = data;
RotationData rot = RotationData();
rot.axis = RotationData::YAxis;
rot.angle = internalCubeAngle * i;
rot.xRotationPoint = rect.width() / 2;
rot.zRotationPoint = -point;
newData.rotation = &rot;
newData.rotation.setAxis(Qt::YAxis);
newData.rotation.setAngle(internalCubeAngle * i);
newData.rotation.setOrigin(QVector3D(rect.width() / 2, 0.0, -point));
newData.zTranslate = -zTranslate;
effects->paintScreen(mask, region, newData);
}
@ -1381,11 +1379,9 @@ void CubeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPa
if (shader) {
data.xTranslate = -rect.width();
} else {
RotationData rot = RotationData();
rot.axis = RotationData::YAxis;
rot.xRotationPoint = rect.width() - w->x();
rot.angle = 360.0f / effects->numberOfDesktops();
data.rotation = &rot;
data.rotation.setAxis(Qt::YAxis);
data.rotation.setOrigin(QVector3D(rect.width() - w->x(), 0.0, 0.0));
data.rotation.setAngle(-360.0f / effects->numberOfDesktops());
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
QMatrix4x4 matrix;
@ -1407,11 +1403,9 @@ void CubeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPa
if (shader) {
data.xTranslate = rect.width();
} else {
RotationData rot = RotationData();
rot.axis = RotationData::YAxis;
rot.xRotationPoint = -w->x();
rot.angle = -360.0f / effects->numberOfDesktops();
data.rotation = &rot;
data.rotation.setAxis(Qt::YAxis);
data.rotation.setOrigin(QVector3D(-w->x(), 0.0, 0.0));
data.rotation.setAngle(-360.0f / effects->numberOfDesktops());
float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2) / (float)effects->numberOfDesktops() * 180.0f);
float point = rect.width() / 2 * tan(cubeAngle * 0.5f * M_PI / 180.0f);
QMatrix4x4 matrix;

View file

@ -118,14 +118,12 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData&
ScreenPaintData firstFaceData = data;
ScreenPaintData secondFaceData = data;
RotationData firstFaceRot = RotationData();
RotationData secondFaceRot = RotationData();
RotationDirection direction = slideRotations.head();
int secondDesktop;
switch(direction) {
case Left:
firstFaceRot.axis = RotationData::YAxis;
secondFaceRot.axis = RotationData::YAxis;
firstFaceData.rotation.setAxis(Qt::YAxis);
secondFaceData.rotation.setAxis(Qt::YAxis);
if (usePagerLayout)
secondDesktop = effects->desktopToLeft(front_desktop, true);
else {
@ -133,12 +131,12 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData&
if (secondDesktop == 0)
secondDesktop = effects->numberOfDesktops();
}
firstFaceRot.angle = 90.0f * timeLine.currentValue();
secondFaceRot.angle = -90.0f * (1.0f - timeLine.currentValue());
firstFaceData.rotation.setAngle(90.0f * timeLine.currentValue());
secondFaceData.rotation.setAngle(-90.0f * (1.0f - timeLine.currentValue()));
break;
case Right:
firstFaceRot.axis = RotationData::YAxis;
secondFaceRot.axis = RotationData::YAxis;
firstFaceData.rotation.setAxis(Qt::YAxis);
secondFaceData.rotation.setAxis(Qt::YAxis);
if (usePagerLayout)
secondDesktop = effects->desktopToRight(front_desktop, true);
else {
@ -146,23 +144,23 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData&
if (secondDesktop > effects->numberOfDesktops())
secondDesktop = 1;
}
firstFaceRot.angle = -90.0f * timeLine.currentValue();
secondFaceRot.angle = 90.0f * (1.0f - timeLine.currentValue());
firstFaceData.rotation.setAngle(-90.0f * timeLine.currentValue());
secondFaceData.rotation.setAngle(90.0f * (1.0f - timeLine.currentValue()));
break;
case Upwards:
firstFaceRot.axis = RotationData::XAxis;
secondFaceRot.axis = RotationData::XAxis;
firstFaceData.rotation.setAxis(Qt::XAxis);
secondFaceData.rotation.setAxis(Qt::XAxis);
secondDesktop = effects->desktopAbove(front_desktop, true);
firstFaceRot.angle = -90.0f * timeLine.currentValue();
secondFaceRot.angle = 90.0f * (1.0f - timeLine.currentValue());
firstFaceData.rotation.setAngle(-90.0f * timeLine.currentValue());
secondFaceData.rotation.setAngle(90.0f * (1.0f - timeLine.currentValue()));
point = rect.height() / 2 * tan(45.0f * M_PI / 180.0f);
break;
case Downwards:
firstFaceRot.axis = RotationData::XAxis;
secondFaceRot.axis = RotationData::XAxis;
firstFaceData.rotation.setAxis(Qt::XAxis);
secondFaceData.rotation.setAxis(Qt::XAxis);
secondDesktop = effects->desktopBelow(front_desktop, true);
firstFaceRot.angle = 90.0f * timeLine.currentValue();
secondFaceRot.angle = -90.0f * (1.0f - timeLine.currentValue());
firstFaceData.rotation.setAngle(90.0f * timeLine.currentValue());
secondFaceData.rotation.setAngle(-90.0f * (1.0f - timeLine.currentValue()));
point = rect.height() / 2 * tan(45.0f * M_PI / 180.0f);
break;
default:
@ -170,10 +168,7 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData&
return;
}
// front desktop
firstFaceRot.xRotationPoint = rect.width() / 2;
firstFaceRot.yRotationPoint = rect.height() / 2;
firstFaceRot.zRotationPoint = -point;
firstFaceData.rotation = &firstFaceRot;
firstFaceData.rotation.setOrigin(QVector3D(rect.width() / 2, rect.height() / 2, -point));
other_desktop = secondDesktop;
firstDesktop = true;
effects->paintScreen(mask, region, firstFaceData);
@ -181,10 +176,7 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData&
other_desktop = painting_desktop;
painting_desktop = secondDesktop;
firstDesktop = false;
secondFaceRot.xRotationPoint = rect.width() / 2;
secondFaceRot.yRotationPoint = rect.height() / 2;
secondFaceRot.zRotationPoint = -point;
secondFaceData.rotation = &secondFaceRot;
secondFaceData.rotation.setOrigin(QVector3D(rect.width() / 2, rect.height() / 2, -point));
effects->paintScreen(mask, region, secondFaceData);
cube_painting = false;
painting_desktop = effects->currentDesktop();

View file

@ -289,14 +289,13 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
}
int winMask = PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_TRANSLUCENT;
RotationData rot;
rot.axis = RotationData::YAxis;
rot.angle = m_angle * m_startStopTimeLine.currentValue();
// fade in/out one window at the end of the stack during animation
if (m_animation && !m_scheduledDirections.isEmpty()) {
EffectWindow* w = m_flipOrderedWindows.last();
if (ItemInfo *info = m_windows.value(w,0)) {
WindowPaintData data(w);
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(m_angle * m_startStopTimeLine.currentValue());
data.opacity = info->opacity;
data.brightness = info->brightness;
data.saturation = info->saturation;
@ -317,7 +316,6 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
if (effects->numScreens() > 1) {
adjustWindowMultiScreen(w, data);
}
data.rotation = &rot;
effects->drawWindow(w, winMask, infiniteRegion(), data);
}
}
@ -327,6 +325,8 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
if (!info)
continue;
WindowPaintData data(w);
data.rotation.setAxis(Qt::YAxis);
data.rotation.setAngle(m_angle * m_startStopTimeLine.currentValue());
data.opacity = info->opacity;
data.brightness = info->brightness;
data.saturation = info->saturation;
@ -378,7 +378,6 @@ void FlipSwitchEffect::paintScreen(int mask, QRegion region, ScreenPaintData& da
adjustWindowMultiScreen(w, data);
}
data.rotation = &rot;
effects->drawWindow(w, winMask, infiniteRegion(), data);
}

View file

@ -98,10 +98,8 @@ void GlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowP
InfoHash::const_iterator info = windows.constFind(w);
if (info != windows.constEnd()) {
const double progress = info->timeLine->currentValue();
RotationData rot;
rot.axis = RotationData::XAxis;
rot.angle = angle * (1 - progress);
data.rotation = &rot;
data.rotation.setAxis(Qt::XAxis);
data.rotation.setAngle(angle * (1 - progress));
data.opacity *= progress;
switch(effect) {
default:

View file

@ -89,10 +89,9 @@ void SheetEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowP
InfoMap::const_iterator info = windows.constFind(w);
if (info != windows.constEnd()) {
const double progress = info->timeLine->currentValue();
RotationData rot;
rot.axis = RotationData::XAxis;
rot.angle = 60.0 * (1.0 - progress);
data.rotation = &rot;
QGraphicsRotation rot;
data.rotation.setAxis(Qt::XAxis);
data.rotation.setAngle(60.0 * (1.0 - progress));
data.yScale *= progress;
data.zScale *= progress;
data.yTranslate -= (w->y() - info->parentY) * (1.0 - progress);

View file

@ -463,10 +463,9 @@ void AnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
break;
}
case Rotation: {
RotationData rot;
rot.axis = (RotationData::RotationAxis)metaData(Axis, anim->meta);
data.rotation.setAxis((Qt::Axis)metaData(Axis, anim->meta));
const float prgrs = progress(*anim);
rot.angle = anim->from[0] + prgrs*(anim->to[0] - anim->from[0]);
data.rotation.setAngle(anim->from[0] + prgrs*(anim->to[0] - anim->from[0]));
const QRect geo = w->rect();
const uint sAnchor = metaData(SourceAnchor, anim->meta),
@ -477,10 +476,7 @@ void AnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
QPointF pt2(xCoord(geo, tAnchor), yCoord(geo, tAnchor));
pt += static_cast<qreal>(prgrs)*(pt2 - pt);
}
rot.xRotationPoint = pt.x();
rot.yRotationPoint = pt.y();
data.rotation = &rot;
data.rotation.setOrigin(QVector3D(pt));
break;
}
case Generic:

View file

@ -73,11 +73,31 @@ WindowPaintData::WindowPaintData(EffectWindow* w)
, saturation(1)
, brightness(1)
, shader(NULL)
, rotation(NULL)
{
quads = w->buildQuads();
}
WindowPaintData::WindowPaintData(const WindowPaintData &other)
: opacity(other.opacity)
, contents_opacity(other.contents_opacity)
, decoration_opacity(other.decoration_opacity)
, xScale(other.xScale)
, yScale(other.yScale)
, zScale(other.zScale)
, xTranslate(other.xTranslate)
, yTranslate(other.yTranslate)
, zTranslate(other.zTranslate)
, saturation(other.saturation)
, brightness(other.brightness)
, quads(other.quads)
, shader(other.shader)
{
rotation.setOrigin(other.rotation.origin());
rotation.setAxis(other.rotation.axis());
rotation.setAngle(other.rotation.angle());
}
ScreenPaintData::ScreenPaintData()
: xScale(1)
, yScale(1)
@ -85,17 +105,34 @@ ScreenPaintData::ScreenPaintData()
, xTranslate(0)
, yTranslate(0)
, zTranslate(0)
, rotation(NULL)
{
}
RotationData::RotationData()
: axis(ZAxis)
, angle(0.0)
, xRotationPoint(0.0)
, yRotationPoint(0.0)
, zRotationPoint(0.0)
ScreenPaintData::ScreenPaintData(const ScreenPaintData &other)
: xScale(other.xScale)
, yScale(other.yScale)
, zScale(other.zScale)
, xTranslate(other.xTranslate)
, yTranslate(other.yTranslate)
, zTranslate(other.zTranslate)
{
rotation.setOrigin(other.rotation.origin());
rotation.setAxis(other.rotation.axis());
rotation.setAngle(other.rotation.angle());
}
ScreenPaintData &ScreenPaintData::operator=(const ScreenPaintData &rhs)
{
this->xScale = rhs.xScale;
this->yScale = rhs.yScale;
this->zScale = rhs.zScale;
this->xTranslate = rhs.xTranslate;
this->yTranslate = rhs.yTranslate;
this->zTranslate = rhs.zTranslate;
this->rotation.setOrigin(rhs.rotation.origin());
this->rotation.setAxis(rhs.rotation.axis());
this->rotation.setAngle(rhs.rotation.angle());
return *this;
}
//****************************************

View file

@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QtCore/QPair>
#include <QtCore/QSet>
#include <QtCore/QRect>
#include <QtGui/QGraphicsRotation>
#include <QtGui/QRegion>
#include <QtCore/QVector>
@ -60,7 +61,6 @@ class Effect;
class WindowQuad;
class GLShader;
class XRenderPicture;
class RotationData;
class WindowQuadList;
class WindowPrePaintData;
class WindowPaintData;
@ -1652,6 +1652,7 @@ class KWIN_EXPORT WindowPaintData
{
public:
WindowPaintData(EffectWindow* w);
WindowPaintData(const WindowPaintData &other);
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
* Opacity for contents is opacity*contents_opacity, the same
@ -1686,20 +1687,22 @@ public:
* Shader to be used for rendering, if any.
*/
GLShader* shader;
RotationData* rotation;
QGraphicsRotation rotation;
};
class KWIN_EXPORT ScreenPaintData
{
public:
ScreenPaintData();
ScreenPaintData(const ScreenPaintData &other);
double xScale;
double yScale;
double zScale;
int xTranslate;
int yTranslate;
double zTranslate;
RotationData* rotation;
QGraphicsRotation rotation;
ScreenPaintData& operator=(const ScreenPaintData &rhs);
};
class KWIN_EXPORT ScreenPrePaintData
@ -1709,22 +1712,6 @@ public:
QRegion paint;
};
class KWIN_EXPORT RotationData
{
public:
RotationData();
enum RotationAxis {
XAxis,
YAxis,
ZAxis
};
RotationAxis axis;
float angle;
float xRotationPoint;
float yRotationPoint;
float zRotationPoint;
};
/**
* @short Helper class for restricting painting area only to allowed area.
*

View file

@ -136,23 +136,15 @@ QMatrix4x4 SceneOpenGL::transformation(int mask, const ScreenPaintData &data) co
matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
matrix.scale(data.xScale, data.yScale, data.zScale);
if (!data.rotation)
if (data.rotation.angle() == 0.0)
return matrix;
// Apply the rotation
const qreal xAxis = (data.rotation->axis == RotationData::XAxis ? 1.0 : 0.0);
const qreal yAxis = (data.rotation->axis == RotationData::YAxis ? 1.0 : 0.0);
const qreal zAxis = (data.rotation->axis == RotationData::ZAxis ? 1.0 : 0.0);
matrix.translate(data.rotation->xRotationPoint,
data.rotation->yRotationPoint,
data.rotation->zRotationPoint);
matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
matrix.translate(-data.rotation->xRotationPoint,
-data.rotation->yRotationPoint,
-data.rotation->zRotationPoint);
// cannot use data.rotation->applyTo(&matrix) as QGraphicsRotation uses projectedRotate to map back to 2D
matrix.translate(data.rotation.origin());
const QVector3D axis = data.rotation.axis();
matrix.rotate(data.rotation.angle(), axis.x(), axis.y(), axis.z());
matrix.translate(-data.rotation.origin());
return matrix;
}
@ -427,23 +419,15 @@ QMatrix4x4 SceneOpenGL::Window::transformation(int mask, const WindowPaintData &
matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
matrix.scale(data.xScale, data.yScale, data.zScale);
if (!data.rotation)
if (data.rotation.angle() == 0.0)
return matrix;
// Apply the rotation
const qreal xAxis = (data.rotation->axis == RotationData::XAxis ? 1.0 : 0.0);
const qreal yAxis = (data.rotation->axis == RotationData::YAxis ? 1.0 : 0.0);
const qreal zAxis = (data.rotation->axis == RotationData::ZAxis ? 1.0 : 0.0);
matrix.translate(data.rotation->xRotationPoint,
data.rotation->yRotationPoint,
data.rotation->zRotationPoint);
matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
matrix.translate(-data.rotation->xRotationPoint,
-data.rotation->yRotationPoint,
-data.rotation->zRotationPoint);
// cannot use data.rotation.applyTo(&matrix) as QGraphicsRotation uses projectedRotate to map back to 2D
matrix.translate(data.rotation.origin());
const QVector3D axis = data.rotation.axis();
matrix.rotate(data.rotation.angle(), axis.x(), axis.y(), axis.z());
matrix.translate(-data.rotation.origin());
return matrix;
}