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 Lib3dsLight*
lib3ds_light_new(const char * name)22 lib3ds_light_new(const char *name) {
23     Lib3dsLight *light;
24 
25     assert(name);
26     assert(strlen(name) < 64);
27 
28     light = (Lib3dsLight*)calloc(sizeof(Lib3dsLight), 1);
29     if (!light) {
30         return(0);
31     }
32     strcpy(light->name, name);
33     return(light);
34 }
35 
36 
37 void
lib3ds_light_free(Lib3dsLight * light)38 lib3ds_light_free(Lib3dsLight *light) {
39     memset(light, 0, sizeof(Lib3dsLight));
40     free(light);
41 }
42 
43 
44 static void
spotlight_read(Lib3dsLight * light,Lib3dsIo * io)45 spotlight_read(Lib3dsLight *light, Lib3dsIo *io) {
46     Lib3dsChunk c;
47     uint16_t chunk;
48     int i;
49 
50     lib3ds_chunk_read_start(&c, CHK_DL_SPOTLIGHT, io);
51 
52     light->spot_light = TRUE;
53     for (i = 0; i < 3; ++i) {
54         light->target[i] = lib3ds_io_read_float(io);
55     }
56     light->hotspot = lib3ds_io_read_float(io);
57     light->falloff = lib3ds_io_read_float(io);
58     lib3ds_chunk_read_tell(&c, io);
59 
60     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
61         switch (chunk) {
62             case CHK_DL_SPOT_ROLL:
63                 light->roll = lib3ds_io_read_float(io);
64                 break;
65 
66             case CHK_DL_SHADOWED: {
67                 light->shadowed = TRUE;
68                 break;
69             }
70 
71             case CHK_DL_LOCAL_SHADOW2: {
72                 light->shadow_bias = lib3ds_io_read_float(io);
73                 light->shadow_filter = lib3ds_io_read_float(io);
74                 light->shadow_size = lib3ds_io_read_intw(io);
75                 break;
76             }
77 
78             case CHK_DL_SEE_CONE: {
79                 light->see_cone = TRUE;
80                 break;
81             }
82 
83             case CHK_DL_SPOT_RECTANGULAR: {
84                 light->rectangular_spot = TRUE;
85                 break;
86             }
87 
88             case CHK_DL_SPOT_ASPECT: {
89                 light->spot_aspect = lib3ds_io_read_float(io);
90                 break;
91             }
92 
93             case CHK_DL_SPOT_PROJECTOR: {
94                 light->use_projector = TRUE;
95                 lib3ds_io_read_string(io, light->projector, 64);
96                 break;
97             }
98 
99             case CHK_DL_SPOT_OVERSHOOT: {
100                 light->spot_overshoot = TRUE;
101                 break;
102             }
103 
104             case CHK_DL_RAY_BIAS: {
105                 light->ray_bias = lib3ds_io_read_float(io);
106                 break;
107             }
108 
109             case CHK_DL_RAYSHAD: {
110                 light->ray_shadows = TRUE;
111                 break;
112             }
113 
114             default:
115                 lib3ds_chunk_unknown(chunk, io);
116         }
117     }
118 
119     lib3ds_chunk_read_end(&c, io);
120 }
121 
122 
123 void
lib3ds_light_read(Lib3dsLight * light,Lib3dsIo * io)124 lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io) {
125     Lib3dsChunk c;
126     uint16_t chunk;
127 
128     lib3ds_chunk_read_start(&c, CHK_N_DIRECT_LIGHT, io);
129 
130     {
131         int i;
132         for (i = 0; i < 3; ++i) {
133             light->position[i] = lib3ds_io_read_float(io);
134         }
135     }
136     lib3ds_chunk_read_tell(&c, io);
137 
138     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
139         switch (chunk) {
140             case CHK_COLOR_F: {
141                 int i;
142                 for (i = 0; i < 3; ++i) {
143                     light->color[i] = lib3ds_io_read_float(io);
144                 }
145                 break;
146             }
147 
148             case CHK_DL_OFF:
149                 light->off = TRUE;
150                 break;
151 
152             case CHK_DL_OUTER_RANGE:
153                 light->outer_range = lib3ds_io_read_float(io);
154                 break;
155 
156             case CHK_DL_INNER_RANGE:
157                 light->inner_range = lib3ds_io_read_float(io);
158                 break;
159 
160             case CHK_DL_MULTIPLIER:
161                 light->multiplier = lib3ds_io_read_float(io);
162                 break;
163 
164             case CHK_DL_EXCLUDE: {
165                 /* FIXME: */
166                 lib3ds_chunk_unknown(chunk, io);
167                 break;
168             }
169 
170             case CHK_DL_ATTENUATE:
171                 light->attenuation = lib3ds_io_read_float(io);
172                 break;
173 
174             case CHK_DL_SPOTLIGHT: {
175                 lib3ds_chunk_read_reset(&c, io);
176                 spotlight_read(light, io);
177                 break;
178             }
179 
180             default:
181                 lib3ds_chunk_unknown(chunk, io);
182         }
183     }
184 
185     lib3ds_chunk_read_end(&c, io);
186 }
187 
188 
189 void
lib3ds_light_write(Lib3dsLight * light,Lib3dsIo * io)190 lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io) {
191     Lib3dsChunk c;
192 
193     c.chunk = CHK_N_DIRECT_LIGHT;
194     lib3ds_chunk_write_start(&c, io);
195 
196     lib3ds_io_write_vector(io, light->position);
197     { /*---- LIB3DS_COLOR_F ----*/
198         Lib3dsChunk c;
199         c.chunk = CHK_COLOR_F;
200         c.size = 18;
201         lib3ds_chunk_write(&c, io);
202         lib3ds_io_write_rgb(io, light->color);
203     }
204     if (light->off) { /*---- LIB3DS_DL_OFF ----*/
205         Lib3dsChunk c;
206         c.chunk = CHK_DL_OFF;
207         c.size = 6;
208         lib3ds_chunk_write(&c, io);
209     }
210     { /*---- LIB3DS_DL_OUTER_RANGE ----*/
211         Lib3dsChunk c;
212         c.chunk = CHK_DL_OUTER_RANGE;
213         c.size = 10;
214         lib3ds_chunk_write(&c, io);
215         lib3ds_io_write_float(io, light->outer_range);
216     }
217     { /*---- LIB3DS_DL_INNER_RANGE ----*/
218         Lib3dsChunk c;
219         c.chunk = CHK_DL_INNER_RANGE;
220         c.size = 10;
221         lib3ds_chunk_write(&c, io);
222         lib3ds_io_write_float(io, light->inner_range);
223     }
224     { /*---- LIB3DS_DL_MULTIPLIER ----*/
225         Lib3dsChunk c;
226         c.chunk = CHK_DL_MULTIPLIER;
227         c.size = 10;
228         lib3ds_chunk_write(&c, io);
229         lib3ds_io_write_float(io, light->multiplier);
230     }
231     if (light->attenuation) { /*---- LIB3DS_DL_ATTENUATE ----*/
232         Lib3dsChunk c;
233         c.chunk = CHK_DL_ATTENUATE;
234         c.size = 6;
235         lib3ds_chunk_write(&c, io);
236     }
237 
238     if (light->spot_light) {
239         Lib3dsChunk c;
240 
241         c.chunk = CHK_DL_SPOTLIGHT;
242         lib3ds_chunk_write_start(&c, io);
243 
244         lib3ds_io_write_vector(io, light->target);
245         lib3ds_io_write_float(io, light->hotspot);
246         lib3ds_io_write_float(io, light->falloff);
247 
248         { /*---- LIB3DS_DL_SPOT_ROLL ----*/
249             Lib3dsChunk c;
250             c.chunk = CHK_DL_SPOT_ROLL;
251             c.size = 10;
252             lib3ds_chunk_write(&c, io);
253             lib3ds_io_write_float(io, light->roll);
254         }
255         if (light->shadowed) { /*---- LIB3DS_DL_SHADOWED ----*/
256             Lib3dsChunk c;
257             c.chunk = CHK_DL_SHADOWED;
258             c.size = 6;
259             lib3ds_chunk_write(&c, io);
260         }
261         if ((fabs(light->shadow_bias) > LIB3DS_EPSILON) ||
262             (fabs(light->shadow_filter) > LIB3DS_EPSILON) ||
263             (light->shadow_size != 0)) { /*---- LIB3DS_DL_LOCAL_SHADOW2 ----*/
264             Lib3dsChunk c;
265             c.chunk = CHK_DL_LOCAL_SHADOW2;
266             c.size = 16;
267             lib3ds_chunk_write(&c, io);
268             lib3ds_io_write_float(io, light->shadow_bias);
269             lib3ds_io_write_float(io, light->shadow_filter);
270             lib3ds_io_write_intw(io, (int16_t)light->shadow_size);
271         }
272         if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/
273             Lib3dsChunk c;
274             c.chunk = CHK_DL_SEE_CONE;
275             c.size = 6;
276             lib3ds_chunk_write(&c, io);
277         }
278         if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/
279             Lib3dsChunk c;
280             c.chunk = CHK_DL_SPOT_RECTANGULAR;
281             c.size = 6;
282             lib3ds_chunk_write(&c, io);
283         }
284         if (fabs(light->spot_aspect) > LIB3DS_EPSILON) { /*---- LIB3DS_DL_SPOT_ASPECT ----*/
285             Lib3dsChunk c;
286             c.chunk = CHK_DL_SPOT_ASPECT;
287             c.size = 10;
288             lib3ds_chunk_write(&c, io);
289             lib3ds_io_write_float(io, light->spot_aspect);
290         }
291         if (light->use_projector) { /*---- LIB3DS_DL_SPOT_PROJECTOR ----*/
292             Lib3dsChunk c;
293             c.chunk = CHK_DL_SPOT_PROJECTOR;
294             c.size = 10;
295             lib3ds_chunk_write(&c, io);
296             lib3ds_io_write_string(io, light->projector);
297         }
298         if (light->spot_overshoot) { /*---- LIB3DS_DL_SPOT_OVERSHOOT ----*/
299             Lib3dsChunk c;
300             c.chunk = CHK_DL_SPOT_OVERSHOOT;
301             c.size = 6;
302             lib3ds_chunk_write(&c, io);
303         }
304         if (fabs(light->ray_bias) > LIB3DS_EPSILON) { /*---- LIB3DS_DL_RAY_BIAS ----*/
305             Lib3dsChunk c;
306             c.chunk = CHK_DL_RAY_BIAS;
307             c.size = 10;
308             lib3ds_chunk_write(&c, io);
309             lib3ds_io_write_float(io, light->ray_bias);
310         }
311         if (light->ray_shadows) { /*---- LIB3DS_DL_RAYSHAD ----*/
312             Lib3dsChunk c;
313             c.chunk = CHK_DL_RAYSHAD;
314             c.size = 6;
315             lib3ds_chunk_write(&c, io);
316         }
317         lib3ds_chunk_write_end(&c, io);
318     }
319 
320     lib3ds_chunk_write_end(&c, io);
321 }
322 
323 
324