如何在Rust中解析OBJ文件的指定面行并转换为Vec4?
在Rust中解析OBJ文件的面(f)行
实现思路
针对你给出的OBJ面行格式(每个顶点为数字//数字,且同面的第二个数字一致),解析步骤如下:
- 筛选出以
f开头的行,去除首尾空白 - 拆分出行内的顶点片段,跳过开头的
f标识 - 对每个顶点片段按
//拆分,提取前后两个数字 - 验证同面所有顶点的第二个数字(即w分量)一致,取前三个顶点的第一个数字作为x、y、z分量,构造
Vec4
代码示例
首先定义你的Vec4结构体:
#[derive(Debug)] struct Vec4 { x: u32, y: u32, z: u32, w: u32, } impl Vec4 { fn new(x: u32, y: u32, z: u32, w: u32) -> Self { Vec4 { x, y, z, w } } }
然后实现核心解析函数:
fn parse_face_line(line: &str) -> Option<Vec4> { let trimmed_line = line.trim(); // 跳过非面行 if !trimmed_line.starts_with("f ") { return None; } // 拆分顶点部分,跳过第一个"f" let vertex_parts: Vec<&str> = trimmed_line.split_whitespace().skip(1).collect(); // 仅处理三角形面(示例均为3顶点) if vertex_parts.len() != 3 { return None; } let mut vertex_values = Vec::with_capacity(3); let mut target_w = None; for part in vertex_parts { // 按//拆分顶点的两个数值 let nums = part.split("//").collect::<Vec<_>>(); if nums.len() != 2 { return None; } // 解析数值为u32,失败则返回None let v = nums[0].parse::<u32>().ok()?; let current_w = nums[1].parse::<u32>().ok()?; // 校验同面所有w值一致 if let Some(w_val) = target_w { if current_w != w_val { return None; } } else { target_w = Some(current_w); } vertex_values.push(v); } // 构造Vec4 target_w.map(|w| Vec4::new(vertex_values[0], vertex_values[1], vertex_values[2], w)) }
测试代码
可以用你给出的面行测试解析效果:
fn main() { let face_lines = [ " f 3//2 8//2 4//2", " f 7//3 6//3 8//3", " f 2//4 8//4 6//4", " f 1//5 4//5 2//5", " f 5//6 2//6 6//6", ]; for line in face_lines { match parse_face_line(line) { Some(vec4) => println!("解析结果: {:?}", vec4), None => println!("无效面行: {}", line), } } }
运行后会输出每个面对应的Vec4实例,比如第一行的结果是Vec4 { x: 3, y: 8, z: 4, w: 2 },完全符合你的需求。
内容的提问来源于stack exchange,提问作者user17400329
相关产品推荐
相关产品推荐

