1 /*
2  * The 3D Studio File Format Library
3  * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
4  * All rights reserved.
5  *
6  * This program is  free  software;  you can redistribute it and/or modify it
7  * under the terms of the  GNU Lesser General Public License  as published by
8  * the  Free Software Foundation;  either version 2.1 of the License,  or (at
9  * your option) any later version.
10  *
11  * This  program  is  distributed in  the  hope that it will  be useful,  but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public
14  * License for more details.
15  *
16  * You should  have received  a copy of the GNU Lesser General Public License
17  * along with  this program;  if not, write to the  Free Software Foundation,
18  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * $Id: background.c,v 1.12 2007/06/20 17:04:08 jeh Exp $
21  */
22 #include <lib3ds/background.h>
23 #include <lib3ds/chunk.h>
24 #include <lib3ds/io.h>
25 #include <string.h>
26 #include <math.h>
27 
28 
29 /*!
30  * \defgroup background Background Settings
31  */
32 
33 
34 static Lib3dsBool
solid_bgnd_read(Lib3dsBackground * background,Lib3dsIo * io)35 solid_bgnd_read(Lib3dsBackground *background, Lib3dsIo *io)
36 {
37   Lib3dsChunk c;
38   Lib3dsWord chunk;
39   Lib3dsBool have_lin=LIB3DS_FALSE;
40 
41   if (!lib3ds_chunk_read_start(&c, LIB3DS_SOLID_BGND, io)) {
42     return(LIB3DS_FALSE);
43   }
44 
45   while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
46     switch (chunk) {
47       case LIB3DS_LIN_COLOR_F:
48         lib3ds_io_read_rgb(io, background->solid.col);
49         have_lin=LIB3DS_TRUE;
50         break;
51       case LIB3DS_COLOR_F:
52         lib3ds_io_read_rgb(io, background->solid.col);
53         break;
54       default:
55         lib3ds_chunk_unknown(chunk);
56     }
57   }
58 
59   lib3ds_chunk_read_end(&c, io);
60   return(LIB3DS_TRUE);
61 }
62 
63 
64 static Lib3dsBool
v_gradient_read(Lib3dsBackground * background,Lib3dsIo * io)65 v_gradient_read(Lib3dsBackground *background, Lib3dsIo *io)
66 {
67   Lib3dsChunk c;
68   Lib3dsWord chunk;
69   int index[2];
70   Lib3dsRgb col[2][3];
71   int have_lin=0;
72 
73 
74   if (!lib3ds_chunk_read_start(&c, LIB3DS_V_GRADIENT, io)) {
75     return(LIB3DS_FALSE);
76   }
77   background->gradient.percent=lib3ds_io_read_float(io);
78   lib3ds_chunk_read_tell(&c, io);
79 
80   index[0]=index[1]=0;
81   while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
82     switch (chunk) {
83       case LIB3DS_COLOR_F:
84         lib3ds_io_read_rgb(io, col[0][index[0]]);
85         index[0]++;
86         break;
87       case LIB3DS_LIN_COLOR_F:
88         lib3ds_io_read_rgb(io, col[1][index[1]]);
89         index[1]++;
90         have_lin=1;
91         break;
92       default:
93         lib3ds_chunk_unknown(chunk);
94     }
95   }
96   {
97     int i;
98     for (i=0; i<3; ++i) {
99       background->gradient.top[i]=col[have_lin][0][i];
100       background->gradient.middle[i]=col[have_lin][1][i];
101       background->gradient.bottom[i]=col[have_lin][2][i];
102     }
103   }
104   lib3ds_chunk_read_end(&c, io);
105   return(LIB3DS_TRUE);
106 }
107 
108 
109 /*!
110  * \ingroup background
111  */
112 Lib3dsBool
lib3ds_background_read(Lib3dsBackground * background,Lib3dsIo * io)113 lib3ds_background_read(Lib3dsBackground *background, Lib3dsIo *io)
114 {
115   Lib3dsChunk c;
116 
117   if (!lib3ds_chunk_read(&c, io)) {
118     return(LIB3DS_FALSE);
119   }
120 
121   switch (c.chunk) {
122     case LIB3DS_BIT_MAP:
123       {
124         if (!lib3ds_io_read_string(io, background->bitmap.name, 64)) {
125             return(LIB3DS_FALSE);
126         }
127       }
128       break;
129     case LIB3DS_SOLID_BGND:
130       {
131         lib3ds_chunk_read_reset(&c, io);
132         if (!solid_bgnd_read(background, io)) {
133           return(LIB3DS_FALSE);
134         }
135       }
136       break;
137     case LIB3DS_V_GRADIENT:
138       {
139         lib3ds_chunk_read_reset(&c, io);
140         if (!v_gradient_read(background, io)) {
141           return(LIB3DS_FALSE);
142         }
143       }
144       break;
145     case LIB3DS_USE_BIT_MAP:
146       {
147         background->bitmap.use=LIB3DS_TRUE;
148       }
149       break;
150     case LIB3DS_USE_SOLID_BGND:
151       {
152         background->solid.use=LIB3DS_TRUE;
153       }
154       break;
155     case LIB3DS_USE_V_GRADIENT:
156       {
157         background->gradient.use=LIB3DS_TRUE;
158       }
159       break;
160   }
161 
162   return(LIB3DS_TRUE);
163 }
164 
165 
166 static Lib3dsBool
colorf_write(Lib3dsRgba rgb,Lib3dsIo * io)167 colorf_write(Lib3dsRgba rgb, Lib3dsIo *io)
168 {
169   Lib3dsChunk c;
170 
171   c.chunk=LIB3DS_COLOR_F;
172   c.size=18;
173   lib3ds_chunk_write(&c,io);
174   lib3ds_io_write_rgb(io, rgb);
175 
176   c.chunk=LIB3DS_LIN_COLOR_F;
177   c.size=18;
178   lib3ds_chunk_write(&c,io);
179   lib3ds_io_write_rgb(io, rgb);
180   return(LIB3DS_TRUE);
181 }
182 
183 
184 static Lib3dsBool
colorf_defined(Lib3dsRgba rgb)185 colorf_defined(Lib3dsRgba rgb)
186 {
187   int i;
188   for (i=0; i<3; ++i) {
189     if (fabs(rgb[i])>LIB3DS_EPSILON) {
190       break;
191     }
192   }
193   return(i<3);
194 }
195 
196 
197 /*!
198  * \ingroup background
199  */
200 Lib3dsBool
lib3ds_background_write(Lib3dsBackground * background,Lib3dsIo * io)201 lib3ds_background_write(Lib3dsBackground *background, Lib3dsIo *io)
202 {
203   if (strlen(background->bitmap.name)) { /*---- LIB3DS_BIT_MAP ----*/
204     Lib3dsChunk c;
205     c.chunk=LIB3DS_BIT_MAP;
206     c.size=6+1+(Lib3dsDword)strlen(background->bitmap.name);
207     lib3ds_chunk_write(&c,io);
208     lib3ds_io_write_string(io, background->bitmap.name);
209   }
210 
211   if (colorf_defined(background->solid.col)) { /*---- LIB3DS_SOLID_BGND ----*/
212     Lib3dsChunk c;
213     c.chunk=LIB3DS_SOLID_BGND;
214     c.size=42;
215     lib3ds_chunk_write(&c,io);
216     colorf_write(background->solid.col, io);
217   }
218 
219   if (colorf_defined(background->gradient.top) ||
220     colorf_defined(background->gradient.middle) ||
221     colorf_defined(background->gradient.bottom)) { /*---- LIB3DS_V_GRADIENT ----*/
222     Lib3dsChunk c;
223     c.chunk=LIB3DS_V_GRADIENT;
224     c.size=118;
225     lib3ds_chunk_write(&c,io);
226     lib3ds_io_write_float(io, background->gradient.percent);
227     colorf_write(background->gradient.top,io);
228     colorf_write(background->gradient.middle,io);
229     colorf_write(background->gradient.bottom,io);
230   }
231 
232   if (background->bitmap.use) { /*---- LIB3DS_USE_BIT_MAP ----*/
233     Lib3dsChunk c;
234     c.chunk=LIB3DS_USE_BIT_MAP;
235     c.size=6;
236     lib3ds_chunk_write(&c,io);
237   }
238 
239   if (background->solid.use) { /*---- LIB3DS_USE_SOLID_BGND ----*/
240     Lib3dsChunk c;
241     c.chunk=LIB3DS_USE_SOLID_BGND;
242     c.size=6;
243     lib3ds_chunk_write(&c,io);
244   }
245 
246   if (background->gradient.use) { /*---- LIB3DS_USE_V_GRADIENT ----*/
247     Lib3dsChunk c;
248     c.chunk=LIB3DS_USE_V_GRADIENT;
249     c.size=6;
250     lib3ds_chunk_write(&c,io);
251   }
252 
253   return(LIB3DS_TRUE);
254 }
255 
256