dropped all dependencies apart from SDL into the libs subdir
[summerhack] / libs / lib3ds / light.c
1 /*
2  * The 3D Studio File Format Library
3  * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
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: light.c,v 1.10 2001/07/11 13:47:35 jeh Exp $
21  */
22 #define LIB3DS_EXPORT
23 #include <lib3ds/light.h>
24 #include <lib3ds/chunk.h>
25 #include <lib3ds/io.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <string.h>
29 #ifdef WITH_DMALLOC
30 #include <dmalloc.h>
31 #endif
32
33
34 /*!
35  * \defgroup light Lights
36  *
37  * \author J.E. Hoffmann <je-h@gmx.net>
38  */
39 /*!
40
41 \typedef Lib3dsLight
42   \ingroup light
43   \sa _Lib3dsLight
44
45 */
46
47
48
49 /*!
50  * \ingroup light
51  */
52 Lib3dsLight*
53 lib3ds_light_new(const char *name)
54 {
55   Lib3dsLight *light;
56
57   ASSERT(name);
58   ASSERT(strlen(name)<64);
59   
60   light=(Lib3dsLight*)calloc(sizeof(Lib3dsLight), 1);
61   if (!light) {
62     return(0);
63   }
64   strcpy(light->name, name);
65   return(light);
66 }
67
68
69 /*!
70  * \ingroup light
71  */
72 void
73 lib3ds_light_free(Lib3dsLight *light)
74 {
75   memset(light, 0, sizeof(Lib3dsLight));
76   free(light);
77 }
78
79
80 /*!
81  * \ingroup light
82  */
83 void
84 lib3ds_light_dump(Lib3dsLight *light)
85 {
86   ASSERT(light);
87   printf("  name:             %s\n", light->name);
88   printf("  spot_light:       %s\n", light->spot_light ? "yes" : "no");
89   printf("  see_cone:         %s\n", light->see_cone ? "yes" : "no");
90   printf("  color:            (%f, %f, %f)\n", 
91     light->color[0], light->color[1], light->color[2]);
92   printf("  position          (%f, %f, %f)\n", 
93     light->position[0], light->position[1], light->position[2]);
94   printf("  spot              (%f, %f, %f)\n", 
95     light->spot[0], light->spot[1], light->spot[2]);
96   printf("  roll:             %f\n", light->roll);
97   printf("  off:              %s\n", light->off ? "yes" : "no");
98   printf("  outer_range:      %f\n", light->outer_range);
99   printf("  inner_range:      %f\n", light->inner_range);
100   printf("  multiplier:       %f\n", light->multiplier);
101   printf("  attenuation:      %f\n", light->attenuation);
102   printf("  rectangular_spot: %s\n", light->rectangular_spot ? "yes" : "no");
103   printf("  shadowed:         %s\n", light->shadowed ? "yes" : "no");
104   printf("  shadow_bias:      %f\n", light->shadow_bias);
105   printf("  shadow_filter:    %f\n", light->shadow_filter);
106   printf("  shadow_size:      %d\n", light->shadow_size);
107   printf("  spot_aspect:      %f\n", light->spot_aspect);
108   printf("  use_projector:    %s\n", light->use_projector ? "yes" : "no");
109   printf("  projector:        %s\n", light->projector);
110   printf("  spot_overshoot:   %d\n", (int)light->spot_overshoot);
111   printf("  ray_shadows:      %s\n", light->ray_shadows ? "yes" : "no");
112   printf("  ray_bias:         %f\n", light->ray_bias);
113   printf("  hot_spot:         %f\n", light->hot_spot);
114   printf("  fall_off:         %f\n", light->fall_off);
115   printf("\n");
116 }
117
118
119 /*!
120  * \ingroup light
121  */
122 static Lib3dsBool
123 spotlight_read(Lib3dsLight *light, Lib3dsIo *io)
124 {
125   Lib3dsChunk c;
126   Lib3dsWord chunk;
127   int i;
128
129   if (!lib3ds_chunk_read_start(&c, LIB3DS_DL_SPOTLIGHT, io)) {
130     return(LIB3DS_FALSE);
131   }
132   light->spot_light=LIB3DS_TRUE;
133   for (i=0; i<3; ++i) {
134     light->spot[i]=lib3ds_io_read_float(io);
135   }
136   light->hot_spot = lib3ds_io_read_float(io);
137   light->fall_off = lib3ds_io_read_float(io);
138   lib3ds_chunk_read_tell(&c, io);
139   
140   while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
141     switch (chunk) {
142       case LIB3DS_DL_SPOT_ROLL:
143         {
144           light->roll=lib3ds_io_read_float(io);
145         }
146         break;
147       case LIB3DS_DL_SHADOWED:
148         {
149           light->shadowed=LIB3DS_TRUE;
150         }
151         break;
152       case LIB3DS_DL_LOCAL_SHADOW2:
153         {
154           light->shadow_bias=lib3ds_io_read_float(io);
155           light->shadow_filter=lib3ds_io_read_float(io);
156           light->shadow_size=lib3ds_io_read_intw(io);
157         }
158         break;
159       case LIB3DS_DL_SEE_CONE:
160         {
161           light->see_cone=LIB3DS_TRUE;
162         }
163         break;
164       case LIB3DS_DL_SPOT_RECTANGULAR:
165         {
166           light->rectangular_spot=LIB3DS_TRUE;
167         }
168         break;
169       case LIB3DS_DL_SPOT_ASPECT:
170         {
171           light->spot_aspect=lib3ds_io_read_float(io);
172         }
173         break;
174       case LIB3DS_DL_SPOT_PROJECTOR:
175         {
176           light->use_projector=LIB3DS_TRUE;
177           if (!lib3ds_io_read_string(io, light->projector, 64)) {
178             return(LIB3DS_FALSE);
179           }
180         }
181       case LIB3DS_DL_SPOT_OVERSHOOT:
182         {
183           light->spot_overshoot=LIB3DS_TRUE;
184         }
185         break;
186       case LIB3DS_DL_RAY_BIAS:
187         {
188           light->ray_bias=lib3ds_io_read_float(io);
189         }
190         break;
191       case LIB3DS_DL_RAYSHAD:
192         {
193           light->ray_shadows=LIB3DS_TRUE;
194         }
195         break;
196       default:
197         lib3ds_chunk_unknown(chunk);
198     }
199   }
200   
201   lib3ds_chunk_read_end(&c, io);
202   return(LIB3DS_TRUE);
203 }
204
205
206 /*!
207  * \ingroup light
208  */
209 Lib3dsBool
210 lib3ds_light_read(Lib3dsLight *light, Lib3dsIo *io)
211 {
212   Lib3dsChunk c;
213   Lib3dsWord chunk;
214
215   if (!lib3ds_chunk_read_start(&c, LIB3DS_N_DIRECT_LIGHT, io)) {
216     return(LIB3DS_FALSE);
217   }
218   {
219     int i;
220     for (i=0; i<3; ++i) {
221       light->position[i]=lib3ds_io_read_float(io);
222     }
223   }
224   lib3ds_chunk_read_tell(&c, io);
225   
226   while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
227     switch (chunk) {
228       case LIB3DS_COLOR_F:
229         {
230           int i;
231           for (i=0; i<3; ++i) {
232             light->color[i]=lib3ds_io_read_float(io);
233           }
234         }
235         break;
236       case LIB3DS_DL_OFF:
237         {
238           light->off=LIB3DS_TRUE;
239         }
240         break;
241       case LIB3DS_DL_OUTER_RANGE:
242         {
243           light->outer_range=lib3ds_io_read_float(io);
244         }
245         break;
246       case LIB3DS_DL_INNER_RANGE:
247         {
248           light->inner_range=lib3ds_io_read_float(io);
249         }
250         break;
251       case LIB3DS_DL_MULTIPLIER:
252         {
253           light->multiplier=lib3ds_io_read_float(io);
254         }
255         break;
256       case LIB3DS_DL_EXCLUDE:
257         {
258           /* FIXME: */
259           lib3ds_chunk_unknown(chunk);
260         }
261       case LIB3DS_DL_ATTENUATE:
262         {
263           light->attenuation=lib3ds_io_read_float(io);
264         }
265         break;
266       case LIB3DS_DL_SPOTLIGHT:
267         {
268           lib3ds_chunk_read_reset(&c, io);
269           if (!spotlight_read(light, io)) {
270             return(LIB3DS_FALSE);
271           }
272         }
273         break;
274       default:
275         lib3ds_chunk_unknown(chunk);
276     }
277   }
278   
279   lib3ds_chunk_read_end(&c, io);
280   return(LIB3DS_TRUE);
281 }
282
283
284 /*!
285  * \ingroup light
286  */
287 Lib3dsBool
288 lib3ds_light_write(Lib3dsLight *light, Lib3dsIo *io)
289 {
290   Lib3dsChunk c;
291
292   c.chunk=LIB3DS_N_DIRECT_LIGHT;
293   if (!lib3ds_chunk_write_start(&c,io)) {
294     return(LIB3DS_FALSE);
295   }
296   lib3ds_io_write_vector(io, light->position);
297   { /*---- LIB3DS_COLOR_F ----*/
298     Lib3dsChunk c;
299     c.chunk=LIB3DS_COLOR_F;
300     c.size=18;
301     lib3ds_chunk_write(&c, io);
302     lib3ds_io_write_rgb(io, light->color);
303   }
304   if (light->off) { /*---- LIB3DS_DL_OFF ----*/
305     Lib3dsChunk c;
306     c.chunk=LIB3DS_DL_OFF;
307     c.size=6;
308     lib3ds_chunk_write(&c, io);
309   }
310   { /*---- LIB3DS_DL_OUTER_RANGE ----*/
311     Lib3dsChunk c;
312     c.chunk=LIB3DS_DL_OUTER_RANGE;
313     c.size=10;
314     lib3ds_chunk_write(&c, io);
315     lib3ds_io_write_float(io, light->outer_range);
316   }
317   { /*---- LIB3DS_DL_INNER_RANGE ----*/
318     Lib3dsChunk c;
319     c.chunk=LIB3DS_DL_INNER_RANGE;
320     c.size=10;
321     lib3ds_chunk_write(&c, io);
322     lib3ds_io_write_float(io, light->inner_range);
323   }
324   { /*---- LIB3DS_DL_MULTIPLIER ----*/
325     Lib3dsChunk c;
326     c.chunk=LIB3DS_DL_MULTIPLIER;
327     c.size=10;
328     lib3ds_chunk_write(&c, io);
329     lib3ds_io_write_float(io, light->multiplier);
330   }
331   if (light->attenuation) { /*---- LIB3DS_DL_ATTENUATE ----*/
332     Lib3dsChunk c;
333     c.chunk=LIB3DS_DL_ATTENUATE;
334     c.size=6;
335     lib3ds_chunk_write(&c, io);
336   }
337
338   if (light->spot_light) {
339     Lib3dsChunk c;
340
341     c.chunk=LIB3DS_DL_SPOTLIGHT;
342     if (!lib3ds_chunk_write_start(&c,io)) {
343       return(LIB3DS_FALSE);
344     }
345     lib3ds_io_write_vector(io, light->spot);
346     lib3ds_io_write_float(io, light->hot_spot);
347     lib3ds_io_write_float(io, light->fall_off);
348     
349     { /*---- LIB3DS_DL_SPOT_ROLL ----*/
350       Lib3dsChunk c;
351       c.chunk=LIB3DS_DL_SPOT_ROLL;
352       c.size=10;
353       lib3ds_chunk_write(&c, io);
354       lib3ds_io_write_float(io, light->roll);
355     }
356     if (light->shadowed) { /*---- LIB3DS_DL_SHADOWED ----*/
357       Lib3dsChunk c;
358       c.chunk=LIB3DS_DL_SHADOWED;
359       c.size=6;
360       lib3ds_chunk_write(&c, io);
361     }
362     if ((fabs(light->shadow_bias)>LIB3DS_EPSILON) ||
363       (fabs(light->shadow_filter)>LIB3DS_EPSILON) ||
364       (light->shadow_size!=0)) { /*---- LIB3DS_DL_LOCAL_SHADOW2 ----*/
365       Lib3dsChunk c;
366       c.chunk=LIB3DS_DL_LOCAL_SHADOW2;
367       c.size=16;
368       lib3ds_chunk_write(&c, io);
369       lib3ds_io_write_float(io, light->shadow_bias);
370       lib3ds_io_write_float(io, light->shadow_filter);
371       lib3ds_io_write_intw(io, light->shadow_size);
372     }
373     if (light->see_cone) { /*---- LIB3DS_DL_SEE_CONE ----*/
374       Lib3dsChunk c;
375       c.chunk=LIB3DS_DL_SEE_CONE;
376       c.size=6;
377       lib3ds_chunk_write(&c, io);
378     }
379     if (light->rectangular_spot) { /*---- LIB3DS_DL_SPOT_RECTANGULAR ----*/
380       Lib3dsChunk c;
381       c.chunk=LIB3DS_DL_SPOT_RECTANGULAR;
382       c.size=6;
383       lib3ds_chunk_write(&c, io);
384     }
385     if (fabs(light->spot_aspect)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_SPOT_ASPECT ----*/
386       Lib3dsChunk c;
387       c.chunk=LIB3DS_DL_SPOT_ASPECT;
388       c.size=10;
389       lib3ds_chunk_write(&c, io);
390       lib3ds_io_write_float(io, light->spot_aspect);
391     }
392     if (light->use_projector) { /*---- LIB3DS_DL_SPOT_PROJECTOR ----*/
393       Lib3dsChunk c;
394       c.chunk=LIB3DS_DL_SPOT_PROJECTOR;
395       c.size=10;
396       lib3ds_chunk_write(&c, io);
397       lib3ds_io_write_string(io, light->projector);
398     }
399     if (light->spot_overshoot) { /*---- LIB3DS_DL_SPOT_OVERSHOOT ----*/
400       Lib3dsChunk c;
401       c.chunk=LIB3DS_DL_SPOT_OVERSHOOT;
402       c.size=6;
403       lib3ds_chunk_write(&c, io);
404     }
405     if (fabs(light->ray_bias)>LIB3DS_EPSILON) { /*---- LIB3DS_DL_RAY_BIAS ----*/
406       Lib3dsChunk c;
407       c.chunk=LIB3DS_DL_RAY_BIAS;
408       c.size=10;
409       lib3ds_chunk_write(&c, io);
410       lib3ds_io_write_float(io, light->ray_bias);
411     }
412     if (light->ray_shadows) { /*---- LIB3DS_DL_RAYSHAD ----*/
413       Lib3dsChunk c;
414       c.chunk=LIB3DS_DL_RAYSHAD;
415       c.size=6;
416       lib3ds_chunk_write(&c, io);
417     }
418     if (!lib3ds_chunk_write_end(&c,io)) {
419       return(LIB3DS_FALSE);
420     }
421   }
422   if (!lib3ds_chunk_write_end(&c,io)) {
423     return(LIB3DS_FALSE);
424   }
425   return(LIB3DS_TRUE);
426 }
427
428