https://github.com/ialhashim/topo-blend
Revision 39b13612ebd645a65eda854771b517371f2f858a authored by ennetws on 13 March 2015, 18:17:18 UTC, committed by ennetws on 13 March 2015, 18:17:18 UTC
1 parent c702819
Raw File
Tip revision: 39b13612ebd645a65eda854771b517371f2f858a authored by ennetws on 13 March 2015, 18:17:18 UTC
Create README.md
Tip revision: 39b1361
ShapeRenderer.cpp
#include <QTextStream>
#include <QEvent>

#include <SurfaceMeshHelper.h>
using namespace SurfaceMesh;

#include "GlSplat/GLee.h"
#include "ShapeRenderer.h"
#include "qglviewer/camera.h"

Q_DECLARE_METATYPE(qglviewer::Vec)

ShapeRenderer::ShapeRenderer(QString filename, QColor color, bool isFlatShading, int resolution) : color(color), isFlatShading(isFlatShading)
{
    int w = resolution, h = resolution;
    setMinimumSize(w,h);
    setMaximumSize(w,h);

	// Placement off-screen
	int x = -w * 1.2;
	int y = 0;
	this->setGeometry(x,y,w,h);

    QGLFormat f;
    f.setAlpha(true);
    f.setSampleBuffers(true);
    QGLFormat::setDefaultFormat(f);
    this->setFormat(f);

    // Read mesh file
	SurfaceMeshModel mesh;
	mesh.read(qPrintable(filename));
	mesh.update_face_normals();
	mesh.update_vertex_normals();

	if(mesh.n_vertices() < 1)
	{
		mesh.add_vertex(Vector3(0,0,0));
		mesh.add_vertex(Vector3(1,1,1));
		mesh.add_vertex(Vector3(-1,-1,-1));
	}

	mesh.updateBoundingBox();

	Vector3 bbmin = mesh.bbox().min(), bbmax = mesh.bbox().max();
	bmin = QVector3D(bbmin[0],bbmin[1],bbmin[2]);
	bmax = QVector3D(bbmax[0],bbmax[1],bbmax[2]);

	// Save into OpenGL friendly arrays
	Vector3VertexProperty m_points = mesh.vertex_coordinates(); 
	Vector3VertexProperty m_normals = mesh.vertex_normals();
	Vector3FaceProperty m_fnormals = mesh.face_normals();

	foreach(Vertex v, mesh.vertices()){
		Vector3 p = m_points[v];
		Vector3 n = m_normals[v];
		vertices.push_back(GLVertex(p[0],p[1],p[2], n[0],n[1],n[2]));
	}

	foreach(Face f, mesh.faces()){
		foreach(Vertex v, mesh.vertices(f))
			indices.push_back(v.idx());
	}
}

void ShapeRenderer::initializeGL()
{
	// Setup lights and material
	GLfloat ambientLightColor[] = {0.2f,0.2f,0.2f,1};
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightColor);

	GLfloat diffuseLightColor[] = {0.9f,0.9f,0.9f,1};
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLightColor);

	GLfloat specularLightColor[] = {0.95f,0.95f,0.95f,1};
	glLightfv(GL_LIGHT0, GL_SPECULAR, specularLightColor);

	float posLight0[] = { 3, 3, 3, 0 };
	glLightfv(GL_LIGHT0, GL_POSITION, posLight0);

	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);

	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	// Specular lighting
	float specReflection[] = { 0.8f, 0.8f, 0.8f, 1.0f };
	glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection);
	glMateriali(GL_FRONT, GL_SHININESS, 56);
}

void ShapeRenderer::setupCamera()
{
	qglviewer::Camera * sceneCamera = new qglviewer::Camera;

	int w = width(), h = height();
	glViewport( 0, 0, w, h );
	sceneCamera->setScreenWidthAndHeight(w,h);

	qglviewer::Vec cameraDelta = this->property("cameraDelta").value<qglviewer::Vec>();

	sceneCamera->setSceneRadius( 10 );
	sceneCamera->showEntireScene();
	sceneCamera->setUpVector(qglviewer::Vec(0,0,1));
	sceneCamera->setPosition(qglviewer::Vec(-2,-2,1.5) + ((cameraDelta.norm() != 0.0) ? cameraDelta.unit() : qglviewer::Vec(0,0,0)) );
	sceneCamera->lookAt(qglviewer::Vec(0,0,0));
	sceneCamera->setType(qglviewer::Camera::PERSPECTIVE);

	bool isFitToMesh = true;
	if( isFitToMesh )
	{
		qglviewer::Vec viewDir = sceneCamera->viewDirection();
		Eigen::AlignedBox3d bbox(Vector3(bmin.x(),bmin.y(),bmin.z()),Vector3(bmax.x(),bmax.y(),bmax.z()));
		double distance = bbox.diagonal().size() * 1.4;

		double n = cameraDelta.norm();
		if(n > 0.5) distance *= n;

		Vector3 center = bbox.center();
		Vector3 newPos = center - (distance * Vector3(viewDir[0], viewDir[1], viewDir[2]));

		sceneCamera->setRevolveAroundPoint( qglviewer::Vec(center) );
		qglviewer::Vec new_pos(newPos);
		sceneCamera->frame()->setPositionWithConstraint( new_pos );
	}

	sceneCamera->loadProjectionMatrix();
	sceneCamera->loadModelViewMatrix();
}

void ShapeRenderer::paintGL()
{
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	setupCamera();
	
	bool isTestScene = false;
	if(!indices.size()) isTestScene = true;
		
	if( isTestScene )
	{
		glClearColor(0, 0, 0, 1);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		// Draw a white grid "floor" for the tetrahedron to sit on.
		glColor3f(1.0, 1.0, 1.0);
		glBegin(GL_LINES);
		for (GLfloat i = -2.5; i <= 2.5; i += 0.25) {
			glVertex3f(i, 2.5, 0); glVertex3f(i, -2.5, 0);
			glVertex3f(2.5, i, 0); glVertex3f(-2.5, i, 0);
		}
		glEnd();

		// Draw the tetrahedron.
		glBegin(GL_TRIANGLE_STRIP);
		glColor3f(1, 1, 1); glVertex3f(0, 0, 2);
		glColor3f(1, 0, 0); glVertex3f(-1, 1, 0);
		glColor3f(0, 1, 0); glVertex3f(1, 1, 0);
		glColor3f(0, 0, 1); glVertex3f(0, -1.4f, 0);
		glColor3f(1, 1, 1); glVertex3f(0, 0, 2);
		glColor3f(1, 0, 0); glVertex3f(-1, 1, 0);
		glEnd();
	}

	if(!vertices.size() || !indices.size()) return;

	// Lighting and color
	glEnable( GL_LIGHTING );
	qglColor( color );

	// Draw mesh
	if( isFlatShading )
	{
		glBegin(GL_TRIANGLES);
		for(int f = 0; f < (int)indices.size() / 3; f++)
		{
			std::vector<GLVertex> pnts;
			for(int i = 0; i < 3; i++)	pnts.push_back( vertices[ indices[(f*3) + i] ] );

			Vector3 v0(pnts[0].x, pnts[0].y, pnts[0].z);
			Vector3 v1(pnts[1].x, pnts[1].y, pnts[1].z);
			Vector3 v2(pnts[2].x, pnts[2].y, pnts[2].z);

			Vector3 fn = cross(Vector3(v1-v0),Vector3(v2-v0)).normalized();

			glNormal3f( fn[0], fn[1], fn[2] );
			glVertex3f(pnts[0].x, pnts[0].y, pnts[0].z);
			glVertex3f(pnts[1].x, pnts[1].y, pnts[1].z);
			glVertex3f(pnts[2].x, pnts[2].y, pnts[2].z);
		}
		glEnd();
	}
	else
	{
		GLuint vertexbuffer;
		GLuint elementbuffer;
		{
			// Upload geometry to hardware
			glGenBuffers(1, &vertexbuffer);
			glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
			glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * vertices.size(), &vertices[0].x, GL_STATIC_DRAW);

			glGenBuffers(1, &elementbuffer);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &indices[0], GL_STATIC_DRAW);
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_NORMAL_ARRAY);

		// Bind vertices data
		glBindBuffer( GL_ARRAY_BUFFER, vertexbuffer );
		glVertexPointer(3, GL_FLOAT, sizeof(GLVertex), (void*)offsetof(GLVertex, x));
		glNormalPointer(GL_FLOAT, sizeof(GLVertex), (void*)offsetof(GLVertex, nx));

		// Bind triangles data then draw
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
		glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
	}
}

QPixmap ShapeRenderer::render( QString filename, bool isFlatShading, GLVertex cameraDelta )
{
   ShapeRenderer * renderer = new ShapeRenderer(filename, QColor(203, 127, 92), isFlatShading, 512);

   QVariant camDelta;
   camDelta.setValue(qglviewer::Vec(cameraDelta.x,cameraDelta.y,cameraDelta.z));
   renderer->setProperty("cameraDelta", camDelta);

   renderer->show();
   renderer->updateGL();
   QPixmap img = QPixmap::fromImage( renderer->grabFrameBuffer(true) );
   renderer->deleteLater();
   return img;
}
back to top