diff options
Diffstat (limited to 'mazescene.cpp')
-rw-r--r-- | mazescene.cpp | 187 |
1 files changed, 151 insertions, 36 deletions
diff --git a/mazescene.cpp b/mazescene.cpp index 891f9b7..c99aec4 100644 --- a/mazescene.cpp +++ b/mazescene.cpp @@ -40,6 +40,8 @@ #include "entity.h" #include "modelitem.h" +#include <QVector3D> + #ifdef USE_PHONON #include "mediaplayer/mediaplayer.h" #endif @@ -48,11 +50,27 @@ #include <QGLWidget> #endif +View::View() + : m_scene(0) +{ +} + +void View::setScene(MazeScene *scene) +{ + QGraphicsView::setScene(scene); + + m_scene = scene; + m_scene->viewResized(this); +} + void View::resizeEvent(QResizeEvent *) { resetMatrix(); qreal factor = width() / 4.0; scale(factor, factor); + + if (m_scene) + m_scene->viewResized(this); } Light::Light(const QPointF &pos, qreal intensity) @@ -71,6 +89,96 @@ qreal Light::intensityAt(const QPointF &pos) const + linearIntensity / d; } +QMatrix4x4 fromRotation(float angle, Qt::Axis axis) +{ + QMatrix4x4 m; + if (axis == Qt::XAxis) + m.rotate(angle, QVector3D(1, 0, 0)); + else if (axis == Qt::YAxis) + m.rotate(-angle, QVector3D(0, 1, 0)); + else if (axis == Qt::ZAxis) + m.rotate(angle, QVector3D(0, 0, 1)); + return m; +} + +QMatrix4x4 fromProjection(float fovAngle) +{ + float fov = qCos(fovAngle / 2) / qSin(fovAngle / 2); + + float zNear = 0.01; + float zFar = 1000; + + float m33 = (zNear + zFar) / (zNear - zFar); + float m34 = (2 * zNear * zFar) / (zNear - zFar); + + qreal data[] = + { + fov, 0, 0, 0, + 0, fov, 0, 0, + 0, 0, m33, m34, + 0, 0, -1, 0 + }; + return QMatrix4x4(data); +} + +class WalkingItem : public QGraphicsPixmapItem +{ +public: + WalkingItem(MazeScene *scene); + + void mousePressEvent(QGraphicsSceneMouseEvent *event); + + bool walking() const { return m_walking; } + +private: + void updatePixmap(); + + MazeScene *m_scene; + bool m_walking; + + QPixmap m_walkingPixmap; + QPixmap m_standingPixmap; +}; + +QPixmap colorize(const QPixmap &source, const QColor &color) +{ + QImage temp(source.size(), QImage::Format_ARGB32_Premultiplied); + + temp.fill(0x0); + QPainter p(&temp); + p.drawPixmap(0, 0, source); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(temp.rect(), color); + p.end(); + + return QPixmap::fromImage(temp); +} + +WalkingItem::WalkingItem(MazeScene *scene) + : m_scene(scene) + , m_walking(false) + , m_walkingPixmap(colorize(QPixmap("walking.png"), QColor(Qt::green).darker())) + , m_standingPixmap(colorize(QPixmap("standing.png"), QColor(Qt::green).darker())) +{ + setShapeMode(BoundingRectShape); + updatePixmap(); +} + +void WalkingItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + event->accept(); + m_walking = !m_walking; + updatePixmap(); +} + +void WalkingItem::updatePixmap() +{ + if (m_walking) + setPixmap(m_standingPixmap); + else + setPixmap(m_walkingPixmap); +} + MazeScene::MazeScene(const QVector<Light> &lights, const char *map, int width, int height) : m_lights(lights) , m_walkingVelocity(0) @@ -138,6 +246,20 @@ MazeScene::MazeScene(const QVector<Light> &lights, const char *map, int width, i m_time.start(); updateTransforms(); updateRenderer(); + + m_walkingItem = new WalkingItem(this); + m_walkingItem->scale(0.008, 0.008); + m_walkingItem->setZValue(100000); + + addItem(m_walkingItem); +} + +void MazeScene::viewResized(QGraphicsView *view) +{ + QRectF bounds = m_walkingItem->sceneBoundingRect(); + QPointF bottomLeft = view->mapToScene(QPoint(5, view->height() - 5)); + + m_walkingItem->setPos(bottomLeft.x(), bottomLeft.y() - bounds.height()); } void MazeScene::addProjectedItem(ProjectedItem *item) @@ -230,13 +352,13 @@ void Camera::setTime(qreal time) } -const Matrix4x4 &Camera::viewMatrix() const +const QMatrix4x4 &Camera::viewMatrix() const { updateMatrix(); return m_viewMatrix; } -const Matrix4x4 &Camera::viewProjectionMatrix() const +const QMatrix4x4 &Camera::viewProjectionMatrix() const { updateMatrix(); return m_viewProjectionMatrix; @@ -249,13 +371,13 @@ void Camera::updateMatrix() const m_matrixDirty = false; - Matrix4x4 m; - m *= Matrix4x4::fromTranslation(-m_pos.x(), 0.04 * qSin(10 * m_time) + 0.1, -m_pos.y()); - m *= Matrix4x4::fromRotation(m_yaw + 180, Qt::YAxis); - m *= Matrix4x4::fromScale(-1, 1, 1); - m *= Matrix4x4::fromRotation(m_pitch, Qt::XAxis); + QMatrix4x4 m; + m = QMatrix4x4().translate(-m_pos.x(), 0.04 * qSin(10 * m_time) + 0.1, -m_pos.y()) * m; + m = fromRotation(m_yaw + 180, Qt::YAxis) * m; + m = QMatrix4x4().scale(-1, 1, 1) * m; + m = fromRotation(m_pitch, Qt::XAxis) * m; m_viewMatrix = m; - m *= Matrix4x4::fromProjection(m_fov); + m = fromProjection(m_fov) * m; m_viewProjectionMatrix = m; } @@ -274,23 +396,23 @@ void MazeScene::drawBackground(QPainter *painter, const QRectF &) const QRectF r(1, 1, m_width-2, m_height-2); - Matrix4x4 m = m_camera.viewProjectionMatrix(); + QMatrix4x4 m = m_camera.viewProjectionMatrix(); - Matrix4x4 floorMatrix = Matrix4x4::fromRotation(90, Qt::XAxis); - floorMatrix *= Matrix4x4::fromTranslation(0, 0.5, 0); - floorMatrix *= m; + QMatrix4x4 floorMatrix = fromRotation(90, Qt::XAxis); + floorMatrix = QMatrix4x4().translate(0, 0.5, 0) * floorMatrix; + floorMatrix = m * floorMatrix; painter->save(); - painter->setTransform(floorMatrix.toQTransform(), true); + painter->setTransform(floorMatrix.toTransform(0), true); painter->fillRect(r, floorBrush); painter->restore(); - Matrix4x4 ceilingMatrix = Matrix4x4::fromRotation(90, Qt::XAxis); - ceilingMatrix *= Matrix4x4::fromTranslation(0, -0.5, 0); - ceilingMatrix *= m; + QMatrix4x4 ceilingMatrix = fromRotation(90, Qt::XAxis); + ceilingMatrix = QMatrix4x4().translate(0, -0.5, 0) * ceilingMatrix; + ceilingMatrix = m * ceilingMatrix; painter->save(); - painter->setTransform(ceilingMatrix.toQTransform(), true); + painter->setTransform(ceilingMatrix.toTransform(0), true); painter->fillRect(r, ceilingBrush); painter->restore(); } @@ -326,16 +448,6 @@ void ProjectedItem::setLightingEnabled(bool enable) m_shadowItem->setVisible(enable); } -class ResizingView : public QGraphicsView -{ -protected: - void resizeEvent(QResizeEvent *event) { - if (scene()) - scene()->setSceneRect(QRect(QPoint(0, 0), event->size())); - QGraphicsView::resizeEvent(event); - } -}; - class ProxyWidget : public QGraphicsProxyWidget { public: @@ -443,7 +555,6 @@ WallItem::WallItem(MazeScene *scene, const QPointF &a, const QPointF &b, int typ QWebView *view = new QWebView; view->setUrl(QUrl(url)); - childWidget = view; } @@ -585,16 +696,16 @@ void ProjectedItem::updateTransform(const Camera &camera) return; } - Matrix4x4 m; - m *= Matrix4x4::fromRotation(-QLineF(m_b, m_a).angle(), Qt::YAxis); - m *= Matrix4x4::fromTranslation(center.x(), 0, center.y()); - m *= camera.viewProjectionMatrix(); + QMatrix4x4 m; + m = fromRotation(-QLineF(m_b, m_a).angle(), Qt::YAxis) * m; + m = QMatrix4x4().translate(center.x(), 0, center.y()) * m; + m = camera.viewProjectionMatrix() * m; qreal zm = QLineF(camera.pos(), center).length(); setVisible(true); setZValue(-zm); - setTransform(m.toQTransform()); + setTransform(m.toTransform(0)); } @@ -605,7 +716,7 @@ void MazeScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) return; } - if (event->buttons() & Qt::RightButton) { + if (event->buttons() & Qt::LeftButton) { QPointF delta(event->scenePos() - event->lastScenePos()); m_deltaYaw += delta.x() * 80; m_deltaPitch -= delta.y() * 80; @@ -780,13 +891,17 @@ void MazeScene::move() m_deltaPitch += m_pitchSpeed; } + qreal walkingVelocity = m_walkingVelocity; + if (m_walkingItem->walking()) + walkingVelocity = 0.005; + for (int i = 0; i < steps; ++i) { m_camera.setYaw(m_camera.yaw() + m_deltaYaw); m_camera.setPitch(m_camera.pitch() + m_deltaPitch); bool walking = false; - if (m_walkingVelocity != 0) { - QPointF walkingDelta = QLineF::fromPolar(m_walkingVelocity, m_camera.yaw() - 90).p2(); + if (walkingVelocity != 0) { + QPointF walkingDelta = QLineF::fromPolar(walkingVelocity, m_camera.yaw() - 90).p2(); QPointF pos = m_camera.pos(); if (tryMove(pos, walkingDelta)) { walking = true; |