00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <lib3ds/file.h>
00023 #include <lib3ds/chunk.h>
00024 #include <lib3ds/io.h>
00025 #include <lib3ds/material.h>
00026 #include <lib3ds/mesh.h>
00027 #include <lib3ds/camera.h>
00028 #include <lib3ds/light.h>
00029 #include <lib3ds/node.h>
00030 #include <lib3ds/matrix.h>
00031 #include <lib3ds/vector.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <math.h>
00035 #include <float.h>
00036
00037
00043 static Lib3dsBool
00044 fileio_error_func(void *self)
00045 {
00046 FILE *f = (FILE*)self;
00047 return(ferror(f)!=0);
00048 }
00049
00050
00051 static long
00052 fileio_seek_func(void *self, long offset, Lib3dsIoSeek origin)
00053 {
00054 FILE *f = (FILE*)self;
00055 int o;
00056 switch (origin) {
00057 case LIB3DS_SEEK_SET:
00058 o = SEEK_SET;
00059 break;
00060 case LIB3DS_SEEK_CUR:
00061 o = SEEK_CUR;
00062 break;
00063 case LIB3DS_SEEK_END:
00064 o = SEEK_END;
00065 break;
00066 default:
00067 ASSERT(0);
00068 return(0);
00069 }
00070 return (fseek(f, offset, o));
00071 }
00072
00073
00074 static long
00075 fileio_tell_func(void *self)
00076 {
00077 FILE *f = (FILE*)self;
00078 return(ftell(f));
00079 }
00080
00081
00082 static size_t
00083 fileio_read_func(void *self, void *buffer, size_t size)
00084 {
00085 FILE *f = (FILE*)self;
00086 return(fread(buffer, 1, size, f));
00087 }
00088
00089
00090 static size_t
00091 fileio_write_func(void *self, const void *buffer, size_t size)
00092 {
00093 FILE *f = (FILE*)self;
00094 return(fwrite(buffer, 1, size, f));
00095 }
00096
00097
00115 Lib3dsFile*
00116 lib3ds_file_load(const char *filename)
00117 {
00118 FILE *f;
00119 Lib3dsFile *file;
00120 Lib3dsIo *io;
00121
00122 f = fopen(filename, "rb");
00123 if (!f) {
00124 return(0);
00125 }
00126 file = lib3ds_file_new();
00127 if (!file) {
00128 fclose(f);
00129 return(0);
00130 }
00131
00132 io = lib3ds_io_new(
00133 f,
00134 fileio_error_func,
00135 fileio_seek_func,
00136 fileio_tell_func,
00137 fileio_read_func,
00138 fileio_write_func
00139 );
00140 if (!io) {
00141 lib3ds_file_free(file);
00142 fclose(f);
00143 return(0);
00144 }
00145
00146 if (!lib3ds_file_read(file, io)) {
00147 free(file);
00148 lib3ds_io_free(io);
00149 fclose(f);
00150 return(0);
00151 }
00152
00153 lib3ds_io_free(io);
00154 fclose(f);
00155 return(file);
00156 }
00157
00158
00172 Lib3dsBool
00173 lib3ds_file_save(Lib3dsFile *file, const char *filename)
00174 {
00175 FILE *f;
00176 Lib3dsIo *io;
00177 Lib3dsBool result;
00178
00179 f = fopen(filename, "wb");
00180 if (!f) {
00181 return(LIB3DS_FALSE);
00182 }
00183 io = lib3ds_io_new(
00184 f,
00185 fileio_error_func,
00186 fileio_seek_func,
00187 fileio_tell_func,
00188 fileio_read_func,
00189 fileio_write_func
00190 );
00191 if (!io) {
00192 fclose(f);
00193 return LIB3DS_FALSE;
00194 }
00195
00196 result = lib3ds_file_write(file, io);
00197
00198 fclose(f);
00199
00200 lib3ds_io_free(io);
00201 return(result);
00202 }
00203
00204
00213 Lib3dsFile*
00214 lib3ds_file_new()
00215 {
00216 Lib3dsFile *file;
00217
00218 file=(Lib3dsFile*)calloc(sizeof(Lib3dsFile),1);
00219 if (!file) {
00220 return(0);
00221 }
00222 file->mesh_version=3;
00223 file->master_scale=1.0f;
00224 file->keyf_revision=5;
00225 strcpy(file->name, "LIB3DS");
00226
00227 file->frames=100;
00228 file->segment_from=0;
00229 file->segment_to=100;
00230 file->current_frame=0;
00231
00232 return(file);
00233 }
00234
00235
00243 void
00244 lib3ds_file_free(Lib3dsFile* file)
00245 {
00246 ASSERT(file);
00247 lib3ds_viewport_set_views(&file->viewport,0);
00248 lib3ds_viewport_set_views(&file->viewport_keyf,0);
00249 {
00250 Lib3dsMaterial *p,*q;
00251
00252 for (p=file->materials; p; p=q) {
00253 q=p->next;
00254 lib3ds_material_free(p);
00255 }
00256 file->materials=0;
00257 }
00258 {
00259 Lib3dsCamera *p,*q;
00260
00261 for (p=file->cameras; p; p=q) {
00262 q=p->next;
00263 lib3ds_camera_free(p);
00264 }
00265 file->cameras=0;
00266 }
00267 {
00268 Lib3dsLight *p,*q;
00269
00270 for (p=file->lights; p; p=q) {
00271 q=p->next;
00272 lib3ds_light_free(p);
00273 }
00274 file->lights=0;
00275 }
00276 {
00277 Lib3dsMesh *p,*q;
00278
00279 for (p=file->meshes; p; p=q) {
00280 q=p->next;
00281 lib3ds_mesh_free(p);
00282 }
00283 file->meshes=0;
00284 }
00285 {
00286 Lib3dsNode *p,*q;
00287
00288 for (p=file->nodes; p; p=q) {
00289 q=p->next;
00290 lib3ds_node_free(p);
00291 }
00292 }
00293 free(file);
00294 }
00295
00296
00307 void
00308 lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t)
00309 {
00310 Lib3dsNode *p;
00311
00312 for (p=file->nodes; p!=0; p=p->next) {
00313 lib3ds_node_eval(p, t);
00314 }
00315 }
00316
00317
00318 static Lib3dsBool
00319 named_object_read(Lib3dsFile *file, Lib3dsIo *io)
00320 {
00321 Lib3dsChunk c;
00322 char name[64];
00323 Lib3dsWord chunk;
00324 Lib3dsMesh *mesh = NULL;
00325 Lib3dsCamera *camera = NULL;
00326 Lib3dsLight *light = NULL;
00327 Lib3dsDword object_flags;
00328
00329 if (!lib3ds_chunk_read_start(&c, LIB3DS_NAMED_OBJECT, io)) {
00330 return(LIB3DS_FALSE);
00331 }
00332 if (!lib3ds_io_read_string(io, name, 64)) {
00333 return(LIB3DS_FALSE);
00334 }
00335 lib3ds_chunk_dump_info(" NAME=%s", name);
00336 lib3ds_chunk_read_tell(&c, io);
00337
00338 object_flags = 0;
00339 while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00340 switch (chunk) {
00341 case LIB3DS_N_TRI_OBJECT:
00342 {
00343 mesh=lib3ds_mesh_new(name);
00344 if (!mesh) {
00345 return(LIB3DS_FALSE);
00346 }
00347 lib3ds_chunk_read_reset(&c, io);
00348 if (!lib3ds_mesh_read(mesh, io)) {
00349 return(LIB3DS_FALSE);
00350 }
00351 lib3ds_file_insert_mesh(file, mesh);
00352 }
00353 break;
00354
00355 case LIB3DS_N_CAMERA:
00356 {
00357 camera=lib3ds_camera_new(name);
00358 if (!camera) {
00359 return(LIB3DS_FALSE);
00360 }
00361 lib3ds_chunk_read_reset(&c, io);
00362 if (!lib3ds_camera_read(camera, io)) {
00363 return(LIB3DS_FALSE);
00364 }
00365 lib3ds_file_insert_camera(file, camera);
00366 }
00367 break;
00368
00369 case LIB3DS_N_DIRECT_LIGHT:
00370 {
00371 light=lib3ds_light_new(name);
00372 if (!light) {
00373 return(LIB3DS_FALSE);
00374 }
00375 lib3ds_chunk_read_reset(&c, io);
00376 if (!lib3ds_light_read(light, io)) {
00377 return(LIB3DS_FALSE);
00378 }
00379 lib3ds_file_insert_light(file, light);
00380 }
00381 break;
00382
00383 case LIB3DS_OBJ_HIDDEN:
00384 object_flags |= LIB3DS_OBJECT_HIDDEN;
00385 break;
00386
00387 case LIB3DS_OBJ_DOESNT_CAST:
00388 object_flags |= LIB3DS_OBJECT_DOESNT_CAST;
00389 break;
00390
00391 case LIB3DS_OBJ_VIS_LOFTER:
00392 object_flags |= LIB3DS_OBJECT_VIS_LOFTER;
00393 break;
00394
00395 case LIB3DS_OBJ_MATTE:
00396 object_flags |= LIB3DS_OBJECT_MATTE;
00397 break;
00398
00399 case LIB3DS_OBJ_DONT_RCVSHADOW:
00400 object_flags |= LIB3DS_OBJECT_DONT_RCVSHADOW;
00401 break;
00402
00403 case LIB3DS_OBJ_FAST:
00404 object_flags |= LIB3DS_OBJECT_FAST;
00405 break;
00406
00407 case LIB3DS_OBJ_FROZEN:
00408 object_flags |= LIB3DS_OBJECT_FROZEN;
00409 break;
00410
00411 default:
00412 lib3ds_chunk_unknown(chunk);
00413 }
00414 }
00415
00416 if (mesh)
00417 mesh->object_flags = object_flags;
00418 if (camera)
00419 camera->object_flags = object_flags;
00420 if (light)
00421 light->object_flags = object_flags;
00422
00423 lib3ds_chunk_read_end(&c, io);
00424 return(LIB3DS_TRUE);
00425 }
00426
00427
00428 static Lib3dsBool
00429 ambient_read(Lib3dsFile *file, Lib3dsIo *io)
00430 {
00431 Lib3dsChunk c;
00432 Lib3dsWord chunk;
00433 Lib3dsBool have_lin=LIB3DS_FALSE;
00434
00435 if (!lib3ds_chunk_read_start(&c, LIB3DS_AMBIENT_LIGHT, io)) {
00436 return(LIB3DS_FALSE);
00437 }
00438
00439 while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00440 switch (chunk) {
00441 case LIB3DS_LIN_COLOR_F:
00442 {
00443 int i;
00444 for (i=0; i<3; ++i) {
00445 file->ambient[i]=lib3ds_io_read_float(io);
00446 }
00447 }
00448 have_lin=LIB3DS_TRUE;
00449 break;
00450 case LIB3DS_COLOR_F:
00451 {
00452
00453
00454 if (!have_lin) {
00455 int i;
00456 for (i=0; i<3; ++i) {
00457 file->ambient[i]=lib3ds_io_read_float(io);
00458 }
00459 }
00460 }
00461 break;
00462 default:
00463 lib3ds_chunk_unknown(chunk);
00464 }
00465 }
00466
00467 lib3ds_chunk_read_end(&c, io);
00468 return(LIB3DS_TRUE);
00469 }
00470
00471
00472 static Lib3dsBool
00473 mdata_read(Lib3dsFile *file, Lib3dsIo *io)
00474 {
00475 Lib3dsChunk c;
00476 Lib3dsWord chunk;
00477
00478 if (!lib3ds_chunk_read_start(&c, LIB3DS_MDATA, io)) {
00479 return(LIB3DS_FALSE);
00480 }
00481
00482 while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00483 switch (chunk) {
00484 case LIB3DS_MESH_VERSION:
00485 {
00486 file->mesh_version=lib3ds_io_read_intd(io);
00487 }
00488 break;
00489 case LIB3DS_MASTER_SCALE:
00490 {
00491 file->master_scale=lib3ds_io_read_float(io);
00492 }
00493 break;
00494 case LIB3DS_SHADOW_MAP_SIZE:
00495 case LIB3DS_LO_SHADOW_BIAS:
00496 case LIB3DS_HI_SHADOW_BIAS:
00497 case LIB3DS_SHADOW_SAMPLES:
00498 case LIB3DS_SHADOW_RANGE:
00499 case LIB3DS_SHADOW_FILTER:
00500 case LIB3DS_RAY_BIAS:
00501 {
00502 lib3ds_chunk_read_reset(&c, io);
00503 if (!lib3ds_shadow_read(&file->shadow, io)) {
00504 return(LIB3DS_FALSE);
00505 }
00506 }
00507 break;
00508 case LIB3DS_VIEWPORT_LAYOUT:
00509 case LIB3DS_DEFAULT_VIEW:
00510 {
00511 lib3ds_chunk_read_reset(&c, io);
00512 if (!lib3ds_viewport_read(&file->viewport, io)) {
00513 return(LIB3DS_FALSE);
00514 }
00515 }
00516 break;
00517 case LIB3DS_O_CONSTS:
00518 {
00519 int i;
00520 for (i=0; i<3; ++i) {
00521 file->construction_plane[i]=lib3ds_io_read_float(io);
00522 }
00523 }
00524 break;
00525 case LIB3DS_AMBIENT_LIGHT:
00526 {
00527 lib3ds_chunk_read_reset(&c, io);
00528 if (!ambient_read(file, io)) {
00529 return(LIB3DS_FALSE);
00530 }
00531 }
00532 break;
00533 case LIB3DS_BIT_MAP:
00534 case LIB3DS_SOLID_BGND:
00535 case LIB3DS_V_GRADIENT:
00536 case LIB3DS_USE_BIT_MAP:
00537 case LIB3DS_USE_SOLID_BGND:
00538 case LIB3DS_USE_V_GRADIENT:
00539 {
00540 lib3ds_chunk_read_reset(&c, io);
00541 if (!lib3ds_background_read(&file->background, io)) {
00542 return(LIB3DS_FALSE);
00543 }
00544 }
00545 break;
00546 case LIB3DS_FOG:
00547 case LIB3DS_LAYER_FOG:
00548 case LIB3DS_DISTANCE_CUE:
00549 case LIB3DS_USE_FOG:
00550 case LIB3DS_USE_LAYER_FOG:
00551 case LIB3DS_USE_DISTANCE_CUE:
00552 {
00553 lib3ds_chunk_read_reset(&c, io);
00554 if (!lib3ds_atmosphere_read(&file->atmosphere, io)) {
00555 return(LIB3DS_FALSE);
00556 }
00557 }
00558 break;
00559 case LIB3DS_MAT_ENTRY:
00560 {
00561 Lib3dsMaterial *material;
00562
00563 material=lib3ds_material_new();
00564 if (!material) {
00565 return(LIB3DS_FALSE);
00566 }
00567 lib3ds_chunk_read_reset(&c, io);
00568 if (!lib3ds_material_read(material, io)) {
00569 return(LIB3DS_FALSE);
00570 }
00571 lib3ds_file_insert_material(file, material);
00572 }
00573 break;
00574 case LIB3DS_NAMED_OBJECT:
00575 {
00576 lib3ds_chunk_read_reset(&c, io);
00577 if (!named_object_read(file, io)) {
00578 return(LIB3DS_FALSE);
00579 }
00580 }
00581 break;
00582 default:
00583 lib3ds_chunk_unknown(chunk);
00584 }
00585 }
00586
00587 lib3ds_chunk_read_end(&c, io);
00588 return(LIB3DS_TRUE);
00589 }
00590
00591
00592 static Lib3dsBool
00593 kfdata_read(Lib3dsFile *file, Lib3dsIo *io)
00594 {
00595 Lib3dsChunk c;
00596 Lib3dsWord chunk;
00597 Lib3dsDword node_number = 0;
00598
00599 if (!lib3ds_chunk_read_start(&c, LIB3DS_KFDATA, io)) {
00600 return(LIB3DS_FALSE);
00601 }
00602
00603 while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00604 switch (chunk) {
00605 case LIB3DS_KFHDR:
00606 {
00607 file->keyf_revision=lib3ds_io_read_word(io);
00608 if (!lib3ds_io_read_string(io, file->name, 12+1)) {
00609 return(LIB3DS_FALSE);
00610 }
00611 file->frames=lib3ds_io_read_intd(io);
00612 }
00613 break;
00614 case LIB3DS_KFSEG:
00615 {
00616 file->segment_from=lib3ds_io_read_intd(io);
00617 file->segment_to=lib3ds_io_read_intd(io);
00618 }
00619 break;
00620 case LIB3DS_KFCURTIME:
00621 {
00622 file->current_frame=lib3ds_io_read_intd(io);
00623 }
00624 break;
00625 case LIB3DS_VIEWPORT_LAYOUT:
00626 case LIB3DS_DEFAULT_VIEW:
00627 {
00628 lib3ds_chunk_read_reset(&c, io);
00629 if (!lib3ds_viewport_read(&file->viewport_keyf, io)) {
00630 return(LIB3DS_FALSE);
00631 }
00632 }
00633 break;
00634 case LIB3DS_AMBIENT_NODE_TAG:
00635 {
00636 Lib3dsNode *node;
00637
00638 node=lib3ds_node_new_ambient();
00639 if (!node) {
00640 return(LIB3DS_FALSE);
00641 }
00642 node->node_id=node_number++;
00643 lib3ds_chunk_read_reset(&c, io);
00644 if (!lib3ds_node_read(node, file, io)) {
00645 return(LIB3DS_FALSE);
00646 }
00647 lib3ds_file_insert_node(file, node);
00648 }
00649 break;
00650 case LIB3DS_OBJECT_NODE_TAG:
00651 {
00652 Lib3dsNode *node;
00653
00654 node=lib3ds_node_new_object();
00655 if (!node) {
00656 return(LIB3DS_FALSE);
00657 }
00658 node->node_id=node_number++;
00659 lib3ds_chunk_read_reset(&c, io);
00660 if (!lib3ds_node_read(node, file, io)) {
00661 return(LIB3DS_FALSE);
00662 }
00663 lib3ds_file_insert_node(file, node);
00664 }
00665 break;
00666 case LIB3DS_CAMERA_NODE_TAG:
00667 {
00668 Lib3dsNode *node;
00669
00670 node=lib3ds_node_new_camera();
00671 if (!node) {
00672 return(LIB3DS_FALSE);
00673 }
00674 node->node_id=node_number++;
00675 lib3ds_chunk_read_reset(&c, io);
00676 if (!lib3ds_node_read(node, file, io)) {
00677 return(LIB3DS_FALSE);
00678 }
00679 lib3ds_file_insert_node(file, node);
00680 }
00681 break;
00682 case LIB3DS_TARGET_NODE_TAG:
00683 {
00684 Lib3dsNode *node;
00685
00686 node=lib3ds_node_new_target();
00687 if (!node) {
00688 return(LIB3DS_FALSE);
00689 }
00690 node->node_id=node_number++;
00691 lib3ds_chunk_read_reset(&c, io);
00692 if (!lib3ds_node_read(node, file, io)) {
00693 return(LIB3DS_FALSE);
00694 }
00695 lib3ds_file_insert_node(file, node);
00696 }
00697 break;
00698 case LIB3DS_LIGHT_NODE_TAG:
00699 case LIB3DS_SPOTLIGHT_NODE_TAG:
00700 {
00701 Lib3dsNode *node;
00702
00703 node=lib3ds_node_new_light();
00704 if (!node) {
00705 return(LIB3DS_FALSE);
00706 }
00707 node->node_id=node_number++;
00708 lib3ds_chunk_read_reset(&c, io);
00709 if (!lib3ds_node_read(node, file, io)) {
00710 return(LIB3DS_FALSE);
00711 }
00712 lib3ds_file_insert_node(file, node);
00713 }
00714 break;
00715 case LIB3DS_L_TARGET_NODE_TAG:
00716 {
00717 Lib3dsNode *node;
00718
00719 node=lib3ds_node_new_spot();
00720 if (!node) {
00721 return(LIB3DS_FALSE);
00722 }
00723 node->node_id=node_number++;
00724 lib3ds_chunk_read_reset(&c, io);
00725 if (!lib3ds_node_read(node, file, io)) {
00726 return(LIB3DS_FALSE);
00727 }
00728 lib3ds_file_insert_node(file, node);
00729 }
00730 break;
00731 default:
00732 lib3ds_chunk_unknown(chunk);
00733 }
00734 }
00735
00736 lib3ds_chunk_read_end(&c, io);
00737 return(LIB3DS_TRUE);
00738 }
00739
00740
00751 Lib3dsBool
00752 lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io)
00753 {
00754 Lib3dsChunk c;
00755 Lib3dsWord chunk;
00756
00757 if (!lib3ds_chunk_read_start(&c, 0, io)) {
00758 return(LIB3DS_FALSE);
00759 }
00760 switch (c.chunk) {
00761 case LIB3DS_MDATA:
00762 {
00763 lib3ds_chunk_read_reset(&c, io);
00764 if (!mdata_read(file, io)) {
00765 return(LIB3DS_FALSE);
00766 }
00767 }
00768 break;
00769 case LIB3DS_M3DMAGIC:
00770 case LIB3DS_MLIBMAGIC:
00771 case LIB3DS_CMAGIC:
00772 {
00773 while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
00774 switch (chunk) {
00775 case LIB3DS_M3D_VERSION:
00776 {
00777 file->mesh_version=lib3ds_io_read_dword(io);
00778 }
00779 break;
00780 case LIB3DS_MDATA:
00781 {
00782 lib3ds_chunk_read_reset(&c, io);
00783 if (!mdata_read(file, io)) {
00784 return(LIB3DS_FALSE);
00785 }
00786 }
00787 break;
00788 case LIB3DS_KFDATA:
00789 {
00790 lib3ds_chunk_read_reset(&c, io);
00791 if (!kfdata_read(file, io)) {
00792 return(LIB3DS_FALSE);
00793 }
00794 }
00795 break;
00796 default:
00797 lib3ds_chunk_unknown(chunk);
00798 }
00799 }
00800 }
00801 break;
00802 default:
00803 lib3ds_chunk_unknown(c.chunk);
00804 return(LIB3DS_FALSE);
00805 }
00806
00807 lib3ds_chunk_read_end(&c, io);
00808 return(LIB3DS_TRUE);
00809 }
00810
00811
00812 static Lib3dsBool
00813 colorf_write(Lib3dsRgba rgb, Lib3dsIo *io)
00814 {
00815 Lib3dsChunk c;
00816
00817 c.chunk=LIB3DS_COLOR_F;
00818 c.size=18;
00819 lib3ds_chunk_write(&c,io);
00820 lib3ds_io_write_rgb(io, rgb);
00821
00822 c.chunk=LIB3DS_LIN_COLOR_F;
00823 c.size=18;
00824 lib3ds_chunk_write(&c,io);
00825 lib3ds_io_write_rgb(io, rgb);
00826 return(LIB3DS_TRUE);
00827 }
00828
00829
00830 static Lib3dsBool
00831 object_flags_write(Lib3dsDword flags, Lib3dsIo *io)
00832 {
00833 if (flags){
00834 if (flags & LIB3DS_OBJECT_HIDDEN) {
00835 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_HIDDEN, io))
00836 return LIB3DS_FALSE;
00837 }
00838 if (flags & LIB3DS_OBJECT_VIS_LOFTER) {
00839 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_VIS_LOFTER, io))
00840 return LIB3DS_FALSE;
00841 }
00842 if (flags & LIB3DS_OBJECT_DOESNT_CAST) {
00843 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_DOESNT_CAST, io))
00844 return LIB3DS_FALSE;
00845 }
00846 if (flags & LIB3DS_OBJECT_MATTE) {
00847 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_MATTE, io))
00848 return LIB3DS_FALSE;
00849 }
00850 if (flags & LIB3DS_OBJECT_DONT_RCVSHADOW) {
00851 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_DOESNT_CAST, io))
00852 return LIB3DS_FALSE;
00853 }
00854 if (flags & LIB3DS_OBJECT_FAST) {
00855 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_FAST, io))
00856 return LIB3DS_FALSE;
00857 }
00858 if (flags & LIB3DS_OBJECT_FROZEN) {
00859 if (!lib3ds_chunk_write_switch(LIB3DS_OBJ_FROZEN, io))
00860 return LIB3DS_FALSE;
00861 }
00862 }
00863 return LIB3DS_TRUE;
00864 }
00865
00866
00867 static Lib3dsBool
00868 mdata_write(Lib3dsFile *file, Lib3dsIo *io)
00869 {
00870 Lib3dsChunk c;
00871
00872 c.chunk=LIB3DS_MDATA;
00873 if (!lib3ds_chunk_write_start(&c,io)) {
00874 return(LIB3DS_FALSE);
00875 }
00876
00877 {
00878 Lib3dsChunk c;
00879 c.chunk=LIB3DS_MESH_VERSION;
00880 c.size=10;
00881 lib3ds_chunk_write(&c,io);
00882 lib3ds_io_write_intd(io, file->mesh_version);
00883 }
00884 {
00885 Lib3dsChunk c;
00886 c.chunk=LIB3DS_MASTER_SCALE;
00887 c.size=10;
00888 lib3ds_chunk_write(&c,io);
00889 lib3ds_io_write_float(io, file->master_scale);
00890 }
00891 {
00892 int i;
00893 for (i=0; i<3; ++i) {
00894 if (fabs(file->construction_plane[i])>LIB3DS_EPSILON) {
00895 break;
00896 }
00897 }
00898 if (i<3) {
00899 Lib3dsChunk c;
00900 c.chunk=LIB3DS_O_CONSTS;
00901 c.size=18;
00902 lib3ds_chunk_write(&c,io);
00903 lib3ds_io_write_vector(io, file->construction_plane);
00904 }
00905 }
00906
00907 {
00908 int i;
00909 for (i=0; i<3; ++i) {
00910 if (fabs(file->ambient[i])>LIB3DS_EPSILON) {
00911 break;
00912 }
00913 }
00914 if (i<3) {
00915 Lib3dsChunk c;
00916 c.chunk=LIB3DS_AMBIENT_LIGHT;
00917 c.size=42;
00918 lib3ds_chunk_write(&c,io);
00919 colorf_write(file->ambient,io);
00920 }
00921 }
00922 lib3ds_background_write(&file->background, io);
00923 lib3ds_atmosphere_write(&file->atmosphere, io);
00924 lib3ds_shadow_write(&file->shadow, io);
00925 lib3ds_viewport_write(&file->viewport, io);
00926 {
00927 Lib3dsMaterial *p;
00928 for (p=file->materials; p!=0; p=p->next) {
00929 if (!lib3ds_material_write(p,io)) {
00930 return(LIB3DS_FALSE);
00931 }
00932 }
00933 }
00934 {
00935 Lib3dsCamera *p;
00936 Lib3dsChunk c;
00937
00938 for (p=file->cameras; p!=0; p=p->next) {
00939 c.chunk=LIB3DS_NAMED_OBJECT;
00940 if (!lib3ds_chunk_write_start(&c,io)) {
00941 return(LIB3DS_FALSE);
00942 }
00943 lib3ds_io_write_string(io, p->name);
00944 lib3ds_camera_write(p,io);
00945 object_flags_write(p->object_flags,io);
00946 if (!lib3ds_chunk_write_end(&c,io)) {
00947 return(LIB3DS_FALSE);
00948 }
00949 }
00950 }
00951 {
00952 Lib3dsLight *p;
00953 Lib3dsChunk c;
00954
00955 for (p=file->lights; p!=0; p=p->next) {
00956 c.chunk=LIB3DS_NAMED_OBJECT;
00957 if (!lib3ds_chunk_write_start(&c,io)) {
00958 return(LIB3DS_FALSE);
00959 }
00960 lib3ds_io_write_string(io,p->name);
00961 lib3ds_light_write(p,io);
00962 object_flags_write(p->object_flags,io);
00963 if (!lib3ds_chunk_write_end(&c,io)) {
00964 return(LIB3DS_FALSE);
00965 }
00966 }
00967 }
00968 {
00969 Lib3dsMesh *p;
00970 Lib3dsChunk c;
00971
00972 for (p=file->meshes; p!=0; p=p->next) {
00973 c.chunk=LIB3DS_NAMED_OBJECT;
00974 if (!lib3ds_chunk_write_start(&c,io)) {
00975 return(LIB3DS_FALSE);
00976 }
00977 lib3ds_io_write_string(io, p->name);
00978 lib3ds_mesh_write(p,io);
00979 object_flags_write(p->object_flags,io);
00980 if (!lib3ds_chunk_write_end(&c,io)) {
00981 return(LIB3DS_FALSE);
00982 }
00983 }
00984 }
00985
00986 if (!lib3ds_chunk_write_end(&c,io)) {
00987 return(LIB3DS_FALSE);
00988 }
00989 return(LIB3DS_TRUE);
00990 }
00991
00992
00993
00994 static Lib3dsBool
00995 nodes_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io)
00996 {
00997 {
00998 Lib3dsNode *p;
00999 for (p=node->childs; p!=0; p=p->next) {
01000 if (!lib3ds_node_write(p, file, io)) {
01001 return(LIB3DS_FALSE);
01002 }
01003 nodes_write(p, file, io);
01004 }
01005 }
01006 return(LIB3DS_TRUE);
01007 }
01008
01009
01010 static Lib3dsBool
01011 kfdata_write(Lib3dsFile *file, Lib3dsIo *io)
01012 {
01013 Lib3dsChunk c;
01014
01015 if (!file->nodes) {
01016 return(LIB3DS_TRUE);
01017 }
01018
01019 c.chunk=LIB3DS_KFDATA;
01020 if (!lib3ds_chunk_write_start(&c,io)) {
01021 return(LIB3DS_FALSE);
01022 }
01023
01024 {
01025 Lib3dsChunk c;
01026 c.chunk=LIB3DS_KFHDR;
01027 c.size=6 + 2 + (Lib3dsDword)strlen(file->name)+1 +4;
01028 lib3ds_chunk_write(&c,io);
01029 lib3ds_io_write_intw(io, file->keyf_revision);
01030 lib3ds_io_write_string(io, file->name);
01031 lib3ds_io_write_intd(io, file->frames);
01032 }
01033 {
01034 Lib3dsChunk c;
01035 c.chunk=LIB3DS_KFSEG;
01036 c.size=14;
01037 lib3ds_chunk_write(&c,io);
01038 lib3ds_io_write_intd(io, file->segment_from);
01039 lib3ds_io_write_intd(io, file->segment_to);
01040 }
01041 {
01042 Lib3dsChunk c;
01043 c.chunk=LIB3DS_KFCURTIME;
01044 c.size=10;
01045 lib3ds_chunk_write(&c,io);
01046 lib3ds_io_write_intd(io, file->current_frame);
01047 }
01048 lib3ds_viewport_write(&file->viewport_keyf, io);
01049
01050 {
01051 Lib3dsNode *p;
01052 for (p=file->nodes; p!=0; p=p->next) {
01053 if (!lib3ds_node_write(p, file, io)) {
01054 return(LIB3DS_FALSE);
01055 }
01056 if (!nodes_write(p, file, io)) {
01057 return(LIB3DS_FALSE);
01058 }
01059 }
01060 }
01061
01062 if (!lib3ds_chunk_write_end(&c,io)) {
01063 return(LIB3DS_FALSE);
01064 }
01065 return(LIB3DS_TRUE);
01066 }
01067
01068
01079 Lib3dsBool
01080 lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io)
01081 {
01082 Lib3dsChunk c;
01083
01084 c.chunk=LIB3DS_M3DMAGIC;
01085 if (!lib3ds_chunk_write_start(&c,io)) {
01086 LIB3DS_ERROR_LOG;
01087 return(LIB3DS_FALSE);
01088 }
01089
01090 {
01091 Lib3dsChunk c;
01092
01093 c.chunk=LIB3DS_M3D_VERSION;
01094 c.size=10;
01095 lib3ds_chunk_write(&c,io);
01096 lib3ds_io_write_dword(io, file->mesh_version);
01097 }
01098
01099 if (!mdata_write(file, io)) {
01100 return(LIB3DS_FALSE);
01101 }
01102 if (!kfdata_write(file, io)) {
01103 return(LIB3DS_FALSE);
01104 }
01105
01106 if (!lib3ds_chunk_write_end(&c,io)) {
01107 return(LIB3DS_FALSE);
01108 }
01109 return(LIB3DS_TRUE);
01110 }
01111
01112
01125 void
01126 lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material)
01127 {
01128 Lib3dsMaterial *p,*q;
01129
01130 ASSERT(file);
01131 ASSERT(material);
01132 ASSERT(!material->next);
01133
01134 q=0;
01135 for (p=file->materials; p!=0; p=p->next) {
01136 if (strcmp(material->name, p->name)<0) {
01137 break;
01138 }
01139 q=p;
01140 }
01141 if (!q) {
01142 material->next=file->materials;
01143 file->materials=material;
01144 }
01145 else {
01146 material->next=q->next;
01147 q->next=material;
01148 }
01149 }
01150
01151
01164 void
01165 lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material)
01166 {
01167 Lib3dsMaterial *p,*q;
01168
01169 ASSERT(file);
01170 ASSERT(material);
01171 ASSERT(file->materials);
01172 for (p=0,q=file->materials; q; p=q,q=q->next) {
01173 if (q==material) {
01174 break;
01175 }
01176 }
01177 if (!q) {
01178 ASSERT(LIB3DS_FALSE);
01179 return;
01180 }
01181 if (!p) {
01182 file->materials=material->next;
01183 }
01184 else {
01185 p->next=q->next;
01186 }
01187 material->next=0;
01188 }
01189
01190
01201 Lib3dsMaterial*
01202 lib3ds_file_material_by_name(Lib3dsFile *file, const char *name)
01203 {
01204 Lib3dsMaterial *p;
01205
01206 ASSERT(file);
01207 for (p=file->materials; p!=0; p=p->next) {
01208 if (strcmp(p->name,name)==0) {
01209 return(p);
01210 }
01211 }
01212 return(0);
01213 }
01214
01215
01225 void
01226 lib3ds_file_dump_materials(Lib3dsFile *file)
01227 {
01228 Lib3dsMaterial *p;
01229
01230 ASSERT(file);
01231 for (p=file->materials; p!=0; p=p->next) {
01232 lib3ds_material_dump(p);
01233 }
01234 }
01235
01236
01249 void
01250 lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
01251 {
01252 Lib3dsMesh *p,*q;
01253
01254 ASSERT(file);
01255 ASSERT(mesh);
01256 ASSERT(!mesh->next);
01257
01258 q=0;
01259 for (p=file->meshes; p!=0; p=p->next) {
01260 if (strcmp(mesh->name, p->name)<0) {
01261 break;
01262 }
01263 q=p;
01264 }
01265 if (!q) {
01266 mesh->next=file->meshes;
01267 file->meshes=mesh;
01268 }
01269 else {
01270 mesh->next=q->next;
01271 q->next=mesh;
01272 }
01273 }
01274
01275
01288 void
01289 lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
01290 {
01291 Lib3dsMesh *p,*q;
01292
01293 ASSERT(file);
01294 ASSERT(mesh);
01295 ASSERT(file->meshes);
01296 for (p=0,q=file->meshes; q; p=q,q=q->next) {
01297 if (q==mesh) {
01298 break;
01299 }
01300 }
01301 if (!q) {
01302 ASSERT(LIB3DS_FALSE);
01303 return;
01304 }
01305 if (!p) {
01306 file->meshes=mesh->next;
01307 }
01308 else {
01309 p->next=q->next;
01310 }
01311 mesh->next=0;
01312 }
01313
01314
01325 Lib3dsMesh*
01326 lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name)
01327 {
01328 Lib3dsMesh *p;
01329
01330 ASSERT(file);
01331 for (p=file->meshes; p!=0; p=p->next) {
01332 if (strcmp(p->name,name)==0) {
01333 return(p);
01334 }
01335 }
01336 return(0);
01337 }
01338
01339
01349 void
01350 lib3ds_file_dump_meshes(Lib3dsFile *file)
01351 {
01352 Lib3dsMesh *p;
01353
01354 ASSERT(file);
01355 for (p=file->meshes; p!=0; p=p->next) {
01356 lib3ds_mesh_dump(p);
01357 }
01358 }
01359
01360
01361 static void
01362 dump_instances(Lib3dsNode *node, const char* parent)
01363 {
01364 Lib3dsNode *p;
01365 char name[255];
01366
01367 ASSERT(node);
01368 ASSERT(parent);
01369 strcpy(name, parent);
01370 strcat(name, ".");
01371 strcat(name, node->name);
01372 if (node->type==LIB3DS_OBJECT_NODE) {
01373 printf(" %s : %s\n", name, node->data.object.instance);
01374 }
01375 for (p=node->childs; p!=0; p=p->next) {
01376 dump_instances(p, parent);
01377 }
01378 }
01379
01380
01396 void
01397 lib3ds_file_dump_instances(Lib3dsFile *file)
01398 {
01399 Lib3dsNode *p;
01400
01401 ASSERT(file);
01402 for (p=file->nodes; p!=0; p=p->next) {
01403 dump_instances(p,"");
01404 }
01405 }
01406
01407
01420 void
01421 lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera)
01422 {
01423 Lib3dsCamera *p,*q;
01424
01425 ASSERT(file);
01426 ASSERT(camera);
01427 ASSERT(!camera->next);
01428
01429 q=0;
01430 for (p=file->cameras; p!=0; p=p->next) {
01431 if (strcmp(camera->name, p->name)<0) {
01432 break;
01433 }
01434 q=p;
01435 }
01436 if (!q) {
01437 camera->next=file->cameras;
01438 file->cameras=camera;
01439 }
01440 else {
01441 camera->next=q->next;
01442 q->next=camera;
01443 }
01444 }
01445
01446
01459 void
01460 lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera)
01461 {
01462 Lib3dsCamera *p,*q;
01463
01464 ASSERT(file);
01465 ASSERT(camera);
01466 ASSERT(file->cameras);
01467 for (p=0,q=file->cameras; q; p=q,q=q->next) {
01468 if (q==camera) {
01469 break;
01470 }
01471 }
01472 if (!q) {
01473 ASSERT(LIB3DS_FALSE);
01474 return;
01475 }
01476 if (!p) {
01477 file->cameras=camera->next;
01478 }
01479 else {
01480 p->next=q->next;
01481 }
01482 camera->next=0;
01483 }
01484
01485
01496 Lib3dsCamera*
01497 lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name)
01498 {
01499 Lib3dsCamera *p;
01500
01501 ASSERT(file);
01502 for (p=file->cameras; p!=0; p=p->next) {
01503 if (strcmp(p->name,name)==0) {
01504 return(p);
01505 }
01506 }
01507 return(0);
01508 }
01509
01510
01520 void
01521 lib3ds_file_dump_cameras(Lib3dsFile *file)
01522 {
01523 Lib3dsCamera *p;
01524
01525 ASSERT(file);
01526 for (p=file->cameras; p!=0; p=p->next) {
01527 lib3ds_camera_dump(p);
01528 }
01529 }
01530
01531
01544 void
01545 lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light)
01546 {
01547 Lib3dsLight *p,*q;
01548
01549 ASSERT(file);
01550 ASSERT(light);
01551 ASSERT(!light->next);
01552
01553 q=0;
01554 for (p=file->lights; p!=0; p=p->next) {
01555 if (strcmp(light->name, p->name)<0) {
01556 break;
01557 }
01558 q=p;
01559 }
01560 if (!q) {
01561 light->next=file->lights;
01562 file->lights=light;
01563 }
01564 else {
01565 light->next=q->next;
01566 q->next=light;
01567 }
01568 }
01569
01570
01583 void
01584 lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light)
01585 {
01586 Lib3dsLight *p,*q;
01587
01588 ASSERT(file);
01589 ASSERT(light);
01590 ASSERT(file->lights);
01591 for (p=0,q=file->lights; q; p=q,q=q->next) {
01592 if (q==light) {
01593 break;
01594 }
01595 }
01596 if (!q) {
01597 ASSERT(LIB3DS_FALSE);
01598 return;
01599 }
01600 if (!p) {
01601 file->lights=light->next;
01602 }
01603 else {
01604 p->next=q->next;
01605 }
01606 light->next=0;
01607 }
01608
01609
01620 Lib3dsLight*
01621 lib3ds_file_light_by_name(Lib3dsFile *file, const char *name)
01622 {
01623 Lib3dsLight *p;
01624
01625 ASSERT(file);
01626 for (p=file->lights; p!=0; p=p->next) {
01627 if (strcmp(p->name,name)==0) {
01628 return(p);
01629 }
01630 }
01631 return(0);
01632 }
01633
01634
01644 void
01645 lib3ds_file_dump_lights(Lib3dsFile *file)
01646 {
01647 Lib3dsLight *p;
01648
01649 ASSERT(file);
01650 for (p=file->lights; p!=0; p=p->next) {
01651 lib3ds_light_dump(p);
01652 }
01653 }
01654
01655
01672 Lib3dsNode*
01673 lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type)
01674 {
01675 Lib3dsNode *p,*q;
01676
01677 ASSERT(file);
01678 for (p=file->nodes; p!=0; p=p->next) {
01679 if ((p->type==type) && (strcmp(p->name, name)==0)) {
01680 return(p);
01681 }
01682 q=lib3ds_node_by_name(p, name, type);
01683 if (q) {
01684 return(q);
01685 }
01686 }
01687 return(0);
01688 }
01689
01690
01705 Lib3dsNode*
01706 lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id)
01707 {
01708 Lib3dsNode *p,*q;
01709
01710 ASSERT(file);
01711 for (p=file->nodes; p!=0; p=p->next) {
01712 if (p->node_id==node_id) {
01713 return(p);
01714 }
01715 q=lib3ds_node_by_id(p, node_id);
01716 if (q) {
01717 return(q);
01718 }
01719 }
01720 return(0);
01721 }
01722
01723
01743 void
01744 lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node)
01745 {
01746 Lib3dsNode *parent,*p,*n;
01747
01748 ASSERT(node);
01749 ASSERT(!node->next);
01750 ASSERT(!node->parent);
01751
01752 parent=0;
01753 if (node->parent_id!=LIB3DS_NO_PARENT) {
01754 parent=lib3ds_file_node_by_id(file, node->parent_id);
01755 }
01756 node->parent=parent;
01757
01758 if (!parent) {
01759 for (p=0,n=file->nodes; n!=0; p=n,n=n->next) {
01760 if (strcmp(n->name, node->name)>0) {
01761 break;
01762 }
01763 }
01764 if (!p) {
01765 node->next=file->nodes;
01766 file->nodes=node;
01767 }