summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2008-06-24 15:46:51 +0200
committerSamuel Rødal <sroedal@trolltech.com>2008-06-24 15:52:55 +0200
commita8a1a26bd2fd493fbce70c9a4d03bc31a5347b12 (patch)
tree907bf0470446f26e96d3eeff550562e0fab105d1
parent534a00df0b791111f2e87e84e30fbfed66c3f5e9 (diff)
Simplify rotation logic.
-rw-r--r--model.cpp6
-rw-r--r--openglscene.cpp104
-rw-r--r--openglscene.h13
-rw-r--r--point3d.h40
4 files changed, 63 insertions, 100 deletions
diff --git a/model.cpp b/model.cpp
index 5b5360f..09afbb5 100644
--- a/model.cpp
+++ b/model.cpp
@@ -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 &current)
-{
- 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 &current);
-
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
diff --git a/point3d.h b/point3d.h
index 5bf4212..b91b2c0 100644
--- a/point3d.h
+++ b/point3d.h
@@ -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];