223 lines
6.9 KiB
C++
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
|