#include "VEFViewer.h"
#include <QtDebug>
#include <cstdio>
VEFViewer::VEFViewer(QWidget* parent): QGLViewer(parent)
{
restoreStateFromFile();
}
void VEFViewer::init()
{
setBackgroundColor(QColor(0xAA, 0xAA, 0xAA));
// 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);
camera()->centerScene();
camera()->showEntireScene();
std::cout << "Min: " << min << std::endl;
std::cout << "Max: " << max << std::endl;
std::cout << "Center: " << center << std::endl;
}
// Draws a spiral
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(QString s)
{
FILE* file;
if ((file = fopen(s.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << s << " for reading";
return;
}
QFileInfo fi(s);
modelList->addItem(new QVerticesLWI(fi.baseName(), file, this));
fclose(file);
}
void VEFViewer::readEdgeFile(QString s)
{
FILE* file;
if ((file = fopen(s.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << s << " for reading";
return;
}
QFileInfo fi(s);
modelList->addItem(new QEdgesLWI(fi.baseName(), file, this));
fclose(file);
}
void VEFViewer::readSTLFile(QString s)
{
FILE* file;
if ((file = fopen(s.toLocal8Bit().data(), "r")) == NULL)
{
qDebug() << "Could not open file " << s << " for reading";
return;
}
QFileInfo fi(s);
modelList->addItem(new QFacesLWI(fi.baseName(), file, this));
fclose(file);
}
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;
}
// QVertices
void QVerticesLWI::draw() const
{
if (!isVisible()) return;
glColor3f(.5, .65, .65);
glCallList(display_list);
}
void QVerticesLWI::drawWithNames(int offset) const
{}
int QVerticesLWI::numElements() const
{ return 0; }
void QVerticesLWI::highlight(int selected)
{}
QVerticesLWI::QVerticesLWI(QString name, FILE* file, VEFViewer* v):
QDisplayListLWI(name)
{
display_list = glGenLists(1);
glNewList(display_list, GL_COMPILE);
glBegin(GL_POINTS);
float x,y,z;
int result = fscanf(file, "%f %f %f", &x, &y, &z);
while(result != EOF)
{
glVertex3f(x,y,z);
v->updateMinMax(x,y,z);
result = fscanf(file, "%f %f %f", &x, &y, &z);
}
glEnd();
glEndList();
}
/* QFaces */
void QFacesLWI::draw() const
{
if (!isVisible()) return;
// Draw selected
if (highlighted >= 0)
{
glColor3f(.9, .4, 0);
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
glColor3f(0., .4, .6);
if (!isWireframe())
glCallList(display_list);
else
glCallList(wireframe_display_list);
}
void QFacesLWI::drawWithNames(int offset) const
{
if (!isVisible()) 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;
}
QFacesLWI::QFacesLWI(QString name, FILE* file, VEFViewer* v):
QDisplayListLWI(name), highlighted(-1), isWireframe_(false)
{
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));
v->updateMinMax(x0,y0,z0);
v->updateMinMax(x1,y1,z1);
v->updateMinMax(x2,y2,z2);
result = readFacet(file, nx,ny,nz, x0,y0,z0, x1,y1,z1, x2,y2,z2);
}
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::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::draw() const
{
if (!isVisible()) return;
glColor3f(.6, .2, .6);
glCallList(display_list);
}
void QEdgesLWI::drawWithNames(int offset) const
{}
int QEdgesLWI::numElements() const
{ return 0; }
void QEdgesLWI::highlight(int selected)
{}
QEdgesLWI::QEdgesLWI(QString name, FILE* file, VEFViewer* v):
QDisplayListLWI(name)
{
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);
v->updateMinMax(x0,y0,z0);
v->updateMinMax(x1,y1,z1);
result = readEdge(file, x0,y0,z0, x1,y1,z1);
}
glEnd();
glEndList();
}
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;
}