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 /*!
22 * Create and return a new node object.
23 *
24 * The node is returned with an identity matrix. All other fields
25 * are zero.
26 *
27 * \return Lib3dsNode
28 */
29 Lib3dsNode*
lib3ds_node_new(Lib3dsNodeType type)30 lib3ds_node_new(Lib3dsNodeType type) {
31 Lib3dsNode *node;
32 switch (type) {
33 case LIB3DS_NODE_AMBIENT_COLOR: {
34 Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)calloc(sizeof(Lib3dsAmbientColorNode), 1);
35 node = (Lib3dsNode*)n;
36 strcpy(node->name, "$AMBIENT$");
37 n->color_track.type = LIB3DS_TRACK_VECTOR;
38 break;
39 }
40
41 case LIB3DS_NODE_MESH_INSTANCE: {
42 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)calloc(sizeof(Lib3dsMeshInstanceNode), 1);
43 node = (Lib3dsNode*)n;
44 strcpy(node->name, "$$$DUMMY");
45 n->pos_track.type = LIB3DS_TRACK_VECTOR;
46 n->scl_track.type = LIB3DS_TRACK_VECTOR;
47 n->rot_track.type = LIB3DS_TRACK_QUAT;
48 n->hide_track.type = LIB3DS_TRACK_BOOL;
49 break;
50 }
51
52 case LIB3DS_NODE_CAMERA: {
53 Lib3dsCameraNode *n = (Lib3dsCameraNode*)calloc(sizeof(Lib3dsCameraNode), 1);
54 node = (Lib3dsNode*)n;
55 n->pos_track.type = LIB3DS_TRACK_VECTOR;
56 n->fov_track.type = LIB3DS_TRACK_FLOAT;
57 n->roll_track.type = LIB3DS_TRACK_FLOAT;
58 break;
59 }
60
61 case LIB3DS_NODE_CAMERA_TARGET: {
62 Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1);
63 node = (Lib3dsNode*)n;
64 n->pos_track.type = LIB3DS_TRACK_VECTOR;
65 break;
66 }
67
68 case LIB3DS_NODE_OMNILIGHT: {
69 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)calloc(sizeof(Lib3dsOmnilightNode), 1);
70 node = (Lib3dsNode*)n;
71 n->pos_track.type = LIB3DS_TRACK_VECTOR;
72 n->color_track.type = LIB3DS_TRACK_VECTOR;
73 break;
74 }
75
76 case LIB3DS_NODE_SPOTLIGHT: {
77 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)calloc(sizeof(Lib3dsSpotlightNode), 1);
78 node = (Lib3dsNode*)n;
79 n->pos_track.type = LIB3DS_TRACK_VECTOR;
80 n->color_track.type = LIB3DS_TRACK_VECTOR;
81 n->hotspot_track.type = LIB3DS_TRACK_FLOAT;
82 n->falloff_track.type = LIB3DS_TRACK_FLOAT;
83 n->roll_track.type = LIB3DS_TRACK_FLOAT;
84 break;
85 }
86
87 case LIB3DS_NODE_SPOTLIGHT_TARGET: {
88 Lib3dsTargetNode *n = (Lib3dsTargetNode*)calloc(sizeof(Lib3dsTargetNode), 1);
89 node = (Lib3dsNode*)n;
90 n->pos_track.type = LIB3DS_TRACK_VECTOR;
91 break;
92 }
93
94 default:
95 assert(0);
96 return NULL;
97 }
98
99 node->type = type;
100 node->node_id = 65535;
101 node->user_id = 65535;
102 lib3ds_matrix_identity(node->matrix);
103 return node;
104 }
105
106
107 Lib3dsAmbientColorNode*
lib3ds_node_new_ambient_color(float color0[3])108 lib3ds_node_new_ambient_color(float color0[3]) {
109 Lib3dsNode *node;
110 Lib3dsAmbientColorNode *n;
111
112 node = lib3ds_node_new(LIB3DS_NODE_AMBIENT_COLOR);
113
114 n = (Lib3dsAmbientColorNode*)node;
115 lib3ds_track_resize(&n->color_track, 1);
116 if (color0) {
117 lib3ds_vector_copy(n->color_track.keys[0].value, color0);
118 } else {
119 lib3ds_vector_zero(n->color_track.keys[0].value);
120 }
121
122 return n;
123 }
124
125
126 Lib3dsMeshInstanceNode*
lib3ds_node_new_mesh_instance(Lib3dsMesh * mesh,const char * instance_name,float pos0[3],float scl0[3],float rot0[4])127 lib3ds_node_new_mesh_instance(Lib3dsMesh *mesh, const char *instance_name, float pos0[3], float scl0[3], float rot0[4]) {
128 Lib3dsNode *node;
129 Lib3dsMeshInstanceNode *n;
130 int i;
131
132 node = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE);
133 if (mesh) {
134 strcpy(node->name, mesh->name);
135 } else {
136 strcpy(node->name, "$$$DUMMY");
137 }
138
139 n = (Lib3dsMeshInstanceNode*)node;
140 if (instance_name) {
141 strcpy(n->instance_name, instance_name);
142 }
143
144 lib3ds_track_resize(&n->pos_track, 1);
145 if (pos0) {
146 lib3ds_vector_copy(n->pos_track.keys[0].value, pos0);
147 }
148
149 lib3ds_track_resize(&n->scl_track, 1);
150 if (scl0) {
151 lib3ds_vector_copy(n->scl_track.keys[0].value, scl0);
152 } else {
153 lib3ds_vector_make(n->scl_track.keys[0].value, 1, 1, 1);
154 }
155
156 lib3ds_track_resize(&n->rot_track, 1);
157 if (rot0) {
158 for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = rot0[i];
159 } else {
160 for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = 0;
161 }
162
163 return n;
164 }
165
166
167 Lib3dsCameraNode*
lib3ds_node_new_camera(Lib3dsCamera * camera)168 lib3ds_node_new_camera(Lib3dsCamera *camera) {
169 Lib3dsNode *node;
170 Lib3dsCameraNode *n;
171
172 assert(camera);
173 node = lib3ds_node_new(LIB3DS_NODE_CAMERA);
174 strcpy(node->name, camera->name);
175
176 n = (Lib3dsCameraNode*)node;
177 lib3ds_track_resize(&n->pos_track, 1);
178 lib3ds_vector_copy(n->pos_track.keys[0].value, camera->position);
179
180 lib3ds_track_resize(&n->fov_track, 1);
181 n->fov_track.keys[0].value[0] = camera->fov;
182
183 lib3ds_track_resize(&n->roll_track, 1);
184 n->roll_track.keys[0].value[0] = camera->roll;
185
186 return n;
187 }
188
189
190 Lib3dsTargetNode*
lib3ds_node_new_camera_target(Lib3dsCamera * camera)191 lib3ds_node_new_camera_target(Lib3dsCamera *camera) {
192 Lib3dsNode *node;
193 Lib3dsTargetNode *n;
194
195 assert(camera);
196 node = lib3ds_node_new(LIB3DS_NODE_CAMERA_TARGET);
197 strcpy(node->name, camera->name);
198
199 n = (Lib3dsTargetNode*)node;
200 lib3ds_track_resize(&n->pos_track, 1);
201 lib3ds_vector_copy(n->pos_track.keys[0].value, camera->target);
202
203 return n;
204 }
205
206
207 Lib3dsOmnilightNode*
lib3ds_node_new_omnilight(Lib3dsLight * light)208 lib3ds_node_new_omnilight(Lib3dsLight *light) {
209 Lib3dsNode *node;
210 Lib3dsOmnilightNode *n;
211
212 assert(light);
213 node = lib3ds_node_new(LIB3DS_NODE_OMNILIGHT);
214 strcpy(node->name, light->name);
215
216 n = (Lib3dsOmnilightNode*)node;
217 lib3ds_track_resize(&n->pos_track, 1);
218 lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);
219
220 lib3ds_track_resize(&n->color_track, 1);
221 lib3ds_vector_copy(n->color_track.keys[0].value, light->color);
222
223 return n;
224 }
225
226
227 Lib3dsSpotlightNode*
lib3ds_node_new_spotlight(Lib3dsLight * light)228 lib3ds_node_new_spotlight(Lib3dsLight *light) {
229 Lib3dsNode *node;
230 Lib3dsSpotlightNode *n;
231
232 assert(light);
233 node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT);
234 strcpy(node->name, light->name);
235
236 n = (Lib3dsSpotlightNode*)node;
237 lib3ds_track_resize(&n->pos_track, 1);
238 lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);
239
240 lib3ds_track_resize(&n->color_track, 1);
241 lib3ds_vector_copy(n->color_track.keys[0].value, light->color);
242
243 lib3ds_track_resize(&n->hotspot_track, 1);
244 n->hotspot_track.keys[0].value[0] = light->hotspot;
245
246 lib3ds_track_resize(&n->falloff_track, 1);
247 n->falloff_track.keys[0].value[0] = light->falloff;
248
249 lib3ds_track_resize(&n->roll_track, 1);
250 n->roll_track.keys[0].value[0] = light->roll;
251
252 return n;
253 }
254
255
256 Lib3dsTargetNode*
lib3ds_node_new_spotligf_target(Lib3dsLight * light)257 lib3ds_node_new_spotligf_target(Lib3dsLight *light) {
258 Lib3dsNode *node;
259 Lib3dsTargetNode *n;
260
261 assert(light);
262 node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT_TARGET);
263 strcpy(node->name, light->name);
264
265 n = (Lib3dsTargetNode*)node;
266 lib3ds_track_resize(&n->pos_track, 1);
267 lib3ds_vector_copy(n->pos_track.keys[0].value, light->target);
268
269 return n;
270 }
271
272
273 static void
free_node_and_childs(Lib3dsNode * node)274 free_node_and_childs(Lib3dsNode *node) {
275 assert(node);
276 switch (node->type) {
277 case LIB3DS_NODE_AMBIENT_COLOR: {
278 Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
279 lib3ds_track_resize(&n->color_track, 0);
280 break;
281 }
282
283 case LIB3DS_NODE_MESH_INSTANCE: {
284 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
285 lib3ds_track_resize(&n->pos_track, 0);
286 lib3ds_track_resize(&n->rot_track, 0);
287 lib3ds_track_resize(&n->scl_track, 0);
288 lib3ds_track_resize(&n->hide_track, 0);
289 break;
290 }
291
292 case LIB3DS_NODE_CAMERA: {
293 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
294 lib3ds_track_resize(&n->pos_track, 0);
295 lib3ds_track_resize(&n->fov_track, 0);
296 lib3ds_track_resize(&n->roll_track, 0);
297 break;
298 }
299
300 case LIB3DS_NODE_CAMERA_TARGET: {
301 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
302 lib3ds_track_resize(&n->pos_track, 0);
303 break;
304 }
305
306 case LIB3DS_NODE_OMNILIGHT: {
307 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
308 lib3ds_track_resize(&n->pos_track, 0);
309 lib3ds_track_resize(&n->color_track, 0);
310 break;
311 }
312
313 case LIB3DS_NODE_SPOTLIGHT: {
314 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
315 lib3ds_track_resize(&n->pos_track, 0);
316 lib3ds_track_resize(&n->color_track, 0);
317 lib3ds_track_resize(&n->hotspot_track, 0);
318 lib3ds_track_resize(&n->falloff_track, 0);
319 lib3ds_track_resize(&n->roll_track, 0);
320 break;
321 }
322
323 case LIB3DS_NODE_SPOTLIGHT_TARGET: {
324 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
325 lib3ds_track_resize(&n->pos_track, 0);
326 break;
327 }
328 }
329 {
330 Lib3dsNode *p, *q;
331 for (p = node->childs; p; p = q) {
332 q = p->next;
333 free_node_and_childs(p);
334 }
335 }
336 free(node);
337 }
338
339
340 /*!
341 * Free a node and all of its resources.
342 *
343 * \param node Lib3dsNode object to be freed.
344 */
345 void
lib3ds_node_free(Lib3dsNode * node)346 lib3ds_node_free(Lib3dsNode *node) {
347 assert(node);
348 free_node_and_childs(node);
349 }
350
351
352 /*!
353 * Evaluate an animation node.
354 *
355 * Recursively sets node and its children to their appropriate values
356 * for this point in the animation.
357 *
358 * \param node Node to be evaluated.
359 * \param t time value, between 0. and file->frames
360 */
361 void
lib3ds_node_eval(Lib3dsNode * node,float t)362 lib3ds_node_eval(Lib3dsNode *node, float t) {
363 assert(node);
364 switch (node->type) {
365 case LIB3DS_NODE_AMBIENT_COLOR: {
366 Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
367 if (node->parent) {
368 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
369 } else {
370 lib3ds_matrix_identity(node->matrix);
371 }
372 lib3ds_track_eval_vector(&n->color_track, n->color, t);
373 break;
374 }
375
376 case LIB3DS_NODE_MESH_INSTANCE: {
377 float M[4][4];
378 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
379
380 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
381 lib3ds_track_eval_quat(&n->rot_track, n->rot, t);
382 if (n->scl_track.nkeys) {
383 lib3ds_track_eval_vector(&n->scl_track, n->scl, t);
384 } else {
385 n->scl[0] = n->scl[1] = n->scl[2] = 1.0f;
386 }
387 lib3ds_track_eval_bool(&n->hide_track, &n->hide, t);
388
389 lib3ds_matrix_identity(M);
390 lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]);
391 lib3ds_matrix_rotate_quat(M, n->rot);
392 lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]);
393
394 if (node->parent) {
395 lib3ds_matrix_mult(node->matrix, node->parent->matrix, M);
396 } else {
397 lib3ds_matrix_copy(node->matrix, M);
398 }
399 break;
400 }
401
402 case LIB3DS_NODE_CAMERA: {
403 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
404 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
405 lib3ds_track_eval_float(&n->fov_track, &n->fov, t);
406 lib3ds_track_eval_float(&n->roll_track, &n->roll, t);
407 if (node->parent) {
408 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
409 } else {
410 lib3ds_matrix_identity(node->matrix);
411 }
412 lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
413 break;
414 }
415
416 case LIB3DS_NODE_CAMERA_TARGET: {
417 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
418 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
419 if (node->parent) {
420 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
421 } else {
422 lib3ds_matrix_identity(node->matrix);
423 }
424 lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
425 break;
426 }
427
428 case LIB3DS_NODE_OMNILIGHT: {
429 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
430 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
431 lib3ds_track_eval_vector(&n->color_track, n->color, t);
432 if (node->parent) {
433 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
434 } else {
435 lib3ds_matrix_identity(node->matrix);
436 }
437 lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
438 break;
439 }
440
441 case LIB3DS_NODE_SPOTLIGHT: {
442 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
443 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
444 lib3ds_track_eval_vector(&n->color_track, n->color, t);
445 lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t);
446 lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t);
447 lib3ds_track_eval_float(&n->roll_track, &n->roll, t);
448 if (node->parent) {
449 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
450 } else {
451 lib3ds_matrix_identity(node->matrix);
452 }
453 lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
454 break;
455 }
456
457 case LIB3DS_NODE_SPOTLIGHT_TARGET: {
458 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
459 lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
460 if (node->parent) {
461 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
462 } else {
463 lib3ds_matrix_identity(node->matrix);
464 }
465 lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
466 break;
467 }
468 }
469 {
470 Lib3dsNode *p;
471 for (p = node->childs; p != 0; p = p->next) {
472 lib3ds_node_eval(p, t);
473 }
474 }
475 }
476
477
478 /*!
479 * Return a node object by name and type.
480 *
481 * This function performs a recursive search for the specified node.
482 * Both name and type must match.
483 *
484 * \param node The parent node for the search
485 * \param name The target node name.
486 * \param type The target node type
487 *
488 * \return A pointer to the first matching node, or NULL if not found.
489 */
490 Lib3dsNode*
lib3ds_node_by_name(Lib3dsNode * node,const char * name,Lib3dsNodeType type)491 lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeType type) {
492 Lib3dsNode *p, *q;
493
494 for (p = node->childs; p != 0; p = p->next) {
495 if ((p->type == type) && (strcmp(p->name, name) == 0)) {
496 return(p);
497 }
498 q = lib3ds_node_by_name(p, name, type);
499 if (q) {
500 return(q);
501 }
502 }
503 return(0);
504 }
505
506
507 /*!
508 * Return a node object by id.
509 *
510 * This function performs a recursive search for the specified node.
511 *
512 * \param node The parent node for the search
513 * \param node_id The target node id.
514 *
515 * \return A pointer to the first matching node, or NULL if not found.
516 */
517 Lib3dsNode*
lib3ds_node_by_id(Lib3dsNode * node,uint16_t node_id)518 lib3ds_node_by_id(Lib3dsNode *node, uint16_t node_id) {
519 Lib3dsNode *p, *q;
520
521 for (p = node->childs; p != 0; p = p->next) {
522 if (p->node_id == node_id) {
523 return(p);
524 }
525 q = lib3ds_node_by_id(p, node_id);
526 if (q) {
527 return(q);
528 }
529 }
530 return(0);
531 }
532
533
534 void
lib3ds_node_read(Lib3dsNode * node,Lib3dsIo * io)535 lib3ds_node_read(Lib3dsNode *node, Lib3dsIo *io) {
536 Lib3dsChunk c;
537 uint16_t chunk;
538
539 assert(node);
540 lib3ds_chunk_read_start(&c, 0, io);
541
542 switch (c.chunk) {
543 case CHK_AMBIENT_NODE_TAG:
544 case CHK_OBJECT_NODE_TAG:
545 case CHK_CAMERA_NODE_TAG:
546 case CHK_TARGET_NODE_TAG:
547 case CHK_LIGHT_NODE_TAG:
548 case CHK_SPOTLIGHT_NODE_TAG:
549 case CHK_L_TARGET_NODE_TAG:
550 break;
551 default:
552 return;
553 }
554
555 while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
556 switch (chunk) {
557 case CHK_NODE_ID: {
558 node->node_id = lib3ds_io_read_word(io);
559 lib3ds_io_log_indent(io, 1);
560 lib3ds_io_log(io, LIB3DS_LOG_INFO, "ID=%d", (short)node->node_id);
561 lib3ds_io_log_indent(io, -1);
562 break;
563 }
564
565 case CHK_NODE_HDR: {
566 lib3ds_io_read_string(io, node->name, 64);
567 node->flags = lib3ds_io_read_word(io);
568 node->flags |= ((uint32_t)lib3ds_io_read_word(io)) << 16;
569 node->user_id = lib3ds_io_read_word(io);
570
571 lib3ds_io_log_indent(io, 1);
572 lib3ds_io_log(io, LIB3DS_LOG_INFO, "NAME=%s", node->name);
573 lib3ds_io_log(io, LIB3DS_LOG_INFO, "PARENT=%d", (short)node->user_id);
574 lib3ds_io_log_indent(io, -1);
575 break;
576 }
577
578 case CHK_PIVOT: {
579 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
580 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
581 lib3ds_io_read_vector(io, n->pivot);
582 } else {
583 lib3ds_chunk_unknown(chunk, io);
584 }
585 break;
586 }
587
588 case CHK_INSTANCE_NAME: {
589 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
590 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
591 lib3ds_io_read_string(io, n->instance_name, 64);
592 } else {
593 lib3ds_chunk_unknown(chunk, io);
594 }
595 break;
596 }
597
598 case CHK_BOUNDBOX: {
599 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
600 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
601 lib3ds_io_read_vector(io, n->bbox_min);
602 lib3ds_io_read_vector(io, n->bbox_max);
603 } else {
604 lib3ds_chunk_unknown(chunk, io);
605 }
606 break;
607 }
608
609 case CHK_COL_TRACK_TAG: {
610 Lib3dsTrack *track = 0;
611 switch (node->type) {
612 case LIB3DS_NODE_AMBIENT_COLOR: {
613 Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
614 track = &n->color_track;
615 break;
616 }
617 case LIB3DS_NODE_OMNILIGHT: {
618 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
619 track = &n->color_track;
620 break;
621 }
622 case LIB3DS_NODE_SPOTLIGHT: {
623 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
624 track = &n->color_track;
625 break;
626 }
627 default:
628 lib3ds_chunk_unknown(chunk, io);
629 }
630 if (track) {
631 lib3ds_track_read(track, io);
632 }
633 break;
634 }
635
636 case CHK_POS_TRACK_TAG: {
637 Lib3dsTrack *track = 0;
638 switch (node->type) {
639 case LIB3DS_NODE_MESH_INSTANCE: {
640 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
641 track = &n->pos_track;
642 break;
643 }
644 case LIB3DS_NODE_CAMERA: {
645 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
646 track = &n->pos_track;
647 break;
648 }
649 case LIB3DS_NODE_CAMERA_TARGET: {
650 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
651 track = &n->pos_track;
652 break;
653 }
654 case LIB3DS_NODE_OMNILIGHT: {
655 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
656 track = &n->pos_track;
657 break;
658 }
659 case LIB3DS_NODE_SPOTLIGHT: {
660 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
661 track = &n->pos_track;
662 break;
663 }
664 case LIB3DS_NODE_SPOTLIGHT_TARGET: {
665 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
666 track = &n->pos_track;
667 break;
668 }
669 default:
670 lib3ds_chunk_unknown(chunk, io);
671 }
672 if (track) {
673 lib3ds_track_read(track, io);
674 }
675 break;
676 }
677
678 case CHK_ROT_TRACK_TAG: {
679 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
680 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
681 n->rot_track.type = LIB3DS_TRACK_QUAT;
682 lib3ds_track_read(&n->rot_track, io);
683 } else {
684 lib3ds_chunk_unknown(chunk, io);
685 }
686 break;
687 }
688
689 case CHK_SCL_TRACK_TAG: {
690 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
691 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
692 n->scl_track.type = LIB3DS_TRACK_VECTOR;
693 lib3ds_track_read(&n->scl_track, io);
694 } else {
695 lib3ds_chunk_unknown(chunk, io);
696 }
697 break;
698 }
699
700 case CHK_FOV_TRACK_TAG: {
701 if (node->type == LIB3DS_NODE_CAMERA) {
702 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
703 n->fov_track.type = LIB3DS_TRACK_FLOAT;
704 lib3ds_track_read(&n->fov_track, io);
705 } else {
706 lib3ds_chunk_unknown(chunk, io);
707 }
708 break;
709 }
710
711 case CHK_HOT_TRACK_TAG: {
712 if (node->type == LIB3DS_NODE_SPOTLIGHT) {
713 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
714 n->hotspot_track.type = LIB3DS_TRACK_FLOAT;
715 lib3ds_track_read(&n->hotspot_track, io);
716 } else {
717 lib3ds_chunk_unknown(chunk, io);
718 }
719 break;
720 }
721
722 case CHK_FALL_TRACK_TAG: {
723 if (node->type == LIB3DS_NODE_SPOTLIGHT) {
724 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
725 n->falloff_track.type= LIB3DS_TRACK_FLOAT;
726 lib3ds_track_read(&n->falloff_track, io);
727 } else {
728 lib3ds_chunk_unknown(chunk, io);
729 }
730 break;
731 }
732
733 case CHK_ROLL_TRACK_TAG: {
734 switch (node->type) {
735 case LIB3DS_NODE_CAMERA: {
736 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
737 n->roll_track.type = LIB3DS_TRACK_FLOAT;
738 lib3ds_track_read(&n->roll_track, io);
739 break;
740 }
741 case LIB3DS_NODE_SPOTLIGHT: {
742 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
743 n->roll_track.type = LIB3DS_TRACK_FLOAT;
744 lib3ds_track_read(&n->roll_track, io);
745 break;
746 }
747 default:
748 lib3ds_chunk_unknown(chunk, io);
749 }
750 break;
751 }
752
753 case CHK_HIDE_TRACK_TAG: {
754 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
755 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
756 n->hide_track.type = LIB3DS_TRACK_BOOL;
757 lib3ds_track_read(&n->hide_track, io);
758 } else {
759 lib3ds_chunk_unknown(chunk, io);
760 }
761 break;
762 }
763
764 case CHK_MORPH_SMOOTH: {
765 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
766 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
767 n->morph_smooth = lib3ds_io_read_float(io);
768 } else {
769 lib3ds_chunk_unknown(chunk, io);
770 }
771 }
772 break;
773
774 /*
775 case LIB3DS_MORPH_TRACK_TAG: {
776 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
777 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
778 n->morph_track = lib3ds_track_new(node, LIB3DS_TRACK_MORPH, 0);
779 lib3ds_track_read(n->morph_track, io);
780 } else {
781 lib3ds_chunk_unknown(chunk, io);
782 }
783 }
784 break;
785 */
786
787 default:
788 lib3ds_chunk_unknown(chunk, io);
789 }
790 }
791
792 lib3ds_chunk_read_end(&c, io);
793 }
794
795
796 void
lib3ds_node_write(Lib3dsNode * node,uint16_t node_id,uint16_t parent_id,Lib3dsIo * io)797 lib3ds_node_write(Lib3dsNode *node, uint16_t node_id, uint16_t parent_id, Lib3dsIo *io) {
798 Lib3dsChunk c;
799
800 switch (node->type) {
801 case LIB3DS_NODE_AMBIENT_COLOR:
802 c.chunk = CHK_AMBIENT_NODE_TAG;
803 break;
804
805 case LIB3DS_NODE_MESH_INSTANCE:
806 c.chunk = CHK_OBJECT_NODE_TAG;
807 break;
808
809 case LIB3DS_NODE_CAMERA:
810 c.chunk = CHK_CAMERA_NODE_TAG;
811 break;
812
813 case LIB3DS_NODE_CAMERA_TARGET:
814 c.chunk = CHK_TARGET_NODE_TAG;
815 break;
816
817 case LIB3DS_NODE_OMNILIGHT:
818 c.chunk = CHK_LIGHT_NODE_TAG;
819 break;
820
821 case LIB3DS_NODE_SPOTLIGHT:
822 c.chunk = CHK_SPOTLIGHT_NODE_TAG;
823 break;
824
825 case LIB3DS_NODE_SPOTLIGHT_TARGET:
826 c.chunk = CHK_L_TARGET_NODE_TAG;
827 break;
828
829 default:
830 assert(0);
831 return;
832 }
833
834 lib3ds_chunk_write_start(&c, io);
835
836 { /*---- CHK_NODE_ID ----*/
837 Lib3dsChunk c;
838 c.chunk = CHK_NODE_ID;
839 c.size = 8;
840 lib3ds_chunk_write(&c, io);
841 lib3ds_io_write_intw(io, node_id);
842 }
843
844 { /*---- CHK_NODE_HDR ----*/
845 Lib3dsChunk c;
846 c.chunk = CHK_NODE_HDR;
847 c.size = 6 + 1 + (uint32_t)strlen(node->name) + 2 + 2 + 2;
848 lib3ds_chunk_write(&c, io);
849 lib3ds_io_write_string(io, node->name);
850 lib3ds_io_write_word(io, node->flags & 0xffff);
851 lib3ds_io_write_word(io, (node->flags >> 16) & 0xffff);
852 lib3ds_io_write_word(io, parent_id);
853 }
854
855 switch (c.chunk) {
856 case CHK_AMBIENT_NODE_TAG: {
857 Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
858 if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
859 Lib3dsChunk c;
860 c.chunk = CHK_COL_TRACK_TAG;
861 lib3ds_chunk_write_start(&c, io);
862 lib3ds_track_write(&n->color_track, io);
863 lib3ds_chunk_write_end(&c, io);
864 }
865 break;
866 }
867
868 case CHK_OBJECT_NODE_TAG: {
869 Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
870 { /*---- CHK_PIVOT ----*/
871 Lib3dsChunk c;
872 c.chunk = CHK_PIVOT;
873 c.size = 18;
874 lib3ds_chunk_write(&c, io);
875 lib3ds_io_write_vector(io, n->pivot);
876 }
877
878 { /*---- CHK_INSTANCE_NAME ----*/
879 Lib3dsChunk c;
880 const char *name;
881 if (strlen(n->instance_name)) {
882 name = n->instance_name;
883
884 c.chunk = CHK_INSTANCE_NAME;
885 c.size = 6 + 1 + (uint32_t)strlen(name);
886 lib3ds_chunk_write(&c, io);
887 lib3ds_io_write_string(io, name);
888 }
889 }
890 {
891 int i;
892 for (i = 0; i < 3; ++i) {
893 if ((fabs(n->bbox_min[i]) > LIB3DS_EPSILON) ||
894 (fabs(n->bbox_max[i]) > LIB3DS_EPSILON)) {
895 break;
896 }
897 }
898
899 if (i < 3) { /*---- CHK_BOUNDBOX ----*/
900 Lib3dsChunk c;
901 c.chunk = CHK_BOUNDBOX;
902 c.size = 30;
903 lib3ds_chunk_write(&c, io);
904 lib3ds_io_write_vector(io, n->bbox_min);
905 lib3ds_io_write_vector(io, n->bbox_max);
906 }
907 }
908
909 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
910 Lib3dsChunk c;
911 c.chunk = CHK_POS_TRACK_TAG;
912 lib3ds_chunk_write_start(&c, io);
913 lib3ds_track_write(&n->pos_track, io);
914 lib3ds_chunk_write_end(&c, io);
915 }
916 if (n->rot_track.nkeys) { /*---- CHK_ROT_TRACK_TAG ----*/
917 Lib3dsChunk c;
918 c.chunk = CHK_ROT_TRACK_TAG;
919 lib3ds_chunk_write_start(&c, io);
920 lib3ds_track_write(&n->rot_track, io);
921 lib3ds_chunk_write_end(&c, io);
922 }
923 if (n->scl_track.nkeys) { /*---- LIB3DS_SCL_TRACK_TAG ----*/
924 Lib3dsChunk c;
925 c.chunk = CHK_SCL_TRACK_TAG;
926 lib3ds_chunk_write_start(&c, io);
927 lib3ds_track_write(&n->scl_track, io);
928 lib3ds_chunk_write_end(&c, io);
929 }
930 if (n->hide_track.nkeys) { /*---- CHK_HIDE_TRACK_TAG ----*/
931 Lib3dsChunk c;
932 c.chunk = CHK_HIDE_TRACK_TAG;
933 lib3ds_chunk_write_start(&c, io);
934 lib3ds_track_write(&n->hide_track, io);
935 lib3ds_chunk_write_end(&c, io);
936 }
937 if (fabs(n->morph_smooth) > LIB3DS_EPSILON) { /*---- CHK_MORPH_SMOOTH ----*/
938 Lib3dsChunk c;
939 c.chunk = CHK_MORPH_SMOOTH;
940 c.size = 10;
941 lib3ds_chunk_write(&c, io);
942 lib3ds_io_write_float(io, n->morph_smooth);
943 }
944 break;
945 }
946
947 case CHK_CAMERA_NODE_TAG: {
948 Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
949 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
950 Lib3dsChunk c;
951 c.chunk = CHK_POS_TRACK_TAG;
952 lib3ds_chunk_write_start(&c, io);
953 lib3ds_track_write(&n->pos_track, io);
954 lib3ds_chunk_write_end(&c, io);
955 }
956 if (n->fov_track.nkeys) { /*---- CHK_FOV_TRACK_TAG ----*/
957 Lib3dsChunk c;
958 c.chunk = CHK_FOV_TRACK_TAG;
959 lib3ds_chunk_write_start(&c, io);
960 lib3ds_track_write(&n->fov_track, io);
961 lib3ds_chunk_write_end(&c, io);
962 }
963 if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/
964 Lib3dsChunk c;
965 c.chunk = CHK_ROLL_TRACK_TAG;
966 lib3ds_chunk_write_start(&c, io);
967 lib3ds_track_write(&n->roll_track, io);
968 lib3ds_chunk_write_end(&c, io);
969 }
970 break;
971 }
972
973 case CHK_TARGET_NODE_TAG: {
974 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
975 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
976 Lib3dsChunk c;
977 c.chunk = CHK_POS_TRACK_TAG;
978 lib3ds_chunk_write_start(&c, io);
979 lib3ds_track_write(&n->pos_track, io);
980 lib3ds_chunk_write_end(&c, io);
981 }
982 break;
983 }
984
985 case CHK_LIGHT_NODE_TAG: {
986 Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
987 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
988 Lib3dsChunk c;
989 c.chunk = CHK_POS_TRACK_TAG;
990 lib3ds_chunk_write_start(&c, io);
991 lib3ds_track_write(&n->pos_track, io);
992 lib3ds_chunk_write_end(&c, io);
993 }
994 if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
995 Lib3dsChunk c;
996 c.chunk = CHK_COL_TRACK_TAG;
997 lib3ds_chunk_write_start(&c, io);
998 lib3ds_track_write(&n->color_track, io);
999 lib3ds_chunk_write_end(&c, io);
1000 }
1001 break;
1002 }
1003
1004 case CHK_SPOTLIGHT_NODE_TAG: {
1005 Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
1006 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
1007 Lib3dsChunk c;
1008 c.chunk = CHK_POS_TRACK_TAG;
1009 lib3ds_chunk_write_start(&c, io);
1010 lib3ds_track_write(&n->pos_track, io);
1011 lib3ds_chunk_write_end(&c, io);
1012 }
1013 if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
1014 Lib3dsChunk c;
1015 c.chunk = CHK_COL_TRACK_TAG;
1016 lib3ds_chunk_write_start(&c, io);
1017 lib3ds_track_write(&n->color_track, io);
1018 lib3ds_chunk_write_end(&c, io);
1019 }
1020 if (n->hotspot_track.nkeys) { /*---- CHK_HOT_TRACK_TAG ----*/
1021 Lib3dsChunk c;
1022 c.chunk = CHK_HOT_TRACK_TAG;
1023 lib3ds_chunk_write_start(&c, io);
1024 lib3ds_track_write(&n->hotspot_track, io);
1025 lib3ds_chunk_write_end(&c, io);
1026 }
1027 if (n->falloff_track.nkeys) { /*---- CHK_FALL_TRACK_TAG ----*/
1028 Lib3dsChunk c;
1029 c.chunk = CHK_FALL_TRACK_TAG;
1030 lib3ds_chunk_write_start(&c, io);
1031 lib3ds_track_write(&n->falloff_track, io);
1032 lib3ds_chunk_write_end(&c, io);
1033 }
1034 if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/
1035 Lib3dsChunk c;
1036 c.chunk = CHK_ROLL_TRACK_TAG;
1037 lib3ds_chunk_write_start(&c, io);
1038 lib3ds_track_write(&n->roll_track, io);
1039 lib3ds_chunk_write_end(&c, io);
1040 }
1041 break;
1042 }
1043
1044 case CHK_L_TARGET_NODE_TAG: {
1045 Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
1046 if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
1047 Lib3dsChunk c;
1048 c.chunk = CHK_POS_TRACK_TAG;
1049 lib3ds_chunk_write_start(&c, io);
1050 lib3ds_track_write(&n->pos_track, io);
1051 lib3ds_chunk_write_end(&c, io);
1052 }
1053 break;
1054 }
1055
1056 default:
1057 break;
1058 }
1059
1060 lib3ds_chunk_write_end(&c, io);
1061 }
1062
1063