Line data Source code
1 : """
2 : writeobjmesh(io, mesh[;
3 : position=Val(:x), texcoord=Val(:u),
4 : normal=nothing, color=Val(:c),
5 : format="%g"])
6 :
7 : Write `mesh` to `io` in [OBJ format](https://paulbourke.net/dataformats/obj/)
8 : using attributes
9 :
10 : - `position`
11 : - `texcoord` optional vertex texture coordinates, possibly stored per face
12 : (as `hattr`).
13 : - `normal` optional vertex normal, possibly stored per face
14 : (as `hattr`)
15 : - `color` optional vertex color
16 : ([format](https://paulbourke.net/dataformats/obj/colour.html))
17 :
18 : Pass `nothing` to ignore an *optional* attribute. Attributes the are
19 : disabled are also ignored, i.e., not written.
20 :
21 : The optional `format` argument specifies the output format of a
22 : floating point number as a `String` using `sprintf`-syntax.
23 :
24 : !!! note
25 : This method is called by [`writemesh`](@ref).
26 :
27 : See also [`writemesh`](@ref), [`readobjmesh`](@ref), [`readobj`](@ref)
28 : """
29 6 : function writeobjmesh(io::IO, mesh::Mesh{V, F, H, E};
30 : position=Val(:x),
31 : texcoord=Val(:u),
32 : normal=nothing,
33 : color=Val(:c),
34 : format::String="%g") where {V, F, H, E}
35 3 : println(io, "# PMesh")
36 :
37 3 : formatter = generate_formatter(format)
38 :
39 : # NOTE: There may be unsued VHnd!
40 11351 : vindices = zeros(Int, PMesh.n_total(vattr(mesh)))
41 :
42 3 : ax = vattr(mesh, position)
43 :
44 3 : if PMesh.hasvattr(mesh, color) && isenabled(vattr(mesh, color))
45 1 : ac = vattr(mesh, color)
46 2 : for (i, v) in enumerate(vertices(mesh))
47 9222 : vindices[Int(v)] = i
48 9222 : print(io, "v ")
49 9222 : print(io, join(formatter.(ax[v]), ' '))
50 9222 : (length(eltype(ax)) == 2) && print(io, " 0")
51 9222 : print(io, " ")
52 9222 : rbg = (ac[v].r, ac[v].g, ac[v].b)
53 18444 : println(io, join(formatter.(rbg), ' '))
54 18443 : end
55 : else
56 4 : for (i, v) in enumerate(vertices(mesh))
57 2129 : vindices[Int(v)] = i
58 2129 : print(io, "v ")
59 2129 : println(io, join(formatter.(ax[v]), ' '))
60 2129 : end
61 : end
62 :
63 : # TODO: We could search for equal uv coordinates and "reuse" indices
64 : # Requires map. Probably not worthwhile as we read per half-edge.
65 : # Same for normals.
66 :
67 3 : face_uv_idx = false
68 :
69 3 : if PMesh.hasvattr(mesh, texcoord) && isenabled(vattr(mesh, texcoord))
70 0 : au = vattr(mesh, texcoord)
71 :
72 0 : for v in vertices(mesh)
73 0 : print(io, "vt ")
74 0 : println(io, join(formatter.(au[v]), ' '))
75 0 : end
76 3 : elseif PMesh.hashattr(mesh, texcoord) && isenabled(vattr(mesh, texcoord))
77 0 : au = hattr(mesh, texcoord)
78 :
79 0 : for f in faces(mesh)
80 0 : for h in halfedges(mesh, f) # Reuse indexing
81 0 : print(io, "vt ")
82 0 : print(io, join(formatter.(au[h]), ' '))
83 0 : println(io)
84 0 : end
85 0 : end
86 :
87 0 : face_uv_idx = true
88 : end
89 :
90 3 : face_normal_idx = false
91 :
92 3 : if PMesh.hasvattr(mesh, normal) && isenabled(vattr(mesh, normal))
93 0 : an = vattr(mesh, normal)
94 :
95 0 : for v in vertices(mesh)
96 0 : print(io, "vn ")
97 0 : println(io, join(formatter.(an[v]), ' '))
98 0 : end
99 3 : elseif PMesh.hashattr(mesh, normal) && isenabled(vattr(mesh, normal))
100 0 : au = hattr(mesh, normal)
101 :
102 0 : for f in faces(mesh)
103 0 : for h in halfedges(mesh, f) # Reuse indexing
104 0 : print(io, "vn ")
105 0 : print(io, join(formatter.(an[h]), ' '))
106 0 : end
107 0 : println(io)
108 0 : end
109 :
110 0 : face_normal_idx = true
111 : end
112 :
113 6 : if face_uv_idx || face_normal_idx
114 0 : nh = 0
115 0 : for f in faces(mesh)
116 0 : print(io, "f")
117 0 : vidx = map(v -> vindices(v), Int.(vertices(mesh, f)))
118 0 : hidx = nh+1:length(vidx)
119 :
120 0 : for (v, h) in zip(vidx, hidx)
121 0 : face_uv_idx && face_normal_idx && print(io, " $(v)/$(h)/$(h)")
122 0 : face_uv_idx && print(io, " $(v)/$(h)")
123 0 : face_normal_idx && print(io, " $(v)//$(h)")
124 0 : end
125 :
126 0 : println(io)
127 0 : hidx += length(vidx)
128 0 : end
129 : else
130 6 : for f in faces(mesh)
131 21714 : print(io, "f ")
132 21714 : println(io, join(Int.(vertices(mesh, f)), ' '))
133 21714 : end
134 : end
135 :
136 3 : nothing
137 : end
|