summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <srodal@gmail.com>2008-11-29 20:07:06 +0100
committerSamuel Rødal <srodal@gmail.com>2008-11-29 20:07:06 +0100
commit406717252f90d1d8b318114c86ec87ad338265a6 (patch)
treeb8cb397c12db798297d8d44492f03d52801d1fc5
parent36253b8255967b683805d0808feef0bfcb747921 (diff)
Add simple Matrix4x4 class for more generic transformations.
-rw-r--r--matrix4x4.cpp141
-rw-r--r--matrix4x4.h30
-rw-r--r--mazescene.cpp49
-rw-r--r--qt3d.pro4
4 files changed, 202 insertions, 22 deletions
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 <qnamespace.h>
+#include <QTransform>
+
+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 <qmath.h>
#include <qdebug.h>
+#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