Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 826 lines (744 sloc) 29.286 kb
a552d9c @giniu initial import
giniu authored
1 %%
2 %% wings_ff_wings.erl --
3 %%
4 %% This module contain the functions for reading and writing .wings files.
5 %%
235be9f @bjorng Use an array instead of a gb_tree for the edge table.
bjorng authored
6 %% Copyright (c) 2001-2009 Bjorn Gustavsson
a552d9c @giniu initial import
giniu authored
7 %%
8 %% See the file "license.terms" for information on usage and redistribution
9 %% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 %%
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
11 %% $Id$
a552d9c @giniu initial import
giniu authored
12 %%
13
14 -module(wings_ff_wings).
15 -export([import/2,export/2]).
16
17 -include("wings.hrl").
18 -include("e3d_image.hrl").
0493e4e @bjorng Convert old holes when loading .wings files
bjorng authored
19 -import(lists, [sort/1,reverse/1,foldl/3,any/2,keymember/3,keyfind/3]).
a552d9c @giniu initial import
giniu authored
20
21 -define(WINGS_HEADER, "#!WINGS-1.0\r\n\032\04").
22
23 %% Load a wings file.
24
25 import(Name, St) ->
26 wings_pb:start(?__(1,"opening wings file")),
27 wings_pb:update(0.07, ?__(2,"reading file")),
28 wings_pb:done(import_1(Name, St)).
29
30 import_1(Name, St0) ->
31 case file:read_file(Name) of
5f74848 @bjorng Using tuple_size/1 or byte_size/1 instead of size/1. (R12B required.)
bjorng authored
32 {ok,<<?WINGS_HEADER,Sz:32,Data/binary>>} when byte_size(Data) =:= Sz ->
a552d9c @giniu initial import
giniu authored
33 wings_pb:update(0.08, ?__(1,"converting binary")),
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
34 try binary_to_term(Data) of
a552d9c @giniu initial import
giniu authored
35 {wings,0,_Shapes} ->
36 {error, ?__(2,"Pre-0.80 Wings format no longer supported.")};
37 {wings,1,_,_,_} ->
38 %% Pre-0.92. No longer supported.
39 {error,?__(3,"Pre-0.92 Wings format no longer supported.")};
40 {wings,2,{Shapes,Materials,Props}} ->
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
41 Dir = filename:dirname(Name),
42 import_vsn2(Shapes, Materials, Props, Dir, St0);
a552d9c @giniu initial import
giniu authored
43 {wings,_,_} ->
44 {error,?__(4,"unknown wings format")};
45 Other ->
46 io:format("~P\n", [Other,20]),
47 {error,?__(5,"corrupt Wings file")}
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
48 catch
49 error:badarg ->
50 {error,?__(5,"corrupt Wings file")}
a552d9c @giniu initial import
giniu authored
51 end;
52 {ok,_Bin} ->
53 {error,?__(6,"not a Wings file (or old Wings format)")};
54 {error,Reason} ->
55 {error,file:format_error(Reason)}
56 end.
57
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
58 -record(va, {color_lt=none,
59 color_rt=none,
60 uv_lt=none,
61 uv_rt=none}).
62
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
63 import_vsn2(Shapes, Materials0, Props, Dir, St0) ->
a552d9c @giniu initial import
giniu authored
64 wings_pb:update(0.10, ?__(1,"images and materials")),
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
65 Images = import_images(Dir,Props),
a552d9c @giniu initial import
giniu authored
66 Materials1 = translate_materials(Materials0),
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
67 Materials2 = translate_map_images(Materials1, Images),
68 Materials = translate_object_modes(Materials2, Shapes),
a552d9c @giniu initial import
giniu authored
69 {St1,NameMap0} = wings_material:add_materials(Materials, St0),
70 NameMap1 = gb_trees:from_orddict(sort(NameMap0)),
71 NameMap = optimize_name_map(Materials, NameMap1, []),
72 St = import_props(Props, St1),
73 wings_pb:update(1.0,?__(2,"objects")),
74 import_objects(Shapes, NameMap, St).
75
76 optimize_name_map([{Name,_}|Ms], NameMap, Acc) ->
77 case gb_trees:lookup(Name, NameMap) of
78 none ->
79 optimize_name_map(Ms, NameMap, [{Name,Name}|Acc]);
80 {value,NewName} ->
81 optimize_name_map(Ms, NameMap, [{Name,NewName}|Acc])
82 end;
83 optimize_name_map([], _, Acc) -> gb_trees:from_orddict(sort(Acc)).
84
85 import_objects(Shapes, NameMap, #st{selmode=Mode,shapes=Shs0,onext=Oid0}=St) ->
86 {Objs,Oid} = import_objects(Shapes, Mode, NameMap, Oid0, []),
87 Shs = gb_trees:from_orddict(gb_trees:to_list(Shs0) ++ Objs),
88 St#st{shapes=Shs,onext=Oid}.
89
90 import_objects([Sh0|Shs], Mode, NameMap, Oid, ShAcc) ->
91 {object,Name,{winged,Es,Fs,Vs,He},Props} = Sh0,
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
92 Etab = import_edges(Es, 0, []),
e596416 @bjorng Fix bug when the default material in a .wings file does not match curren...
bjorng authored
93 %% The 'default' material saved in this .wings file might not
94 %% match the current default material, so it could have been
95 %% renamed (to 'default2', for instance). We must make sure
96 %% that we use the correctly named default material on faces
97 %% without explicit material.
98 DefaultMat = case gb_trees:lookup(default, NameMap) of
99 none -> default;
100 {value,DefaultMat0} -> DefaultMat0
101 end,
102 FaceMat = import_face_mat(Fs, NameMap, DefaultMat, 0, []),
a552d9c @giniu initial import
giniu authored
103 Vtab = import_vs(Vs, 0, []),
104 Htab = gb_sets:from_list(He),
105 Perm = import_perm(Props),
106 Mirror = proplists:get_value(mirror_face, Props, none),
d0a9d76 @bjorng Fix loading of .wings files with holes
bjorng authored
107 Holes = proplists:get_value(holes, Props, []),
a552d9c @giniu initial import
giniu authored
108 Pst0 = proplists:get_value(plugin_states, Props, []),
109 Pst = try gb_trees:from_orddict(Pst0)
110 catch error:_ -> gb_trees:empty()
111 end,
d2c9d17 @bjorng Add support for saving and loading objects with holes
bjorng authored
112 We = #we{he=Htab,perm=Perm,holes=Holes,pst=Pst,
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
113 id=Oid,name=Name,mirror=Mirror,mat=FaceMat},
a552d9c @giniu initial import
giniu authored
114 HiddenFaces = proplists:get_value(num_hidden_faces, Props, 0),
235be9f @bjorng Use an array instead of a gb_tree for the edge table.
bjorng authored
115 import_objects(Shs, Mode, NameMap, Oid+1, [{HiddenFaces,We,{Vtab,Etab}}|ShAcc]);
a552d9c @giniu initial import
giniu authored
116 import_objects([], _Mode, _NameMap, Oid, Objs0) ->
117 %%io:format("flat_size: ~p\n", [erts_debug:flat_size(Objs0)]),
118 Objs = share_list(Objs0),
119 %%io:format("size: ~p\n", [erts_debug:size(Objs)]),
120 {Objs,Oid}.
121
d125d3f @bjorng Optimize loading of edges without vertex attributes
bjorng authored
122 import_edges([[{edge,Va,Vb,Lf,Rf,Ltpr,Ltsu,Rtpr,Rtsu}]|Es], Edge, Acc) ->
123 Rec = #edge{vs=Va,ve=Vb,lf=Lf,rf=Rf,
124 ltpr=Ltpr,ltsu=Ltsu,rtpr=Rtpr,rtsu=Rtsu},
125 EdgeData = {Rec,none},
126 import_edges(Es, Edge+1, [{Edge,EdgeData}|Acc]);
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
127 import_edges([E|Es], Edge, Acc) ->
128 EdgeData = import_edge(E, none, #va{}),
129 import_edges(Es, Edge+1, [{Edge,EdgeData}|Acc]);
130 import_edges([], _Edge, Acc) -> reverse(Acc).
131
132 import_edge([{edge,Va,Vb,Lf,Rf,Ltpr,Ltsu,Rtpr,Rtsu}|T], _, Attrs) ->
133 Rec = #edge{vs=Va,ve=Vb,lf=Lf,rf=Rf,
134 ltpr=Ltpr,ltsu=Ltsu,rtpr=Rtpr,rtsu=Rtsu},
135 import_edge(T, Rec, Attrs);
136 import_edge([{uv_lt,<<U/float,V/float>>}|T], Rec, Attrs) ->
137 import_edge(T, Rec, Attrs#va{uv_lt={U,V}});
138 import_edge([{uv_rt,<<U/float,V/float>>}|T], Rec, Attrs) ->
139 import_edge(T, Rec, Attrs#va{uv_rt={U,V}});
140 import_edge([{color_lt,<<R:32/float,G:32/float,B:32/float>>}|T], Rec, Attrs) ->
141 import_edge(T, Rec, Attrs#va{color_lt={R,G,B}});
142 import_edge([{color_rt,<<R:32/float,G:32/float,B:32/float>>}|T], Rec, Attrs) ->
143 import_edge(T, Rec, Attrs#va{color_rt={R,G,B}});
144 import_edge([{color,Bin}|T], Rec, Attrs) ->
a552d9c @giniu initial import
giniu authored
145 %% Old-style vertex colors (pre 0.98.15).
146 <<R1/float,G1/float,B1/float,R2/float,G2/float,B2/float>> = Bin,
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
147 import_edge(T, Rec, Attrs#va{color_lt={R1,G1,B1},color_rt={R2,G2,B2}});
148 import_edge([{uv,Bin}|T], Rec, Attrs) ->
a552d9c @giniu initial import
giniu authored
149 %% Old-style UV coordinates (pre 0.98.15).
150 <<U1/float,V1/float,U2/float,V2/float>> = Bin,
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
151 import_edge(T, Rec, Attrs#va{uv_lt={U1,V1},uv_rt={U2,V2}});
152 import_edge([_|T], Rec, Attrs) ->
153 import_edge(T, Rec, Attrs);
154 import_edge([], Rec, Attrs) -> {Rec,Attrs}.
a552d9c @giniu initial import
giniu authored
155
e596416 @bjorng Fix bug when the default material in a .wings file does not match curren...
bjorng authored
156 import_face_mat([F|Fs], NameMap, Default, Face, Acc) ->
157 Mat = import_face_mat_1(F, NameMap, Default),
158 import_face_mat(Fs, NameMap, Default, Face+1, [{Face,Mat}|Acc]);
159 import_face_mat([], _, _, _, Acc) -> reverse(Acc).
a552d9c @giniu initial import
giniu authored
160
e596416 @bjorng Fix bug when the default material in a .wings file does not match curren...
bjorng authored
161 import_face_mat_1([{material,Name}|T], NameMap, Default) ->
a552d9c @giniu initial import
giniu authored
162 %% Silently ignore materials not found in the name map.
163 Mat = case gb_trees:lookup(Name, NameMap) of
e596416 @bjorng Fix bug when the default material in a .wings file does not match curren...
bjorng authored
164 none -> Default;
a552d9c @giniu initial import
giniu authored
165 {value,Other} -> Other
166 end,
167 import_face_mat_1(T, NameMap, Mat);
168 import_face_mat_1([_|T], NameMap, Mat) ->
169 import_face_mat_1(T, NameMap, Mat);
170 import_face_mat_1([], _, Mat) -> Mat.
171
172 import_vs([Vtx|Vs], V, Acc) ->
173 Rec = import_vertex(Vtx, []),
174 import_vs(Vs, V+1, [{V,Rec}|Acc]);
175 import_vs([], _V, Acc) -> reverse(Acc).
176
177 import_vertex([<<X/float,Y/float,Z/float>>|T], _) ->
178 import_vertex(T, {X,Y,Z});
179 import_vertex([_|T], Rec) ->
180 import_vertex(T, Rec);
181 import_vertex([], Rec) -> Rec.
182
183 import_perm(Props) ->
184 case proplists:get_value(state, Props) of
185 undefined -> 0;
186 locked -> 1;
187 hidden -> 2;
188 hidden_locked -> 3;
189 {hidden,Mode,Set} -> {Mode,gb_sets:from_list(Set)};
190 _Unknown -> 0
191 end.
192
193 import_props([{selection,{Mode,Sel0}}|Ps], St) ->
194 Sel = import_sel(Sel0, St),
195 import_props(Ps, St#st{selmode=Mode,sel=Sel});
196 import_props([{saved_selection,{Mode,Sel0}}|Ps], St0) ->
197 Sel = import_sel(Sel0, St0),
198 St = new_sel_group(?__(1,"<Stored Selection>"), Mode, Sel, St0),
199 import_props(Ps, St);
200 import_props([{{selection_group,Name},{Mode,Sel0}}|Ps], St0) ->
201 Sel = import_sel(Sel0, St0),
202 St = new_sel_group(Name, Mode, Sel, St0),
203 import_props(Ps, St);
204 import_props([{lights,Lights}|Ps], St0) ->
205 St = wings_light:import(Lights, St0),
206 import_props(Ps, St);
207 import_props([{views,Views}|Ps], St0) ->
208 St = wings_view:import_views(Views, St0),
209 import_props(Ps, St);
210 import_props([{current_view,CurrentView}|Ps], #st{views={_,Views}}=St) ->
211 import_props(Ps, St#st{views={CurrentView,Views}});
212 import_props([{palette,Palette}|Ps], St) ->
213 import_props(Ps, St#st{pal=Palette});
214 import_props([{scene_prefs,ScenePrefs}|Ps], St) ->
215 lists:foreach(fun({Key,Val}) ->
216 wings_pref:set_scene_value(Key, Val)
217 end,
218 ScenePrefs),
219 import_props(Ps, St);
220 import_props([{plugin_states,Pst0}|Ps], St0 =#st{pst=Previous}) ->
221 St = try
222 case gb_trees:keys(Previous) of
223 [] ->
224 Pst = gb_trees:from_orddict(lists:sort(Pst0)),
225 St0#st{pst=Pst};
226 _ when Pst0 =:= [] ->
227 St0;
228 PrevKeys ->
229 M=fun({Mod,Data},Acc) ->
230 case lists:member(Mod,PrevKeys) of
231 true ->
232 try
233 Pst = Mod:merge_st(Data,St0),
234 [{Mod,Pst}|lists:keydelete(Mod,1,Acc)]
235 catch _:_ -> Acc
236 end;
237 false ->
238 [{Mod,Data}|Acc]
239 end
240 end,
241 Pst1 = lists:foldl(M,gb_trees:to_list(Previous),Pst0),
242 Pst = gb_trees:from_orddict(lists:sort(Pst1)),
243 St0#st{pst=Pst}
244 end
245 catch error:Reason ->
246 io:format("Failed importing plugins state Not a gb_tree ~p ~n",
247 [Reason]),
248 St0
249 end,
250 import_props(Ps,St);
251 import_props([_|Ps], St) ->
252 import_props(Ps, St);
253 import_props([], St) -> St.
254
255 import_sel(Sel, #st{onext=IdBase}) ->
256 [{IdBase+Id,gb_sets:from_list(Elems)} || {Id,Elems} <- Sel].
257
258 new_sel_group(Name, Mode, Sel, #st{ssels=Ssels0}=St) ->
259 Key = {Mode,Name},
260 case gb_trees:is_defined(Key, Ssels0) of
261 true -> St;
262 false ->
263 Ssels = gb_trees:insert(Key, Sel, Ssels0),
264 St#st{ssels=Ssels}
265 end.
266
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
267 import_images(Dir,Props) ->
a552d9c @giniu initial import
giniu authored
268 Empty = gb_trees:empty(),
269 case proplists:get_value(images, Props) of
270 undefined -> Empty;
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
271 Images -> import_images_1(Images, Dir, Empty)
a552d9c @giniu initial import
giniu authored
272 end.
273
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
274 import_images_1([{Id0,Im}|T], Dir, Map) ->
a552d9c @giniu initial import
giniu authored
275 try
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
276 #e3d_image{name=Name} = E3D = import_image(Im,Dir),
a552d9c @giniu initial import
giniu authored
277 Id = wings_image:new(Name, E3D),
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
278 import_images_1(T, Dir, gb_trees:insert(Id0, Id, Map))
a552d9c @giniu initial import
giniu authored
279 catch
280 throw:{bad_image,Image} ->
281 E3d = #e3d_image{name=Image,width=1,height=1,image= <<0,0,0>>},
282 ID = wings_image:new(Image, E3d),
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
283 import_images_1(T, Dir, gb_trees:insert(Id0, ID, Map))
a552d9c @giniu initial import
giniu authored
284 end;
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
285 import_images_1([], _, Map) -> Map.
a552d9c @giniu initial import
giniu authored
286
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
287 import_image(Im,Dir) ->
a552d9c @giniu initial import
giniu authored
288 Name = proplists:get_value(name, Im, ?__(1,"unnamed image")),
289 case proplists:get_value(filename, Im) of
290 undefined ->
291 W = proplists:get_value(width, Im, 0),
292 H = proplists:get_value(height, Im, 0),
293 PP = proplists:get_value(samples_per_pixel, Im, 0),
294 Pixels = proplists:get_value(pixels, Im),
295 if
5f74848 @bjorng Using tuple_size/1 or byte_size/1 instead of size/1. (R12B required.)
bjorng authored
296 W*H*PP =:= byte_size(Pixels) ->
a552d9c @giniu initial import
giniu authored
297 ok;
298 true ->
299 Str = io_lib:format(?__(2,"Bad image: ~p\n"), [Name]),
300 wings_u:message(lists:flatten(Str)),
301 throw({bad_image,Name})
302 end,
303 MaskSize = proplists:get_value(mask_size, Im),
304 Type = case PP of
305 1 when MaskSize =:= 1 -> a8;
306 1 -> g8;
307 2 -> g8a8;
308 3 -> r8g8b8;
309 4 -> r8g8b8a8
310 end,
311 #e3d_image{name=Name,width=W,height=H,type=Type,order=lower_left,
312 alignment=1,bytes_pp=PP,image=Pixels};
313 Filename ->
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
314 Ps = [{filename,Filename}, {opt_dir,Dir}],
a552d9c @giniu initial import
giniu authored
315 case wings_image:image_read(Ps) of
316 #e3d_image{}=E3D ->
f436c26 @dgud Fixed relative file paths for textures, wings
dgud authored
317 E3D#e3d_image{name=Name};
a552d9c @giniu initial import
giniu authored
318 {error,_} ->
319 Str = io_lib:format(?__(2,"Bad image: ~p\n"), [Name]),
320 wings_u:message(lists:flatten(Str)),
321 throw({bad_image,Name})
322 end
323 end.
324
325 translate_map_images(Mats, ImMap) ->
326 [translate_map_images_1(M, ImMap) || M <- Mats].
327
328 translate_map_images_1({Name,Props0}=Mat, ImMap) ->
329 case proplists:get_value(maps, Props0, []) of
330 [] -> Mat;
331 Maps ->
332 Props = lists:keydelete(maps, 1, Props0),
333 {Name,[{maps,translate_map_images_2(Maps, Name, ImMap)}|Props]}
334 end.
335
336 translate_map_images_2([{Type,Im0}|T], Mat, ImMap) when is_integer(Im0) ->
337 case gb_trees:lookup(Im0, ImMap) of
338 none ->
339 %% Something wrong here.
340 io:format( ?__(1,"Material ~p, ~p texture: reference to non-existing image ~p\n"),
341 [Mat,Type,Im0]),
342 translate_map_images_2(T, Mat, ImMap);
343 {value,Im} ->
344 if Type == normal -> wings_image:is_normalmap(Im);
345 true -> ok
346 end,
347 [{Type,Im}|translate_map_images_2(T, Mat, ImMap)]
348 end;
349 translate_map_images_2([H|T], Mat, ImMap) ->
350 [H|translate_map_images_2(T, Mat, ImMap)];
351 translate_map_images_2([], _, _) -> [].
352
353 %%%
354 %%% Sharing of floating point numbers on import.
355 %%%
356
357 share_list(Wes) ->
235be9f @bjorng Use an array instead of a gb_tree for the edge table.
bjorng authored
358 Tabs0 = [Tabs || {_,_,{_,_}=Tabs} <- Wes],
a552d9c @giniu initial import
giniu authored
359 Floats = share_floats(Tabs0, tuple_to_list(wings_color:white())),
360 Tabs = share_list_1(Tabs0, Floats, gb_trees:empty(), []),
361 share_list_2(Tabs, Wes, []).
362
363 share_list_1([{Vtab0,Etab0}|Ts], Floats, Tuples0, Acc) ->
364 Vtab = share_vs(Vtab0, Floats, []),
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
365 {Etab,Attr,Tuples} = share_es(Etab0, Floats, [], [], Tuples0),
366 share_list_1(Ts, Floats, Tuples, [{Vtab,Etab,Attr}|Acc]);
a552d9c @giniu initial import
giniu authored
367 share_list_1([], _, _, Ts) -> reverse(Ts).
368
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
369 share_list_2([{Vtab0,Etab0,Attr}|Ts],
235be9f @bjorng Use an array instead of a gb_tree for the edge table.
bjorng authored
370 [{NumHidden,#we{id=Id,mat=FaceMat}=We0,_}|Wes], Acc) ->
73c6320 @bjorng Use arrays instead of gb_trees for the vertex tables.
bjorng authored
371 Vtab = array:from_orddict(Vtab0),
235be9f @bjorng Use an array instead of a gb_tree for the edge table.
bjorng authored
372 Etab = array:from_orddict(Etab0),
a552d9c @giniu initial import
giniu authored
373 We1 = wings_we:rebuild(We0#we{vp=Vtab,es=Etab,mat=default}),
374 We2 = wings_facemat:assign(FaceMat, We1),
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
375
376 %% Hide invisible faces and set holes.
fa945ea @bjorng Fix bad mirror face in old Wings files
bjorng authored
377 We3 = if
d0a9d76 @bjorng Fix loading of .wings files with holes
bjorng authored
378 NumHidden =:= 0 -> We2;
379 true ->
380 Hidden = lists:seq(0, NumHidden-1),
381 Holes = ordsets:from_list([-F-1 || F <- We2#we.holes]),
382 wings_we:hide_faces(Hidden, We2#we{holes=Holes})
383 end,
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
384 We4 = translate_old_holes(We3),
385 We5 = validate_holes(We4),
386
30c8046 @bjorng Use wings_we:validate_mirror/1 and wings_we:visible/{1,2}
bjorng authored
387 %% Very old Wings files can have invalid mirror faces for some reason.
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
388 We6 = wings_we:validate_mirror(We5),
389
390 %% Set attributes (if any) for all edges.
391 We7 = foldl(fun({E,Lt,Rt}, W) ->
392 wings_va:set_both_edge_attrs(E, Lt, Rt, W)
393 end, We6, Attr),
394
395 %% At last, hide the virtual mirror face.
396 We = case We7 of
57ccce7 @bjorng Make the virtual mirror face invisible
bjorng authored
397 #we{mirror=none} ->
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
398 We7;
57ccce7 @bjorng Make the virtual mirror face invisible
bjorng authored
399 #we{mirror=MirrorFace} ->
400 %% Hide the virtual mirror face.
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
401 We8 = wings_we:hide_faces([MirrorFace], We7),
402 We8#we{mirror=-MirrorFace-1}
57ccce7 @bjorng Make the virtual mirror face invisible
bjorng authored
403 end,
a552d9c @giniu initial import
giniu authored
404 share_list_2(Ts, Wes, [{Id,We}|Acc]);
405 share_list_2([], [], Wes) -> sort(Wes).
406
407 share_floats([{Vtab,Etab}|T], Shared0) ->
408 Shared1 = share_floats_1(Vtab, Shared0),
409 Shared = share_floats_2(Etab, Shared1),
410 share_floats(T, Shared);
411 share_floats([], Shared0) ->
412 Shared1 = ordsets:from_list(Shared0),
413 Shared = share_floats_4(Shared1, []),
414 gb_trees:from_orddict(Shared).
415
416 share_floats_1([{_,{A,B,C}}|T], Shared) ->
417 share_floats_1(T, [A,B,C|Shared]);
418 share_floats_1([], Shared) -> Shared.
419
d125d3f @bjorng Optimize loading of edges without vertex attributes
bjorng authored
420 share_floats_2([{_,{_,none}}|T], Shared) ->
421 share_floats_2(T, Shared);
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
422 share_floats_2([{_,{_,#va{}=Va}}|T], Shared0) ->
423 Shared1 = share_floats_3(Va#va.color_lt, Shared0),
424 Shared2 = share_floats_3(Va#va.color_rt, Shared1),
425 Shared3 = share_floats_3(Va#va.uv_lt, Shared2),
426 Shared = share_floats_3(Va#va.uv_rt, Shared3),
a552d9c @giniu initial import
giniu authored
427 share_floats_2(T, Shared);
428 share_floats_2([], Shared) -> Shared.
429
430 share_floats_3({A,B}, [A,B|_]=Shared) -> Shared;
431 share_floats_3({A,B,C}, [A,B,C|_]=Shared) -> Shared;
432 share_floats_3({A,B}, Shared) -> [A,B|Shared];
433 share_floats_3({A,B,C}, Shared) -> [A,B,C|Shared];
434 share_floats_3(none, Shared) -> Shared.
435
436 share_floats_4([F|Fs], Acc) ->
437 share_floats_4(Fs, [{F,F}|Acc]);
438 share_floats_4([], Acc) -> reverse(Acc).
439
440 share_vs([{V,{X0,Y0,Z0}}|Vs], Floats, Acc) ->
441 X = gb_trees:get(X0, Floats),
442 Y = gb_trees:get(Y0, Floats),
443 Z = gb_trees:get(Z0, Floats),
444 share_vs(Vs, Floats, [{V,{X,Y,Z}}|Acc]);
445 share_vs([], _, Acc) -> reverse(Acc).
446
d125d3f @bjorng Optimize loading of edges without vertex attributes
bjorng authored
447 share_es([{E,{Rec,none}}|Vs], Floats, Acc, AttrAcc, Shared) ->
448 share_es(Vs, Floats, [{E,Rec}|Acc], AttrAcc, Shared);
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
449 share_es([{E,{Rec,Va0}}|Vs], Floats, Acc, AttrAcc0, Shared0) ->
450 #va{color_lt=ColLt0,color_rt=ColRt0,
451 uv_lt=UvLt0,uv_rt=UvRt0} = Va0,
452 {ColLt,Shared1} = share_tuple(ColLt0, Floats, Shared0),
453 {ColRt,Shared2} = share_tuple(ColRt0, Floats, Shared1),
454 {UvLt,Shared3} = share_tuple(UvLt0, Floats, Shared2),
455 {UvRt,Shared} = share_tuple(UvRt0, Floats, Shared3),
456 LtAttr = wings_va:new_attr(ColLt, UvLt),
457 RtAttr = wings_va:new_attr(ColRt, UvRt),
458 AttrAcc = [{E,LtAttr,RtAttr}|AttrAcc0],
459 share_es(Vs, Floats, [{E,Rec}|Acc], AttrAcc, Shared);
460 share_es([], _, Acc, AttrAcc, Shared) ->
461 {reverse(Acc),AttrAcc,Shared}.
a552d9c @giniu initial import
giniu authored
462
463 share_tuple({A0,B0}=Tuple0, Floats, Shared) ->
464 case gb_trees:lookup(Tuple0, Shared) of
465 none ->
466 A = gb_trees:get(A0, Floats),
467 B = gb_trees:get(B0, Floats),
468 Tuple = {A,B},
469 {Tuple,gb_trees:insert(Tuple, Tuple, Shared)};
470 {value,Tuple} -> {Tuple,Shared}
471 end;
472 share_tuple({A0,B0,C0}=Tuple0, Floats, Shared) ->
473 case gb_trees:lookup(Tuple0, Shared) of
474 none ->
475 A = gb_trees:get(A0, Floats),
476 B = gb_trees:get(B0, Floats),
477 C = gb_trees:get(C0, Floats),
478 Tuple = {A,B,C},
479 {Tuple,gb_trees:insert(Tuple, Tuple, Shared)};
480 {value,Tuple} -> {Tuple,Shared}
481 end;
482 share_tuple(none, _, Shared) -> {none,Shared}.
483
484 %%%
485 %%% Import of old materials format (up to and including wings-0.94.02).
486 %%%
487
488 translate_materials(Mats) ->
489 [translate_material(M) || M <- Mats].
490
491 translate_material({Name,Props}=Mat) ->
492 case proplists:is_defined(opengl, Props) of
493 true -> Mat;
494 false ->
495 Opac = proplists:get_value(opacity, Props),
496 {Name,translate_material(Props, Opac, [], [])}
497 end.
498
499 translate_material([Mat|Mats], Opac, OpenGL, Maps) ->
500 case Mat of
501 {diffuse_map,Map} ->
502 translate_material(Mats, Opac, OpenGL, [{diffuse,Map}|Maps]);
503 {diffuse,_}=Diff ->
504 translate_material(Mats, Opac, [trans(Diff, Opac)|OpenGL], Maps);
505 {ambient,_}=Amb ->
506 translate_material(Mats, Opac, [trans(Amb, Opac)|OpenGL], Maps);
507 {specular,_}=Spec ->
508 translate_material(Mats, Opac, [trans(Spec, Opac)|OpenGL], Maps);
509 {shininess,Sh} ->
510 translate_material(Mats, Opac, [{shininess,1.0-Sh}|OpenGL], Maps);
511 _ ->
512 translate_material(Mats, OpenGL, Opac, Maps)
513 end;
514 translate_material([], _, OpenGL, Maps) ->
515 [{opengl,OpenGL},{maps,Maps}].
516
517 trans({Key,{R,G,B}}, Opac) -> {Key,{R,G,B,Opac}}.
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
518
519 %%
520 %% Object modes were removed after the 1.1.7 release and
521 %% replaced with information about vertex colors in the
522 %% materials. At the same time the 'default' material was
523 %% changed to show vertex colors for the faces it was applied
524 %% to.
525 %%
526 %% Left alone, there would be two annoyances when loading
527 %% old models:
528 %%
529 %% 1. Vertex colors would not be shown.
530 %%
531 %% 2. Since the 'default' materials do not match, the 'default'
532 %% material in the file will be renamed to 'default2' (or
0493e4e @bjorng Convert old holes when loading .wings files
bjorng authored
533 %% something similar) and there would be a new 'default'
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
534 %% material.
535 %%
536 %% We will avoid both those annoyances by changing the 'default'
537 %% material in the file so that it is more likely to match
538 %% current 'default' material. We will only do this change if
539 %% the file contains an implicit object mode for some object,
540 %% i.e. was saved by 1.1.7 or earlier.
541 %%
542 translate_object_modes(Mats, Objects) ->
543 OldFile = any(fun(Obj) ->
544 {object,_Name,_Winged,Props} = Obj,
545 keymember(mode, 1, Props)
546 end, Objects),
547 case OldFile of
548 false -> Mats;
549 true -> [translate_object_mode(M) || M <- Mats]
550 end.
551
552 translate_object_mode({default=Name,Props0}) ->
553 OpenGL0 = proplists:get_value(opengl, Props0, []),
554 OpenGL = [{vertex_colors,set}|OpenGL0],
555 Props = [{opengl,OpenGL}|lists:keydelete(opengl, 1, Props0)],
556 {Name,Props};
557 translate_object_mode(Mat) -> Mat.
0493e4e @bjorng Convert old holes when loading .wings files
bjorng authored
558
559 %%
560 %% There used to be a '_hole_' material up to the 1.1.10 release.
561 %% The '_hole_' material was pre-defined and was specially handled
562 %% when exporting (faces having the material would not be exported)
563 %% and importing (missing faces would be created and assigned the
564 %% material).
565 %%
566 %% Translate faces with the '_hole_' material to the new type
567 %% of holes introduced after the 1.1.10 release.
568 %%
569 translate_old_holes(#we{holes=[]}=We) ->
570 case wings_facemat:is_material_used('_hole_', We) of
571 false -> We;
572 true -> translate_old_holes_1(We)
573 end;
574 translate_old_holes(We) -> We.
575
576 translate_old_holes_1(#we{fs=Ftab}=We0) ->
577 MatFaces = wings_facemat:mat_faces(gb_trees:to_list(Ftab), We0),
578 {_,Holes0} = keyfind('_hole_', 1, MatFaces),
579 Holes = [F || {F,_} <- Holes0],
580 We1 = wings_dissolve:faces(Holes, We0),
581 NewHoleFaces = wings_we:new_items_as_ordset(face, We0, We1),
582 We = wings_facemat:assign(default, NewHoleFaces, We1),
583 HiddenNewHoleFaces = ordsets:from_list([-F-1 || F <- NewHoleFaces]),
584 wings_we:hide_faces(NewHoleFaces, We#we{holes=HiddenNewHoleFaces}).
f0b66db @bjorng Validate hole faces when loading wings files
bjorng authored
585
586 %% validate_holes(We0) -> We
587 %% Remove any invalid entries in We#we.holes. Ideally, there should
588 %% be no invalid entries, but because of bugs there could be.
589 %%
590 validate_holes(#we{fs=Ftab,holes=Holes0}=We) ->
591 %% Only keep faces that exist and are invisible.
592 Holes = [F || F <- Holes0, F < 0, gb_trees:is_defined(F, Ftab)],
593 We#we{holes=Holes}.
a552d9c @giniu initial import
giniu authored
594
595 %%%
596 %%% Save a Wings file (in version 2).
597 %%%
598
599 export(Name, St0) ->
600 wings_pb:start( ?__(1,"saving")),
601 wings_pb:update(0.01, ?__(2,"lights")),
f883994 @bjorng Fix crash in Yafray export of area lights
bjorng authored
602 Lights = wings_light:export_bc(St0),
7b5fbe5 save unused materials option for .wings files
Richard Jones authored
603 Materials = case wings_pref:get_value(save_unused_materials) of
604 true ->
605 #st{mat=Mat} = St0,
606 gb_trees:to_list(Mat);
607 false ->
608 wings_material:used_materials(St0)
609 end,
a552d9c @giniu initial import
giniu authored
610 #st{shapes=Shs0,views={CurrentView,_}} = St =
7b5fbe5 save unused materials option for .wings files
Richard Jones authored
611 remove_lights(St0),
a552d9c @giniu initial import
giniu authored
612 Sel0 = collect_sel(St),
613 wings_pb:update(0.65, ?__(3,"renumbering")),
57ccce7 @bjorng Make the virtual mirror face invisible
bjorng authored
614 Shs1 = [{Id,show_mirror_face(We)} ||
615 {Id,We} <- gb_trees:to_list(Shs0)],
616 {Shs2,Sel} = renumber(Shs1, Sel0, 0, [], []),
617 Shs = foldl(fun shape/2, [], Shs2),
a552d9c @giniu initial import
giniu authored
618 wings_pb:update(0.98, ?__(4,"objects")),
619 Props0 = export_props(Sel),
620 Props1 = case Lights of
621 [] -> Props0;
622 [_|_] -> [{lights,Lights}|Props0]
623 end,
624 Props2 = case export_images() of
625 [] -> Props1;
626 Images -> [{images,Images}|Props1]
627 end,
628 Props3 = case wings_view:export_views(St) of
629 [] -> Props2;
630 Views -> [{current_view,CurrentView},{views,Views}|Props2]
631 end,
632 Props4 = case wings_palette:palette(St) of
633 [] -> Props3;
634 Palette -> [{palette, Palette}|Props3]
635 end,
636 Props5 = export_pst(St#st.pst,Props4),
637 Props = [{scene_prefs,wings_pref:get_scene_value()}|Props5],
638 Wings = {wings,2,{Shs,Materials,Props}},
639 wings_pb:update(0.99, ?__(5,"compressing")),
640 Bin = term_to_binary(Wings, [compressed]),
641 wings_pb:update(1.0, ?__(6,"writing file")),
642 wings_pb:done(write_file(Name, Bin)).
643
644 remove_lights(#st{sel=Sel0,shapes=Shs0}=St) ->
645 Shs1 = foldl(fun(We, A) when ?IS_ANY_LIGHT(We) -> A;
646 (#we{id=Id}=We, A) -> [{Id,We}|A]
647 end, [], gb_trees:values(Shs0)),
648 Shs = gb_trees:from_orddict(reverse(Shs1)),
649 Sel = [S || {Id,_}=S <- Sel0, gb_trees:is_defined(Id, Shs)],
650 St#st{sel=Sel,shapes=Shs}.
651
652 collect_sel(#st{selmode=Mode,sel=Sel0,ssels=Ssels}=St) ->
653 Sel1 = [{Id,{Mode,gb_sets:to_list(Elems),selection}} ||
654 {Id,Elems} <- Sel0],
655 Sel2 = collect_sel_groups(gb_trees:to_list(Ssels), St, Sel1),
656 Sel3 = sofs:relation(Sel2, [{id,data}]),
657 Sel = sofs:relation_to_family(Sel3),
658 sofs:to_external(Sel).
659
660 collect_sel_groups([{{Mode,Name},Sel}|Gs], St, Acc0) ->
661 Acc = [{Id,{Mode,gb_sets:to_list(Elems),{selection_group,Name}}} ||
662 {Id,Elems} <- wings_sel:valid_sel(Sel, Mode, St)] ++ Acc0,
663 collect_sel_groups(Gs, St, Acc);
664 collect_sel_groups([], _, Acc) -> Acc.
665
57ccce7 @bjorng Make the virtual mirror face invisible
bjorng authored
666 show_mirror_face(#we{mirror=none}=We) -> We;
667 show_mirror_face(#we{mirror=Face}=We) ->
668 %% The mirror face should not be hidden in a .wings file.
669 %% (For compatibility with previous versions.)
670 wings_we:show_faces([Face], We#we{mirror=-Face-1}).
671
a552d9c @giniu initial import
giniu authored
672 renumber([{Id,We0}|Shs], [{Id,Root0}|Sel], NewId, WeAcc, RootAcc) ->
673 Hidden = wings_we:num_hidden(We0),
674 {We,Root} = wings_we:renumber(We0, 0, Root0),
675 renumber(Shs, Sel, NewId+1, [{Hidden,We}|WeAcc],
676 [{NewId,Root}|RootAcc]);
677 renumber([{_,We0}|Shs], Sel, NewId, WeAcc, RootAcc) ->
678 Hidden = wings_we:num_hidden(We0),
679 We = wings_we:renumber(We0, 0),
680 renumber(Shs, Sel, NewId+1, [{Hidden,We}|WeAcc], RootAcc);
681 renumber([], [], _NewId, WeAcc, RootAcc) ->
682 {WeAcc,RootAcc}.
683
684 export_props(Sel0) ->
685 Sel1 = sofs:family(Sel0, [{id,[{mode,list,key}]}]),
686 Sel2 = sofs:family_to_relation(Sel1),
687 Sel3 = sofs:projection(
688 {external,fun({Id,{Mode,Elems,Key}}) ->
689 {{Key,Mode},{Id,Elems}}
690 end}, Sel2),
691 Sel = sofs:relation_to_family(Sel3),
692 export_props_1(sofs:to_external(Sel), []).
693
694 export_props_1([{{What,Mode},Sel}|T], Acc) ->
695 export_props_1(T, [{What,{Mode,Sel}}|Acc]);
696 export_props_1([], Acc) -> Acc.
697
698 export_pst(undefined, Props0) -> Props0;
699 export_pst(Pst0,Props0) ->
700 try
701 Pst1 = gb_trees:to_list(Pst0),
702 Pst = lists:filter(fun({Mod,_}) when is_atom(Mod) -> true;
703 (_) -> false end, Pst1),
704 [{plugin_states,Pst}|Props0]
705 catch error:Reason ->
706 io:format("Failed exporting plugins state NOT a gb_tree ~p ~n",
707 [Reason]),
708 Props0
709 end.
710
711 write_file(Name, Bin) ->
5f74848 @bjorng Using tuple_size/1 or byte_size/1 instead of size/1. (R12B required.)
bjorng authored
712 Data = <<?WINGS_HEADER,(byte_size(Bin)):32,Bin/binary>>,
a552d9c @giniu initial import
giniu authored
713 case file:write_file(Name, Data) of
714 ok -> ok;
715 {error,Reason} -> {error,file:format_error(Reason)}
716 end.
717
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
718 shape({Hidden,#we{name=Name,vp=Vs0,es=Es0,he=Htab,pst=Pst}=We}, Acc) ->
73c6320 @bjorng Use arrays instead of gb_trees for the vertex tables.
bjorng authored
719 Vs1 = foldl(fun export_vertex/2, [], array:sparse_to_list(Vs0)),
a552d9c @giniu initial import
giniu authored
720 Vs = reverse(Vs1),
721 UvFaces = gb_sets:from_ordset(wings_we:uv_mapped_faces(We)),
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
722 Es1 = array:sparse_foldl(fun(E, Rec, A) ->
723 export_edge(E, Rec, UvFaces, We, A)
724 end, [], Es0),
a552d9c @giniu initial import
giniu authored
725 Es = reverse(Es1),
726 Fs1 = foldl(fun export_face/2, [], wings_facemat:all(We)),
727 Fs = reverse(Fs1),
728 He = gb_sets:to_list(Htab),
972bdf3 @bjorng Ignore the object mode when reading and writing .wings files
bjorng authored
729 Props0 = export_perm(We),
a552d9c @giniu initial import
giniu authored
730 Props1 = hidden_faces(Hidden, Props0),
731 Props2 = mirror(We, Props1),
d2c9d17 @bjorng Add support for saving and loading objects with holes
bjorng authored
732 Props3 = export_holes(We, Props2),
733 Props = export_pst(Pst, Props3),
a552d9c @giniu initial import
giniu authored
734 [{object,Name,{winged,Es,Fs,Vs,He},Props}|Acc].
735
736 mirror(#we{mirror=none}, Props) -> Props;
737 mirror(#we{mirror=Face}, Props) -> [{mirror_face,Face}|Props].
738
739 hidden_faces(0, Props) -> Props;
740 hidden_faces(N, Props) -> [{num_hidden_faces,N}|Props].
741
d2c9d17 @bjorng Add support for saving and loading objects with holes
bjorng authored
742 export_holes(#we{holes=[]}, Props) -> Props;
743 export_holes(#we{holes=Holes}, Props) -> [{holes,Holes}|Props].
744
a552d9c @giniu initial import
giniu authored
745 export_perm(#we{perm=[]}) ->
746 [{state,hidden_locked}]; %Only for backward compatibility.
747 export_perm(#we{perm=0}) -> [];
748 export_perm(#we{perm=1}) -> [{state,locked}];
749 export_perm(#we{perm=2}) -> [{state,hidden}];
750 export_perm(#we{perm=3}) -> [{state,hidden_locked}];
751 export_perm(#we{perm={Mode,Elems}}) ->
752 [{state,{hidden,Mode,gb_sets:to_list(Elems)}}].
753
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
754 export_edge(E, Rec, UvFaces, We, Acc) ->
a552d9c @giniu initial import
giniu authored
755 #edge{vs=Va,ve=Vb,lf=Lf,rf=Rf,
756 ltpr=Ltpr,ltsu=Ltsu,rtpr=Rtpr,rtsu=Rtsu} = Rec,
757 Data0 = [{edge,Va,Vb,Lf,Rf,Ltpr,Ltsu,Rtpr,Rtsu}],
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
758 Data = edge_data(E, Rec, We, UvFaces, Data0),
a552d9c @giniu initial import
giniu authored
759 [Data|Acc].
760
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
761 edge_data(E, #edge{lf=Lf,rf=Rf}, We, UvFaces, Acc0) ->
762 A = wings_va:edge_attrs(E, left, We),
763 B = wings_va:edge_attrs(E, right, We),
764
765 %% If there are both vertex colors and UV coordinates,
766 %% we want them in the following order:
767 %% [{color_*,_},{uv_*,_}]
768 %% On import in an old version of Wings, the UV coordinates
769 %% will be used.
770 Acc1 = edge_data_uv(left, Lf, wings_va:attr(uv, A), UvFaces, Acc0),
771 Acc2 = edge_data_uv(right, Rf, wings_va:attr(uv, B), UvFaces, Acc1),
772 Acc = edge_data_color(left, wings_va:attr(color, A), Acc2),
773 edge_data_color(right, wings_va:attr(color, B), Acc).
774
775 edge_data_uv(Side, Face, {U,V}, UvFaces, Acc) ->
a552d9c @giniu initial import
giniu authored
776 case gb_sets:is_member(Face, UvFaces) of
777 false -> Acc;
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
778 true when Side =:= left -> [{uv_lt,<<U/float,V/float>>}|Acc];
779 true when Side =:= right -> [{uv_rt,<<U/float,V/float>>}|Acc]
a552d9c @giniu initial import
giniu authored
780 end;
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
781 edge_data_uv(_, _, _, _, Acc) -> Acc.
782
783 edge_data_color(left, {R,G,B}, Acc) ->
a552d9c @giniu initial import
giniu authored
784 [{color_lt,<<R:32/float,G:32/float,B:32/float>>}|Acc];
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
785 edge_data_color(right, {R,G,B}, Acc) ->
a552d9c @giniu initial import
giniu authored
786 [{color_rt,<<R:32/float,G:32/float,B:32/float>>}|Acc];
f15bca3 @bjorng Rewrite all core modules to use wings_va
bjorng authored
787 edge_data_color(_, _, Acc) -> Acc.
a552d9c @giniu initial import
giniu authored
788
789 export_face({_,default}, Acc) -> [[]|Acc];
790 export_face({_,Mat}, Acc) -> [[{material,Mat}]|Acc].
791
792 export_vertex({X,Y,Z}, Acc) ->
793 [[<<X/float,Y/float,Z/float>>]|Acc].
794
795 export_images() ->
796 export_images_1(wings_image:images()).
797
798 export_images_1([{Id,Im}|T]) ->
799 [{Id,export_image(Im)}|export_images_1(T)];
800 export_images_1([]) -> [].
801
802 export_image(#e3d_image{filename=none,type=Type0,order=Order}=Im0) ->
803 Im = case {export_img_type(Type0),Order} of
804 {Type0=Type,lower_left} -> Im0;
805 {Type,_} -> e3d_image:convert(Im0, Type, 1, lower_left)
806 end,
807 #e3d_image{width=W,height=H,bytes_pp=PP,image=Pixels,name=Name} = Im,
808 MaskSize = mask_size(Type),
809 [{name,Name},{width,W},{height,H},{samples_per_pixel,PP},
810 {mask_size,MaskSize},{pixels,Pixels}];
811 export_image(#e3d_image{name=Name,filename=Filename}=Im) ->
812 case filelib:is_file(Filename) of
813 false ->
814 export_image(Im#e3d_image{filename=none});
815 true ->
816 [{name,Name},{filename,Filename}]
817 end.
818
819 export_img_type(b8g8r8) -> r8g8b8;
820 export_img_type(b8g8r8a8) -> r8g8b8a8;
821 export_img_type(Type) -> Type.
822
823 mask_size(r8g8b8a8) -> 1;
824 mask_size(a8) -> 1;
825 mask_size(_) -> 0.
Something went wrong with that request. Please try again.