|
2 | 2 |
|
3 | 3 | #include <fstream> |
4 | 4 | #include <iostream> |
| 5 | +#include <sstream> |
5 | 6 | #include <string> |
6 | 7 | #include <vector> |
7 | 8 |
|
@@ -32,25 +33,85 @@ class Mesh { |
32 | 33 | std::ifstream file(filename, std::ios::binary); |
33 | 34 | if (file.is_open()) { |
34 | 35 | std::string line; |
35 | | - while (std::getline(file, line) && !file.eof()) { |
36 | | - if (line.find("v ") != std::string::npos) { |
37 | | - // Parse the vertex |
38 | | - Vector3D vertex; |
39 | | - if (sscanf(line.c_str(), "v %lf %lf %lf", &vertex.x, &vertex.y, &vertex.z) == 3) { addVertex(vertex); } |
40 | | - } else if (line.find("vt ") != std::string::npos) { |
| 36 | + while (std::getline(file, line)) { |
| 37 | + if (line.rfind("vt ", 0) == 0) { |
41 | 38 | // Parse the texture coordinate |
42 | 39 | Texture2D texture; |
43 | 40 | if (sscanf(line.c_str(), "vt %lf %lf", &texture.u, &texture.v) == 2) { addTexture(texture); } |
44 | | - } else if (line.find("f ") != std::string::npos) { |
45 | | - // Parse the face |
46 | | - int v1, v2, v3, t1, t2, t3, n1, n2, n3; |
47 | | - if (sscanf(line.c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &v1, &t1, &n1, &v2, &t2, &n2, &v3, &t3, &n3) == |
48 | | - 9) { |
49 | | - addFace(v1, v2, v3, textures[t1 - 1], textures[t2 - 1], textures[t3 - 1], WHITE); |
| 41 | + } else if (line.rfind("v ", 0) == 0) { |
| 42 | + // Parse the vertex |
| 43 | + Vector3D vertex; |
| 44 | + if (sscanf(line.c_str(), "v %lf %lf %lf", &vertex.x, &vertex.y, &vertex.z) == 3) { addVertex(vertex); } |
| 45 | + } else if (line.rfind("f ", 0) == 0) { |
| 46 | + std::stringstream ss(line.substr(2)); |
| 47 | + std::string token; |
| 48 | + std::vector<int> v_indices, t_indices, n_indices; |
| 49 | + |
| 50 | + while (ss >> token) { |
| 51 | + int v = 0, t = 0, n = 0; |
| 52 | + if (sscanf(token.c_str(), "%d/%d/%d", &v, &t, &n) == 3) { |
| 53 | + v_indices.push_back(v); |
| 54 | + t_indices.push_back(t); |
| 55 | + n_indices.push_back(n); |
| 56 | + } else if (sscanf(token.c_str(), "%d//%d", &v, &n) == 2) { |
| 57 | + v_indices.push_back(v); |
| 58 | + n_indices.push_back(n); |
| 59 | + } else if (sscanf(token.c_str(), "%d/%d", &v, &t) == 2) { |
| 60 | + v_indices.push_back(v); |
| 61 | + t_indices.push_back(t); |
| 62 | + } else if (sscanf(token.c_str(), "%d", &v) == 1) { |
| 63 | + v_indices.push_back(v); |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + // Triangulate polygon faces |
| 68 | + if (v_indices.size() >= 3) { |
| 69 | + for (size_t i = 1; i < v_indices.size() - 1; ++i) { |
| 70 | + Texture2D tex[3]; |
| 71 | + if (t_indices.size() == v_indices.size()) { |
| 72 | + auto get_abs_idx = [](int idx, size_t s) -> size_t { |
| 73 | + if (idx > 0) return idx - 1; |
| 74 | + if (idx < 0) return s + idx; |
| 75 | + return (size_t)-1; // Invalid index |
| 76 | + }; |
| 77 | + |
| 78 | + size_t t0 = get_abs_idx(t_indices[0], textures.size()); |
| 79 | + size_t ti = get_abs_idx(t_indices[i], textures.size()); |
| 80 | + size_t ti1 = get_abs_idx(t_indices[i + 1], textures.size()); |
| 81 | + |
| 82 | + if (t0 < textures.size() && ti < textures.size() && ti1 < textures.size()) { |
| 83 | + tex[0] = textures[t0]; |
| 84 | + tex[1] = textures[ti]; |
| 85 | + tex[2] = textures[ti1]; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + addFace(v_indices[0], v_indices[i], v_indices[i + 1], tex[0], tex[1], tex[2], WHITE); |
| 90 | + } |
50 | 91 | } |
51 | 92 | } |
52 | 93 | } |
53 | 94 | file.close(); |
| 95 | + |
| 96 | + // Center the mesh to its origin |
| 97 | + if (!vertices.empty()) { |
| 98 | + Vector3D center(0, 0, 0); |
| 99 | + for (const auto& v : vertices) { |
| 100 | + center.x += v.x; |
| 101 | + center.y += v.y; |
| 102 | + center.z += v.z; |
| 103 | + } |
| 104 | + center.x /= vertices.size(); |
| 105 | + center.y /= vertices.size(); |
| 106 | + center.z /= vertices.size(); |
| 107 | + |
| 108 | + for (auto& v : vertices) { |
| 109 | + v.x -= center.x; |
| 110 | + v.y -= center.y; |
| 111 | + v.z -= center.z; |
| 112 | + } |
| 113 | + } |
| 114 | + |
54 | 115 | return true; |
55 | 116 | } else { |
56 | 117 | std::cerr << "Failed to open mesh file: " << filename << std::endl; |
|
0 commit comments