-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmesh.h
105 lines (94 loc) · 4.12 KB
/
mesh.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#ifndef RAY_TRACING_MESH_H
#define RAY_TRACING_MESH_H
#include <algorithm> // std::count()
#include <fstream> // std::ifstream, is_open(), close()
#include <sstream> // std::stringstream
#include <vector> // std::vector
#include <string> // std::string
#include <cstdlib> // exit()
#include "objects.h" // Object, Sphere, Triangle, MISS
#include "vector.h" // float3
struct Mesh : Object {
std::vector<Triangle> triangles;
Sphere boundingSphere;
Mesh(Material m, const std::string &path, float size, const float3 &position,
const float3 &rotate = float3(0.0f, 0.0f, 0.0f)) :
Object(std::move(m)), boundingSphere(m, position, size) {
std::vector<float3> vertices, faces;
obj_parser(path, vertices, faces);
float3 center(0.0f, 0.0f, 0.0f);
float3 minDist = vertices.front(), maxDist = vertices.front();
for (auto &vertex : vertices) {
center += vertex;
for (uint k = 0; k < 3; ++k) {
minDist[k] = std::fmin(minDist[k], vertex[k]);
maxDist[k] = std::fmax(maxDist[k], vertex[k]);
}
}
center /= vertices.size();
float scale = size / (maxDist - minDist).max();
for (auto &vertex : vertices) {
vertex = vertex.rotX(rotate.x).rotY(rotate.y).rotZ(rotate.z);
vertex = (vertex - center) * scale + position;
}
for (auto &face : faces) {
triangles.emplace_back(Triangle(m, vertices[face[0]], vertices[face[1]], vertices[face[2]]));
}
}
static void obj_parser(const std::string &path,
std::vector<float3> &vertices,
std::vector<float3> &faces) {
std::ifstream ifs(path);
if (!ifs.is_open()) {
std::cerr << "[Error]: can not open file: \"" << path << "\"" << std::endl;
exit(-1);
}
std::string buffer;
for (ifs >> buffer; !ifs.eof(); ifs >> buffer) {
if (buffer == "v") {
// template: v x y z
float x, y, z;
ifs >> x >> y >> z;
vertices.emplace_back(x, y, z);
} else if (buffer == "f") {
int x, y, z, t;
std::string line;
getline(ifs, line);
if (line.find('/') != std::string::npos &&
std::count(line.begin(), line.end(), '/') == 6) {
// template: f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
sscanf(line.c_str(), " %d/%d/%d %d/%d/%d %d/%d/%d\n", &x, &t, &t, &y, &t, &t, &z, &t, &t);
} else if (line.find('/') != std::string::npos &&
std::count(line.begin(), line.end(), '/') == 3) {
// template: f v1/vn1 v2/vn2 v3/vn3
sscanf(line.c_str(), " %d/%d %d/%d %d/%d\n", &x, &t, &y, &t, &z, &t);
} else if (line.find("//") != std::string::npos &&
std::count(line.begin(), line.end(), '/') == 6) {
// template: f v1//vn1 v2//vn2 v3//vn3
sscanf(line.c_str(), " %d//%d %d//%d %d//%d\n", &x, &t, &y, &t, &z, &t);
} else {
// template: f v1 v2 v3
sscanf(line.c_str(), " %d %d %d\n", &x, &y, &z);
}
faces.emplace_back(x - 1, y - 1, z - 1);
}
}
ifs.close();
}
bool is_ray_intersect(const Ray &ray, float &t, float3 &P, float3 &N, float3 &color) const override {
float3 tmpP, tmpN, tmpC;
if (boundingSphere.is_ray_intersect(ray, t, tmpP, tmpN, tmpC)) {
float curDist, closestDist = std::numeric_limits<float>::max();
for (const auto &triangle : triangles) {
if (triangle.is_ray_intersect(ray, curDist, tmpP, tmpN, tmpC) && curDist < closestDist) {
closestDist = curDist;
P = tmpP, N = tmpN, color = tmpC;
}
}
t = closestDist;
return t >= 0;
}
return MISS;
}
};
#endif // RAY_TRACING_MESH_H