summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2008-06-23 10:01:08 +0200
committerSamuel Rødal <sroedal@trolltech.com>2008-06-23 10:01:08 +0200
commit3984206b94c0cf6ddf332caf2a0679fe28e7f865 (patch)
treec32939358e2221986cb3d7b2ef628a54d2046de6
parent8b44c875279603745a02ac3b80f83806a4bfbfc6 (diff)
Added some more controls.
-rw-r--r--main.cpp100
-rw-r--r--model.cpp118
-rw-r--r--model.h13
3 files changed, 208 insertions, 23 deletions
diff --git a/main.cpp b/main.cpp
index 5110a1e..fd70298 100644
--- a/main.cpp
+++ b/main.cpp
@@ -17,10 +17,21 @@ public:
public slots:
void setModel(Model *model);
+ void enableAutoRotate(bool enabled);
void enableWireframe(bool enabled);
+ void enableNormals(bool enabled);
+ void setLightPosition(int pos);
+ void setColor(QRgb color);
private:
bool m_wireframeEnabled;
+ bool m_normalsEnabled;
+ bool m_autoRotate;
+
+ float m_angle;
+ float m_lightPos;
+
+ QRgb m_color;
Model *m_model;
};
@@ -35,19 +46,24 @@ public:
private slots:
void loadModel(const QString &model);
void modelLoaded();
+ void setColor(bool showDialog = true);
private:
GraphicsScene *m_scene;
QFutureWatcher<Model *> m_modelLoader;
QComboBox *m_models;
+ QRgb m_color;
};
Controls::Controls(GraphicsScene *scene)
: m_scene(scene)
, m_models(new QComboBox)
+ , m_color(qRgb(180, 100, 255))
{
QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(new QLabel("Model:"));
+
QDir dir("models");
dir.setNameFilters(QStringList() << "*.obj");
m_models->addItems(dir.entryList());
@@ -56,14 +72,35 @@ Controls::Controls(GraphicsScene *scene)
if (m_models->count() > 0)
loadModel(m_models->currentText());
-
layout->addWidget(m_models);
- QCheckBox *wireframe = new QCheckBox("Wireframe");
+ QCheckBox *autoRotate = new QCheckBox("Auto-rotate");
+ autoRotate->setChecked(true);
+ connect(autoRotate, SIGNAL(toggled(bool)), m_scene, SLOT(enableAutoRotate(bool)));
+ layout->addWidget(autoRotate);
+
+ QCheckBox *wireframe = new QCheckBox("Render as wireframe");
wireframe->setChecked(true);
connect(wireframe, SIGNAL(toggled(bool)), m_scene, SLOT(enableWireframe(bool)));
-
layout->addWidget(wireframe);
+
+ QCheckBox *normals = new QCheckBox("Display normals vectors");
+ wireframe->setChecked(false);
+ connect(normals, SIGNAL(toggled(bool)), m_scene, SLOT(enableNormals(bool)));
+ layout->addWidget(normals);
+
+ layout->addWidget(new QLabel("Light position:"));
+ QSlider *lightPosition = new QSlider(Qt::Horizontal);
+ lightPosition->setRange(-1000, 1000);
+ connect(lightPosition, SIGNAL(valueChanged(int)), m_scene, SLOT(setLightPosition(int)));
+ layout->addWidget(lightPosition);
+
+ m_scene->setLightPosition(lightPosition->value());
+
+ QPushButton *colorButton = new QPushButton("Set model color");
+ connect(colorButton, SIGNAL(pressed()), this, SLOT(setColor()));
+ layout->addWidget(colorButton);
+ setColor(false);
}
Model *loadModel(const QString &filename)
@@ -85,15 +122,26 @@ void Controls::modelLoaded()
QApplication::restoreOverrideCursor();
}
+void Controls::setColor(bool showDialog)
+{
+ if (showDialog)
+ m_color = QColorDialog::getRgba(m_color);
+
+ m_scene->setColor(m_color);
+}
+
GraphicsScene::GraphicsScene()
: m_wireframeEnabled(true)
+ , m_normalsEnabled(false)
+ , m_autoRotate(true)
+ , m_angle(0)
, m_model(0)
{
Controls *controls = new Controls(this);
controls->setWindowOpacity(0.8);
addWidget(controls)->translate(10, 10);
- setSceneRect(QRect(0, 0, 800, 600));
+ setSceneRect(QRect(0, 0, 1024, 768));
}
void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
@@ -101,7 +149,7 @@ void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
painter->save();
glClearColor(1, 1, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bool useMultisample = static_cast<QGLWidget *>(painter->device())->format().sampleBuffers();
@@ -109,21 +157,26 @@ void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
- glOrtho(-1, 1, 1, -1, -10, 10);
+ gluPerspective(70, painter->device()->width() / float(painter->device()->height()), 0.01, 1000);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
+ float pos[] = { m_lightPos, 5, 2, 0 };
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glColor4f(qRed(m_color)/255.0f, qGreen(m_color)/255.0f, qBlue(m_color)/255.0f, 1.0f);
+
if (useMultisample)
glEnable(GL_MULTISAMPLE);
- static float rot = 0;
- glRotatef(rot, 0, 1, 0);
- rot += 0.1;
+ glTranslatef(0, 0, -1.5);
+ glRotatef(m_angle, 0.5, 1, 0.1);
+
+ if (m_autoRotate)
+ m_angle += 0.4;
- glColor3f(0, 0, 0);
- m_model->render(m_wireframeEnabled);
+ m_model->render(m_wireframeEnabled, m_normalsEnabled);
if (useMultisample)
glDisable(GL_MULTISAMPLE);
@@ -136,7 +189,7 @@ void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
painter->restore();
- update();
+ QTimer::singleShot(20, this, SLOT(update()));
}
void GraphicsScene::setModel(Model *model)
@@ -146,11 +199,34 @@ void GraphicsScene::setModel(Model *model)
update();
}
+void GraphicsScene::enableAutoRotate(bool enabled)
+{
+ m_autoRotate = enabled;
+ update();
+}
+
void GraphicsScene::enableWireframe(bool enabled)
{
m_wireframeEnabled = enabled;
}
+void GraphicsScene::enableNormals(bool enabled)
+{
+ m_normalsEnabled = enabled;
+}
+
+void GraphicsScene::setLightPosition(int pos)
+{
+ m_lightPos = pos * 0.005;
+ update();
+}
+
+void GraphicsScene::setColor(QRgb color)
+{
+ m_color = color;
+ update();
+}
+
int main(int argc, char **argv)
{
QApplication app(argc, argv);
diff --git a/model.cpp b/model.cpp
index 20c91ba..54b5223 100644
--- a/model.cpp
+++ b/model.cpp
@@ -45,9 +45,6 @@ Model::Model(const QString &filename)
QVector<Point3d> pointData;
QVector<Point3d> normalData;
- QVector<int> pointIndices;
- QVector<int> normalIndices;
-
QTextStream in(&file);
while (!in.atEnd()) {
QString input = in.readLine();
@@ -63,6 +60,7 @@ Model::Model(const QString &filename)
Point3d p = readPoint(ts);
p.y = -p.y;
pointData << p;
+ normalData << Point3d();
min.x = qMin(min.x, p.x);
min.y = qMin(min.y, p.y);
@@ -91,13 +89,26 @@ Model::Model(const QString &filename)
}
for (int i = 0; i < 3; ++i)
- pointIndices << p[i];
+ m_pointIndices << p[i];
if (p.size() == 4)
for (int i = 0; i < 3; ++i)
- pointIndices << p[(i + 2) % 4];
+ m_pointIndices << p[(i + 2) % 4];
+ }
+ }
+
+#if 0
+ for (int i = 0; i < m_pointIndices.size(); ++i) {
+ Point3d p1 = pointData.at(m_pointIndices.at(i));
+ for (int j = 0; j < m_pointIndices.at(i); ++j) {
+ Point3d p2 = pointData.at(j);
+ if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z) {
+ m_pointIndices[i] = j;
+ break;
+ }
}
}
+#endif
Point3d bounds = max - min;
qreal scale = 1 / qMax(bounds.x, qMax(bounds.y, bounds.z));
@@ -114,22 +125,109 @@ Model::Model(const QString &filename)
p.z *= scale;
}
- for (int i = 0; i < pointIndices.size(); ++i)
- m_points << pointData.at(pointIndices.at(i));
+ QVector<int> counts(normalData.size());
+
+ for (int i = 0; i < counts.size(); ++i)
+ counts[i] = 0;
+
+ for (int i = 0; i < m_pointIndices.size(); i += 3) {
+ const Point3d a = pointData.at(m_pointIndices.at(i));
+ const Point3d b = pointData.at(m_pointIndices.at(i+1));
+ const Point3d c = pointData.at(m_pointIndices.at(i+2));
+
+ Point3d normal = cross(c - a, b - a).normalize();
+
+ for (int j = 0; j < 3; ++j) {
+ Point3d old = normalData.at(m_pointIndices.at(i + j));
+ normalData[m_pointIndices.at(i + j)] = old + normal;
+ ++counts[m_pointIndices.at(i + j)];
+ }
+ }
+
+ for (int i = 0; i < normalData.size(); ++i) {
+ float r = 1. / counts.at(i);
+ normalData[i] = normalData.at(i) * r;//.normalize();
+ }
+
+#if 0
+ Point3d normal;
+ for (int i = 0; i < m_pointIndices.size(); ++i) {
+#if 0
+ if ((i % 3) == 0) {
+ Point3d a = pointData.at(m_pointIndices.at(i));
+ Point3d b = pointData.at(m_pointIndices.at(i+1));
+ Point3d c = pointData.at(m_pointIndices.at(i+2));
+
+ normal = cross(c - a, b - a).normalize();
+
+ //float len = normal.x * normal.x +normal.y * normal.y +normal.z * normal.z;
+ }
+#endif
+
+ m_points << pointData.at(m_pointIndices.at(i));
+ m_normals << normalData.at(m_pointIndices.at(i)).normalize();
+
+#if 0
+ Point3d p = m_points.last();
+ Point3d n = m_normals.last();
+
+ printf("Index: %d, point: %f %f %f, normal: %f %f %f\n", m_pointIndices.at(i),
+ p.x, p.y, p.z,
+ n.x, n.y, n.z);
+#endif
+ }
+#endif
+
+ m_points = pointData;
+ m_normals = normalData;
foreach(const Edge &edge, QVector<Edge>::fromList(edges.toList()))
m_edges << pointData.at(edge.pointA) << pointData.at(edge.pointB);
}
-void Model::render(bool wireframe) const
+void Model::render(bool wireframe, bool normals) const
{
glEnableClientState(GL_VERTEX_ARRAY);
if (wireframe) {
+ glColor3f(0, 0, 0);
glVertexPointer(3, GL_FLOAT, 0, m_edges.data());
glDrawArrays(GL_LINES, 0, m_edges.size());
} else {
- glVertexPointer(3, GL_FLOAT, 0, m_points.data());
- glDrawArrays(GL_TRIANGLES, 0, m_points.size());
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_COLOR_MATERIAL);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ glVertexPointer(3, GL_FLOAT, 0, (float *)m_points.data());
+ glNormalPointer(GL_FLOAT, 0, (float *)m_normals.data());
+
+ glDrawElements(GL_TRIANGLES, m_pointIndices.size(), GL_UNSIGNED_INT, m_pointIndices.data());
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glDisable(GL_DEPTH_TEST);
+
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHT0);
+ glDisable(GL_LIGHTING);
}
glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (normals) {
+ glColor3f(1, 0, 0);
+ glBegin(GL_LINES);
+ for (int i = 0; i < m_normals.size(); ++i) {
+ Point3d a = m_points.at(i);
+ Point3d b = m_points.at(i) + m_normals.at(i) * 0.02;
+ glVertex3f(a.x, a.y, a.z);
+ glVertex3f(b.x, b.y, b.z);
+ }
+ glEnd();
+ }
}
+
diff --git a/model.h b/model.h
index cde14f8..3c95800 100644
--- a/model.h
+++ b/model.h
@@ -28,11 +28,21 @@ struct Point3d
return Point3d(x - p.x, y - p.y, z - p.z);
}
+ Point3d operator+(const Point3d &p) const
+ {
+ return Point3d(x + p.x, y + p.y, z + p.z);
+ }
+
Point3d normalize() const
{
float r = 1. / sqrt(x * x + y * y + z * z);
return Point3d(x * r, y * r, z * r);
}
+
+ Point3d operator*(float f) const
+ {
+ return Point3d(x * f, y * f, z * f);
+ }
};
inline float dot(const Point3d &a, const Point3d &b)
@@ -52,12 +62,13 @@ class Model
public:
Model(const QString &filename);
- void render(bool wireframe = false) const;
+ void render(bool wireframe = false, bool normals = false) const;
private:
QVector<Point3d> m_points;
QVector<Point3d> m_normals;
QVector<Point3d> m_edges;
+ QVector<int> m_pointIndices;
};
#endif