diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2008-06-24 15:46:51 +0200 |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2008-06-24 15:52:55 +0200 |
commit | a8a1a26bd2fd493fbce70c9a4d03bc31a5347b12 (patch) | |
tree | 907bf0470446f26e96d3eeff550562e0fab105d1 | |
parent | 534a00df0b791111f2e87e84e30fbfed66c3f5e9 (diff) |
Simplify rotation logic.
-rw-r--r-- | model.cpp | 6 | ||||
-rw-r--r-- | openglscene.cpp | 104 | ||||
-rw-r--r-- | openglscene.h | 13 | ||||
-rw-r--r-- | point3d.h | 40 |
4 files changed, 63 insertions, 100 deletions
@@ -95,10 +95,8 @@ Model::Model(const QString &filename) const Point3d normal = cross(b - a, c - a).normalize(); - for (int j = 0; j < 3; ++j) { - Point3d &n = m_normals[m_pointIndices.at(i + j)]; - n = n + normal; - } + for (int j = 0; j < 3; ++j) + m_normals[m_pointIndices.at(i + j)] += normal; } for (int i = 0; i < m_normals.size(); ++i) diff --git a/openglscene.cpp b/openglscene.cpp index 1c66d9d..8e10bf5 100644 --- a/openglscene.cpp +++ b/openglscene.cpp @@ -135,17 +135,11 @@ OpenGLScene::OpenGLScene() : m_wireframeEnabled(true) , m_normalsEnabled(false) , m_rotating(false) - , m_axis(0.0f, 1.0f, 0.0f) - , m_angle(20.0f) , m_distance(1.4f) , m_model(0) , m_lastTime(0) + , m_angularMomentum(0, 40, 0) { - // set identity matrix - for (int i = 0; i < 4; ++i) - for (int j = 0; j < 4; ++j) - m_matrix[i][j] = (i == j); - Controls *controls = new Controls(this); controls->setWindowOpacity(0.8); @@ -156,20 +150,6 @@ OpenGLScene::OpenGLScene() m_time.start(); } -void OpenGLScene::updateMatrix(qreal delta) -{ - if (!QGLContext::currentContext()) - return; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glRotatef(m_angle * delta, m_axis.x, m_axis.y, m_axis.z); - glMultMatrixf(&m_matrix[0][0]); - glGetFloatv(GL_MODELVIEW_MATRIX, &m_matrix[0][0]); - glPopMatrix(); -} - void OpenGLScene::drawBackground(QPainter *painter, const QRectF &) { if (painter->paintEngine()->type() != QPaintEngine::OpenGL) { @@ -188,20 +168,22 @@ void OpenGLScene::drawBackground(QPainter *painter, const QRectF &) glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); + float pos[] = { m_lightPos, 5, 2, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, pos); glColor4f(qRed(m_modelColor)/255.0f, qGreen(m_modelColor)/255.0f, qBlue(m_modelColor)/255.0f, 1.0f); - unsigned int current = m_time.elapsed(); - unsigned int delta = current - m_lastTime; - m_lastTime = current; - - if (!m_rotating) - updateMatrix(delta / 1000.0); + if (!m_rotating) { + const int delta = m_time.elapsed() - m_lastTime; + m_rotation += m_angularMomentum * (delta / 1000.0); + m_lastTime += delta; + } glLoadIdentity(); glTranslatef(0, 0, -m_distance); - glMultMatrixf(&m_matrix[0][0]); + glRotatef(m_rotation.x, 1, 0, 0); + glRotatef(m_rotation.y, 0, 1, 0); + glRotatef(m_rotation.z, 0, 0, 1); glEnable(GL_MULTISAMPLE); if (m_model) @@ -213,7 +195,7 @@ void OpenGLScene::drawBackground(QPainter *painter, const QRectF &) glMatrixMode(GL_PROJECTION); glPopMatrix(); - if (m_angle != 0) + if (!m_rotating) QTimer::singleShot(20, this, SLOT(update())); } @@ -252,56 +234,20 @@ void OpenGLScene::setBackgroundColor(QRgb color) update(); } -static Point3d spherical(const QPointF &point, qreal w, qreal h) -{ - qreal R = qMax(w, h); - - Point3d p; - p.x = -(point.x() - w / 2); - p.y = point.y() - h / 2; - p.z = sqrt(R * R - p.x * p.x - p.y * p.y); - - p.x /= R; - p.y /= R; - p.z /= R; - return p; -} - -void OpenGLScene::updateRotation(const QPointF &last, const QPointF ¤t) -{ - Point3d pos = spherical(current, width(), height()); - Point3d lastPos = spherical(last, width(), height()); - - m_axis.x = lastPos.y * pos.z - lastPos.z * pos.y; - m_axis.y = lastPos.z * pos.x - lastPos.x * pos.z; - m_axis.z = lastPos.x * pos.y - lastPos.y * pos.x; - - qreal length = sqrt(m_axis.x * m_axis.x + m_axis.y * m_axis.y + m_axis.z * m_axis.z); - - if (length == 0) { - m_angle = 0; - } else { - m_angle = -15 * asin(sqrt(length)); - - m_axis.x /= length; - m_axis.y /= length; - m_axis.z /= length; - - m_accumulated += m_angle; - - updateMatrix(); - update(); - } -} - void OpenGLScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseMoveEvent(event); if (event->isAccepted() || !m_rotating) return; - updateRotation(event->lastScenePos(), event->scenePos()); + const QPointF delta = event->scenePos() - event->lastScenePos(); + const Point3d angularImpulse = Point3d(delta.y(), delta.x(), 0) * 0.1; + + m_rotation += angularImpulse; + m_angularMomentum += angularImpulse; + event->accept(); + update(); } void OpenGLScene::mousePressEvent(QGraphicsSceneMouseEvent *event) @@ -310,11 +256,11 @@ void OpenGLScene::mousePressEvent(QGraphicsSceneMouseEvent *event) if (event->isAccepted()) return; - m_startTime = m_time.elapsed(); - m_accumulated = 0; + m_lastTime = m_time.elapsed(); + m_angularMomentum = Point3d(); + m_rotating = true; event->accept(); - m_rotating = true; } void OpenGLScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) @@ -323,11 +269,13 @@ void OpenGLScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) if (event->isAccepted()) return; - const unsigned int delta = m_time.elapsed() - m_startTime; - m_angle = delta ? m_accumulated / (delta / 1000.0) : 0; + const int delta = m_time.elapsed() - m_lastTime; + m_angularMomentum *= (1000.0 / qMax(1, delta)); + m_lastTime += delta; + m_rotating = false; event->accept(); - m_rotating = false; + update(); } void OpenGLScene::wheelEvent(QGraphicsSceneWheelEvent *event) diff --git a/openglscene.h b/openglscene.h index ef014d8..70f1c41 100644 --- a/openglscene.h +++ b/openglscene.h @@ -32,15 +32,10 @@ protected: void wheelEvent(QGraphicsSceneWheelEvent * wheelEvent); private: - void updateMatrix(qreal delta = 1); - void updateRotation(const QPointF &last, const QPointF ¤t); - bool m_wireframeEnabled; bool m_normalsEnabled; bool m_rotating; - Point3d m_axis; - float m_angle; float m_lightPos; float m_distance; @@ -50,12 +45,10 @@ private: Model *m_model; QTime m_time; - unsigned int m_lastTime; - unsigned int m_startTime; - - qreal m_accumulated; + int m_lastTime; - float m_matrix[4][4]; + Point3d m_rotation; + Point3d m_angularMomentum; }; #endif @@ -23,27 +23,51 @@ struct Point3d { } + Point3d operator+(const Point3d &p) const + { + return Point3d(*this) += p; + } + Point3d operator-(const Point3d &p) const { - return Point3d(x - p.x, y - p.y, z - p.z); + return Point3d(*this) -= p; } - Point3d operator+(const Point3d &p) const + Point3d operator*(float f) const { - return Point3d(x + p.x, y + p.y, z + p.z); + return Point3d(*this) *= f; } - Point3d normalize() const + + Point3d &operator+=(const Point3d &p) { - float r = 1. / sqrt(x * x + y * y + z * z); - return Point3d(x * r, y * r, z * r); + x += p.x; + y += p.y; + z += p.z; + return *this; } - Point3d operator*(float f) const + Point3d &operator-=(const Point3d &p) { - return Point3d(x * f, y * f, z * f); + x -= p.x; + y -= p.y; + z -= p.z; + return *this; } + Point3d &operator*=(float f) + { + x *= f; + y *= f; + z *= f; + return *this; + } + + Point3d normalize() const + { + float r = 1. / sqrt(x * x + y * y + z * z); + return Point3d(x * r, y * r, z * r); + } float &operator[](unsigned int index) { Q_ASSERT(index < 3); return (&x)[index]; |