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