1#ifndef MECACELL_3DOBJ_HPP
2#define MECACELL_3DOBJ_HPP
21 using UV = std::array<double, 2>;
53 std::pair<std::pair<size_t, double>, std::pair<size_t, double>> hits{
54 {0, std::numeric_limits<double>::max()},
55 {0, std::numeric_limits<double>::max()}};
62 for (
auto &f : obj.faces) {
63 auto raycast =
rayInTriangle(obj.vertices[f[Obj3D::TriangleData::V][0]],
64 obj.vertices[f[Obj3D::TriangleData::V][1]],
65 obj.vertices[f[Obj3D::TriangleData::V][2]], v,
69 auto sqdist = (v - raycast.second).sqlength();
70 if (sqdist < hits.first.second) {
71 hits.first.second = sqdist;
75 raycast =
rayInTriangle(obj.vertices[f[Obj3D::TriangleData::V][0]],
76 obj.vertices[f[Obj3D::TriangleData::V][1]],
77 obj.vertices[f[Obj3D::TriangleData::V][2]], v,
81 auto sqdist = (v - raycast.second).sqlength();
82 if (sqdist < hits.second.second) hits.second.second = sqdist;
86 if (hits.first.first % 2 == 1 && hits.second.first % 2 == 1) {
87 containers.
push_back(std::pair<std::string, double>(
88 o.first, hits.first.second + hits.second.second));
91 std::sort(containers.
begin(), containers.
end(),
92 [](
const auto &a,
const auto &b) { return a.second < b.second; });
94 for (
auto &c : containers) result.
push_back(c.first);
102 for (
size_t i = 0; i < to.
vertices.size(); ++i)
104 for (
size_t i = 0; i < to.
normals.size(); ++i)
131 void load(
const string &filepath) {
132 std::ifstream file(filepath);
133 if (!file.is_open()) {
134 throw std::runtime_error(
"Unable to open scene3D file");
138 Obj3D *currentObjPtr =
nullptr;
139 std::string currentObj =
"";
140 size_t currentObjVertexId = 0, currentObjUVId = 0, currentObjNormalId = 0;
141 while (std::getline(file, line)) {
147 currentObjVertexId += currentObjPtr->
vertices.size();
148 currentObjUVId += currentObjPtr->
uv.
size();
149 currentObjNormalId += currentObjPtr->
normals.size();
157 if (vs[0] ==
"v" && vs.
size() > 3) {
159 Vec(stod(vs[1]), stod(vs[2]), stod(vs[3])));
160 }
else if (vs[0] ==
"vt" && vs.
size() > 2) {
161 currentObjPtr->
uv.
push_back({{stod(vs[1]), stod(vs[2])}});
162 }
else if (vs[0] ==
"vn" && vs.
size() > 3) {
163 currentObjPtr->
normals.push_back(
164 Vec(stod(vs[1]), stod(vs[2]), stod(vs[3])));
165 }
else if (vs[0] ==
"f" &&
167 std::array<triangle_t, 3> face;
168 for (
size_t i = 1; i < vs.
size(); ++i) {
170 assert(index.
size() == 3);
171 auto vid = stoul(index[0]) - 1 - currentObjVertexId;
172 assert(vid < currentObjPtr->vertices.size() && vid >= 0);
173 face[Obj3D::TriangleData::V][i - 1] = vid;
174 if (!index[1].empty()) {
175 auto uvid = stoul(index[1]) - 1 - currentObjUVId;
176 assert(uvid < currentObjPtr->uv.size() && uvid >= 0);
177 face[Obj3D::TriangleData::VT][i - 1] = uvid;
179 auto nid = stoul(index[2]) - 1 - currentObjNormalId;
180 assert(nid < currentObjPtr->normals.size() && nid >= 0);
181 face[Obj3D::TriangleData::VN][i - 1] = stoul(index[2]) - 1;
general purpose 3D vector/point class.
A simple vector class template.
void push_back(const T &value)
Adds an element to the end of the vector.
iterator begin()
Returns an iterator to the first element.
iterator end()
Returns an iterator to the last element.
size_t size() const
Returns the number of elements in the vector.
this file contains various miscellanious utility functions & helpers *
std::pair< bool, Vec > rayInTriangle(const Vec &v0, const Vec &v1, const Vec &v2, const Vec &o, const Vec &r, const double tolerance=0)
test if a ray hits a triangle
Vector3D Vec
alias for Vector3D
std::vector< std::string > splitStr(const std::string &s, char delim)
String spliting.
void scale(const V &s)
Multiplies this matrix by another that scales coordinates by the components of the given vector.
void rotate(const R &r)
Multiplies this matrix by another that rotates coordinates by the according to the given rotation.
void translate(const V &v)
Multiplies this matrix by another that translates coordinates by the components of the given vector.
3D object representation: contains the vertices, UV coordinates, normals and faces
std::array< size_t, 3 > triangle_t
std::array< double, 2 > UV
std::vector< Vector3D > vertices
std::vector< std::array< triangle_t, 3 > > faces
std::vector< Vector3D > normals
Class allowing to load a 3D scene from an obj file. It contains one or several Obj3D as well as vario...
std::unordered_map< std::string, Obj3D > originalObjects
Obj3D::triangle_t triangle_t
std::vector< std::string > isInside(const Vector3D &v) const
usefull to test if a point v is inside an object of the scene
void updateFromTransformation()
Scene3D(const string &filename)
void translate(const Vec &t)
void rotate(const Rotation< Vec > &r)
void load(const string &filepath)
Loads an obj (wavefront) file.
std::unordered_map< std::string, Obj3D > transformedObjects