Home | API | File List | Examples | Download

lib3ds_node.c

00001 /*
00002     Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
00003     All rights reserved.
00004     
00005     This program is free  software: you can redistribute it and/or modify 
00006     it under the terms of the GNU Lesser General Public License as published 
00007     by the Free Software Foundation, either version 2.1 of the License, or 
00008     (at your option) any later version.
00009 
00010     Thisprogram  is  distributed in the hope that it will be useful, 
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
00013     GNU Lesser General Public License for more details.
00014     
00015     You should  have received a copy of the GNU Lesser General Public License
00016     along with  this program; If not, see <http://www.gnu.org/licenses/>. 
00017 */
00018 #include "lib3ds_impl.h"
00019 
00020 
00029 Lib3dsNode*
00030 lib3ds_node_new(Lib3dsNodeType type) {
00031     Lib3dsNode *node;
00032     switch (type) {
00033         case LIB3DS_NODE_AMBIENT_COLOR: {
00034             Lib3dsAmbientColorNode *n = calloc(sizeof(Lib3dsAmbientColorNode), 1);
00035             node = (Lib3dsNode*)n;
00036             strcpy(node->name, "$AMBIENT$");
00037             n->color_track.type = LIB3DS_TRACK_VECTOR;
00038             break;
00039         }
00040 
00041         case LIB3DS_NODE_MESH_INSTANCE: {
00042             Lib3dsMeshInstanceNode *n = calloc(sizeof(Lib3dsMeshInstanceNode), 1);
00043             node = (Lib3dsNode*)n;
00044             strcpy(node->name, "$$$DUMMY");
00045             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00046             n->scl_track.type = LIB3DS_TRACK_VECTOR;
00047             n->rot_track.type = LIB3DS_TRACK_QUAT;
00048             n->hide_track.type = LIB3DS_TRACK_BOOL;
00049             break;
00050         }
00051 
00052         case LIB3DS_NODE_CAMERA: {
00053             Lib3dsCameraNode *n = calloc(sizeof(Lib3dsCameraNode), 1);
00054             node = (Lib3dsNode*)n;
00055             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00056             n->fov_track.type = LIB3DS_TRACK_FLOAT;
00057             n->roll_track.type = LIB3DS_TRACK_FLOAT;
00058             break;
00059         }
00060 
00061         case LIB3DS_NODE_CAMERA_TARGET: {
00062             Lib3dsTargetNode *n = calloc(sizeof(Lib3dsTargetNode), 1);
00063             node = (Lib3dsNode*)n;
00064             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00065             break;
00066         }
00067 
00068         case LIB3DS_NODE_OMNILIGHT: {
00069             Lib3dsOmnilightNode *n = calloc(sizeof(Lib3dsOmnilightNode), 1);
00070             node = (Lib3dsNode*)n;
00071             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00072             n->color_track.type = LIB3DS_TRACK_VECTOR;
00073             break;
00074         }
00075 
00076         case LIB3DS_NODE_SPOTLIGHT: {
00077             Lib3dsSpotlightNode *n = calloc(sizeof(Lib3dsSpotlightNode), 1);
00078             node = (Lib3dsNode*)n;
00079             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00080             n->color_track.type = LIB3DS_TRACK_VECTOR;
00081             n->hotspot_track.type = LIB3DS_TRACK_FLOAT;
00082             n->falloff_track.type = LIB3DS_TRACK_FLOAT;
00083             n->roll_track.type = LIB3DS_TRACK_FLOAT;
00084             break;
00085         }
00086 
00087         case LIB3DS_NODE_SPOTLIGHT_TARGET: {
00088             Lib3dsTargetNode *n = calloc(sizeof(Lib3dsTargetNode), 1);
00089             node = (Lib3dsNode*)n;
00090             n->pos_track.type = LIB3DS_TRACK_VECTOR;
00091             break;
00092         }
00093 
00094         default:
00095             assert(0);
00096             return NULL;
00097     }
00098 
00099     node->type = type;
00100     node->node_id = 65535;
00101     node->user_id = 65535;
00102     lib3ds_matrix_identity(node->matrix);
00103     return node;
00104 }
00105 
00106 
00107 Lib3dsAmbientColorNode* 
00108 lib3ds_node_new_ambient_color(float color0[3]) {
00109     Lib3dsNode *node;
00110     Lib3dsAmbientColorNode *n;
00111 
00112     node = lib3ds_node_new(LIB3DS_NODE_AMBIENT_COLOR);
00113 
00114     n = (Lib3dsAmbientColorNode*)node;
00115     lib3ds_track_resize(&n->color_track, 1);
00116     if (color0) {
00117         lib3ds_vector_copy(n->color_track.keys[0].value, color0);
00118     } else {
00119         lib3ds_vector_zero(n->color_track.keys[0].value);
00120     }
00121 
00122     return n;
00123 }
00124 
00125 
00126 Lib3dsMeshInstanceNode* 
00127 lib3ds_node_new_mesh_instance(Lib3dsMesh *mesh, const char *instance_name, float pos0[3], float scl0[3], float rot0[4]) {
00128     Lib3dsNode *node;
00129     Lib3dsMeshInstanceNode *n;
00130     int i;
00131 
00132     node = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE);
00133     if (mesh) {
00134         strcpy(node->name, mesh->name);
00135     } else {
00136         strcpy(node->name, "$$$DUMMY");
00137     }
00138 
00139     n = (Lib3dsMeshInstanceNode*)node;
00140     if (instance_name) {
00141         strcpy(n->instance_name, instance_name);
00142     }
00143 
00144     lib3ds_track_resize(&n->pos_track, 1);
00145     if (pos0) {
00146         lib3ds_vector_copy(n->pos_track.keys[0].value, pos0);
00147     }
00148 
00149     lib3ds_track_resize(&n->scl_track, 1);
00150     if (scl0) {
00151         lib3ds_vector_copy(n->scl_track.keys[0].value, scl0);
00152     } else {
00153         lib3ds_vector_make(n->scl_track.keys[0].value, 1, 1, 1);
00154     }
00155 
00156     lib3ds_track_resize(&n->rot_track, 1);
00157     if (rot0) {
00158         for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = rot0[i];
00159     } else {
00160         for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = 0;
00161     }
00162 
00163     return n;
00164 }
00165 
00166 
00167 Lib3dsCameraNode* 
00168 lib3ds_node_new_camera(Lib3dsCamera *camera) {
00169     Lib3dsNode *node = lib3ds_node_new(LIB3DS_NODE_CAMERA);
00170     Lib3dsCameraNode *n;
00171     
00172     assert(camera);
00173     node = lib3ds_node_new(LIB3DS_NODE_CAMERA);
00174     strcpy(node->name, camera->name);
00175 
00176     n = (Lib3dsCameraNode*)node;
00177     lib3ds_track_resize(&n->pos_track, 1);
00178     lib3ds_vector_copy(n->pos_track.keys[0].value, camera->position);
00179 
00180     lib3ds_track_resize(&n->fov_track, 1);
00181     n->fov_track.keys[0].value[0] = camera->fov;
00182 
00183     lib3ds_track_resize(&n->roll_track, 1);
00184     n->roll_track.keys[0].value[0] = camera->roll;
00185 
00186     return n;
00187 }
00188 
00189 
00190 Lib3dsTargetNode* 
00191 lib3ds_node_new_camera_target(Lib3dsCamera *camera) {
00192     Lib3dsNode *node;
00193     Lib3dsTargetNode *n;
00194     
00195     assert(camera);
00196     node = lib3ds_node_new(LIB3DS_NODE_CAMERA_TARGET);
00197     strcpy(node->name, camera->name);
00198 
00199     n = (Lib3dsTargetNode*)node;
00200     lib3ds_track_resize(&n->pos_track, 1);
00201     lib3ds_vector_copy(n->pos_track.keys[0].value, camera->target);
00202 
00203     return n;
00204 }
00205 
00206 
00207 Lib3dsOmnilightNode* 
00208 lib3ds_node_new_omnilight(Lib3dsLight *light) {
00209     Lib3dsNode *node;
00210     Lib3dsOmnilightNode *n;
00211 
00212     assert(light);
00213     node = lib3ds_node_new(LIB3DS_NODE_OMNILIGHT);
00214     strcpy(node->name, light->name);
00215 
00216     n = (Lib3dsOmnilightNode*)node;
00217     lib3ds_track_resize(&n->pos_track, 1);
00218     lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);
00219 
00220     lib3ds_track_resize(&n->color_track, 1);
00221     lib3ds_vector_copy(n->color_track.keys[0].value, light->color);
00222 
00223     return n;
00224 }
00225 
00226 
00227 Lib3dsSpotlightNode* 
00228 lib3ds_node_new_spotlight(Lib3dsLight *light) {
00229     Lib3dsNode *node;
00230     Lib3dsSpotlightNode *n;
00231 
00232     assert(light);
00233     node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT);
00234     strcpy(node->name, light->name);
00235 
00236     n = (Lib3dsSpotlightNode*)node;
00237     lib3ds_track_resize(&n->pos_track, 1);
00238     lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);
00239 
00240     lib3ds_track_resize(&n->color_track, 1);
00241     lib3ds_vector_copy(n->color_track.keys[0].value, light->color);
00242 
00243     lib3ds_track_resize(&n->hotspot_track, 1);
00244     n->hotspot_track.keys[0].value[0] = light->hotspot;
00245 
00246     lib3ds_track_resize(&n->falloff_track, 1);
00247     n->falloff_track.keys[0].value[0] = light->falloff;
00248 
00249     lib3ds_track_resize(&n->roll_track, 1);
00250     n->roll_track.keys[0].value[0] = light->roll;
00251 
00252     return n;
00253 }
00254 
00255 
00256 Lib3dsTargetNode* 
00257 lib3ds_node_new_spotligf_target(Lib3dsLight *light) {
00258     Lib3dsNode *node;
00259     Lib3dsTargetNode *n;
00260     
00261     assert(light);
00262     node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT_TARGET);
00263     strcpy(node->name, light->name);
00264 
00265     n = (Lib3dsTargetNode*)node;
00266     lib3ds_track_resize(&n->pos_track, 1);
00267     lib3ds_vector_copy(n->pos_track.keys[0].value, light->target);
00268 
00269     return n;
00270 }
00271 
00272 
00273 static void
00274 free_node_and_childs(Lib3dsNode *node) {
00275     assert(node);
00276     switch (node->type) {
00277         case LIB3DS_NODE_AMBIENT_COLOR: {
00278             Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
00279             lib3ds_track_resize(&n->color_track, 0);
00280             break;
00281         }
00282 
00283         case LIB3DS_NODE_MESH_INSTANCE: {
00284             Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00285             lib3ds_track_resize(&n->pos_track, 0);
00286             lib3ds_track_resize(&n->rot_track, 0);
00287             lib3ds_track_resize(&n->scl_track, 0);
00288             lib3ds_track_resize(&n->hide_track, 0);
00289             break;
00290         }
00291 
00292         case LIB3DS_NODE_CAMERA: {
00293             Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00294             lib3ds_track_resize(&n->pos_track, 0);
00295             lib3ds_track_resize(&n->fov_track, 0);
00296             lib3ds_track_resize(&n->roll_track, 0);
00297             break;
00298         }
00299 
00300         case LIB3DS_NODE_CAMERA_TARGET: {
00301             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00302             lib3ds_track_resize(&n->pos_track, 0);
00303             break;
00304         }
00305 
00306         case LIB3DS_NODE_OMNILIGHT: {
00307             Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
00308             lib3ds_track_resize(&n->pos_track, 0);
00309             lib3ds_track_resize(&n->color_track, 0);
00310             break;
00311         }
00312 
00313         case LIB3DS_NODE_SPOTLIGHT: {
00314             Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00315             lib3ds_track_resize(&n->pos_track, 0);
00316             lib3ds_track_resize(&n->color_track, 0);
00317             lib3ds_track_resize(&n->hotspot_track, 0);
00318             lib3ds_track_resize(&n->falloff_track, 0);
00319             lib3ds_track_resize(&n->roll_track, 0);
00320             break;
00321         }
00322 
00323         case LIB3DS_NODE_SPOTLIGHT_TARGET: {
00324             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00325             lib3ds_track_resize(&n->pos_track, 0);
00326             break;
00327         }
00328     } 
00329     {
00330         Lib3dsNode *p, *q;
00331         for (p = node->childs; p; p = q) {
00332             q = p->next;
00333             free_node_and_childs(p);
00334         }
00335     }
00336     free(node);
00337 }
00338 
00339 
00345 void
00346 lib3ds_node_free(Lib3dsNode *node) {
00347     assert(node);
00348     free_node_and_childs(node);
00349 }
00350 
00351 
00361 void
00362 lib3ds_node_eval(Lib3dsNode *node, float t) {
00363     assert(node);
00364     switch (node->type) {
00365         case LIB3DS_NODE_AMBIENT_COLOR: {
00366             Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
00367             if (node->parent) {
00368                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00369             } else {
00370                 lib3ds_matrix_identity(node->matrix);
00371             }
00372             lib3ds_track_eval_vector(&n->color_track, n->color, t);
00373             break;
00374         }
00375 
00376         case LIB3DS_NODE_MESH_INSTANCE: {
00377             float M[4][4];
00378             Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00379 
00380             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00381             lib3ds_track_eval_quat(&n->rot_track, n->rot, t);
00382             if (n->scl_track.nkeys) {
00383                 lib3ds_track_eval_vector(&n->scl_track, n->scl, t);
00384             } else {
00385                 n->scl[0] = n->scl[1] = n->scl[2] = 1.0f;
00386             }
00387             lib3ds_track_eval_bool(&n->hide_track, &n->hide, t);
00388 
00389             lib3ds_matrix_identity(M);
00390             lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]);
00391             lib3ds_matrix_rotate_quat(M, n->rot);
00392             lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]);
00393 
00394             if (node->parent) {
00395                 lib3ds_matrix_mult(node->matrix, node->parent->matrix, M);
00396             } else {
00397                 lib3ds_matrix_copy(node->matrix, M);
00398             }
00399             break;
00400         }
00401 
00402         case LIB3DS_NODE_CAMERA: {
00403             Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00404             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00405             lib3ds_track_eval_float(&n->fov_track, &n->fov, t);
00406             lib3ds_track_eval_float(&n->roll_track, &n->roll, t);
00407             if (node->parent) {
00408                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00409             } else {
00410                 lib3ds_matrix_identity(node->matrix);
00411             }
00412             lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
00413             break;
00414         }
00415 
00416         case LIB3DS_NODE_CAMERA_TARGET: {
00417             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00418             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00419             if (node->parent) {
00420                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00421             } else {
00422                 lib3ds_matrix_identity(node->matrix);
00423             }
00424             lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
00425             break;
00426         }
00427 
00428         case LIB3DS_NODE_OMNILIGHT: {
00429             Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
00430             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00431             lib3ds_track_eval_vector(&n->color_track, n->color, t);
00432             if (node->parent) {
00433                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00434             } else {
00435                 lib3ds_matrix_identity(node->matrix);
00436             }
00437             lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
00438             break;
00439         }
00440 
00441         case LIB3DS_NODE_SPOTLIGHT: {
00442             Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00443             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00444             lib3ds_track_eval_vector(&n->color_track, n->color, t);
00445             lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t);
00446             lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t);
00447             lib3ds_track_eval_float(&n->roll_track, &n->roll, t);
00448             if (node->parent) {
00449                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00450             } else {
00451                 lib3ds_matrix_identity(node->matrix);
00452             }
00453             lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
00454             break;
00455         }
00456 
00457         case LIB3DS_NODE_SPOTLIGHT_TARGET: {
00458             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00459             lib3ds_track_eval_vector(&n->pos_track, n->pos, t);
00460             if (node->parent) {
00461                 lib3ds_matrix_copy(node->matrix, node->parent->matrix);
00462             } else {
00463                 lib3ds_matrix_identity(node->matrix);
00464             }
00465             lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]);
00466             break;
00467         }
00468     }
00469     {
00470         Lib3dsNode *p;
00471         for (p = node->childs; p != 0; p = p->next) {
00472             lib3ds_node_eval(p, t);
00473         }
00474     }
00475 }
00476 
00477 
00490 Lib3dsNode*
00491 lib3ds_node_by_name(Lib3dsNode *node, const char* name, Lib3dsNodeType type) {
00492     Lib3dsNode *p, *q;
00493 
00494     for (p = node->childs; p != 0; p = p->next) {
00495         if ((p->type == type) && (strcmp(p->name, name) == 0)) {
00496             return(p);
00497         }
00498         q = lib3ds_node_by_name(p, name, type);
00499         if (q) {
00500             return(q);
00501         }
00502     }
00503     return(0);
00504 }
00505 
00506 
00517 Lib3dsNode*
00518 lib3ds_node_by_id(Lib3dsNode *node, uint16_t node_id) {
00519     Lib3dsNode *p, *q;
00520 
00521     for (p = node->childs; p != 0; p = p->next) {
00522         if (p->node_id == node_id) {
00523             return(p);
00524         }
00525         q = lib3ds_node_by_id(p, node_id);
00526         if (q) {
00527             return(q);
00528         }
00529     }
00530     return(0);
00531 }
00532 
00533 
00534 void
00535 lib3ds_node_read(Lib3dsNode *node, Lib3dsIo *io) {
00536     Lib3dsChunk c;
00537     uint16_t chunk;
00538 
00539     assert(node);
00540     lib3ds_chunk_read_start(&c, 0, io);
00541 
00542     switch (c.chunk) {
00543         case CHK_AMBIENT_NODE_TAG:
00544         case CHK_OBJECT_NODE_TAG:
00545         case CHK_CAMERA_NODE_TAG:
00546         case CHK_TARGET_NODE_TAG:
00547         case CHK_LIGHT_NODE_TAG:
00548         case CHK_SPOTLIGHT_NODE_TAG:
00549         case CHK_L_TARGET_NODE_TAG:
00550             break;
00551         default:
00552             return;
00553     }
00554 
00555     while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0)  {
00556         switch (chunk) {
00557             case CHK_NODE_ID: {
00558                 node->node_id = lib3ds_io_read_word(io);
00559                 lib3ds_io_log_indent(io, 1);
00560                 lib3ds_io_log(io, LIB3DS_LOG_INFO, "ID=%d", (short)node->node_id);
00561                 lib3ds_io_log_indent(io, -1);
00562                 break;
00563             }
00564 
00565             case CHK_NODE_HDR: {
00566                 lib3ds_io_read_string(io, node->name, 64);
00567                 node->flags = lib3ds_io_read_word(io);
00568                 node->flags |= ((uint32_t)lib3ds_io_read_word(io)) << 16;
00569                 node->user_id = lib3ds_io_read_word(io);
00570 
00571                 lib3ds_io_log_indent(io, 1);
00572                 lib3ds_io_log(io, LIB3DS_LOG_INFO, "NAME=%s", node->name);
00573                 lib3ds_io_log(io, LIB3DS_LOG_INFO, "PARENT=%d", (short)node->user_id);
00574                 lib3ds_io_log_indent(io, -1);
00575                 break;
00576             }
00577 
00578             case CHK_PIVOT: {
00579                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00580                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00581                     lib3ds_io_read_vector(io, n->pivot);
00582                 } else {
00583                     lib3ds_chunk_unknown(chunk, io);
00584                 }
00585                 break;
00586             }
00587 
00588             case CHK_INSTANCE_NAME: {
00589                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00590                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00591                     lib3ds_io_read_string(io, n->instance_name, 64);
00592                 } else {
00593                     lib3ds_chunk_unknown(chunk, io);
00594                 }
00595                 break;
00596             }
00597 
00598             case CHK_BOUNDBOX: {
00599                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00600                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00601                     lib3ds_io_read_vector(io, n->bbox_min);
00602                     lib3ds_io_read_vector(io, n->bbox_max);
00603                 } else {
00604                     lib3ds_chunk_unknown(chunk, io);
00605                 }
00606                 break;
00607             }
00608 
00609             case CHK_COL_TRACK_TAG: {
00610                 Lib3dsTrack *track = 0;
00611                 switch (node->type) {
00612                     case LIB3DS_NODE_AMBIENT_COLOR: {
00613                         Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
00614                         track = &n->color_track;
00615                         break;
00616                     }              
00617                     case LIB3DS_NODE_OMNILIGHT: {
00618                         Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
00619                         track = &n->color_track;
00620                         break;
00621                     }
00622                     case LIB3DS_NODE_SPOTLIGHT: {
00623                         Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00624                         track = &n->color_track;
00625                         break;
00626                     }
00627                     default:
00628                         lib3ds_chunk_unknown(chunk, io);
00629                 }
00630                 if (track) {
00631                     lib3ds_track_read(track, io);
00632                 }
00633                 break;
00634             }
00635 
00636             case CHK_POS_TRACK_TAG: {
00637                 Lib3dsTrack *track = 0;
00638                 switch (node->type) {
00639                     case LIB3DS_NODE_MESH_INSTANCE: {
00640                         Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00641                         track = &n->pos_track;
00642                         break;
00643                     }
00644                     case LIB3DS_NODE_CAMERA: {
00645                         Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00646                         track = &n->pos_track;
00647                         break;
00648                     }
00649                     case LIB3DS_NODE_CAMERA_TARGET: {
00650                         Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00651                         track = &n->pos_track;
00652                         break;
00653                     }
00654                     case LIB3DS_NODE_OMNILIGHT: {
00655                         Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
00656                         track = &n->pos_track;
00657                         break;
00658                     }
00659                     case LIB3DS_NODE_SPOTLIGHT: {
00660                         Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00661                         track = &n->pos_track;
00662                         break;
00663                     }
00664                     case LIB3DS_NODE_SPOTLIGHT_TARGET: {
00665                         Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00666                         track = &n->pos_track;
00667                         break;
00668                     }
00669                     default:
00670                         lib3ds_chunk_unknown(chunk, io);
00671                 }
00672                 if (track) {
00673                     lib3ds_track_read(track, io);
00674                 }
00675                 break;
00676             }
00677 
00678             case CHK_ROT_TRACK_TAG: {
00679                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00680                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00681                     n->rot_track.type = LIB3DS_TRACK_QUAT;
00682                     lib3ds_track_read(&n->rot_track, io);
00683                 } else {
00684                     lib3ds_chunk_unknown(chunk, io);
00685                 }
00686                 break;
00687             }
00688 
00689             case CHK_SCL_TRACK_TAG: {
00690                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00691                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00692                     n->scl_track.type = LIB3DS_TRACK_VECTOR;
00693                     lib3ds_track_read(&n->scl_track, io);
00694                 } else {
00695                     lib3ds_chunk_unknown(chunk, io);
00696                 }
00697                 break;
00698             }
00699 
00700             case CHK_FOV_TRACK_TAG: {
00701                 if (node->type == LIB3DS_NODE_CAMERA) {
00702                     Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00703                     n->fov_track.type = LIB3DS_TRACK_FLOAT;
00704                     lib3ds_track_read(&n->fov_track, io);
00705                 } else {
00706                     lib3ds_chunk_unknown(chunk, io);
00707                 }
00708                 break;
00709             }
00710 
00711             case CHK_HOT_TRACK_TAG: {
00712                 if (node->type == LIB3DS_NODE_SPOTLIGHT) {
00713                     Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00714                     n->hotspot_track.type = LIB3DS_TRACK_FLOAT;
00715                     lib3ds_track_read(&n->hotspot_track, io);
00716                 } else {
00717                     lib3ds_chunk_unknown(chunk, io);
00718                 }
00719                 break;
00720             }
00721 
00722             case CHK_FALL_TRACK_TAG: {
00723                 if (node->type == LIB3DS_NODE_SPOTLIGHT) {
00724                     Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00725                     n->falloff_track.type= LIB3DS_TRACK_FLOAT;
00726                     lib3ds_track_read(&n->falloff_track, io);
00727                 } else {
00728                     lib3ds_chunk_unknown(chunk, io);
00729                 }
00730                 break;
00731             }
00732 
00733             case CHK_ROLL_TRACK_TAG: {
00734                 switch (node->type) {
00735                     case LIB3DS_NODE_CAMERA: {
00736                         Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00737                         n->roll_track.type = LIB3DS_TRACK_FLOAT;
00738                         lib3ds_track_read(&n->roll_track, io);
00739                         break;
00740                     }
00741                     case LIB3DS_NODE_SPOTLIGHT: {
00742                         Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
00743                         n->roll_track.type = LIB3DS_TRACK_FLOAT;
00744                         lib3ds_track_read(&n->roll_track, io);
00745                         break;
00746                     }
00747                     default:
00748                         lib3ds_chunk_unknown(chunk, io);
00749                 }
00750                 break;
00751             }
00752 
00753             case CHK_HIDE_TRACK_TAG: {
00754                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00755                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00756                     n->hide_track.type = LIB3DS_TRACK_BOOL;
00757                     lib3ds_track_read(&n->hide_track, io);
00758                 } else {
00759                     lib3ds_chunk_unknown(chunk, io);
00760                 }
00761                 break;
00762             }
00763 
00764             case CHK_MORPH_SMOOTH: {
00765                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00766                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00767                     n->morph_smooth = lib3ds_io_read_float(io);
00768                 } else {
00769                     lib3ds_chunk_unknown(chunk, io);
00770                 }
00771             }
00772             break;
00773 
00774             /*
00775             case LIB3DS_MORPH_TRACK_TAG: {
00776                 if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
00777                     Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00778                     n->morph_track = lib3ds_track_new(node, LIB3DS_TRACK_MORPH, 0);
00779                     lib3ds_track_read(n->morph_track, io);
00780                 } else {
00781                     lib3ds_chunk_unknown(chunk, io);
00782                 }
00783             }
00784             break;
00785             */
00786 
00787             default:
00788                 lib3ds_chunk_unknown(chunk, io);
00789         }
00790     }
00791 
00792     lib3ds_chunk_read_end(&c, io);
00793 }
00794 
00795 
00796 void
00797 lib3ds_node_write(Lib3dsNode *node, uint16_t node_id, uint16_t parent_id, Lib3dsIo *io) {
00798     Lib3dsChunk c;
00799 
00800     switch (node->type) {
00801         case LIB3DS_NODE_AMBIENT_COLOR:
00802             c.chunk = CHK_AMBIENT_NODE_TAG;
00803             break;
00804 
00805         case LIB3DS_NODE_MESH_INSTANCE:
00806             c.chunk = CHK_OBJECT_NODE_TAG;
00807             break;
00808 
00809         case LIB3DS_NODE_CAMERA:
00810             c.chunk = CHK_CAMERA_NODE_TAG;
00811             break;
00812 
00813         case LIB3DS_NODE_CAMERA_TARGET:
00814             c.chunk = CHK_TARGET_NODE_TAG;
00815             break;
00816 
00817         case LIB3DS_NODE_OMNILIGHT:
00818             c.chunk = CHK_LIGHT_NODE_TAG;
00819             break;
00820 
00821         case LIB3DS_NODE_SPOTLIGHT:
00822             c.chunk = CHK_SPOTLIGHT_NODE_TAG;
00823             break;
00824 
00825         case LIB3DS_NODE_SPOTLIGHT_TARGET:
00826             c.chunk = CHK_L_TARGET_NODE_TAG;
00827             break;
00828 
00829         default:
00830             assert(0);
00831             return;
00832     }
00833     
00834     lib3ds_chunk_write_start(&c, io);
00835 
00836     { /*---- CHK_NODE_ID ----*/
00837         Lib3dsChunk c;
00838         c.chunk = CHK_NODE_ID;
00839         c.size = 8;
00840         lib3ds_chunk_write(&c, io);
00841         lib3ds_io_write_intw(io, node_id);
00842     }
00843 
00844     { /*---- CHK_NODE_HDR ----*/
00845         Lib3dsChunk c;
00846         c.chunk = CHK_NODE_HDR;
00847         c.size = 6 + 1 + (uint32_t)strlen(node->name) + 2 + 2 + 2;
00848         lib3ds_chunk_write(&c, io);
00849         lib3ds_io_write_string(io, node->name);
00850         lib3ds_io_write_word(io, node->flags & 0xffff);
00851         lib3ds_io_write_word(io, (node->flags >> 16) & 0xffff);
00852         lib3ds_io_write_word(io, parent_id);
00853     }
00854 
00855     switch (c.chunk) {
00856         case CHK_AMBIENT_NODE_TAG: {
00857             Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node;
00858             if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
00859                 Lib3dsChunk c;
00860                 c.chunk = CHK_COL_TRACK_TAG;
00861                 lib3ds_chunk_write_start(&c, io);
00862                 lib3ds_track_write(&n->color_track, io);
00863                 lib3ds_chunk_write_end(&c, io);
00864             }
00865             break;
00866         }
00867 
00868         case CHK_OBJECT_NODE_TAG: {
00869             Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
00870             { /*---- CHK_PIVOT ----*/
00871                 Lib3dsChunk c;
00872                 c.chunk = CHK_PIVOT;
00873                 c.size = 18;
00874                 lib3ds_chunk_write(&c, io);
00875                 lib3ds_io_write_vector(io, n->pivot);
00876             }
00877 
00878             { /*---- CHK_INSTANCE_NAME ----*/
00879                 Lib3dsChunk c;
00880                 const char *name;
00881                 if (strlen(n->instance_name)) {
00882                     name = n->instance_name;
00883 
00884                     c.chunk = CHK_INSTANCE_NAME;
00885                     c.size = 6 + 1 + (uint32_t)strlen(name);
00886                     lib3ds_chunk_write(&c, io);
00887                     lib3ds_io_write_string(io, name);
00888                 }
00889             }
00890             {
00891                 int i;
00892                 for (i = 0; i < 3; ++i) {
00893                     if ((fabs(n->bbox_min[i]) > LIB3DS_EPSILON) ||
00894                         (fabs(n->bbox_max[i]) > LIB3DS_EPSILON)) {
00895                         break;
00896                     }
00897                 }
00898 
00899                 if (i < 3) { /*---- CHK_BOUNDBOX ----*/
00900                     Lib3dsChunk c;
00901                     c.chunk = CHK_BOUNDBOX;
00902                     c.size = 30;
00903                     lib3ds_chunk_write(&c, io);
00904                     lib3ds_io_write_vector(io, n->bbox_min);
00905                     lib3ds_io_write_vector(io, n->bbox_max);
00906                 }
00907             }
00908 
00909             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
00910                 Lib3dsChunk c;
00911                 c.chunk = CHK_POS_TRACK_TAG;
00912                 lib3ds_chunk_write_start(&c, io);
00913                 lib3ds_track_write(&n->pos_track, io);
00914                 lib3ds_chunk_write_end(&c, io);
00915             }
00916             if (n->rot_track.nkeys) { /*---- CHK_ROT_TRACK_TAG ----*/
00917                 Lib3dsChunk c;
00918                 c.chunk = CHK_ROT_TRACK_TAG;
00919                 lib3ds_chunk_write_start(&c, io);
00920                 lib3ds_track_write(&n->rot_track, io);
00921                 lib3ds_chunk_write_end(&c, io);
00922             }
00923             if (n->scl_track.nkeys) { /*---- LIB3DS_SCL_TRACK_TAG ----*/
00924                 Lib3dsChunk c;
00925                 c.chunk = CHK_SCL_TRACK_TAG;
00926                 lib3ds_chunk_write_start(&c, io);
00927                 lib3ds_track_write(&n->scl_track, io);
00928                 lib3ds_chunk_write_end(&c, io);
00929             }
00930             if (n->hide_track.nkeys) { /*---- CHK_HIDE_TRACK_TAG ----*/
00931                 Lib3dsChunk c;
00932                 c.chunk = CHK_HIDE_TRACK_TAG;
00933                 lib3ds_chunk_write_start(&c, io);
00934                 lib3ds_track_write(&n->hide_track, io);
00935                 lib3ds_chunk_write_end(&c, io);
00936             }
00937             if (fabs(n->morph_smooth) > LIB3DS_EPSILON) { /*---- CHK_MORPH_SMOOTH ----*/
00938                 Lib3dsChunk c;
00939                 c.chunk = CHK_MORPH_SMOOTH;
00940                 c.size = 10;
00941                 lib3ds_chunk_write(&c, io);
00942                 lib3ds_io_write_float(io, n->morph_smooth);
00943             }
00944             break;
00945         }
00946 
00947         case CHK_CAMERA_NODE_TAG: {
00948             Lib3dsCameraNode *n = (Lib3dsCameraNode*)node;
00949             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
00950                 Lib3dsChunk c;
00951                 c.chunk = CHK_POS_TRACK_TAG;
00952                 lib3ds_chunk_write_start(&c, io);
00953                 lib3ds_track_write(&n->pos_track, io);
00954                 lib3ds_chunk_write_end(&c, io);
00955             }
00956             if (n->fov_track.nkeys) { /*---- CHK_FOV_TRACK_TAG ----*/
00957                 Lib3dsChunk c;
00958                 c.chunk = CHK_FOV_TRACK_TAG;
00959                 lib3ds_chunk_write_start(&c, io);
00960                 lib3ds_track_write(&n->fov_track, io);
00961                 lib3ds_chunk_write_end(&c, io);
00962             }
00963             if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/
00964                 Lib3dsChunk c;
00965                 c.chunk = CHK_ROLL_TRACK_TAG;
00966                 lib3ds_chunk_write_start(&c, io);
00967                 lib3ds_track_write(&n->roll_track, io);
00968                 lib3ds_chunk_write_end(&c, io);
00969             }
00970             break;
00971         }
00972 
00973         case CHK_TARGET_NODE_TAG: {
00974             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
00975             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
00976                 Lib3dsChunk c;
00977                 c.chunk = CHK_POS_TRACK_TAG;
00978                 lib3ds_chunk_write_start(&c, io);
00979                 lib3ds_track_write(&n->pos_track, io);
00980                 lib3ds_chunk_write_end(&c, io);
00981             }
00982             break;
00983         }
00984 
00985         case CHK_LIGHT_NODE_TAG: {
00986             Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node;
00987             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
00988                 Lib3dsChunk c;
00989                 c.chunk = CHK_POS_TRACK_TAG;
00990                 lib3ds_chunk_write_start(&c, io);
00991                 lib3ds_track_write(&n->pos_track, io);
00992                 lib3ds_chunk_write_end(&c, io);
00993             }
00994             if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
00995                 Lib3dsChunk c;
00996                 c.chunk = CHK_COL_TRACK_TAG;
00997                 lib3ds_chunk_write_start(&c, io);
00998                 lib3ds_track_write(&n->color_track, io);
00999                 lib3ds_chunk_write_end(&c, io);
01000             }
01001             break;
01002         }
01003 
01004         case CHK_SPOTLIGHT_NODE_TAG: {
01005             Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node;
01006             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
01007                 Lib3dsChunk c;
01008                 c.chunk = CHK_POS_TRACK_TAG;
01009                 lib3ds_chunk_write_start(&c, io);
01010                 lib3ds_track_write(&n->pos_track, io);
01011                 lib3ds_chunk_write_end(&c, io);
01012             }
01013             if (n->color_track.nkeys) { /*---- CHK_COL_TRACK_TAG ----*/
01014                 Lib3dsChunk c;
01015                 c.chunk = CHK_COL_TRACK_TAG;
01016                 lib3ds_chunk_write_start(&c, io);
01017                 lib3ds_track_write(&n->color_track, io);
01018                 lib3ds_chunk_write_end(&c, io);
01019             }
01020             if (n->hotspot_track.nkeys) { /*---- CHK_HOT_TRACK_TAG ----*/
01021                 Lib3dsChunk c;
01022                 c.chunk = CHK_HOT_TRACK_TAG;
01023                 lib3ds_chunk_write_start(&c, io);
01024                 lib3ds_track_write(&n->hotspot_track, io);
01025                 lib3ds_chunk_write_end(&c, io);
01026             }
01027             if (n->falloff_track.nkeys) { /*---- CHK_FALL_TRACK_TAG ----*/
01028                 Lib3dsChunk c;
01029                 c.chunk = CHK_FALL_TRACK_TAG;
01030                 lib3ds_chunk_write_start(&c, io);
01031                 lib3ds_track_write(&n->falloff_track, io);
01032                 lib3ds_chunk_write_end(&c, io);
01033             }
01034             if (n->roll_track.nkeys) { /*---- CHK_ROLL_TRACK_TAG ----*/
01035                 Lib3dsChunk c;
01036                 c.chunk = CHK_ROLL_TRACK_TAG;
01037                 lib3ds_chunk_write_start(&c, io);
01038                 lib3ds_track_write(&n->roll_track, io);
01039                 lib3ds_chunk_write_end(&c, io);
01040             }
01041             break; 
01042         }
01043 
01044         case CHK_L_TARGET_NODE_TAG: {
01045             Lib3dsTargetNode *n = (Lib3dsTargetNode*)node;
01046             if (n->pos_track.nkeys) { /*---- CHK_POS_TRACK_TAG ----*/
01047                 Lib3dsChunk c;
01048                 c.chunk = CHK_POS_TRACK_TAG;
01049                 lib3ds_chunk_write_start(&c, io);
01050                 lib3ds_track_write(&n->pos_track, io);
01051                 lib3ds_chunk_write_end(&c, io);
01052             }
01053             break;
01054         }
01055 
01056         default:
01057             break;
01058     }
01059 
01060     lib3ds_chunk_write_end(&c, io);
01061 }
01062