Changed the order of application initialization to avoid window popping up with -h option
#include "VEFViewer.h"
#include <QtDebug>
#include <cstdio>
#include "sphere.h"
VEFViewer::VEFViewer(QWidget* parent): QGLViewer(parent)
{
restoreStateFromFile();
}
void VEFViewer::init()
{
setBackgroundColor(QColor(0xAA, 0xAA, 0xAA));
setWheelBinding(Qt::AltModifier, CAMERA, MOVE_FORWARD);
// Lights
glEnable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glEnable(GL_LIGHT1);
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
//glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 120.0);
//glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 3.0);
// Basic settings
glShadeModel(GL_FLAT);
glEnable(GL_NORMALIZE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glPointSize(2.0);
}
void VEFViewer::addFile(QString s)
{
GLuint display_list;
QFileInfo fi(s);
QString ext = fi.suffix();
if (ext == "vrt")
readVertexFile(s);
else if (ext == "edg")
readEdgeFile(s);
else if (ext == "stl")
readSTLFile(s);
else
return;
setSceneBoundingBox(min, max);
setSceneCenter(center);
if (modelList->count() == 1)
{
camera()->centerScene();
camera()->showEntireScene();
}
std::cout << "Min: " << min << std::endl;
std::cout << "Max: " << max << std::endl;
std::cout << "Center: " << center << std::endl;
}
void VEFViewer::draw()
{
// GL_LIGHT0
const GLfloat light_pos0[4] = {center.x, center.y, center.z, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_pos0);
// GL_LIGHT1
qglviewer::Vec camera_pos = camera()->position();
qglviewer::Vec camera_dir = camera()->viewDirection();
const GLfloat light_pos1[4] = {camera_pos.x, camera_pos.y, camera_pos.z, 1.0};
const GLfloat light_spot_dir1[3] = {camera_dir.x, camera_dir.y, camera_dir.z};
glLightfv(GL_LIGHT1, GL_POSITION, light_pos1);
//glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_spot_dir1);
for (int i = 0; i < modelList->count(); i++)
{
QDisplayListLWI* dl = static_cast<QDisplayListLWI*>(modelList->item(i));
dl->draw();
}
//drawLight(GL_LIGHT0);
//drawLight(GL_LIGHT1);
}
void VEFViewer::drawWithNames()
{
int offset = 0;
for (int i = 0; i < modelList->count(); i++)
{
QDisplayListLWI* dl = static_cast<QDisplayListLWI*>(modelList->item(i));
dl->drawWithNames(offset);
offset += dl->numElements();
}
}
void VEFViewer::postSelection(const QPoint& point)
{
int i;
int selected = selectedName();
QDisplayListLWI* dl;
for (i = 0; i < modelList->count(); i++)
{
dl = static_cast<QDisplayListLWI*>(modelList->item(i));
if (selected < dl->numElements())
break;
selected -= dl->numElements();
}
dl->highlight(selected);
}
QString VEFViewer::helpString() const
{
QString text("<h2>VEFViewer</h2>");
text += "Displays vertices (vrt), edges (edg), and face (stl) files.";
return text;
}
void VEFViewer::listItemDoubleClicked(QListWidgetItem* item)
{
(static_cast<QDisplayListLWI*>(item))->toggleVisible();
updateGL();
}
void VEFViewer::customContextMenuRequested(const QPoint& pos)
{
QDisplayListLWI* dl = static_cast<QDisplayListLWI*>(modelList->itemAt(pos));
if (dl == 0) return;
QMenu m(this);
dl->setupMenu(m);
m.exec(modelList->mapToGlobal(pos) + QPoint(10,10));
updateGL();
}
void VEFViewer::setModelList(QListWidget* l)
{
modelList = l;
connect(modelList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
this, SLOT(listItemDoubleClicked(QListWidgetItem*)));
connect(modelList, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(customContextMenuRequested(const QPoint&)));
}
void VEFViewer::keyPressEvent(QKeyEvent* e)
{
const Qt::KeyboardModifiers modifiers = e->modifiers();
bool handled = false;
if ((e->key() == Qt::Key_O) && (modifiers == Qt::NoButton))
{
QString s = QFileDialog::getOpenFileName(this, "Choose file to open", ".", "3D data (*.vrt *.edg *.stl)");
if (!s.isNull())
addFile(s);
}
if (!handled)
QGLViewer::keyPressEvent(e);
}
void VEFViewer::readVertexFile(const QString& s)
{
modelList->addItem(new QVerticesLWI(s, this));
}
void VEFViewer::readEdgeFile(const QString& s)
{
modelList->addItem(new QEdgesLWI(s, this));
}
void VEFViewer::readSTLFile(const QString& s)
{
modelList->addItem(new QFacesLWI(s, this));
}
void VEFViewer::updateMinMax(float x, float y, float z)
{
if (x < min.x) min.x = x;
if (y < min.y) min.y = y;
if (z < min.z) min.z = z;
if (x > max.x) max.x = x;
if (y > max.y) max.y = y;
if (z > max.z) max.z = z;
updateWeightedCenter(x, y, z);
}
void VEFViewer::updateWeightedCenter(float x, float y, float z)
{
vertex_count++;
center.x = float(vertex_count - 1)/vertex_count * center.x + x/vertex_count;
center.y = float(vertex_count - 1)/vertex_count * center.y + y/vertex_count;
center.z = float(vertex_count - 1)/vertex_count * center.z + z/vertex_count;
}
// QDisplayListLWI
void QDisplayListLWI::draw() const
{
if (!isVisible()) return;
glColor3f(color_.redF(), color_.greenF(), color_.blueF());
glCallList(display_list_);
}
// QVertices
void QVerticesLWI::draw() const
{
if (!isVisible()) return;
glColor3f(color_.redF(), color_.greenF(), color_.blueF());
if (!isSphere())
glCallList(display_list_);
else
glCallList(sphere_display_list_);
}
void QVerticesLWI::drawWithNames(int offset) const
{}
int QVerticesLWI::numElements() const
{ return 0; }
void QVerticesLWI::highlight(int selected)
{}
QVerticesLWI::QVerticesLWI(QString fname, VEFViewer* v):
QDisplayListLWI(fname, QColor::fromRgbF(.5, .65, .65)), isSphere_(false), viewer_(v)
{
filename_ = fname;
QFileInfo fi(filename_);
setText(fi.baseName());
init();
}
void QVerticesLWI::init()
{
FILE* file;
if ((file = fopen(filename_.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << filename_ << " for reading";
return;
}
// Read in vertices
Point p;
int result = fscanf(file, "%f %f %f", &p.x, &p.y, &p.z);
while(result != EOF)
{
vertices_.push_back(p);
viewer_->updateMinMax(p.x,p.y,p.z);
result = fscanf(file, "%f %f %f", &p.x, &p.y, &p.z);
}
// Create display list of points
display_list_ = glGenLists(1);
glNewList(display_list_, GL_COMPILE);
glBegin(GL_POINTS);
for (VertexContainer::const_iterator cur = vertices_.begin(); cur != vertices_.end(); ++cur)
glVertex3f(cur->x,cur->y,cur->z);
glEnd();
glEndList();
// Create display list of spheres
sphere_display_list_ = glGenLists(1);
glNewList(sphere_display_list_, GL_COMPILE);
for (VertexContainer::const_iterator cur = vertices_.begin(); cur != vertices_.end(); ++cur)
{
XYZ c;
c.x = cur->x; c.y = cur->y; c.z = cur->z;
CreateSphere(c, .01, 6);
}
glEnd();
glEndList();
fclose(file);
}
void QVerticesLWI::destroy()
{
vertices_.clear();
glDeleteLists(sphere_display_list_, 1);
QDisplayListLWI::destroy();
}
/* QFaces */
void QFacesLWI::draw() const
{
if (!isVisible()) return;
// Draw selected
if (highlighted_ >= 0)
{
glColor3f(color_.light(200).redF(), color_.light(200).greenF(), color_.light(200).blueF());
glBegin(GL_TRIANGLES);
const Triangle& t = triangles_[highlighted_];
glNormal3f(t.nx, t.ny, t.nz);
glVertex3f(t.x0, t.y0, t.z0);
glVertex3f(t.x1, t.y1, t.z1);
glVertex3f(t.x2, t.y2, t.z2);
glEnd();
}
// Draw the object
if (!isWireframe())
{
glColor3f(color_.light(150).redF(), color_.light(150).greenF(), color_.light(150).blueF());
glCallList(display_list_);
}
else
{
glColor3f(color_.redF(), color_.greenF(), color_.blueF());
glCallList(wireframe_display_list_);
}
}
void QFacesLWI::drawWithNames(int offset) const
{
if (!isVisible()) return;
if (isWireframe()) return;
for (int i = 0; i < triangles_.size(); i++)
{
const Triangle& t = triangles_[i];
glPushName(offset + i);
glBegin(GL_TRIANGLES);
glVertex3f(t.x0, t.y0, t.z0);
glVertex3f(t.x1, t.y1, t.z1);
glVertex3f(t.x2, t.y2, t.z2);
glEnd();
glPopName();
}
}
int QFacesLWI::numElements() const
{ return triangles_.size(); }
void QFacesLWI::highlight(int selected)
{
highlighted_ = selected;
if (highlighted_ < 0) return;
const Triangle& t = triangles_[highlighted_];
std::cout << "Highlighted: (" << t.x0 << " " << t.y0 << " " << t.z0 << std::endl;
std::cout << " " << t.x1 << " " << t.y1 << " " << t.z1 << std::endl;
std::cout << " " << t.x2 << " " << t.y2 << " " << t.z2 << ")" << std::endl;
}
QFacesLWI::QFacesLWI(QString fname, VEFViewer* v):
QDisplayListLWI(fname, QColor::fromRgbF(0,.4,.6)), highlighted_(-1), isWireframe_(false), viewer_(v)
{
filename_ = fname;
QFileInfo fi(filename_);
setText(fi.baseName());
init();
}
void QFacesLWI::init()
{
FILE* file;
if ((file = fopen(filename_.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << filename_ << " for reading";
return;
}
float nx,ny,nz; // not used
float x0,y0,z0;
float x1,y1,z1;
float x2,y2,z2;
// Read in the vector of Triangles
int result = readFacet(file, nx,ny,nz, x0,y0,z0, x1,y1,z1, x2,y2,z2);
while(result != EOF)
{
qglviewer::Vec n = computeNormal(qglviewer::Vec(x0,y0,z0),
qglviewer::Vec(x1,y1,z1),
qglviewer::Vec(x2,y2,z2));
triangles_.push_back(Triangle(n.x,n.y,n.z, x0,y0,z0, x1,y1,z1, x2,y2,z2));
viewer_->updateMinMax(x0,y0,z0);
viewer_->updateMinMax(x1,y1,z1);
viewer_->updateMinMax(x2,y2,z2);
result = readFacet(file, nx,ny,nz, x0,y0,z0, x1,y1,z1, x2,y2,z2);
}
fclose(file);
std::cout << "Triangles read: " << triangles_.size() << std::endl;
// Create triangles display list
display_list_ = glGenLists(1);
glNewList(display_list_, GL_COMPILE);
drawTriangles(GL_TRIANGLES);
glEndList();
// Create wireframe display list
wireframe_display_list_ = glGenLists(1);
glNewList(wireframe_display_list_, GL_COMPILE);
drawTriangles(GL_LINE_LOOP);
glEndList();
}
void QFacesLWI::destroy()
{
triangles_.clear();
glDeleteLists(wireframe_display_list_, 1);
QDisplayListLWI::destroy();
}
void QFacesLWI::drawTriangles(GLenum mode) const
{
for (TrianglesContainer::const_iterator cur = triangles_.begin(); cur != triangles_.end(); ++cur)
{
glBegin(mode);
glNormal3f(cur->nx,cur->ny,cur->nz);
glVertex3f(cur->x0,cur->y0,cur->z0);
glVertex3f(cur->x1,cur->y1,cur->z1);
glVertex3f(cur->x2,cur->y2,cur->z2);
glEnd();
}
}
qglviewer::Vec QFacesLWI::computeNormal(qglviewer::Vec v0, qglviewer::Vec v1, qglviewer::Vec v2) const
{
qglviewer::Vec n = cross((v1 - v0), (v2 - v0));
return n;
}
int QFacesLWI::readFacet(FILE* file,
float& nx, float& ny, float& nz,
float& x0, float& y0, float& z0,
float& x1, float& y1, float& z1,
float& x2, float& y2, float& z2)
{
int result;
result = fscanf(file, "%*s %*s %f %f %f", &nx, &ny, &nz);
result = fscanf(file, "%*s %*s");
result = fscanf(file, "%*s %f %f %f", &x0, &y0, &z0);
result = fscanf(file, "%*s %f %f %f", &x1, &y1, &z1);
result = fscanf(file, "%*s %f %f %f", &x2, &y2, &z2);
result = fscanf(file, "%*s");
result = fscanf(file, "%*s");
return result;
}
/* QEdges */
void QEdgesLWI::drawWithNames(int offset) const
{}
int QEdgesLWI::numElements() const
{ return 0; }
void QEdgesLWI::highlight(int selected)
{}
QEdgesLWI::QEdgesLWI(QString fname, VEFViewer* v):
QDisplayListLWI(fname, QColor::fromRgbF(.6,.2,.6)), viewer_(v)
{
filename_ = fname;
QFileInfo fi(filename_);
setText(fi.baseName());
init();
}
void QEdgesLWI::init()
{
FILE* file;
if ((file = fopen(filename_.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << filename_ << " for reading";
return;
}
display_list_ = glGenLists(1);
glNewList(display_list_, GL_COMPILE);
glBegin(GL_LINES);
float nx,ny,nz;
float x0,y0,z0;
float x1,y1,z1;
int result = readEdge(file, x0,y0,z0, x1,y1,z1);
while(result != EOF)
{
glVertex3f(x0,y0,z0);
glVertex3f(x1,y1,z1);
viewer_->updateMinMax(x0,y0,z0);
viewer_->updateMinMax(x1,y1,z1);
result = readEdge(file, x0,y0,z0, x1,y1,z1);
}
glEnd();
glEndList();
fclose(file);
}
int QEdgesLWI::readEdge (FILE* file,
float& x0, float& y0, float& z0,
float& x1, float& y1, float& z1)
{
int result = fscanf(file, "%f %f %f", &x0, &y0, &z0);
result = fscanf(file, "%f %f %f", &x1, &y1, &z1);
return result;
}