TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
3 / 3
100.0%
Branches:
3 / 4
75.0%
Functions:
1 / 1, 1 excl
100.0%

mesh/io/mesh_io.h
Line Branch Exec Source
1 /// @file
2 /// @brief Reading and writing triangle meshes and instanced scenes as OBJ with MTL, glTF and STL.
3 #pragma once
4
5 #include "terraingen/mesh/mesh.h"
6
7 #include <array>
8 #include <cstddef>
9 #include <filesystem>
10 #include <string>
11 #include <vector>
12
13 namespace terraingen {
14
15 /// A mesh's material: a name and a diffuse colour.
16 struct MeshMaterial {
17 90 std::string name = "default"; ///< Name in OBJ/MTL and glTF.
18 14 std::array<double, 3> colour{0.5, 0.5, 0.5}; ///< Linear RGB, each in [0, 1].
19
20
3/4
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
90 bool operator==(const MeshMaterial&) const = default;
21 };
22
23 /// A mesh with optional normals and its material.
24 struct SceneMesh {
25 TriangleMesh mesh; ///< The mesh, in metres.
26 std::vector<Vec3d> normals; ///< Empty, or one unit normal per vertex.
27 MeshMaterial material{}; ///< Written as an MTL material or a glTF base colour.
28 };
29
30 /// An instance of a scene mesh: its vertices scaled per axis by `scale`, then moved by
31 /// `pose`, as glTF composes a node's scale, rotation and translation.
32 struct SceneNode {
33 std::size_t mesh = 0; ///< Index into the scene's meshes.
34 Vec3d scale{1.0, 1.0, 1.0}; ///< Per-axis scale, nonzero and finite.
35 RigidTransform pose{}; ///< Rotation and translation applied after the scale.
36 };
37
38 /// Whether `path` names a mesh format by its extension: .obj, .gltf, .glb or .stl.
39 bool IsMeshPath(const std::filesystem::path& path);
40
41 /// Writes meshes drawn once per node, in the format the extension names. glTF (.glb, or .gltf
42 /// with a .bin beside it) stores each mesh once and instances it; OBJ (with an .mtl beside it)
43 /// writes one object per node; both are y-up, TerrainGen's z-up (x, y, z) written as (x, z, -y).
44 /// STL (binary) gets every node's mesh merged, z-up, without materials.
45 /// @throws std::invalid_argument for another extension, no meshes or nodes, an empty or invalid
46 /// mesh, mismatched normals, a node naming no mesh, a scale that is zero or not finite, or a pose
47 /// whose rotation is not a rotation.
48 /// @throws std::runtime_error if a file cannot be written.
49 void WriteScene(const std::filesystem::path& path, const std::vector<SceneMesh>& meshes,
50 const std::vector<SceneNode>& nodes);
51
52 /// Writes one mesh, as `WriteScene` with a single node.
53 /// @throws std::invalid_argument and std::runtime_error as `WriteScene`.
54 void WriteMesh(const std::filesystem::path& path, const SceneMesh& mesh);
55
56 /// Reads every triangle of an .obj (polygons triangulated), a .gltf or .glb (every triangle
57 /// primitive of the default scene, with its nodes' transforms), a binary or ASCII .stl, or an ICQ
58 /// shape model in kilometres (.icq, as `ReadIcq` and `IcqToMesh`), in metres and z-up, with the
59 /// first material's diffuse colour where the format has one. Normals are not read.
60 /// @throws std::invalid_argument for another extension.
61 /// @throws std::runtime_error if the file cannot be read or holds no triangles.
62 SceneMesh ReadMesh(const std::filesystem::path& path);
63
64 } // namespace terraingen
65