feat: 测试覆盖扩展 + 文档更新
This commit is contained in:
+101
-10
@@ -10,29 +10,76 @@ ObjMeshData read_obj(const std::string& filepath) {
|
||||
if (!file) return data;
|
||||
|
||||
std::string line;
|
||||
std::string current_material;
|
||||
|
||||
while (std::getline(file, line)) {
|
||||
// Trim trailing \r
|
||||
if (!line.empty() && line.back() == '\r') line.pop_back();
|
||||
|
||||
if (line.empty() || line[0] == '#') continue;
|
||||
std::istringstream iss(line);
|
||||
std::string token;
|
||||
iss >> token;
|
||||
|
||||
if (token == "v") {
|
||||
double x, y, z;
|
||||
iss >> x >> y >> z;
|
||||
data.vertices.emplace_back(x, y, z);
|
||||
} else if (token == "vn") {
|
||||
}
|
||||
else if (token == "vt") {
|
||||
double u, v, w = 0.0;
|
||||
iss >> u >> v;
|
||||
if (iss >> w) { /* 1D/3D texcoord — keep only uv */ }
|
||||
data.texcoords.emplace_back(u, v);
|
||||
}
|
||||
else if (token == "vn") {
|
||||
double nx, ny, nz;
|
||||
iss >> nx >> ny >> nz;
|
||||
data.normals.emplace_back(nx, ny, nz);
|
||||
} else if (token == "f") {
|
||||
std::vector<int> face;
|
||||
}
|
||||
else if (token == "usemtl") {
|
||||
iss >> current_material;
|
||||
}
|
||||
else if (token == "f") {
|
||||
std::vector<int> face_v;
|
||||
std::vector<int> face_vt;
|
||||
std::vector<int> face_vn;
|
||||
|
||||
std::string vertex;
|
||||
while (iss >> vertex) {
|
||||
std::istringstream viss(vertex);
|
||||
std::string vi_str;
|
||||
std::getline(viss, vi_str, '/');
|
||||
face.push_back(std::stoi(vi_str) - 1);
|
||||
// Parse v/vt/vn, v//vn, v/vt formats
|
||||
int v_idx = -1;
|
||||
int vt_idx = -1;
|
||||
int vn_idx = -1;
|
||||
|
||||
// Count slashes
|
||||
size_t slash1 = vertex.find('/');
|
||||
if (slash1 == std::string::npos) {
|
||||
// "v" only
|
||||
v_idx = std::stoi(vertex) - 1;
|
||||
} else {
|
||||
v_idx = std::stoi(vertex.substr(0, slash1)) - 1;
|
||||
size_t slash2 = vertex.find('/', slash1 + 1);
|
||||
if (slash2 == std::string::npos) {
|
||||
// "v/vt"
|
||||
vt_idx = std::stoi(vertex.substr(slash1 + 1)) - 1;
|
||||
} else {
|
||||
// "v/vt/vn" or "v//vn"
|
||||
std::string mid = vertex.substr(slash1 + 1, slash2 - slash1 - 1);
|
||||
if (!mid.empty()) vt_idx = std::stoi(mid) - 1;
|
||||
vn_idx = std::stoi(vertex.substr(slash2 + 1)) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
face_v.push_back(v_idx);
|
||||
face_vt.push_back(vt_idx);
|
||||
face_vn.push_back(vn_idx);
|
||||
}
|
||||
data.faces.push_back(std::move(face));
|
||||
|
||||
data.faces.push_back(std::move(face_v));
|
||||
data.face_texcoords.push_back(std::move(face_vt));
|
||||
data.face_normals.push_back(std::move(face_vn));
|
||||
data.face_materials.push_back(current_material);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
@@ -40,13 +87,57 @@ ObjMeshData read_obj(const std::string& filepath) {
|
||||
|
||||
void write_obj(const std::string& filepath, const ObjMeshData& data) {
|
||||
std::ofstream file(filepath);
|
||||
if (!file) return;
|
||||
|
||||
file.precision(12);
|
||||
|
||||
// Vertices
|
||||
for (const auto& v : data.vertices)
|
||||
file << "v " << v.x() << " " << v.y() << " " << v.z() << "\n";
|
||||
|
||||
// Texture coordinates
|
||||
for (const auto& vt : data.texcoords)
|
||||
file << "vt " << vt.x() << " " << vt.y() << "\n";
|
||||
|
||||
// Normals
|
||||
bool has_vt = data.has_texcoords();
|
||||
bool has_vn = !data.normals.empty();
|
||||
|
||||
for (const auto& n : data.normals)
|
||||
file << "vn " << n.x() << " " << n.y() << " " << n.z() << "\n";
|
||||
for (const auto& f : data.faces) {
|
||||
|
||||
// Faces with material tracking
|
||||
std::string current_mtl;
|
||||
for (size_t fi = 0; fi < data.faces.size(); ++fi) {
|
||||
// Emit material change
|
||||
if (fi < data.face_materials.size() && data.face_materials[fi] != current_mtl) {
|
||||
current_mtl = data.face_materials[fi];
|
||||
if (!current_mtl.empty())
|
||||
file << "usemtl " << current_mtl << "\n";
|
||||
}
|
||||
|
||||
file << "f";
|
||||
for (int vi : f) file << " " << (vi + 1);
|
||||
const auto& fv = data.faces[fi];
|
||||
for (size_t vi = 0; vi < fv.size(); ++vi) {
|
||||
file << " " << (fv[vi] + 1); // 0-based → 1-based
|
||||
|
||||
bool wrote_slash = false;
|
||||
if (has_vt && fi < data.face_texcoords.size() && vi < data.face_texcoords[fi].size()) {
|
||||
int vt = data.face_texcoords[fi][vi];
|
||||
if (vt >= 0) {
|
||||
if (!wrote_slash) { file << "/"; wrote_slash = true; }
|
||||
file << (vt + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_vn && fi < data.face_normals.size() && vi < data.face_normals[fi].size()) {
|
||||
int vn = data.face_normals[fi][vi];
|
||||
if (vn >= 0) {
|
||||
if (!wrote_slash) file << "/";
|
||||
file << "/" << (vn + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
file << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user