dropped all dependencies apart from SDL into the libs subdir
[summerhack] / src / 3dengfx / libs / lib3ds / file.c
diff --git a/src/3dengfx/libs/lib3ds/file.c b/src/3dengfx/libs/lib3ds/file.c
deleted file mode 100644 (file)
index 33df4b9..0000000
+++ /dev/null
@@ -1,1917 +0,0 @@
-/*
- * The 3D Studio File Format Library
- * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
- * All rights reserved.
- *
- * This program is  free  software;  you can redistribute it and/or modify it
- * under the terms of the  GNU Lesser General Public License  as published by 
- * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
- * your option) any later version.
- *
- * This  program  is  distributed in  the  hope that it will  be useful,  but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
- * License for more details.
- *
- * You should  have received  a copy of the GNU Lesser General Public License
- * along with  this program;  if not, write to the  Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: file.c,v 1.23 2005/01/11 10:20:36 madmac Exp $
- */
-#define LIB3DS_EXPORT
-#include <lib3ds/file.h>
-#include <lib3ds/chunk.h>
-#include <lib3ds/io.h>
-#include <lib3ds/material.h>
-#include <lib3ds/mesh.h>
-#include <lib3ds/camera.h>
-#include <lib3ds/light.h>
-#include <lib3ds/node.h>
-#include <lib3ds/vector.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#ifdef WITH_DMALLOC
-#include <dmalloc.h>
-#endif
-
-
-
-/*!
- * \defgroup file Files
- *
- * \author J.E. Hoffmann <je-h@gmx.net>
- */
-
-
-static Lib3dsBool
-fileio_error_func(void *self)
-{
-  FILE *f = (FILE*)self;
-  return(ferror(f)!=0);
-}
-
-
-static long
-fileio_seek_func(void *self, long offset, Lib3dsIoSeek origin)
-{
-  FILE *f = (FILE*)self;
-  int o;
-  switch (origin) {
-    case LIB3DS_SEEK_SET:
-      o = SEEK_SET;
-      break;
-    case LIB3DS_SEEK_CUR:
-      o = SEEK_CUR;
-      break;
-    case LIB3DS_SEEK_END:
-      o = SEEK_END;
-      break;
-    default:
-      ASSERT(0);
-      return(0);
-  }
-  return (fseek(f, offset, o));
-}
-
-
-static long
-fileio_tell_func(void *self)
-{
-  FILE *f = (FILE*)self;
-  return(ftell(f));
-}
-
-
-static int
-fileio_read_func(void *self, Lib3dsByte *buffer, int size)
-{
-  FILE *f = (FILE*)self;
-  return(fread(buffer, 1, size, f));
-}
-
-
-static int
-fileio_write_func(void *self, const Lib3dsByte *buffer, int size)
-{
-  FILE *f = (FILE*)self;
-  return(fwrite(buffer, 1, size, f));
-}
-
-
-/*!
- * Loads a .3DS file from disk into memory.
- *
- * \param filename  The filename of the .3DS file
- *
- * \return   A pointer to the Lib3dsFile structure containing the
- *           data of the .3DS file. 
- *           If the .3DS file can not be loaded NULL is returned.
- *
- * \note     To free the returned structure use lib3ds_free.
- *
- * \see lib3ds_file_save
- * \see lib3ds_file_new
- * \see lib3ds_file_free
- *
- * \ingroup file
- */
-Lib3dsFile*
-lib3ds_file_load(const char *filename)
-{
-  FILE *f;
-  Lib3dsFile *file;
-  Lib3dsIo *io;
-
-
-  f = fopen(filename, "rb");
-  if (!f) {
-    return(0);
-  }
-  file = lib3ds_file_new();
-  if (!file) {
-    fclose(f);
-    return(0);
-  }
-  io = lib3ds_io_new(
-    f, 
-    fileio_error_func,
-    fileio_seek_func,
-    fileio_tell_func,
-    fileio_read_func,
-    fileio_write_func
-  );
-  if (!io) {
-    lib3ds_file_free(file);
-    fclose(f);
-    return(0);
-  }
-
-  if (!lib3ds_file_read(file, io)) {
-    free(file);
-    fclose(f);
-    return(0);
-  }
-
-  lib3ds_io_free(io);
-  fclose(f);
-  return(file);
-}
-
-
-/*!
- * Saves a .3DS file from memory to disk.
- *
- * \param file      A pointer to a Lib3dsFile structure containing the
- *                  the data that should be stored.
- * \param filename  The filename of the .3DS file to store the data in.
- *
- * \return          TRUE on success, FALSE otherwise.
- *
- * \see lib3ds_file_load
- *
- * \ingroup file
- */
-Lib3dsBool
-lib3ds_file_save(Lib3dsFile *file, const char *filename)
-{
-  FILE *f;
-  Lib3dsIo *io;
-  Lib3dsBool result;
-
-  f = fopen(filename, "wb");
-  if (!f) {
-    return(LIB3DS_FALSE);
-  }
-  io = lib3ds_io_new(
-    f, 
-    fileio_error_func,
-    fileio_seek_func,
-    fileio_tell_func,
-    fileio_read_func,
-    fileio_write_func
-  );
-  if (!io) {
-    fclose(f);
-    return LIB3DS_FALSE;
-  }
-  
-  result = lib3ds_file_write(file, io);
-
-  fclose(f);
-
-  lib3ds_io_free(io);
-  return(result);
-}
-
-
-/*!
- * Creates and returns a new, empty Lib3dsFile object.
- *
- * \return     A pointer to the Lib3dsFile structure.
- *             If the structure cannot be allocated, NULL is returned.
- *
- * \ingroup file
- */
-Lib3dsFile*
-lib3ds_file_new()
-{
-  Lib3dsFile *file;
-
-  file=(Lib3dsFile*)calloc(sizeof(Lib3dsFile),1);
-  if (!file) {
-    return(0);
-  }
-  file->mesh_version=3;
-  file->master_scale=1.0f;
-  file->keyf_revision=5;
-  strcpy(file->name, "LIB3DS");
-
-  file->frames=100;
-  file->segment_from=0;
-  file->segment_to=100;
-  file->current_frame=0;
-
-  return(file);
-}
-
-
-/*!
- * Free a Lib3dsFile object and all of its resources.
- *
- * \param file The Lib3dsFile object to be freed.
- *
- * \ingroup file
- */
-void
-lib3ds_file_free(Lib3dsFile* file)
-{
-  ASSERT(file);
-  lib3ds_viewport_set_views(&file->viewport,0);
-  {
-    Lib3dsMaterial *p,*q;
-    
-    for (p=file->materials; p; p=q) {
-      q=p->next;
-      lib3ds_material_free(p);
-    }
-    file->materials=0;
-  }
-  {
-    Lib3dsCamera *p,*q;
-    
-    for (p=file->cameras; p; p=q) {
-      q=p->next;
-      lib3ds_camera_free(p);
-    }
-    file->cameras=0;
-  }
-  {
-    Lib3dsLight *p,*q;
-    
-    for (p=file->lights; p; p=q) {
-      q=p->next;
-      lib3ds_light_free(p);
-    }
-    file->lights=0;
-  }
-  {
-    Lib3dsMesh *p,*q;
-    
-    for (p=file->meshes; p; p=q) {
-      q=p->next;
-      lib3ds_mesh_free(p);
-    }
-    file->meshes=0;
-  }
-  {
-    Lib3dsNode *p,*q;
-  
-    for (p=file->nodes; p; p=q) {
-      q=p->next;
-      lib3ds_node_free(p);
-    }
-  }
-  free(file);
-}
-
-
-/*!
- * Evaluate all of the nodes in this Lib3dsFile object.
- *
- * \param file The Lib3dsFile object to be evaluated.
- * \param t time value, between 0. and file->frames
- *
- * \see lib3ds_node_eval
- *
- * \ingroup file
- */
-void
-lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t)
-{
-  Lib3dsNode *p;
-
-  for (p=file->nodes; p!=0; p=p->next) {
-    lib3ds_node_eval(p, t);
-  }
-}
-
-
-static Lib3dsBool
-named_object_read(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  char name[64];
-  Lib3dsWord chunk;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_NAMED_OBJECT, io)) {
-    return(LIB3DS_FALSE);
-  }
-  if (!lib3ds_io_read_string(io, name, 64)) {
-    return(LIB3DS_FALSE);
-  }
-  lib3ds_chunk_dump_info("  NAME=%s", name);
-  lib3ds_chunk_read_tell(&c, io);
-
-  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-    switch (chunk) {
-      case LIB3DS_N_TRI_OBJECT:
-        {
-          Lib3dsMesh *mesh;
-
-          mesh=lib3ds_mesh_new(name);
-          if (!mesh) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_mesh_read(mesh, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_mesh(file, mesh);
-        }
-        break;
-      case LIB3DS_N_CAMERA:
-        {
-          Lib3dsCamera *camera;
-
-          camera=lib3ds_camera_new(name);
-          if (!camera) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_camera_read(camera, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_camera(file, camera);
-        }
-        break;
-      case LIB3DS_N_DIRECT_LIGHT:
-        {
-          Lib3dsLight *light;
-
-          light=lib3ds_light_new(name);
-          if (!light) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_light_read(light, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_light(file, light);
-        }
-        break;
-      default:
-        lib3ds_chunk_unknown(chunk);
-    }
-  }
-  
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-ambient_read(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-  Lib3dsBool have_lin=LIB3DS_FALSE;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_AMBIENT_LIGHT, io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-    switch (chunk) {
-      case LIB3DS_LIN_COLOR_F:
-        {
-          int i;
-          for (i=0; i<3; ++i) {
-            file->ambient[i]=lib3ds_io_read_float(io);
-          }
-        }
-        have_lin=LIB3DS_TRUE;
-        break;
-      case LIB3DS_COLOR_F:
-        {
-          /* gamma corrected color chunk
-             replaced in 3ds R3 by LIN_COLOR_24 */
-          if (!have_lin) {
-            int i;
-            for (i=0; i<3; ++i) {
-              file->ambient[i]=lib3ds_io_read_float(io);
-            }
-          }
-        }
-        break;
-      default:
-        lib3ds_chunk_unknown(chunk);
-    }
-  }
-  
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-mdata_read(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_MDATA, io)) {
-    return(LIB3DS_FALSE);
-  }
-  
-  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-    switch (chunk) {
-      case LIB3DS_MESH_VERSION:
-        {
-          file->mesh_version=lib3ds_io_read_intd(io);
-        }
-        break;
-      case LIB3DS_MASTER_SCALE:
-        {
-          file->master_scale=lib3ds_io_read_float(io);
-        }
-        break;
-      case LIB3DS_SHADOW_MAP_SIZE:
-      case LIB3DS_LO_SHADOW_BIAS:
-      case LIB3DS_HI_SHADOW_BIAS:
-      case LIB3DS_SHADOW_SAMPLES:
-      case LIB3DS_SHADOW_RANGE:
-      case LIB3DS_SHADOW_FILTER:
-      case LIB3DS_RAY_BIAS:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_shadow_read(&file->shadow, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_VIEWPORT_LAYOUT:
-      case LIB3DS_DEFAULT_VIEW:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_viewport_read(&file->viewport, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_O_CONSTS:
-        {
-          int i;
-          for (i=0; i<3; ++i) {
-            file->construction_plane[i]=lib3ds_io_read_float(io);
-          }
-        }
-        break;
-      case LIB3DS_AMBIENT_LIGHT:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!ambient_read(file, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_BIT_MAP:
-      case LIB3DS_SOLID_BGND:
-      case LIB3DS_V_GRADIENT:
-      case LIB3DS_USE_BIT_MAP:
-      case LIB3DS_USE_SOLID_BGND:
-      case LIB3DS_USE_V_GRADIENT:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_background_read(&file->background, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_FOG:
-      case LIB3DS_LAYER_FOG:
-      case LIB3DS_DISTANCE_CUE:
-      case LIB3DS_USE_FOG:
-      case LIB3DS_USE_LAYER_FOG:
-      case LIB3DS_USE_DISTANCE_CUE:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_atmosphere_read(&file->atmosphere, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_MAT_ENTRY:
-        {
-          Lib3dsMaterial *material;
-
-          material=lib3ds_material_new();
-          if (!material) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_material_read(material, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_material(file, material);
-        }
-        break;
-      case LIB3DS_NAMED_OBJECT:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!named_object_read(file, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      default:
-        lib3ds_chunk_unknown(chunk);
-    }
-  }
-
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-kfdata_read(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_KFDATA, io)) {
-    return(LIB3DS_FALSE);
-  }
-  
-  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-    switch (chunk) {
-      case LIB3DS_KFHDR:
-        {
-          file->keyf_revision=lib3ds_io_read_word(io);
-          if (!lib3ds_io_read_string(io, file->name, 12+1)) {
-            return(LIB3DS_FALSE);
-          }
-          file->frames=lib3ds_io_read_intd(io);
-        }
-        break;
-      case LIB3DS_KFSEG:
-        {
-          file->segment_from=lib3ds_io_read_intd(io);
-          file->segment_to=lib3ds_io_read_intd(io);
-        }
-        break;
-      case LIB3DS_KFCURTIME:
-        {
-          file->current_frame=lib3ds_io_read_intd(io);
-        }
-        break;
-      case LIB3DS_VIEWPORT_LAYOUT:
-      case LIB3DS_DEFAULT_VIEW:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_viewport_read(&file->viewport_keyf, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_AMBIENT_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_ambient();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      case LIB3DS_OBJECT_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_object();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      case LIB3DS_CAMERA_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_camera();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      case LIB3DS_TARGET_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_target();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      case LIB3DS_LIGHT_NODE_TAG:
-      case LIB3DS_SPOTLIGHT_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_light();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      case LIB3DS_L_TARGET_NODE_TAG:
-        {
-          Lib3dsNode *node;
-
-          node=lib3ds_node_new_spot();
-          if (!node) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_chunk_read_reset(&c, io);
-          if (!lib3ds_node_read(node, file, io)) {
-            return(LIB3DS_FALSE);
-          }
-          lib3ds_file_insert_node(file, node);
-        }
-        break;
-      default:
-        lib3ds_chunk_unknown(chunk);
-    }
-  }
-
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Read 3ds file data into a Lib3dsFile object.
- *
- * \param file The Lib3dsFile object to be filled.
- * \param io A Lib3dsIo object previously set up by the caller.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup file
- */
-Lib3dsBool
-lib3ds_file_read(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-
-  if (!lib3ds_chunk_read_start(&c, 0, io)) {
-    return(LIB3DS_FALSE);
-  }
-  switch (c.chunk) {
-    case LIB3DS_MDATA:
-      {
-        lib3ds_chunk_read_reset(&c, io);
-        if (!mdata_read(file, io)) {
-          return(LIB3DS_FALSE);
-        }
-      }
-      break;
-    case LIB3DS_M3DMAGIC:
-    case LIB3DS_MLIBMAGIC:
-    case LIB3DS_CMAGIC:
-      {
-        while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-          switch (chunk) {
-            case LIB3DS_M3D_VERSION:
-              {
-                file->mesh_version=lib3ds_io_read_dword(io);
-              }
-              break;
-            case LIB3DS_MDATA:
-              {
-                lib3ds_chunk_read_reset(&c, io);
-                if (!mdata_read(file, io)) {
-                  return(LIB3DS_FALSE);
-                }
-              }
-              break;
-            case LIB3DS_KFDATA:
-              {
-                lib3ds_chunk_read_reset(&c, io);
-                if (!kfdata_read(file, io)) {
-                  return(LIB3DS_FALSE);
-                }
-              }
-              break;
-            default:
-              lib3ds_chunk_unknown(chunk);
-          }
-        }
-      }
-      break;
-    default:
-      lib3ds_chunk_unknown(c.chunk);
-      return(LIB3DS_FALSE);
-  }
-
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-colorf_write(Lib3dsRgba rgb, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-
-  c.chunk=LIB3DS_COLOR_F;
-  c.size=18;
-  lib3ds_chunk_write(&c,io);
-  lib3ds_io_write_rgb(io, rgb);
-
-  c.chunk=LIB3DS_LIN_COLOR_F;
-  c.size=18;
-  lib3ds_chunk_write(&c,io);
-  lib3ds_io_write_rgb(io, rgb);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-mdata_write(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-
-  c.chunk=LIB3DS_MDATA;
-  if (!lib3ds_chunk_write_start(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  { /*---- LIB3DS_MESH_VERSION ----*/
-    Lib3dsChunk c;
-    c.chunk=LIB3DS_MESH_VERSION;
-    c.size=10;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_intd(io, file->mesh_version);
-  }
-  { /*---- LIB3DS_MASTER_SCALE ----*/
-    Lib3dsChunk c;
-    c.chunk=LIB3DS_MASTER_SCALE;
-    c.size=10;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_float(io, file->master_scale);
-  }
-  { /*---- LIB3DS_O_CONSTS ----*/
-    int i;
-    for (i=0; i<3; ++i) {
-      if (fabs(file->construction_plane[i])>LIB3DS_EPSILON) {
-        break;
-      }
-    }
-    if (i<3) {
-      Lib3dsChunk c;
-      c.chunk=LIB3DS_O_CONSTS;
-      c.size=18;
-      lib3ds_chunk_write(&c,io);
-      lib3ds_io_write_vector(io, file->construction_plane);
-    }
-  }
-  
-  { /*---- LIB3DS_AMBIENT_LIGHT ----*/
-    int i;
-    for (i=0; i<3; ++i) {
-      if (fabs(file->ambient[i])>LIB3DS_EPSILON) {
-        break;
-      }
-    }
-    if (i<3) {
-      Lib3dsChunk c;
-      c.chunk=LIB3DS_AMBIENT_LIGHT;
-      c.size=42;
-      lib3ds_chunk_write(&c,io);
-      colorf_write(file->ambient,io);
-    }
-  }
-  lib3ds_background_write(&file->background, io);
-  lib3ds_atmosphere_write(&file->atmosphere, io);
-  lib3ds_shadow_write(&file->shadow, io);
-  lib3ds_viewport_write(&file->viewport, io);
-  {
-    Lib3dsMaterial *p;
-    for (p=file->materials; p!=0; p=p->next) {
-      if (!lib3ds_material_write(p,io)) {
-        return(LIB3DS_FALSE);
-      }
-    }
-  }
-  {
-    Lib3dsCamera *p;
-    Lib3dsChunk c;
-    
-    for (p=file->cameras; p!=0; p=p->next) {
-      c.chunk=LIB3DS_NAMED_OBJECT;
-      if (!lib3ds_chunk_write_start(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-      lib3ds_io_write_string(io, p->name);
-      lib3ds_camera_write(p,io);
-      if (!lib3ds_chunk_write_end(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-    }
-  }
-  {
-    Lib3dsLight *p;
-    Lib3dsChunk c;
-    
-    for (p=file->lights; p!=0; p=p->next) {
-      c.chunk=LIB3DS_NAMED_OBJECT;
-      if (!lib3ds_chunk_write_start(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-      lib3ds_io_write_string(io,p->name);
-      lib3ds_light_write(p,io);
-      if (!lib3ds_chunk_write_end(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-    }
-  }
-  {
-    Lib3dsMesh *p;
-    Lib3dsChunk c;
-    
-    for (p=file->meshes; p!=0; p=p->next) {
-      c.chunk=LIB3DS_NAMED_OBJECT;
-      if (!lib3ds_chunk_write_start(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-      lib3ds_io_write_string(io, p->name);
-      lib3ds_mesh_write(p,io);
-      if (!lib3ds_chunk_write_end(&c,io)) {
-        return(LIB3DS_FALSE);
-      }
-    }
-  }
-
-  if (!lib3ds_chunk_write_end(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-
-static Lib3dsBool
-nodes_write(Lib3dsNode *node, Lib3dsFile *file, Lib3dsIo *io)
-{
-  {
-    Lib3dsNode *p;
-    for (p=node->childs; p!=0; p=p->next) {
-      if (!lib3ds_node_write(p, file, io)) {
-        return(LIB3DS_FALSE);
-      }
-      nodes_write(p, file, io);
-    }
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-kfdata_write(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-
-  if (!file->nodes) {
-    return(LIB3DS_TRUE);
-  }
-  
-  c.chunk=LIB3DS_KFDATA;
-  if (!lib3ds_chunk_write_start(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  
-  { /*---- LIB3DS_KFHDR ----*/
-    Lib3dsChunk c;
-    c.chunk=LIB3DS_KFHDR;
-    c.size=6 + 2 + strlen(file->name)+1 +4;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_intw(io, file->keyf_revision);
-    lib3ds_io_write_string(io, file->name);
-    lib3ds_io_write_intd(io, file->frames);
-  }
-  { /*---- LIB3DS_KFSEG ----*/
-    Lib3dsChunk c;
-    c.chunk=LIB3DS_KFSEG;
-    c.size=14;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_intd(io, file->segment_from);
-    lib3ds_io_write_intd(io, file->segment_to);
-  }
-  { /*---- LIB3DS_KFCURTIME ----*/
-    Lib3dsChunk c;
-    c.chunk=LIB3DS_KFCURTIME;
-    c.size=10;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_intd(io, file->current_frame);
-  }
-  lib3ds_viewport_write(&file->viewport_keyf, io);
-  
-  {
-    Lib3dsNode *p;
-    for (p=file->nodes; p!=0; p=p->next) {
-      if (!lib3ds_node_write(p, file, io)) {
-        return(LIB3DS_FALSE);
-      }
-      if (!nodes_write(p, file, io)) {
-        return(LIB3DS_FALSE);
-      }
-    }
-  }
-  
-  if (!lib3ds_chunk_write_end(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Write 3ds file data from a Lib3dsFile object to a file.
- *
- * \param file The Lib3dsFile object to be written.
- * \param io A Lib3dsIo object previously set up by the caller.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup file
- */
-Lib3dsBool
-lib3ds_file_write(Lib3dsFile *file, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-
-  c.chunk=LIB3DS_M3DMAGIC;
-  if (!lib3ds_chunk_write_start(&c,io)) {
-    LIB3DS_ERROR_LOG;
-    return(LIB3DS_FALSE);
-  }
-
-  { /*---- LIB3DS_M3D_VERSION ----*/
-    Lib3dsChunk c;
-
-    c.chunk=LIB3DS_M3D_VERSION;
-    c.size=10;
-    lib3ds_chunk_write(&c,io);
-    lib3ds_io_write_dword(io, file->mesh_version);
-  }
-
-  if (!mdata_write(file, io)) {
-    return(LIB3DS_FALSE);
-  }
-  if (!kfdata_write(file, io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  if (!lib3ds_chunk_write_end(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Insert a new Lib3dsMaterial object into the materials list of
- * a Lib3dsFile object.
- *
- * The new Lib3dsMaterial object is inserted into the materials list
- * in alphabetic order by name.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsMaterial object to be inserted into file->materials
- *
- * \ingroup file
- */
-void
-lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material)
-{
-  Lib3dsMaterial *p,*q;
-  
-  ASSERT(file);
-  ASSERT(material);
-  ASSERT(!material->next);
-
-  q=0;
-  for (p=file->materials; p!=0; p=p->next) {
-    if (strcmp(material->name, p->name)<0) {
-      break;
-    }
-    q=p;
-  }
-  if (!q) {
-    material->next=file->materials;
-    file->materials=material;
-  }
-  else {
-    material->next=q->next;
-    q->next=material;
-  }
-}
-
-
-/*!
- * Remove a Lib3dsMaterial object from the materials list of
- * a Lib3dsFile object.
- *
- * If the Lib3dsMaterial is not found in the materials list, nothing is
- * done (except that an error log message may be generated.)
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsMaterial object to be removed from file->materials
- *
- * \ingroup file
- */
-void
-lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material)
-{
-  Lib3dsMaterial *p,*q;
-
-  ASSERT(file);
-  ASSERT(material);
-  ASSERT(file->materials);
-  for (p=0,q=file->materials; q; p=q,q=q->next) {
-    if (q==material) {
-      break;
-    }
-  }
-  if (!q) {
-    ASSERT(LIB3DS_FALSE);
-    return;
-  }
-  if (!p) {
-    file->materials=material->next;
-  }
-  else {
-    p->next=q->next;
-  }
-  material->next=0;
-}
-
-
-/*!
- * Return a Lib3dsMaterial object by name.
- *
- * \param file Lib3dsFile object to be searched.
- * \param name Name of the Lib3dsMaterial object to be searched for.
- *
- * \return A pointer to the named Lib3dsMaterial, or NULL if not found.
- *
- * \ingroup file
- */
-Lib3dsMaterial*
-lib3ds_file_material_by_name(Lib3dsFile *file, const char *name)
-{
-  Lib3dsMaterial *p;
-
-  ASSERT(file);
-  for (p=file->materials; p!=0; p=p->next) {
-    if (strcmp(p->name,name)==0) {
-      return(p);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Dump all Lib3dsMaterial objects found in a Lib3dsFile object.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_material_dump
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_materials(Lib3dsFile *file)
-{
-  Lib3dsMaterial *p;
-
-  ASSERT(file);
-  for (p=file->materials; p!=0; p=p->next) {
-    lib3ds_material_dump(p);
-  }
-}
-
-
-/*!
- * Insert a new Lib3dsMesh object into the meshes list of
- * a Lib3dsFile object.
- *
- * The new Lib3dsMesh object is inserted into the meshes list
- * in alphabetic order by name.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsMesh object to be inserted into file->meshes
- *
- * \ingroup file
- */
-void
-lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
-{
-  Lib3dsMesh *p,*q;
-  
-  ASSERT(file);
-  ASSERT(mesh);
-  ASSERT(!mesh->next);
-
-  q=0;
-  for (p=file->meshes; p!=0; p=p->next) {
-    if (strcmp(mesh->name, p->name)<0) {
-      break;
-    }
-    q=p;
-  }
-  if (!q) {
-    mesh->next=file->meshes;
-    file->meshes=mesh;
-  }
-  else {
-    mesh->next=q->next;
-    q->next=mesh;
-  }
-}
-
-
-/*!
- * Remove a Lib3dsMesh object from the meshes list of
- * a Lib3dsFile object.
- *
- * If the Lib3dsMesh is not found in the meshes list, nothing is done
- * (except that an error log message may be generated.)
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsMesh object to be removed from file->meshes
- *
- * \ingroup file
- */
-void
-lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
-{
-  Lib3dsMesh *p,*q;
-
-  ASSERT(file);
-  ASSERT(mesh);
-  ASSERT(file->meshes);
-  for (p=0,q=file->meshes; q; p=q,q=q->next) {
-    if (q==mesh) {
-      break;
-    }
-  }
-  if (!q) {
-    ASSERT(LIB3DS_FALSE);
-    return;
-  }
-  if (!p) {
-    file->meshes=mesh->next;
-  }
-  else {
-    p->next=q->next;
-  }
-  mesh->next=0;
-}
-
-
-/*!
- * Return a Lib3dsMesh object from a Lib3dsFile by name.
- *
- * \param file Lib3dsFile object to be searched.
- * \param name Name of the Lib3dsMesh object to be searched for.
- *
- * \return A pointer to the named Lib3dsMesh, or NULL if not found.
- *
- * \ingroup file
- */
-Lib3dsMesh*
-lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name)
-{
-  Lib3dsMesh *p;
-
-  ASSERT(file);
-  for (p=file->meshes; p!=0; p=p->next) {
-    if (strcmp(p->name,name)==0) {
-      return(p);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Dump all Lib3dsMesh objects found in a Lib3dsFile object.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_mesh_dump
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_meshes(Lib3dsFile *file)
-{
-  Lib3dsMesh *p;
-
-  ASSERT(file);
-  for (p=file->meshes; p!=0; p=p->next) {
-    lib3ds_mesh_dump(p);
-  }
-}
-
-
-static void
-dump_instances(Lib3dsNode *node, const char* parent)
-{
-  Lib3dsNode *p;
-  char name[255];
-
-  ASSERT(node);
-  ASSERT(parent);
-  strcpy(name, parent);
-  strcat(name, ".");
-  strcat(name, node->name);
-  if (node->type==LIB3DS_OBJECT_NODE) {
-    printf("  %s : %s\n", name, node->data.object.instance);
-  }
-  for (p=node->childs; p!=0; p=p->next) {
-    dump_instances(p, parent);
-  }
-}
-
-
-/*!
- * Dump all Lib3dsNode object names found in a Lib3dsFile object.
- *
- * For each node of type OBJECT_NODE, its name and data.object.instance
- * fields are printed to stdout.  Consider using lib3ds_file_dump_nodes()
- * instead, as that function dumps more information.
- *
- * Nodes are dumped recursively.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_file_dump_nodes
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_instances(Lib3dsFile *file)
-{
-  Lib3dsNode *p;
-
-  ASSERT(file);
-  for (p=file->nodes; p!=0; p=p->next) {
-    dump_instances(p,"");
-  }
-}
-
-
-/*!
- * Insert a new Lib3dsCamera object into the cameras list of
- * a Lib3dsFile object.
- *
- * The new Lib3dsCamera object is inserted into the cameras list
- * in alphabetic order by name.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsCamera object to be inserted into file->cameras
- *
- * \ingroup file
- */
-void
-lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera)
-{
-  Lib3dsCamera *p,*q;
-  
-  ASSERT(file);
-  ASSERT(camera);
-  ASSERT(!camera->next);
-
-  q=0;
-  for (p=file->cameras; p!=0; p=p->next) {
-    if (strcmp(camera->name, p->name)<0) {
-      break;
-    }
-    q=p;
-  }
-  if (!q) {
-    camera->next=file->cameras;
-    file->cameras=camera;
-  }
-  else {
-    camera->next=q->next;
-    q->next=camera;
-  }
-}
-
-
-/*!
- * Remove a Lib3dsCamera object from the cameras list of
- * a Lib3dsFile object.
- *
- * If the Lib3dsCamera is not found in the cameras list, nothing is done
- * (except that an error log message may be generated.)
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsCamera object to be removed from file->cameras
- *
- * \ingroup file
- */
-void
-lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera)
-{
-  Lib3dsCamera *p,*q;
-
-  ASSERT(file);
-  ASSERT(camera);
-  ASSERT(file->cameras);
-  for (p=0,q=file->cameras; q; p=q,q=q->next) {
-    if (q==camera) {
-      break;
-    }
-  }
-  if (!q) {
-    ASSERT(LIB3DS_FALSE);
-    return;
-  }
-  if (!p) {
-    file->cameras=camera->next;
-  }
-  else {
-    p->next=q->next;
-  }
-  camera->next=0;
-}
-
-
-/*!
- * Return a Lib3dsCamera object from a Lib3dsFile by name.
- *
- * \param file Lib3dsFile object to be searched.
- * \param name Name of the Lib3dsCamera object to be searched for.
- *
- * \return A pointer to the named Lib3dsCamera, or NULL if not found.
- *
- * \ingroup file
- */
-Lib3dsCamera*
-lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name)
-{
-  Lib3dsCamera *p;
-
-  ASSERT(file);
-  for (p=file->cameras; p!=0; p=p->next) {
-    if (strcmp(p->name,name)==0) {
-      return(p);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Dump all Lib3dsCamera objects found in a Lib3dsFile object.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_camera_dump
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_cameras(Lib3dsFile *file)
-{
-  Lib3dsCamera *p;
-
-  ASSERT(file);
-  for (p=file->cameras; p!=0; p=p->next) {
-    lib3ds_camera_dump(p);
-  }
-}
-
-
-/*!
- * Insert a new Lib3dsLight object into the lights list of
- * a Lib3dsFile object.
- *
- * The new Lib3dsLight object is inserted into the lights list
- * in alphabetic order by name.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsLight object to be inserted into file->lights
- *
- * \ingroup file
- */
-void
-lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light)
-{
-  Lib3dsLight *p,*q;
-  
-  ASSERT(file);
-  ASSERT(light);
-  ASSERT(!light->next);
-
-  q=0;
-  for (p=file->lights; p!=0; p=p->next) {
-    if (strcmp(light->name, p->name)<0) {
-      break;
-    }
-    q=p;
-  }
-  if (!q) {
-    light->next=file->lights;
-    file->lights=light;
-  }
-  else {
-    light->next=q->next;
-    q->next=light;
-  }
-}
-
-
-/*!
- * Remove a Lib3dsLight object from the lights list of
- * a Lib3dsFile object.
- *
- * If the Lib3dsLight is not found in the lights list, nothing is done
- * (except that an error log message may be generated.)
- *
- * \param file The Lib3dsFile object to be modified.
- * \param material The Lib3dsLight object to be removed from file->lights
- *
- * \ingroup file
- */
-void
-lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light)
-{
-  Lib3dsLight *p,*q;
-
-  ASSERT(file);
-  ASSERT(light);
-  ASSERT(file->lights);
-  for (p=0,q=file->lights; q; p=q,q=q->next) {
-    if (q==light) {
-      break;
-    }
-  }
-  if (!q) {
-    ASSERT(LIB3DS_FALSE);
-    return;
-  }
-  if (!p) {
-    file->lights=light->next;
-  }
-  else {
-    p->next=q->next;
-  }
-  light->next=0;
-}
-
-
-/*!
- * Return a Lib3dsLight object from a Lib3dsFile by name.
- *
- * \param file Lib3dsFile object to be searched.
- * \param name Name of the Lib3dsLight object to be searched for.
- *
- * \return A pointer to the named Lib3dsLight, or NULL if not found.
- *
- * \ingroup file
- */
-Lib3dsLight*
-lib3ds_file_light_by_name(Lib3dsFile *file, const char *name)
-{
-  Lib3dsLight *p;
-
-  ASSERT(file);
-  for (p=file->lights; p!=0; p=p->next) {
-    if (strcmp(p->name,name)==0) {
-      return(p);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Dump all Lib3dsLight objects found in a Lib3dsFile object.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_light_dump
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_lights(Lib3dsFile *file)
-{
-  Lib3dsLight *p;
-
-  ASSERT(file);
-  for (p=file->lights; p!=0; p=p->next) {
-    lib3ds_light_dump(p);
-  }
-}
-
-
-/*!
- * Compute the bounding box for Lib3dsFile objects.
- *
- * This function computes the bounding box for all meshes
- * in the Lib3dsFile object.  Cameras and lights are not included.
- *
- * \param file The Lib3dsFile object to be examined.
- * \param min Returned minimum x,y,z values.
- * \param max Returned maximum x,y,z values.
- *
- * \ingroup file
- */
-void
-lib3ds_object_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
-{
-  {
-    Lib3dsVector lmin, lmax;
-    Lib3dsMesh *p=file->meshes;
-
-    if (p) {
-      lib3ds_mesh_bounding_box(p, min, max);
-      p = p->next;  
-    }
-    while (p) {
-      lib3ds_mesh_bounding_box(p, lmin, lmax);
-      lib3ds_vector_min(min, lmin);
-      lib3ds_vector_max(max, lmax);
-      p=p->next;
-    }
-  }
-}  
-
-
-/*!
- * Compute the bounding box for a Lib3dsFile.
- *
- * This function computes the bounding box for all meshes, cameras,
- * and lights in the Lib3dsFile object.
- *
- * \param file The Lib3dsFile object to be examined.
- * \param min Returned minimum x,y,z values.
- * \param max Returned maximum x,y,z values.
- *
- * \ingroup file
- */
-void
-lib3ds_file_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
-{
-  Lib3dsBool init=LIB3DS_FALSE;
-
-  {
-    Lib3dsVector lmin, lmax;
-    Lib3dsMesh *p=file->meshes;
-
-    if (!init && p) {
-      init = LIB3DS_TRUE;
-      lib3ds_mesh_bounding_box(p, min, max);
-      p = p->next;  
-    }
-    while (p) {
-      lib3ds_mesh_bounding_box(p, lmin, lmax);
-      lib3ds_vector_min(min, lmin);
-      lib3ds_vector_max(max, lmax);
-      p=p->next;
-    }
-  }
-  {
-    Lib3dsCamera *p=file->cameras;
-    if (!init && p) {
-      init = LIB3DS_TRUE;
-      lib3ds_vector_copy(min, p->position);
-      lib3ds_vector_copy(max, p->position);
-    }
-
-    while (p) {
-      lib3ds_vector_min(min, p->position);
-      lib3ds_vector_max(max, p->position);
-      lib3ds_vector_min(min, p->target);
-      lib3ds_vector_max(max, p->target);
-      p=p->next;
-    }
-  }
-  {
-    Lib3dsLight *p=file->lights;
-    if (!init && p) {
-      init = LIB3DS_TRUE;
-      lib3ds_vector_copy(min, p->position);
-      lib3ds_vector_copy(max, p->position);
-    }
-
-    while (p) {
-      lib3ds_vector_min(min, p->position);
-      lib3ds_vector_max(max, p->position);
-      if (p->spot_light) {
-        lib3ds_vector_min(min, p->spot);
-        lib3ds_vector_max(max, p->spot);
-      }
-      p=p->next;
-    }
-  }
-}  
-
-
-/*!
- * Return a node object by name and type.
- *
- * This function performs a recursive search for the specified node.
- * Both name and type must match.
- *
- * \param file The Lib3dsFile to be searched.
- * \param name The target node name.
- * \param type The target node type
- *
- * \return A pointer to the first matching node, or NULL if not found.
- *
- * \see lib3ds_node_by_name
- *
- * \ingroup file
- */
-Lib3dsNode*
-lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type)
-{
-  Lib3dsNode *p,*q;
-
-  ASSERT(file);
-  for (p=file->nodes; p!=0; p=p->next) {
-    if ((p->type==type) && (strcmp(p->name, name)==0)) {
-      return(p);
-    }
-    q=lib3ds_node_by_name(p, name, type);
-    if (q) {
-      return(q);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Return a node object by id.
- *
- * This function performs a recursive search for the specified node.
- *
- * \param file The Lib3dsFile to be searched.
- * \param node_id The target node id.
- *
- * \return A pointer to the first matching node, or NULL if not found.
- *
- * \see lib3ds_node_by_id
- *
- * \ingroup file
- */
-Lib3dsNode*
-lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id)
-{
-  Lib3dsNode *p,*q;
-
-  ASSERT(file);
-  for (p=file->nodes; p!=0; p=p->next) {
-    if (p->node_id==node_id) {
-      return(p);
-    }
-    q=lib3ds_node_by_id(p, node_id);
-    if (q) {
-      return(q);
-    }
-  }
-  return(0);
-}
-
-
-/*!
- * Insert a new node into a Lib3dsFile object.
- *
- * If the node's parent_id structure is not LIB3DS_NO_PARENT and the
- * specified parent is found inside the Lib3dsFile object, then the
- * node is inserted as a child of that parent.  If the parent_id
- * structure is LIB3DS_NO_PARENT or the specified parent is not found,
- * then the node is inserted at the top level.
- *
- * Node is inserted in alphabetic order by name.
- *
- * Finally, if any other top-level nodes in file specify this node as
- * their parent, they are relocated as a child of this node.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param node The node to be inserted into file
- *
- * \ingroup file
- */
-void
-lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node)
-{
-  Lib3dsNode *parent,*p,*n;
-  
-  ASSERT(node);
-  ASSERT(!node->next);
-  ASSERT(!node->parent);
-
-  parent=0;
-  if (node->parent_id!=LIB3DS_NO_PARENT) {
-    parent=lib3ds_file_node_by_id(file, node->parent_id);
-  }
-  node->parent=parent;
-  
-  if (!parent) {
-    for (p=0,n=file->nodes; n!=0; p=n,n=n->next) {
-      if (strcmp(n->name, node->name)>0) {
-        break;
-      }
-    }
-    if (!p) {
-      node->next=file->nodes;
-      file->nodes=node;
-    }
-    else {
-      node->next=p->next;
-      p->next=node;
-    }
-  }
-  else {
-    for (p=0,n=parent->childs; n!=0; p=n,n=n->next) {
-      if (strcmp(n->name, node->name)>0) {
-        break;
-      }
-    }
-    if (!p) {
-      node->next=parent->childs;
-      parent->childs=node;
-    }
-    else {
-      node->next=p->next;
-      p->next=node;
-    }
-  }
-
-  if (node->node_id!=LIB3DS_NO_PARENT) {
-    for (n=file->nodes; n!=0; n=p) {
-      p=n->next;
-      if (n->parent_id==node->node_id) {
-        lib3ds_file_remove_node(file, n);
-        lib3ds_file_insert_node(file, n);
-      }
-    }
-  }
-}
-
-
-/*!
- * Remove a node from the a Lib3dsFile object.
- *
- * \param file The Lib3dsFile object to be modified.
- * \param node The Lib3dsNode object to be removed from file
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE if node is not found in file
- *
- * \ingroup file
- */
-Lib3dsBool
-lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node)
-{
-  Lib3dsNode *p,*n;
-
-  if (node->parent) {
-    for (p=0,n=node->parent->childs; n; p=n,n=n->next) {
-      if (n==node) {
-        break;
-      }
-    }
-    if (!n) {
-      return(LIB3DS_FALSE);
-    }
-    
-    if (!p) {
-      node->parent->childs=n->next;
-    }
-    else {
-      p->next=n->next;
-    }
-  }
-  else {
-    for (p=0,n=file->nodes; n; p=n,n=n->next) {
-      if (n==node) {
-        break;
-      }
-    }
-    if (!n) {
-      return(LIB3DS_FALSE);
-    }
-    
-    if (!p) {
-      file->nodes=n->next;
-    }
-    else {
-      p->next=n->next;
-    }
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Dump all node objects found in a Lib3dsFile object.
- *
- * Nodes are dumped recursively.
- *
- * \param file Lib3dsFile object to be dumped.
- *
- * \see lib3ds_node_dump
- *
- * \ingroup file
- */
-void
-lib3ds_file_dump_nodes(Lib3dsFile *file)
-{
-  Lib3dsNode *p;
-
-  ASSERT(file);
-  for (p=file->nodes; p!=0; p=p->next) {
-    lib3ds_node_dump(p,1);
-  }
-}
-
-
-/*!
-
-\typedef Lib3dsFile
-  \ingroup file
-  \sa _Lib3dsFile
-
-*/
-
-
-
-/* Programming trick to force users to compile their source code against the
- * correct headers.  The symbol lib3ds_version1_3 will be defined iff the users
- * compile with the current version of <lib3ds/types.h>
- */
-
-/*
-extern int lib3ds_version1_3;
-static const int *lib3ds_version = &lib3ds_version1_3;
-*/