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