1 /*
2     Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
3     All rights reserved.
4 
5     This program is free  software: you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as published
7     by the Free Software Foundation, either version 2.1 of the License, or
8     (at your option) any later version.
9 
10     Thisprogram  is  distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU Lesser General Public License for more details.
14 
15     You should  have received a copy of the GNU Lesser General Public License
16     along with  this program; If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "lib3ds_impl.h"
19 
20 
21 static void
initialize_texture_map(Lib3dsTextureMap * map)22 initialize_texture_map(Lib3dsTextureMap *map) {
23     map->flags = 0x10;
24     map->percent = 1.0f;
25     map->scale[0] = 1.0f;
26     map->scale[1] = 1.0f;
27 }
28 
29 
30 /*!
31  * Creates and returns a new, empty Lib3dsMaterial object.
32  *
33  * Initial value of the material is a shiny grey.
34  *
35  * \return A pointer to the Lib3dsMaterial structure.
36  *  If the structure cannot be allocated, NULL is returned.
37  */
38 Lib3dsMaterial*
lib3ds_material_new(const char * name)39 lib3ds_material_new(const char* name) {
40     Lib3dsMaterial *mat;
41 
42     mat = (Lib3dsMaterial*)calloc(sizeof(Lib3dsMaterial), 1);
43     if (!mat) {
44         return(0);
45     }
46 
47     if (name) {
48         strcpy(mat->name, name);
49     }
50     mat->ambient[0] = mat->ambient[1] = mat->ambient[2] = 0.588235f;
51     mat->diffuse[0] = mat->diffuse[1] = mat->diffuse[2] = 0.588235f;
52     mat->specular[0] = mat->specular[1] = mat->specular[2] = 0.898039f;
53     mat->shininess = 0.1f;
54     mat->wire_size = 1.0f;
55     mat->shading = 3;
56 
57     initialize_texture_map(&mat->texture1_map);
58     initialize_texture_map(&mat->texture1_mask);
59     initialize_texture_map(&mat->texture2_map);
60     initialize_texture_map(&mat->texture2_mask);
61     initialize_texture_map(&mat->opacity_map);
62     initialize_texture_map(&mat->opacity_mask);
63     initialize_texture_map(&mat->bump_map);
64     initialize_texture_map(&mat->bump_mask);
65     initialize_texture_map(&mat->specular_map);
66     initialize_texture_map(&mat->specular_mask);
67     initialize_texture_map(&mat->shininess_map);
68     initialize_texture_map(&mat->shininess_mask);
69     initialize_texture_map(&mat->self_illum_map);
70     initialize_texture_map(&mat->self_illum_mask);
71     initialize_texture_map(&mat->reflection_map);
72     initialize_texture_map(&mat->reflection_mask);
73 
74     return(mat);
75 }
76 
77 
78 void
lib3ds_material_free(Lib3dsMaterial * material)79 lib3ds_material_free(Lib3dsMaterial *material) {
80     memset(material, 0, sizeof(Lib3dsMaterial));
81     free(material);
82 }
83 
84 
85 static void
color_read(float rgb[3],Lib3dsIo * io)86 color_read(float rgb[3], Lib3dsIo *io) {
87     Lib3dsChunk c;
88     uint16_t chunk;
89     int have_lin = FALSE;
90 
91     lib3ds_chunk_read_start(&c, 0, io);
92 
93     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
94         switch (chunk) {
95             case CHK_LIN_COLOR_24: {
96                 int i;
97                 for (i = 0; i < 3; ++i) {
98                     rgb[i] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
99                 }
100                 have_lin = TRUE;
101                 break;
102             }
103 
104             case CHK_COLOR_24: {
105                 /* gamma corrected color chunk
106                    replaced in 3ds R3 by LIN_COLOR_24 */
107                 if (!have_lin) {
108                     int i;
109                     for (i = 0; i < 3; ++i) {
110                         rgb[i] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
111                     }
112                 }
113                 break;
114             }
115 
116             case CHK_LIN_COLOR_F: {
117                 int i;
118                 for (i = 0; i < 3; ++i) {
119                     rgb[i] = lib3ds_io_read_float(io);
120                 }
121                 have_lin = TRUE;
122                 break;
123             }
124 
125             case CHK_COLOR_F: {
126                 if (!have_lin) {
127                     int i;
128                     for (i = 0; i < 3; ++i) {
129                         rgb[i] = lib3ds_io_read_float(io);
130                     }
131                 }
132                 break;
133             }
134 
135             default:
136                 lib3ds_chunk_unknown(chunk, io);
137         }
138     }
139 
140     lib3ds_chunk_read_end(&c, io);
141 }
142 
143 
144 static void
int_percentage_read(float * p,Lib3dsIo * io)145 int_percentage_read(float *p, Lib3dsIo *io) {
146     Lib3dsChunk c;
147     uint16_t chunk;
148 
149     lib3ds_chunk_read_start(&c, 0, io);
150 
151     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
152         switch (chunk) {
153             case CHK_INT_PERCENTAGE: {
154                 int16_t i = lib3ds_io_read_intw(io);
155                 *p = (float)(1.0 * i / 100.0);
156                 break;
157             }
158 
159             default:
160                 lib3ds_chunk_unknown(chunk, io);
161         }
162     }
163 
164     lib3ds_chunk_read_end(&c, io);
165 }
166 
167 
168 static void
texture_map_read(Lib3dsTextureMap * map,Lib3dsIo * io)169 texture_map_read(Lib3dsTextureMap *map, Lib3dsIo *io) {
170     Lib3dsChunk c;
171     uint16_t chunk;
172 
173     lib3ds_chunk_read_start(&c, 0, io);
174 
175     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
176         switch (chunk) {
177             case CHK_INT_PERCENTAGE: {
178                 map->percent = 1.0f * lib3ds_io_read_intw(io) / 100.0f;
179                 break;
180             }
181 
182             case CHK_MAT_MAPNAME: {
183                 lib3ds_io_read_string(io, map->name, 64);
184                 lib3ds_io_log(io, LIB3DS_LOG_INFO, "  NAME=%s", map->name);
185                 break;
186             }
187 
188             case CHK_MAT_MAP_TILING: {
189                 map->flags = lib3ds_io_read_word(io);
190                 break;
191             }
192 
193             case CHK_MAT_MAP_TEXBLUR:
194                 map->blur = lib3ds_io_read_float(io);
195                 break;
196 
197             case CHK_MAT_MAP_USCALE:
198                 map->scale[0] = lib3ds_io_read_float(io);
199                 break;
200 
201             case CHK_MAT_MAP_VSCALE: {
202                 map->scale[1] = lib3ds_io_read_float(io);
203                 break;
204             }
205             case CHK_MAT_MAP_UOFFSET: {
206                 map->offset[0] = lib3ds_io_read_float(io);
207                 break;
208             }
209 
210             case CHK_MAT_MAP_VOFFSET: {
211                 map->offset[1] = lib3ds_io_read_float(io);
212                 break;
213             }
214 
215             case CHK_MAT_MAP_ANG: {
216                 map->rotation = lib3ds_io_read_float(io);
217                 break;
218             }
219 
220             case CHK_MAT_MAP_COL1: {
221                 map->tint_1[0] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
222                 map->tint_1[1] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
223                 map->tint_1[2] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
224                 break;
225             }
226 
227             case CHK_MAT_MAP_COL2: {
228                 map->tint_2[0] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
229                 map->tint_2[1] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
230                 map->tint_2[2] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
231                 break;
232             }
233 
234             case CHK_MAT_MAP_RCOL: {
235                 map->tint_r[0] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
236                 map->tint_r[1] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
237                 map->tint_r[2] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
238                 break;
239             }
240 
241             case CHK_MAT_MAP_GCOL: {
242                 map->tint_g[0] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
243                 map->tint_g[1] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
244                 map->tint_g[2] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
245                 break;
246             }
247 
248             case CHK_MAT_MAP_BCOL: {
249                 map->tint_b[0] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
250                 map->tint_b[1] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
251                 map->tint_b[2] = 1.0f * lib3ds_io_read_byte(io) / 255.0f;
252                 break;
253             }
254 
255             default:
256                 lib3ds_chunk_unknown(chunk,io);
257         }
258     }
259 
260     lib3ds_chunk_read_end(&c, io);
261 }
262 
263 
264 void
lib3ds_material_read(Lib3dsMaterial * material,Lib3dsIo * io)265 lib3ds_material_read(Lib3dsMaterial *material, Lib3dsIo *io) {
266     Lib3dsChunk c;
267     uint16_t chunk;
268 
269     assert(material);
270     lib3ds_chunk_read_start(&c, CHK_MAT_ENTRY, io);
271 
272     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
273         switch (chunk) {
274             case CHK_MAT_NAME: {
275                 lib3ds_io_read_string(io, material->name, 64);
276                 lib3ds_io_log(io, LIB3DS_LOG_INFO, "  NAME=%s", material->name);
277                 break;
278             }
279 
280             case CHK_MAT_AMBIENT: {
281                 lib3ds_chunk_read_reset(&c, io);
282                 color_read(material->ambient, io);
283                 break;
284             }
285 
286             case CHK_MAT_DIFFUSE: {
287                 lib3ds_chunk_read_reset(&c, io);
288                 color_read(material->diffuse, io);
289                 break;
290             }
291 
292             case CHK_MAT_SPECULAR: {
293                 lib3ds_chunk_read_reset(&c, io);
294                 color_read(material->specular, io);
295                 break;
296             }
297 
298             case CHK_MAT_SHININESS: {
299                 lib3ds_chunk_read_reset(&c, io);
300                 int_percentage_read(&material->shininess, io);
301                 break;
302             }
303 
304             case CHK_MAT_SHIN2PCT: {
305                 lib3ds_chunk_read_reset(&c, io);
306                 int_percentage_read(&material->shin_strength, io);
307                 break;
308             }
309 
310             case CHK_MAT_TRANSPARENCY: {
311                 lib3ds_chunk_read_reset(&c, io);
312                 int_percentage_read(&material->transparency, io);
313                 break;
314             }
315 
316             case CHK_MAT_XPFALL: {
317                 lib3ds_chunk_read_reset(&c, io);
318                 int_percentage_read(&material->falloff, io);
319                 break;
320             }
321 
322             case CHK_MAT_SELF_ILPCT: {
323                 lib3ds_chunk_read_reset(&c, io);
324                 int_percentage_read(&material->self_illum, io);
325                 break;
326             }
327 
328             case CHK_MAT_USE_XPFALL: {
329                 material->use_falloff = TRUE;
330                 break;
331             }
332 
333             case CHK_MAT_REFBLUR: {
334                 lib3ds_chunk_read_reset(&c, io);
335                 int_percentage_read(&material->blur, io);
336                 break;
337             }
338 
339             case CHK_MAT_USE_REFBLUR: {
340                 material->use_blur = TRUE;
341                 break;
342             }
343 
344             case CHK_MAT_SHADING: {
345                 material->shading = lib3ds_io_read_intw(io);
346                 break;
347             }
348 
349             case CHK_MAT_SELF_ILLUM: {
350                 material->self_illum_flag = TRUE;
351                 break;
352             }
353 
354             case CHK_MAT_TWO_SIDE: {
355                 material->two_sided = TRUE;
356                 break;
357             }
358 
359             case CHK_MAT_DECAL: {
360                 material->map_decal = TRUE;
361                 break;
362             }
363 
364             case CHK_MAT_ADDITIVE: {
365                 material->is_additive = TRUE;
366                 break;
367             }
368 
369             case CHK_MAT_FACEMAP: {
370                 material->face_map = TRUE;
371                 break;
372             }
373 
374             case CHK_MAT_TRANSPARENCY_FALLOFF: {
375                 material->transparency_falloff = TRUE;
376                 break;
377             }
378 
379             case CHK_MAT_PHONGSOFT: {
380                 material->soften = TRUE;
381                 break;
382             }
383 
384             case CHK_MAT_WIRE: {
385                 material->use_wire = TRUE;
386                 break;
387             }
388 
389             case CHK_MAT_WIREABS: {
390                 material->use_wire_abs = TRUE;
391                 break;
392             }
393             case CHK_MAT_WIRE_SIZE: {
394                 material->wire_size = lib3ds_io_read_float(io);
395                 break;
396             }
397 
398             case CHK_MAT_TEXMAP: {
399                 lib3ds_chunk_read_reset(&c, io);
400                 texture_map_read(&material->texture1_map, io);
401                 break;
402             }
403 
404             case CHK_MAT_TEXMASK: {
405                 lib3ds_chunk_read_reset(&c, io);
406                 texture_map_read(&material->texture1_mask, io);
407                 break;
408             }
409 
410             case CHK_MAT_TEX2MAP: {
411                 lib3ds_chunk_read_reset(&c, io);
412                 texture_map_read(&material->texture2_map, io);
413                 break;
414             }
415 
416             case CHK_MAT_TEX2MASK: {
417                 lib3ds_chunk_read_reset(&c, io);
418                 texture_map_read(&material->texture2_mask, io);
419                 break;
420             }
421 
422             case CHK_MAT_OPACMAP: {
423                 lib3ds_chunk_read_reset(&c, io);
424                 texture_map_read(&material->opacity_map, io);
425                 break;
426             }
427 
428             case CHK_MAT_OPACMASK: {
429                 lib3ds_chunk_read_reset(&c, io);
430                 texture_map_read(&material->opacity_mask, io);
431                 break;
432             }
433 
434             case CHK_MAT_BUMPMAP: {
435                 lib3ds_chunk_read_reset(&c, io);
436                 texture_map_read(&material->bump_map, io);
437                 break;
438             }
439             case CHK_MAT_BUMPMASK: {
440                 lib3ds_chunk_read_reset(&c, io);
441                 texture_map_read(&material->bump_mask, io);
442                 break;
443             }
444             case CHK_MAT_SPECMAP: {
445                 lib3ds_chunk_read_reset(&c, io);
446                 texture_map_read(&material->specular_map, io);
447                 break;
448             }
449 
450             case CHK_MAT_SPECMASK: {
451                 lib3ds_chunk_read_reset(&c, io);
452                 texture_map_read(&material->specular_mask, io);
453                 break;
454             }
455 
456             case CHK_MAT_SHINMAP: {
457                 lib3ds_chunk_read_reset(&c, io);
458                 texture_map_read(&material->shininess_map, io);
459                 break;
460             }
461 
462             case CHK_MAT_SHINMASK: {
463                 lib3ds_chunk_read_reset(&c, io);
464                 texture_map_read(&material->shininess_mask, io);
465                 break;
466             }
467 
468             case CHK_MAT_SELFIMAP: {
469                 lib3ds_chunk_read_reset(&c, io);
470                 texture_map_read(&material->self_illum_map, io);
471                 break;
472             }
473 
474             case CHK_MAT_SELFIMASK: {
475                 lib3ds_chunk_read_reset(&c, io);
476                 texture_map_read(&material->self_illum_mask, io);
477                 break;
478             }
479 
480             case CHK_MAT_REFLMAP: {
481                 lib3ds_chunk_read_reset(&c, io);
482                 texture_map_read(&material->reflection_map, io);
483                 break;
484             }
485 
486             case CHK_MAT_REFLMASK: {
487                 lib3ds_chunk_read_reset(&c, io);
488                 texture_map_read(&material->reflection_mask, io);
489                 break;
490             }
491 
492             case CHK_MAT_ACUBIC: {
493                 lib3ds_io_read_intb(io);
494                 material->autorefl_map_anti_alias = lib3ds_io_read_intb(io);
495                 material->autorefl_map_flags = lib3ds_io_read_intw(io);
496                 material->autorefl_map_size = lib3ds_io_read_intd(io);
497                 material->autorefl_map_frame_step = lib3ds_io_read_intd(io);
498                 break;
499             }
500 
501             default:
502                 lib3ds_chunk_unknown(chunk, io);
503         }
504     }
505 
506     lib3ds_chunk_read_end(&c, io);
507 }
508 
509 
510 static void
color_write(float rgb[3],Lib3dsIo * io)511 color_write(float rgb[3], Lib3dsIo *io) {
512     Lib3dsChunk c;
513 
514     c.chunk = CHK_COLOR_24;
515     c.size = 9;
516     lib3ds_chunk_write(&c, io);
517     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5));
518     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5));
519     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5));
520 
521     c.chunk = CHK_LIN_COLOR_24;
522     c.size = 9;
523     lib3ds_chunk_write(&c, io);
524     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[0] + 0.5));
525     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[1] + 0.5));
526     lib3ds_io_write_byte(io, (uint8_t)floor(255.0*rgb[2] + 0.5));
527 }
528 
529 
530 static void
int_percentage_write(float p,Lib3dsIo * io)531 int_percentage_write(float p, Lib3dsIo *io) {
532     Lib3dsChunk c;
533 
534     c.chunk = CHK_INT_PERCENTAGE;
535     c.size = 8;
536     lib3ds_chunk_write(&c, io);
537     lib3ds_io_write_intw(io, (uint8_t)floor(100.0*p + 0.5));
538 }
539 
540 
541 static void
texture_map_write(uint16_t chunk,Lib3dsTextureMap * map,Lib3dsIo * io)542 texture_map_write(uint16_t chunk, Lib3dsTextureMap *map, Lib3dsIo *io) {
543     Lib3dsChunk c;
544 
545     if (strlen(map->name) == 0) {
546         return;
547     }
548     c.chunk = chunk;
549     lib3ds_chunk_write_start(&c, io);
550 
551     int_percentage_write(map->percent, io);
552 
553     { /*---- CHK_MAT_MAPNAME ----*/
554         Lib3dsChunk c;
555         c.chunk = CHK_MAT_MAPNAME;
556         c.size = 6 + (uint32_t)strlen(map->name) + 1;
557         lib3ds_chunk_write(&c, io);
558         lib3ds_io_write_string(io, map->name);
559     }
560 
561     { /*---- CHK_MAT_MAP_TILING ----*/
562         Lib3dsChunk c;
563         c.chunk = CHK_MAT_MAP_TILING;
564         c.size = 8;
565         lib3ds_chunk_write(&c, io);
566         lib3ds_io_write_word(io, (uint16_t)map->flags);
567     }
568 
569     { /*---- CHK_MAT_MAP_TEXBLUR ----*/
570         Lib3dsChunk c;
571         c.chunk = CHK_MAT_MAP_TEXBLUR;
572         c.size = 10;
573         lib3ds_chunk_write(&c, io);
574         lib3ds_io_write_float(io, map->blur);
575     }
576 
577     { /*---- CHK_MAT_MAP_USCALE ----*/
578         Lib3dsChunk c;
579         c.chunk = CHK_MAT_MAP_USCALE;
580         c.size = 10;
581         lib3ds_chunk_write(&c, io);
582         lib3ds_io_write_float(io, map->scale[0]);
583     }
584 
585     { /*---- CHK_MAT_MAP_VSCALE ----*/
586         Lib3dsChunk c;
587         c.chunk = CHK_MAT_MAP_VSCALE;
588         c.size = 10;
589         lib3ds_chunk_write(&c, io);
590         lib3ds_io_write_float(io, map->scale[1]);
591     }
592 
593     { /*---- CHK_MAT_MAP_UOFFSET ----*/
594         Lib3dsChunk c;
595         c.chunk = CHK_MAT_MAP_UOFFSET;
596         c.size = 10;
597         lib3ds_chunk_write(&c, io);
598         lib3ds_io_write_float(io, map->offset[0]);
599     }
600 
601     { /*---- CHK_MAT_MAP_VOFFSET ----*/
602         Lib3dsChunk c;
603         c.chunk = CHK_MAT_MAP_VOFFSET;
604         c.size = 10;
605         lib3ds_chunk_write(&c, io);
606         lib3ds_io_write_float(io, map->offset[1]);
607     }
608 
609     { /*---- CHK_MAT_MAP_ANG ----*/
610         Lib3dsChunk c;
611         c.chunk = CHK_MAT_MAP_ANG;
612         c.size = 10;
613         lib3ds_chunk_write(&c, io);
614         lib3ds_io_write_float(io, map->rotation);
615     }
616 
617     { /*---- CHK_MAT_MAP_COL1 ----*/
618         Lib3dsChunk c;
619         c.chunk = CHK_MAT_MAP_COL1;
620         c.size = 9;
621         lib3ds_chunk_write(&c, io);
622         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[0] + 0.5));
623         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[1] + 0.5));
624         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_1[2] + 0.5));
625     }
626 
627     { /*---- CHK_MAT_MAP_COL2 ----*/
628         Lib3dsChunk c;
629         c.chunk = CHK_MAT_MAP_COL2;
630         c.size = 9;
631         lib3ds_chunk_write(&c, io);
632         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[0] + 0.5));
633         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[1] + 0.5));
634         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_2[2] + 0.5));
635     }
636 
637     { /*---- CHK_MAT_MAP_RCOL ----*/
638         Lib3dsChunk c;
639         c.chunk = CHK_MAT_MAP_RCOL;
640         c.size = 9;
641         lib3ds_chunk_write(&c, io);
642         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[0] + 0.5));
643         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[1] + 0.5));
644         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_r[2] + 0.5));
645     }
646 
647     { /*---- CHK_MAT_MAP_GCOL ----*/
648         Lib3dsChunk c;
649         c.chunk = CHK_MAT_MAP_GCOL;
650         c.size = 9;
651         lib3ds_chunk_write(&c, io);
652         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[0] + 0.5));
653         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[1] + 0.5));
654         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_g[2] + 0.5));
655     }
656 
657     { /*---- CHK_MAT_MAP_BCOL ----*/
658         Lib3dsChunk c;
659         c.chunk = CHK_MAT_MAP_BCOL;
660         c.size = 9;
661         lib3ds_chunk_write(&c, io);
662         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[0] + 0.5));
663         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[1] + 0.5));
664         lib3ds_io_write_byte(io, (uint8_t)floor(255.0*map->tint_b[2] + 0.5));
665     }
666 
667     lib3ds_chunk_write_end(&c, io);
668 }
669 
670 
671 void
lib3ds_material_write(Lib3dsMaterial * material,Lib3dsIo * io)672 lib3ds_material_write(Lib3dsMaterial *material, Lib3dsIo *io) {
673     Lib3dsChunk c;
674 
675     c.chunk = CHK_MAT_ENTRY;
676     lib3ds_chunk_write_start(&c, io);
677 
678     { /*---- CHK_MAT_NAME ----*/
679         Lib3dsChunk c;
680         c.chunk = CHK_MAT_NAME;
681         c.size = 6 + (uint32_t)strlen(material->name) + 1;
682         lib3ds_chunk_write(&c, io);
683         lib3ds_io_write_string(io, material->name);
684     }
685 
686     { /*---- CHK_MAT_AMBIENT ----*/
687         Lib3dsChunk c;
688         c.chunk = CHK_MAT_AMBIENT;
689         c.size = 24;
690         lib3ds_chunk_write(&c, io);
691         color_write(material->ambient, io);
692     }
693 
694     { /*---- CHK_MAT_DIFFUSE ----*/
695         Lib3dsChunk c;
696         c.chunk = CHK_MAT_DIFFUSE;
697         c.size = 24;
698         lib3ds_chunk_write(&c, io);
699         color_write(material->diffuse, io);
700     }
701 
702     { /*---- CHK_MAT_SPECULAR ----*/
703         Lib3dsChunk c;
704         c.chunk = CHK_MAT_SPECULAR;
705         c.size = 24;
706         lib3ds_chunk_write(&c, io);
707         color_write(material->specular, io);
708     }
709 
710     { /*---- CHK_MAT_SHININESS ----*/
711         Lib3dsChunk c;
712         c.chunk = CHK_MAT_SHININESS;
713         c.size = 14;
714         lib3ds_chunk_write(&c, io);
715         int_percentage_write(material->shininess, io);
716     }
717 
718     { /*---- CHK_MAT_SHIN2PCT ----*/
719         Lib3dsChunk c;
720         c.chunk = CHK_MAT_SHIN2PCT;
721         c.size = 14;
722         lib3ds_chunk_write(&c, io);
723         int_percentage_write(material->shin_strength, io);
724     }
725 
726     { /*---- CHK_MAT_TRANSPARENCY ----*/
727         Lib3dsChunk c;
728         c.chunk = CHK_MAT_TRANSPARENCY;
729         c.size = 14;
730         lib3ds_chunk_write(&c, io);
731         int_percentage_write(material->transparency, io);
732     }
733 
734     { /*---- CHK_MAT_XPFALL ----*/
735         Lib3dsChunk c;
736         c.chunk = CHK_MAT_XPFALL;
737         c.size = 14;
738         lib3ds_chunk_write(&c, io);
739         int_percentage_write(material->falloff, io);
740     }
741 
742     if (material->use_falloff) { /*---- CHK_MAT_USE_XPFALL ----*/
743         Lib3dsChunk c;
744         c.chunk = CHK_MAT_USE_XPFALL;
745         c.size = 6;
746         lib3ds_chunk_write(&c, io);
747     }
748 
749     { /*---- CHK_MAT_SHADING ----*/
750         Lib3dsChunk c;
751         c.chunk = CHK_MAT_SHADING;
752         c.size = 8;
753         lib3ds_chunk_write(&c, io);
754         lib3ds_io_write_intw(io, (int16_t)material->shading);
755     }
756 
757     { /*---- CHK_MAT_REFBLUR ----*/
758         Lib3dsChunk c;
759         c.chunk = CHK_MAT_REFBLUR;
760         c.size = 14;
761         lib3ds_chunk_write(&c, io);
762         int_percentage_write(material->blur, io);
763     }
764 
765     if (material->use_blur) { /*---- CHK_MAT_USE_REFBLUR ----*/
766         Lib3dsChunk c;
767         c.chunk = CHK_MAT_USE_REFBLUR;
768         c.size = 6;
769         lib3ds_chunk_write(&c, io);
770     }
771 
772     if (material->self_illum_flag) { /*---- CHK_MAT_SELF_ILLUM ----*/
773         Lib3dsChunk c;
774         c.chunk = CHK_MAT_SELF_ILLUM;
775         c.size = 6;
776         lib3ds_chunk_write(&c, io);
777     }
778 
779     if (material->two_sided) { /*---- CHK_MAT_TWO_SIDE ----*/
780         Lib3dsChunk c;
781         c.chunk = CHK_MAT_TWO_SIDE;
782         c.size = 6;
783         lib3ds_chunk_write(&c, io);
784     }
785 
786     if (material->map_decal) { /*---- CHK_MAT_DECAL ----*/
787         Lib3dsChunk c;
788         c.chunk = CHK_MAT_DECAL;
789         c.size = 6;
790         lib3ds_chunk_write(&c, io);
791     }
792 
793     if (material->is_additive) { /*---- CHK_MAT_ADDITIVE ----*/
794         Lib3dsChunk c;
795         c.chunk = CHK_MAT_ADDITIVE;
796         c.size = 6;
797         lib3ds_chunk_write(&c, io);
798     }
799 
800     if (material->use_wire) { /*---- CHK_MAT_WIRE ----*/
801         Lib3dsChunk c;
802         c.chunk = CHK_MAT_WIRE;
803         c.size = 6;
804         lib3ds_chunk_write(&c, io);
805     }
806 
807     if (material->use_wire_abs) { /*---- CHK_MAT_WIREABS ----*/
808         Lib3dsChunk c;
809         c.chunk = CHK_MAT_WIREABS;
810         c.size = 6;
811         lib3ds_chunk_write(&c, io);
812     }
813 
814     { /*---- CHK_MAT_WIRE_SIZE ----*/
815         Lib3dsChunk c;
816         c.chunk = CHK_MAT_WIRE_SIZE;
817         c.size = 10;
818         lib3ds_chunk_write(&c, io);
819         lib3ds_io_write_float(io, material->wire_size);
820     }
821 
822     if (material->face_map) { /*---- CHK_MAT_FACEMAP ----*/
823         Lib3dsChunk c;
824         c.chunk = CHK_MAT_FACEMAP;
825         c.size = 6;
826         lib3ds_chunk_write(&c, io);
827     }
828 
829     if (material->transparency_falloff) { /*---- CHK_MAT_TRANSPARENCY_FALLOFF ----*/
830         Lib3dsChunk c;
831         c.chunk = CHK_MAT_TRANSPARENCY_FALLOFF;
832         c.size = 6;
833         lib3ds_chunk_write(&c, io);
834     }
835 
836     if (material->soften) { /*---- CHK_MAT_PHONGSOFT ----*/
837         Lib3dsChunk c;
838         c.chunk = CHK_MAT_PHONGSOFT;
839         c.size = 6;
840         lib3ds_chunk_write(&c, io);
841     }
842 
843     texture_map_write(CHK_MAT_TEXMAP, &material->texture1_map, io);
844     texture_map_write(CHK_MAT_TEXMASK, &material->texture1_mask, io);
845     texture_map_write(CHK_MAT_TEX2MAP, &material->texture2_map, io);
846     texture_map_write(CHK_MAT_TEX2MASK, &material->texture2_mask, io);
847     texture_map_write(CHK_MAT_OPACMAP, &material->opacity_map, io);
848     texture_map_write(CHK_MAT_OPACMASK, &material->opacity_mask, io);
849     texture_map_write(CHK_MAT_BUMPMAP, &material->bump_map, io);
850     texture_map_write(CHK_MAT_BUMPMASK, &material->bump_mask, io);
851     texture_map_write(CHK_MAT_SPECMAP, &material->specular_map, io);
852     texture_map_write(CHK_MAT_SPECMASK, &material->specular_mask, io);
853     texture_map_write(CHK_MAT_SHINMAP, &material->shininess_map, io);
854     texture_map_write(CHK_MAT_SHINMASK, &material->shininess_mask, io);
855     texture_map_write(CHK_MAT_SELFIMAP, &material->self_illum_map, io);
856     texture_map_write(CHK_MAT_SELFIMASK, &material->self_illum_mask, io);
857     texture_map_write(CHK_MAT_REFLMAP,  &material->reflection_map, io);
858     texture_map_write(CHK_MAT_REFLMASK,  &material->reflection_mask, io);
859 
860     { /*---- CHK_MAT_ACUBIC ----*/
861         Lib3dsChunk c;
862         c.chunk = CHK_MAT_ACUBIC;
863         c.size = 18;
864         lib3ds_chunk_write(&c, io);
865         lib3ds_io_write_intb(io, 0);
866         lib3ds_io_write_intb(io, (int8_t)material->autorefl_map_anti_alias);
867         lib3ds_io_write_intw(io, (int16_t)material->autorefl_map_flags);
868         lib3ds_io_write_intd(io, material->autorefl_map_size);
869         lib3ds_io_write_intd(io, material->autorefl_map_frame_step);
870     }
871 
872     lib3ds_chunk_write_end(&c, io);
873 }
874