From 406717252f90d1d8b318114c86ec87ad338265a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Sat, 29 Nov 2008 20:07:06 +0100 Subject: Add simple Matrix4x4 class for more generic transformations. --- matrix4x4.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ matrix4x4.h | 30 +++++++++++++ mazescene.cpp | 49 +++++++++++--------- qt3d.pro | 4 +- 4 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 matrix4x4.cpp create mode 100644 matrix4x4.h diff --git a/matrix4x4.cpp b/matrix4x4.cpp new file mode 100644 index 0000000..66ecb81 --- /dev/null +++ b/matrix4x4.cpp @@ -0,0 +1,141 @@ +#include "matrix4x4.h" + +Matrix4x4::Matrix4x4() +{ + qreal identity[] = + { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + + setData(identity); +} + +Matrix4x4::Matrix4x4(qreal *data) +{ + setData(data); +} + +void Matrix4x4::setData(qreal *data) +{ + for (int i = 0; i < 16; ++i) + m[i] = data[i]; +} + +Matrix4x4 &Matrix4x4::operator*=(const Matrix4x4 &rhs) +{ + const Matrix4x4 lhs = *this; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + m[4*i + j] = 0; + for (int k = 0; k < 4; ++k) + m[4*i + j] += lhs.m[4*i + k] * rhs.m[4*k + j]; + } + } + return *this; +} + +Matrix4x4 Matrix4x4::operator*(const Matrix4x4 &other) const +{ + return Matrix4x4(*this) *= other; +} + +Matrix4x4 Matrix4x4::fromRotation(qreal angle, Qt::Axis axis) +{ + QTransform rot; + rot.rotate(angle); + switch (axis) { + case Qt::XAxis: + { + qreal data[] = + { + 1, 0, 0, 0, + 0, rot.m11(), rot.m12(), 0, + 0, rot.m21(), rot.m22(), 0, + 0, 0, 0, 1 + }; + return Matrix4x4(data); + } + case Qt::YAxis: + { + qreal data[] = + { + rot.m11(), 0, rot.m12(), 0, + 0, 1, 0, 0, + rot.m21(), 0, rot.m22(), 0, + 0, 0, 0, 1 + }; + return Matrix4x4(data); + } + case Qt::ZAxis: + { + qreal data[] = + { + rot.m11(), rot.m12(), 0, 0, + rot.m21(), rot.m22(), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + return Matrix4x4(data); + } + default: + return Matrix4x4(); + } +} + +Matrix4x4 Matrix4x4::fromTranslation(qreal dx, qreal dy, qreal dz) +{ + qreal data[] = + { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + dx, dy, dz, 1 + }; + return Matrix4x4(data); +} + +Matrix4x4 Matrix4x4::fromScale(qreal sx, qreal sy, qreal sz) +{ + qreal data[] = + { + sx, 0, 0, 0, + 0, sy, 0, 0, + 0, 0, sz, 0, + 0, 0, 0, 1 + }; + return Matrix4x4(data); +} + +Matrix4x4 Matrix4x4::fromProjection(qreal fov) +{ + qreal data[] = + { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, fov, + 0, 0, 0, 0 + }; + return Matrix4x4(data); +} + +Matrix4x4 convert2dTo3d() +{ + qreal data[] = + { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 + }; + return Matrix4x4(data); +} + +QTransform Matrix4x4::toQTransform() const +{ + return QTransform(m[0], m[1], m[3], + m[4], m[5], m[7], + m[12], m[13], m[15]); +} diff --git a/matrix4x4.h b/matrix4x4.h new file mode 100644 index 0000000..588bb40 --- /dev/null +++ b/matrix4x4.h @@ -0,0 +1,30 @@ +#ifndef MATRIX4X4_H +#define MATRIX4X4_H + +#include +#include + +class Matrix4x4 +{ +public: + Matrix4x4(); + Matrix4x4(qreal *data); + + Matrix4x4 &operator*=(const Matrix4x4 &other); + Matrix4x4 operator*(const Matrix4x4 &other) const; + + static Matrix4x4 fromRotation(qreal angle, Qt::Axis axis); + static Matrix4x4 fromTranslation(qreal dx, qreal dy, qreal dz); + static Matrix4x4 fromScale(qreal sx, qreal sy, qreal sz); + static Matrix4x4 fromProjection(qreal fov); + static Matrix4x4 convert2dTo3d(); + + QTransform toQTransform() const; + + void setData(qreal *data); + +private: + qreal m[16]; +}; + +#endif diff --git a/mazescene.cpp b/mazescene.cpp index 26fce9d..9b6e1ac 100644 --- a/mazescene.cpp +++ b/mazescene.cpp @@ -14,6 +14,8 @@ #include #include +#include "matrix4x4.h" + #ifdef USE_PHONON #include "mediaplayer/mediaplayer.h" #endif @@ -162,9 +164,6 @@ void MazeScene::drawBackground(QPainter *painter, const QRectF &rect) painter->fillRect(QRectF(rect.topLeft(), QPointF(rect.right(), rect.center().y())), QColor(100, 120, 200)); painter->fillRect(QRectF(QPointF(rect.left(), rect.center().y()), rect.bottomRight()), QColor(127, 190, 100)); - QTransform rotation = rotatingTransform(m_cameraAngle); - rotation.translate(-m_cameraPos.x(), -m_cameraPos.y()); - static QImage floor = QImage("floor.png").convertToFormat(QImage::Format_RGB32); QBrush floorBrush(floor); @@ -176,21 +175,29 @@ void MazeScene::drawBackground(QPainter *painter, const QRectF &rect) floorBrush.setTransform(brushScale); ceilingBrush.setTransform(brushScale); - QTransform project; - const qreal fov = 0.5; - const qreal wallHeight = 0.5 + 0.04 * qSin(0.01 * m_walkTime) + 0.1; - const qreal ceilingHeight = -0.5 + 0.04 * qSin(0.01 * m_walkTime) + 0.1; const QRectF r(1, 1, m_width-2, m_height-2); + Matrix4x4 m; + m *= Matrix4x4::fromRotation(m_cameraAngle, Qt::YAxis); + m *= Matrix4x4::fromProjection(0.5); + + qreal heightOffset = 0.04 * qSin(0.01 * m_walkTime) + 0.1; + + Matrix4x4 floorMatrix = Matrix4x4::fromRotation(90, Qt::XAxis); + floorMatrix *= Matrix4x4::fromTranslation(-m_cameraPos.x(), heightOffset + 0.5, -m_cameraPos.y()); + floorMatrix *= m; + painter->save(); - project = QTransform(rotation.m11(), 0, fov * rotation.m12(), rotation.m21(), 0, fov * rotation.m22(), rotation.m31(), wallHeight, fov * rotation.m32()); - painter->setTransform(project, true); + painter->setTransform(floorMatrix.toQTransform(), true); painter->fillRect(r, floorBrush); painter->restore(); + Matrix4x4 ceilingMatrix = Matrix4x4::fromRotation(90, Qt::XAxis); + ceilingMatrix *= Matrix4x4::fromTranslation(-m_cameraPos.x(), heightOffset - 0.5, -m_cameraPos.y()); + ceilingMatrix *= m; + painter->save(); - project = QTransform(rotation.m11(), 0, fov * rotation.m12(), rotation.m21(), 0, fov * rotation.m22(), rotation.m31(), ceilingHeight, fov * rotation.m32()); - painter->setTransform(project, true); + painter->setTransform(ceilingMatrix.toQTransform(), true); painter->fillRect(r, ceilingBrush); painter->restore(); @@ -423,29 +430,31 @@ void ProjectedItem::setImage(const QImage &image) void ProjectedItem::updateTransform(const QPointF &cameraPos, qreal cameraAngle, qreal time) { - QTransform rotation = rotatingTransform(cameraAngle); - rotation.translate(-cameraPos.x(), -cameraPos.y()); + QTransform rotation; + rotation *= QTransform().translate(-cameraPos.x(), -cameraPos.y()); + rotation *= rotatingTransform(cameraAngle); QPointF ca = rotation.map(m_a); QPointF cb = rotation.map(m_b); + qreal zm = QLineF(QPointF(), (ca + cb) / 2).length(); if (ca.y() <= 0 && cb.y() <= 0) { setVisible(false); return; } - const qreal mx = ca.x() - cb.x(); - const qreal tx = 0.5 * (ca.x() + cb.x()); - const qreal mz = ca.y() - cb.y(); - const qreal tz = 0.5 * (ca.y() + cb.y()); const qreal fov = 0.5; + QPointF center = (m_a + m_b) / 2; - const QTransform project(mx, 0, mz * fov, 0, 1, 0, tx, 0.04 * qSin(10 * time) + 0.1, tz * fov); - const qreal zm = QLineF(QPointF(), (ca + cb) / 2).length(); + Matrix4x4 m; + m *= Matrix4x4::fromRotation(-QLineF(m_b, m_a).angle(), Qt::YAxis); + m *= Matrix4x4::fromTranslation(center.x() - cameraPos.x(), 0.04 * qSin(10 * time) + 0.1, center.y() - cameraPos.y()); + m *= Matrix4x4::fromRotation(cameraAngle, Qt::YAxis); + m *= Matrix4x4::fromProjection(fov); setVisible(true); setZValue(-zm); - setTransform(project); + setTransform(m.toQTransform()); } void MazeScene::keyPressEvent(QKeyEvent *event) diff --git a/qt3d.pro b/qt3d.pro index 7f408c1..974978d 100644 --- a/qt3d.pro +++ b/qt3d.pro @@ -29,5 +29,5 @@ DEPLOYMENT_PLUGIN += phonon_ds9 phonon_waveout } # Input -HEADERS += mazescene.h -SOURCES += main.cpp mazescene.cpp +HEADERS += mazescene.h matrix4x4.h +SOURCES += main.cpp mazescene.cpp matrix4x4.cpp -- cgit v1.2.3