Handle normals in meshes
This commit is contained in:
parent
2789acb5c5
commit
385a03ddbc
3 changed files with 79 additions and 2 deletions
49
Mesh.cpp
49
Mesh.cpp
|
@ -6,11 +6,22 @@ Mesh::Mesh()
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Mesh::add_vertice(const Point& pt) {
|
size_t Mesh::add_vertice(const Point& pt) {
|
||||||
vertices.push_back(pt);
|
return inner_add_vertice(pt, NormalVect());
|
||||||
return vertices.size() - 1;
|
}
|
||||||
|
|
||||||
|
size_t Mesh::add_vertice(const Point& pt, const Point& normal) {
|
||||||
|
return inner_add_vertice(pt, NormalVect(normal, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::add_face(const Face& face) {
|
void Mesh::add_face(const Face& face) {
|
||||||
|
for(int f_id=0; f_id < 3; ++f_id) {
|
||||||
|
if((unsigned)face[f_id] >= normals.size())
|
||||||
|
throw std::out_of_range("Vertice out of range for face");
|
||||||
|
if(!normals[face[f_id]].manual)
|
||||||
|
normals[face[f_id]].dirty = true;
|
||||||
|
|
||||||
|
faces_with_vert[face[f_id]].push_back(faces.size());
|
||||||
|
}
|
||||||
faces.push_back(face);
|
faces.push_back(face);
|
||||||
}
|
}
|
||||||
void Mesh::add_face(size_t f1, size_t f2, size_t f3) {
|
void Mesh::add_face(size_t f1, size_t f2, size_t f3) {
|
||||||
|
@ -50,3 +61,37 @@ const std::vector<Point>& Mesh::get_vertices() const {
|
||||||
const std::vector<Face>& Mesh::get_faces() const {
|
const std::vector<Face>& Mesh::get_faces() const {
|
||||||
return faces;
|
return faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Point& Mesh::get_normal(size_t vert_id) {
|
||||||
|
if(vert_id >= normals.size())
|
||||||
|
throw std::out_of_range("Normal out of range");
|
||||||
|
|
||||||
|
NormalVect& norm = normals[vert_id];
|
||||||
|
if(norm.dirty) {
|
||||||
|
compute_normal(vert_id);
|
||||||
|
norm.dirty = false;
|
||||||
|
}
|
||||||
|
return norm.vect;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Mesh::inner_add_vertice(const Point& pt, const Mesh::NormalVect& normal)
|
||||||
|
{
|
||||||
|
vertices.push_back(pt);
|
||||||
|
normals.push_back(normal);
|
||||||
|
faces_with_vert.push_back(std::vector<size_t>());
|
||||||
|
return vertices.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::compute_normal(size_t vert) {
|
||||||
|
Point normal(0., 0., 0.);
|
||||||
|
for(size_t f_id: faces_with_vert[vert]) {
|
||||||
|
const Face& face = faces[f_id];
|
||||||
|
Point e1 = vertices[face[1]] - vertices[face[0]],
|
||||||
|
e2 = vertices[face[2]] - vertices[face[0]];
|
||||||
|
normal += e1.cross_prod(e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
normal = (1. / ((double) faces_with_vert[vert].size())) * normal;
|
||||||
|
normals[vert].dirty = false;
|
||||||
|
normals[vert].vect = normal;
|
||||||
|
}
|
||||||
|
|
21
Mesh.hpp
21
Mesh.hpp
|
@ -15,6 +15,7 @@ class Mesh {
|
||||||
|
|
||||||
/// Adds a fresh vertice at `pt`, and returns its ID for further use
|
/// Adds a fresh vertice at `pt`, and returns its ID for further use
|
||||||
size_t add_vertice(const Point& pt);
|
size_t add_vertice(const Point& pt);
|
||||||
|
size_t add_vertice(const Point& pt, const Point& normal);
|
||||||
|
|
||||||
/// Creates a new face out of the three given point IDs
|
/// Creates a new face out of the three given point IDs
|
||||||
void add_face(const Face& face);
|
void add_face(const Face& face);
|
||||||
|
@ -31,15 +32,35 @@ class Mesh {
|
||||||
*/
|
*/
|
||||||
void normalize_center(bool keep_position=false);
|
void normalize_center(bool keep_position=false);
|
||||||
|
|
||||||
|
/// Get the normal vector for vertice `vert_id`
|
||||||
|
const Point& get_normal(size_t vert_id);
|
||||||
|
|
||||||
/// Gets the various vertices
|
/// Gets the various vertices
|
||||||
const std::vector<Point>& get_vertices() const;
|
const std::vector<Point>& get_vertices() const;
|
||||||
|
|
||||||
/// Gets the various faces
|
/// Gets the various faces
|
||||||
const std::vector<Face>& get_faces() const;
|
const std::vector<Face>& get_faces() const;
|
||||||
|
|
||||||
|
private: //struct
|
||||||
|
struct NormalVect {
|
||||||
|
NormalVect(const Point& vect, bool manual=false)
|
||||||
|
: vect(vect), dirty(false), manual(manual) {}
|
||||||
|
NormalVect()
|
||||||
|
: vect(Point(0., 0., 0.)), dirty(true), manual(false) {}
|
||||||
|
Point vect;
|
||||||
|
bool dirty;
|
||||||
|
bool manual;
|
||||||
|
};
|
||||||
|
|
||||||
|
private: //meth
|
||||||
|
size_t inner_add_vertice(const Point& pt, const NormalVect& normal);
|
||||||
|
void compute_normal(size_t vert);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Point> vertices;
|
std::vector<Point> vertices;
|
||||||
|
std::vector<NormalVect> normals;
|
||||||
std::vector<Face> faces;
|
std::vector<Face> faces;
|
||||||
|
std::vector<std::vector<size_t> > faces_with_vert;
|
||||||
|
|
||||||
Point center;
|
Point center;
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,6 +46,10 @@ struct Point {
|
||||||
return (*this += Point(-pt.x, -pt.y, -pt.z));
|
return (*this += Point(-pt.x, -pt.y, -pt.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point operator-(const Point& pt) const {
|
||||||
|
return (*this) + (-1 * pt);
|
||||||
|
}
|
||||||
|
|
||||||
friend Point operator*(double scalar, const Point& pt) {
|
friend Point operator*(double scalar, const Point& pt) {
|
||||||
return Point(
|
return Point(
|
||||||
scalar * pt.x,
|
scalar * pt.x,
|
||||||
|
@ -53,6 +57,13 @@ struct Point {
|
||||||
scalar * pt.z);
|
scalar * pt.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point cross_prod(const Point& pt) const {
|
||||||
|
return Point(
|
||||||
|
(*this)[1] * pt[2] - (*this)[2] * pt[1],
|
||||||
|
(*this)[2] * pt[0] - (*this)[0] * pt[2],
|
||||||
|
(*this)[0] * pt[1] - (*this)[1] * pt[0]);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator<(const Point& pt) const {
|
bool operator<(const Point& pt) const {
|
||||||
/// Lexicographic order on (x, y, z)
|
/// Lexicographic order on (x, y, z)
|
||||||
if(x == pt.x) {
|
if(x == pt.x) {
|
||||||
|
|
Loading…
Reference in a new issue