Files
ViewDesignEngine/include/vde/foundation/io_obj.h
T

111 lines
3.2 KiB
C++
Raw Normal View History

#pragma once
#include <string>
#include <vector>
#include "vde/foundation/math_types.h"
namespace vde::foundation {
/**
* @brief OBJ 文件解析结果数据结构
*
* 存储从 Wavefront OBJ 文件读取的完整几何数据,
* 包括顶点位置、纹理坐标、法线、面信息和材质分组。
*
* 内部索引均为 0-based,与文件中的 1-based 索引不同。
*
* @ingroup foundation
*/
struct ObjMeshData {
/// 顶点位置数组
std::vector<Point3D> vertices;
/// 纹理坐标数组(可能为空)
2026-07-23 12:36:39 +00:00
std::vector<Point2D> texcoords;
/// 顶点法线数组(可能为空)
std::vector<Vector3D> normals;
2026-07-23 12:36:39 +00:00
/**
* @brief 每个面的顶点索引列表(0-based)
*
* 无论文件中面的格式如何(纯顶点、"v/vt"、"v/vt/vn"),
* 此字段始终被填充。faces[i] 存储第 i 个面的所有顶点索引。
*/
2026-07-23 12:36:39 +00:00
std::vector<std::vector<int>> faces;
/**
* @brief 每个面的纹理坐标索引列表(0-based)
*
* 与 faces 数组长度相同;若无纹理数据则为空。
*/
2026-07-23 12:36:39 +00:00
std::vector<std::vector<int>> face_texcoords;
/**
* @brief 每个面的法线索引列表(0-based)
*
* 与 faces 数组长度相同;若无法线数据则为空。
*/
2026-07-23 12:36:39 +00:00
std::vector<std::vector<int>> face_normals;
/**
* @brief 每个面对应的材质名称
*
* face_materials[i] 给出第 i 个面使用的材质名。
* 材质名来源于 usemtl 指令,在定义后所有后续面使用该材质。
*/
2026-07-23 12:36:39 +00:00
std::vector<std::string> face_materials;
/// 是否有纹理坐标数据
2026-07-23 12:36:39 +00:00
[[nodiscard]] bool has_texcoords() const { return !texcoords.empty(); }
};
/**
* @brief 读取 Wavefront OBJ 文件
*
* 解析 ASCII OBJ 文件,支持以下 OBJ 特性:
* - v(顶点)、vt(纹理坐标)、vn(法线)
* - f(面):支持三角面和任意多边形面
* - usemtl(材质名称)、g(组名)、o(对象名)
* - # 注释行
*
* @param filepath OBJ 文件路径
* @return 解析后的 ObjMeshData
*
* @throws std::runtime_error 若文件无法打开或格式错误
*
* @note 不解析 MTL 材质文件,仅记录 usemtl 指令中的材质名称
* @note 面索引在内部转换为 0-based;若文件中使用相对索引(负值),自动转换为正向
*
* @code{.cpp}
* auto data = read_obj("model.obj");
* std::cout << "Vertices: " << data.vertices.size() << "\n";
* std::cout << "Faces: " << data.faces.size() << "\n";
* @endcode
*
* @see write_obj, ObjMeshData
* @ingroup foundation
*/
ObjMeshData read_obj(const std::string& filepath);
/**
* @brief 写入 Wavefront OBJ 文件
*
* 将 ObjMeshData 以 ASCII OBJ 格式写出,包含顶点、纹理坐标、
* 法线和面信息。材质名称通过注释嵌入。
*
* @param filepath 输出文件路径
* @param data 要写出的网格数据
*
* @note 输出的面索引为 1-basedOBJ 标准)
*
* @code{.cpp}
* ObjMeshData data;
* // ... 填充 data ...
* write_obj("output.obj", data);
* @endcode
*
* @see read_obj
* @ingroup foundation
*/
void write_obj(const std::string& filepath, const ObjMeshData& data);
} // namespace vde::foundation