paella/src/Geometry/Mesh.cpp

223 lines
6.9 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// Paella
// Copyright (C) 2015 - Thomas FORGIONE, Emilie JALRAS, Marion LENFANT, Thierry MALON, Amandine PAILLOUX
// Authors :
// Thomas FORGIONE
// Emilie JALRAS
// Marion LENFANT
// Thierry MALON
// Amandine PAILLOUX
//
// This file is part of the project Paella
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <sstream>
#include <GL/gl.h>
#include <Geometry/Mesh.hpp>
namespace geo
{
Mesh& Mesh::operator+=(Mesh const& m)
{
for (unsigned int j=0;j<m.faces.size();j++)
{
faces.push_back(m.faces[j] + Vector3<unsigned int>{
static_cast<unsigned int>(vertices.size()),
static_cast<unsigned int>(vertices.size()),
static_cast<unsigned int>(vertices.size())});
}
for (unsigned int i =0;i<m.vertices.size();i++)
{
vertices.push_back(m.vertices[i]);
}
return *this;
}
std::ostream& operator<<(std::ostream& out, Mesh const& mesh)
{
for (auto const& v : mesh.vertices)
out << "v " << v.x() << " " << v.y() << " " << v.z() << "\n";
out << "\n";
for (auto const& f : mesh.faces)
out << "f " << f.x() << " " << f.y() << " " << f.z() << "\n";
return out << std::endl;
}
void Mesh::draw() const
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vector3<float>), &(glVertices[0].x()));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(Vector3<float>), &(glNormals[0].x()));
glColor3f(0,0,1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_BACK);
glDrawArrays(GL_TRIANGLES, 0, glVertices.size());
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_LIGHTING);
}
void Mesh::drawEdges() const
{
glColor3f(1,1,1);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vector3<float>), &(glVertices.at(0).x()));
glDrawArrays(GL_LINES, 0, glVertices.size());
glDisableClientState(GL_VERTEX_ARRAY);
}
void Mesh::prepare(bool gouraudShading)
{
glVertices.clear();
glNormals.clear();
// Generate the vertices for glDrawArrays();
for (auto const& f : faces)
{
glVertices.push_back(Vector3<float>{vertices[f.x()].x(), vertices[f.x()].y(), vertices[f.x()].z()});
glVertices.push_back(Vector3<float>{vertices[f.y()].x(), vertices[f.y()].y(), vertices[f.y()].z()});
glVertices.push_back(Vector3<float>{vertices[f.z()].x(), vertices[f.z()].y(), vertices[f.z()].z()});
// Compute the normal for the current face
auto normal = crossProduct(
glVertices[glVertices.size()-3] - glVertices[glVertices.size()-2],
glVertices[glVertices.size()-3] - glVertices[glVertices.size()-1]);
normal /= normal.norm();
normals.push_back(normal);
}
if (gouraudShading)
prepareGouraudShading();
else
prepareNormalShading();
}
void Mesh::prepareEdges()
{
glVertices.clear();
for (auto const& f : faces)
{
glVertices.push_back(Vector3<float>{vertices.at(f.x()).x(), vertices.at(f.x()).y(), vertices.at(f.x()).z()});
glVertices.push_back(Vector3<float>{vertices.at(f.y()).x(), vertices.at(f.y()).y(), vertices.at(f.y()).z()});
glVertices.push_back(Vector3<float>{vertices.at(f.x()).x(), vertices.at(f.x()).y(), vertices.at(f.x()).z()});
glVertices.push_back(Vector3<float>{vertices.at(f.z()).x(), vertices.at(f.z()).y(), vertices.at(f.z()).z()});
glVertices.push_back(Vector3<float>{vertices.at(f.y()).x(), vertices.at(f.y()).y(), vertices.at(f.y()).z()});
glVertices.push_back(Vector3<float>{vertices.at(f.z()).x(), vertices.at(f.z()).y(), vertices.at(f.z()).z()});
}
}
void Mesh::prepareGouraudShading()
{
// This vector registers the normal on each vertex
std::vector<Vector3<float>> tmpNormals;
for (unsigned int i = 0; i < vertices.size(); i++)
{
tmpNormals.push_back(Vector3<float>{0.0f,0.0f,0.0f});
}
// Compute the normal on each vertex as the sum of the normals
// of the faces in which this vertex appears
for (unsigned int i = 0; i < faces.size(); i++)
{
tmpNormals[faces[i].x()] += normals[i];
tmpNormals[faces[i].y()] += normals[i];
tmpNormals[faces[i].z()] += normals[i];
}
// Normalize the normals on each vertex
for (auto& n : tmpNormals)
{
n /= n.norm();
}
// Fill the glNormals wich the corresponding normal
for (unsigned int i = 0; i < faces.size(); i++)
{
glNormals.push_back(tmpNormals[faces[i].x()]);
glNormals.push_back(tmpNormals[faces[i].y()]);
glNormals.push_back(tmpNormals[faces[i].z()]);
}
}
void Mesh::prepareNormalShading()
{
for (unsigned int i = 0; i < faces.size(); i++)
{
glNormals.push_back(normals[i]);
glNormals.push_back(normals[i]);
glNormals.push_back(normals[i]);
}
}
Mesh splineMeshing(std::vector<Circle<float>> const& circles, unsigned int offset)
{
Mesh m;
unsigned int nbPointsPerCircle = circles[0].points.size();
for (unsigned int i = 0; i < circles.size(); i++)
{
auto circle = circles[i];
for (unsigned int j = 0; j < circle.points.size(); j++)
{
m.vertices.push_back(circle.points[j].second);
}
}
for (unsigned int i = 0; i < circles.size()-1; i++)
{
for (unsigned int j = 0; j < nbPointsPerCircle; j++)
{
unsigned int ip1 = i*nbPointsPerCircle + j;
unsigned int ip2 = i*nbPointsPerCircle + (j + 1)%nbPointsPerCircle;
unsigned int ip3 = (i + 1)*nbPointsPerCircle + (j + 1)%nbPointsPerCircle;
unsigned int ip4 = (i + 1)*nbPointsPerCircle + j;
m.faces.push_back(Vector3<unsigned int> {offset+ip1,offset+ip2,offset+ip3});
m.faces.push_back(Vector3<unsigned int> {offset+ip1,offset+ip3,offset+ip4});
}
}
return m;
}
} // namespace geo