• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ekarpp / lumo / 6054336964

01 Sep 2023 10:00PM UTC coverage: 47.535% (-0.9%) from 48.466%
6054336964

push

github

web-flow
0.3.2 (#33)

- Rewrites sample gathering to use `FilmTiles`
- Fixes splat samples in BDPT
- Some BDPT medium bug fixes (Progresses #31)

Closes #32

180 of 180 new or added lines in 17 files covered. (100.0%)

2179 of 4584 relevant lines covered (47.53%)

6887198.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.48
/src/parser/obj.rs
1
use super::*;
2

3
/// https://github.com/ekzhang/rpt/blob/master/src/io.rs
4
/// https://www.cs.cmu.edu/~mbz/personal/graphics/obj.html
5
pub fn load_file(file: File, material: Material) -> Result<Mesh> {
4✔
6
    let mut vertices: Vec<Point> = Vec::new();
4✔
7
    let mut normals: Vec<Normal> = Vec::new();
4✔
8
    let mut uvs: Vec<Vec2> = Vec::new();
4✔
9
    let mut faces: Vec<Face> = Vec::new();
4✔
10

4✔
11
    let reader = BufReader::new(file);
4✔
12
    for line in reader.lines() {
75,120✔
13
        let line = line?.trim().to_string();
75,120✔
14
        if line.starts_with('#') || line.is_empty() {
75,120✔
15
            continue;
65✔
16
        }
75,055✔
17
        let tokens: Vec<&str> = line.split_ascii_whitespace().collect();
75,055✔
18

75,055✔
19
        parse_tokens(tokens, &mut vertices, &mut normals, &mut uvs, &mut faces)?;
75,055✔
20
    }
21

22
    Ok(TriangleMesh::new(vertices, faces, normals, uvs, material))
4✔
23
}
4✔
24

25

26
pub fn load_scene(file: File, materials: HashMap<String, MtlConfig>) -> Result<Scene> {
×
27
    let mut scene = Scene::default();
×
28
    let mut vertices: Vec<Point> = Vec::new();
×
29
    let mut normals: Vec<Normal> = Vec::new();
×
30
    let mut uvs: Vec<Vec2> = Vec::new();
×
31
    let mut faces: Vec<Face> = Vec::new();
×
32
    let mut meshes: Vec<(Vec<Face>, Material)> = Vec::new();
×
33
    let mut material = Material::Blank;
×
34

×
35
    let reader = BufReader::new(file);
×
36
    for line in reader.lines() {
×
37
        let line = line?.trim().to_string();
×
38
        if line.starts_with('#') || line.is_empty() {
×
39
            continue;
×
40
        }
×
41
        let tokens: Vec<&str> = line.split_ascii_whitespace().collect();
×
42

×
43
        match tokens[0] {
×
44
            "g" | "o" => {
×
45
                if !faces.is_empty() {
×
46
                    meshes.push((faces, material));
×
47
                    faces = Vec::new();
×
48
                    material = Material::Blank;
×
49
                }
×
50
            }
51
            "usemtl" => {
×
52
                match materials.get(tokens[1]) {
×
53
                    Some(mtl_cfg) => material = mtl_cfg.build_material(),
×
54
                    None => {
55
                        return Err(obj_error(
×
56
                            &format!("Could not find material {}", tokens[1])
×
57
                        ));
×
58
                    }
59
                }
60
            }
61
            _ => {
62
                parse_tokens(
×
63
                    tokens,
×
64
                    &mut vertices,
×
65
                    &mut normals,
×
66
                    &mut uvs,
×
67
                    &mut faces
×
68
                )?
×
69
            }
70
        }
71
    }
72

73
    meshes.push((faces, material));
×
74

×
75
    let triangle_mesh = Arc::new(TriangleMesh {
×
76
        vertices,
×
77
        normals,
×
78
        uvs,
×
79
    });
×
80

81
    for (faces, mtl) in meshes {
×
82
        let is_light = matches!(mtl, Material::Light(_));
×
83
        let object = Box::new(TriangleMesh::new_from_faces(
×
84
            triangle_mesh.clone(),
×
85
            faces,
×
86
            mtl,
×
87
        ));
×
88

×
89
        if is_light {
×
90
            scene.add_light(object);
×
91
        } else {
×
92
            scene.add(object);
×
93
        }
×
94
    }
95

96
    Ok(scene)
×
97
}
×
98

99
fn parse_tokens(
75,055✔
100
    tokens: Vec<&str>,
75,055✔
101
    vertices: &mut Vec<Point>,
75,055✔
102
    normals: &mut Vec<Normal>,
75,055✔
103
    uvs: &mut Vec<Vec2>,
75,055✔
104
    faces: &mut Vec<Face>,
75,055✔
105
) -> Result<()> {
75,055✔
106
    match tokens[0] {
75,055✔
107
        "v" => {
75,055✔
108
            let vertex = parse_vec3(&tokens)?;
23,712✔
109
            vertices.push(vertex);
23,712✔
110
        }
111
        "vn" => {
51,343✔
112
            let normal = parse_vec3(&tokens)?;
960✔
113
            normals.push(normal);
960✔
114
        }
115
        "vt" => {
50,383✔
116
            let uv = parse_vec2(&tokens)?;
25,962✔
117
            uvs.push(uv);
25,962✔
118
        }
119
        "f" => {
24,421✔
120
            let face = parse_face(&tokens, vertices, normals, uvs)?;
24,404✔
121
            faces.extend(face);
24,404✔
122
        }
123
        _ => (),
17✔
124
    }
125
    Ok(())
75,055✔
126
}
75,055✔
127

128
/// Parses a face from a .obj file
129
fn parse_face(
24,404✔
130
    tokens: &[&str],
24,404✔
131
    vertices: &[Point],
24,404✔
132
    normals: &[Normal],
24,404✔
133
    uvs: &[Vec2],
24,404✔
134
) -> Result<Vec<Face>> {
24,404✔
135
    let mut vidxs: Vec<usize> = Vec::new();
24,404✔
136
    let mut nidxs: Vec<usize> = Vec::new();
24,404✔
137
    let mut tidxs: Vec<usize> = Vec::new();
24,404✔
138

139
    for token in &tokens[1..] {
96,240✔
140
        let arguments: Vec<&str> = token.split('/').collect();
96,240✔
141

142
        let vidx = parse_idx(arguments[0], vertices.len())?;
96,240✔
143
        vidxs.push(vidx);
96,240✔
144

96,240✔
145
        if arguments.len() > 1 && !arguments[1].is_empty() {
96,240✔
146
            let tidx = parse_idx(arguments[1], uvs.len())?;
96,240✔
147
            tidxs.push(tidx);
96,240✔
148
        }
×
149

150
        if arguments.len() > 2 {
96,240✔
151
            let nidx = parse_idx(arguments[2], normals.len())?;
960✔
152
            nidxs.push(nidx);
960✔
153
        }
95,280✔
154
    }
155

156
    let mut faces: Vec<Face> = Vec::new();
24,404✔
157

158
    for i in 1..vidxs.len() - 1 {
47,432✔
159
        let (a, b, c) = (0, i, i + 1);
47,432✔
160
        let vidx = vec![vidxs[a], vidxs[b], vidxs[c]];
47,432✔
161

162
        let nidx = if nidxs.is_empty() {
47,432✔
163
            Vec::new()
47,112✔
164
        } else {
165
            vec![nidxs[a], nidxs[b], nidxs[c]]
320✔
166
        };
167

168
        let tidx = if tidxs.is_empty() {
47,432✔
169
            Vec::new()
×
170
        } else {
171
            vec![tidxs[a], tidxs[b], tidxs[c]]
47,432✔
172
        };
173

174
        faces.push(Face::new(vidx, nidx, tidx));
47,432✔
175
    }
176

177
    Ok(faces)
24,404✔
178
}
24,404✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc