dropped all dependencies apart from SDL into the libs subdir
[summerhack] / src / 3dengfx / libs / lib3ds / mesh.c
diff --git a/src/3dengfx/libs/lib3ds/mesh.c b/src/3dengfx/libs/lib3ds/mesh.c
deleted file mode 100644 (file)
index f0e5b3e..0000000
+++ /dev/null
@@ -1,1063 +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: mesh.c,v 1.22 2004/11/20 08:33:56 efalk Exp $
- */
-#define LIB3DS_EXPORT
-#include <lib3ds/mesh.h>
-#include <lib3ds/io.h>
-#include <lib3ds/chunk.h>
-#include <lib3ds/vector.h>
-#include <lib3ds/matrix.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#ifdef WITH_DMALLOC
-#include <dmalloc.h>
-#endif
-
-
-/*!
- * \defgroup mesh Meshes
- *
- * \author J.E. Hoffmann <je-h@gmx.net>
- */
-
-
-static Lib3dsBool
-face_array_read(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-  int i;
-  int faces;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, io)) {
-    return(LIB3DS_FALSE);
-  }
-  lib3ds_mesh_free_face_list(mesh);
-  
-  faces=lib3ds_io_read_word(io);
-  if (faces) {
-    if (!lib3ds_mesh_new_face_list(mesh, faces)) {
-      LIB3DS_ERROR_LOG;
-      return(LIB3DS_FALSE);
-    }
-    for (i=0; i<faces; ++i) {
-      strcpy(mesh->faceL[i].material, "");
-      mesh->faceL[i].points[0]=lib3ds_io_read_word(io);
-      mesh->faceL[i].points[1]=lib3ds_io_read_word(io);
-      mesh->faceL[i].points[2]=lib3ds_io_read_word(io);
-      mesh->faceL[i].flags=lib3ds_io_read_word(io);
-    }
-    lib3ds_chunk_read_tell(&c, io);
-
-    while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-      switch (chunk) {
-        case LIB3DS_SMOOTH_GROUP:
-          {
-            unsigned i;
-
-            for (i=0; i<mesh->faces; ++i) {
-              mesh->faceL[i].smoothing=lib3ds_io_read_dword(io);
-            }
-          }
-          break;
-        case LIB3DS_MSH_MAT_GROUP:
-          {
-            char name[64];
-            unsigned faces;
-            unsigned i;
-            unsigned index;
-
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            faces=lib3ds_io_read_word(io);
-            for (i=0; i<faces; ++i) {
-              index=lib3ds_io_read_word(io);
-              ASSERT(index<mesh->faces);
-              strcpy(mesh->faceL[index].material, name);
-            }
-          }
-          break;
-        case LIB3DS_MSH_BOXMAP:
-          {
-            char name[64];
-
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.front, name);
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.back, name);
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.left, name);
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.right, name);
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.top, name);
-            if (!lib3ds_io_read_string(io, name, 64)) {
-              return(LIB3DS_FALSE);
-            }
-            strcpy(mesh->box_map.bottom, name);
-          }
-          break;
-        default:
-          lib3ds_chunk_unknown(chunk);
-      }
-    }
-    
-  }
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Create and return a new empty mesh object.
- *
- * Mesh is initialized with the name and an identity matrix; all
- * other fields are zero.
- *
- * See Lib3dsFaceFlag for definitions of per-face flags.
- *
- * \param name Mesh name.  Must not be NULL.  Must be < 64 characters.
- *
- * \return mesh object or NULL on error.
- *
- * \ingroup mesh
- */
-Lib3dsMesh*
-lib3ds_mesh_new(const char *name)
-{
-  Lib3dsMesh *mesh;
-
-  ASSERT(name);
-  ASSERT(strlen(name)<64);
-  
-  mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1);
-  if (!mesh) {
-    return(0);
-  }
-  strcpy(mesh->name, name);
-  lib3ds_matrix_identity(mesh->matrix);
-  mesh->map_data.maptype=LIB3DS_MAP_NONE;
-  return(mesh);
-}
-
-
-/*!
- * Free a mesh object and all of its resources.
- *
- * \param mesh Mesh object to be freed.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_free(Lib3dsMesh *mesh)
-{
-  lib3ds_mesh_free_point_list(mesh);
-  lib3ds_mesh_free_flag_list(mesh);
-  lib3ds_mesh_free_texel_list(mesh);
-  lib3ds_mesh_free_face_list(mesh);
-  memset(mesh, 0, sizeof(Lib3dsMesh));
-  free(mesh);
-}
-
-
-/*!
- * Allocate point list in mesh object.
- *
- * This function frees the current point list, if any, and allocates
- * a new one large enough to hold the specified number of points.
- *
- * \param mesh Mesh object for which points are to be allocated.
- * \param points Number of points in the new point list.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points)
-{
-  ASSERT(mesh);
-  if (mesh->pointL) {
-    ASSERT(mesh->points);
-    lib3ds_mesh_free_point_list(mesh);
-  }
-  ASSERT(!mesh->pointL && !mesh->points);
-  mesh->points=0;
-  mesh->pointL=calloc(sizeof(Lib3dsPoint)*points,1);
-  if (!mesh->pointL) {
-    LIB3DS_ERROR_LOG;
-    return(LIB3DS_FALSE);
-  }
-  mesh->points=points;
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Free point list in mesh object.
- *
- * The current point list is freed and set to NULL.  mesh->points is
- * set to zero.
- *
- * \param mesh Mesh object to be modified.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_free_point_list(Lib3dsMesh *mesh)
-{
-  ASSERT(mesh);
-  if (mesh->pointL) {
-    ASSERT(mesh->points);
-    free(mesh->pointL);
-    mesh->pointL=0;
-    mesh->points=0;
-  }
-  else {
-    ASSERT(!mesh->points);
-  }
-}
-
-
-/*!
- * Allocate flag list in mesh object.
- *
- * This function frees the current flag list, if any, and allocates
- * a new one large enough to hold the specified number of flags.
- * All flags are initialized to 0
- *
- * \param mesh Mesh object for which points are to be allocated.
- * \param flags Number of flags in the new flag list.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags)
-{
-  ASSERT(mesh);
-  if (mesh->flagL) {
-    ASSERT(mesh->flags);
-    lib3ds_mesh_free_flag_list(mesh);
-  }
-  ASSERT(!mesh->flagL && !mesh->flags);
-  mesh->flags=0;
-  mesh->flagL=calloc(sizeof(Lib3dsWord)*flags,1);
-  if (!mesh->flagL) {
-    LIB3DS_ERROR_LOG;
-    return(LIB3DS_FALSE);
-  }
-  mesh->flags=flags;
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Free flag list in mesh object.
- *
- * The current flag list is freed and set to NULL.  mesh->flags is
- * set to zero.
- *
- * \param mesh Mesh object to be modified.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh)
-{
-  ASSERT(mesh);
-  if (mesh->flagL) {
-    ASSERT(mesh->flags);
-    free(mesh->flagL);
-    mesh->flagL=0;
-    mesh->flags=0;
-  }
-  else {
-    ASSERT(!mesh->flags);
-  }
-}
-
-
-/*!
- * Allocate texel list in mesh object.
- *
- * This function frees the current texel list, if any, and allocates
- * a new one large enough to hold the specified number of texels.
- *
- * \param mesh Mesh object for which points are to be allocated.
- * \param texels Number of texels in the new texel list.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels)
-{
-  ASSERT(mesh);
-  if (mesh->texelL) {
-    ASSERT(mesh->texels);
-    lib3ds_mesh_free_texel_list(mesh);
-  }
-  ASSERT(!mesh->texelL && !mesh->texels);
-  mesh->texels=0;
-  mesh->texelL=calloc(sizeof(Lib3dsTexel)*texels,1);
-  if (!mesh->texelL) {
-    LIB3DS_ERROR_LOG;
-    return(LIB3DS_FALSE);
-  }
-  mesh->texels=texels;
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Free texel list in mesh object.
- *
- * The current texel list is freed and set to NULL.  mesh->texels is
- * set to zero.
- *
- * \param mesh Mesh object to be modified.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh)
-{
-  ASSERT(mesh);
-  if (mesh->texelL) {
-    ASSERT(mesh->texels);
-    free(mesh->texelL);
-    mesh->texelL=0;
-    mesh->texels=0;
-  }
-  else {
-    ASSERT(!mesh->texels);
-  }
-}
-
-
-/*!
- * Allocate face list in mesh object.
- *
- * This function frees the current face list, if any, and allocates
- * a new one large enough to hold the specified number of faces.
- *
- * \param mesh Mesh object for which points are to be allocated.
- * \param faces Number of faces in the new face list.
- *
- * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
- *
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword faces)
-{
-  ASSERT(mesh);
-  if (mesh->faceL) {
-    ASSERT(mesh->faces);
-    lib3ds_mesh_free_face_list(mesh);
-  }
-  ASSERT(!mesh->faceL && !mesh->faces);
-  mesh->faces=0;
-  mesh->faceL=calloc(sizeof(Lib3dsFace)*faces,1);
-  if (!mesh->faceL) {
-    LIB3DS_ERROR_LOG;
-    return(LIB3DS_FALSE);
-  }
-  mesh->faces=faces;
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * Free face list in mesh object.
- *
- * The current face list is freed and set to NULL.  mesh->faces is
- * set to zero.
- *
- * \param mesh Mesh object to be modified.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_free_face_list(Lib3dsMesh *mesh)
-{
-  ASSERT(mesh);
-  if (mesh->faceL) {
-    ASSERT(mesh->faces);
-    free(mesh->faceL);
-    mesh->faceL=0;
-    mesh->faces=0;
-  }
-  else {
-    ASSERT(!mesh->faces);
-  }
-}
-
-
-typedef struct _Lib3dsFaces Lib3dsFaces; 
-
-struct _Lib3dsFaces {
-  Lib3dsFaces *next;
-  Lib3dsFace *face;
-};
-
-
-
-
-/*!
- * Find the bounding box of a mesh object.
- *
- * \param mesh The mesh object
- * \param min Returned bounding box
- * \param max Returned bounding box
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max)
-{
-  unsigned i,j;
-  Lib3dsFloat v;
-
-  if (!mesh->points) {
-    lib3ds_vector_zero(min);
-    lib3ds_vector_zero(max);
-    return;
-  }
-  lib3ds_vector_copy(min, mesh->pointL[0].pos);
-  lib3ds_vector_copy(max, mesh->pointL[0].pos);
-  for (i=1; i<mesh->points; ++i) {
-    for (j=0; j<3; ++j) {
-      v=mesh->pointL[i].pos[j];
-      if (v<min[j]) {
-        min[j]=v;
-      }
-      if (v>max[j]) {
-        max[j]=v;
-      }
-    }
-  };
-}
-
-
-/*!
- * Calculates the vertex normals corresponding to the smoothing group
- * settings for each face of a mesh.
- *
- * \param mesh      A pointer to the mesh to calculate the normals for.
- * \param normalL   A pointer to a buffer to store the calculated
- *                  normals. The buffer must have the size:
- *                  3*sizeof(Lib3dsVector)*mesh->faces. 
- *
- * To allocate the normal buffer do for example the following:
- * \code
- *  Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces);
- * \endcode
- *
- * To access the normal of the i-th vertex of the j-th face do the 
- * following:
- * \code
- *   normalL[3*j+i]
- * \endcode
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
-{
-  Lib3dsFaces **fl; 
-  Lib3dsFaces *fa; 
-  unsigned i,j,k;
-
-  if (!mesh->faces) {
-    return;
-  }
-
-  fl=calloc(sizeof(Lib3dsFaces*),mesh->points);
-  ASSERT(fl);
-  fa=calloc(sizeof(Lib3dsFaces),3*mesh->faces);
-  ASSERT(fa);
-  k=0;
-  for (i=0; i<mesh->faces; ++i) {
-    Lib3dsFace *f=&mesh->faceL[i];
-    for (j=0; j<3; ++j) {
-      Lib3dsFaces* l=&fa[k++];
-      ASSERT(f->points[j]<mesh->points);
-      l->face=f;
-      l->next=fl[f->points[j]];
-      fl[f->points[j]]=l;
-    }
-  }
-  
-  for (i=0; i<mesh->faces; ++i) {
-    Lib3dsFace *f=&mesh->faceL[i];
-    for (j=0; j<3; ++j) {
-      /* FIXME: static array needs at least check!! */
-      Lib3dsVector n,N[128];
-      Lib3dsFaces *p;
-      int k,l;
-      int found;
-
-      ASSERT(f->points[j]<mesh->points);
-
-      if (f->smoothing) {
-        lib3ds_vector_zero(n);
-        k=0;
-        for (p=fl[f->points[j]]; p; p=p->next) {
-          found=0;
-          for (l=0; l<k; ++l) {
-           if( l >= 128 )
-             printf("array N overflow: i=%d, j=%d, k=%d\n", i,j,k);
-            if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
-              found=1;
-              break;
-            }
-          }
-          if (!found) {
-            if (f->smoothing & p->face->smoothing) {
-              lib3ds_vector_add(n,n, p->face->normal);
-              lib3ds_vector_copy(N[k], p->face->normal);
-              ++k;
-            }
-          }
-        }
-      } 
-      else {
-        lib3ds_vector_copy(n, f->normal);
-      }
-      lib3ds_vector_normalize(n);
-
-      lib3ds_vector_copy(normalL[3*i+j], n);
-    }
-  }
-
-  free(fa);
-  free(fl);
-}
-
-
-/*!
- * This function prints data associated with the specified mesh such as
- * vertex and point lists.
- *
- * \param mesh  Points to a mesh that you wish to view the data for.
- *
- * \return None
- *
- * \warning WIN32: Should only be used in a console window not in a GUI.
- *
- * \ingroup mesh
- */
-void
-lib3ds_mesh_dump(Lib3dsMesh *mesh)
-{
-  unsigned i;
-  Lib3dsVector p;
-
-  ASSERT(mesh);
-  printf("  %s vertices=%ld faces=%ld\n",
-    mesh->name,
-    mesh->points,
-    mesh->faces
-  );
-  printf("  matrix:\n");
-  lib3ds_matrix_dump(mesh->matrix);
-  printf("  point list:\n");
-  for (i=0; i<mesh->points; ++i) {
-    lib3ds_vector_copy(p, mesh->pointL[i].pos);
-    printf ("    %8f %8f %8f\n", p[0], p[1], p[2]);
-  }
-  printf("  facelist:\n");
-  for (i=0; i<mesh->faces; ++i) {
-    printf ("    %4d %4d %4d  smoothing:%X  flags:%X  material:\"%s\"\n",
-      mesh->faceL[i].points[0],
-      mesh->faceL[i].points[1],
-      mesh->faceL[i].points[2],
-      (unsigned)mesh->faceL[i].smoothing,
-      mesh->faceL[i].flags,
-      mesh->faceL[i].material
-    );
-  }
-}
-
-
-/*!
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  Lib3dsWord chunk;
-
-  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
-    switch (chunk) {
-      case LIB3DS_MESH_MATRIX:
-        {
-          int i,j;
-          
-          lib3ds_matrix_identity(mesh->matrix);
-          for (i=0; i<4; i++) {
-            for (j=0; j<3; j++) {
-              mesh->matrix[i][j]=lib3ds_io_read_float(io);
-            }
-          }
-        }
-        break;
-      case LIB3DS_MESH_COLOR:
-        {
-          mesh->color=lib3ds_io_read_byte(io);
-        }
-        break;
-      case LIB3DS_POINT_ARRAY:
-        {
-          unsigned i,j;
-          unsigned points;
-          
-          lib3ds_mesh_free_point_list(mesh);
-          points=lib3ds_io_read_word(io);
-          if (points) {
-            if (!lib3ds_mesh_new_point_list(mesh, points)) {
-              LIB3DS_ERROR_LOG;
-              return(LIB3DS_FALSE);
-            }
-            for (i=0; i<mesh->points; ++i) {
-              for (j=0; j<3; ++j) {
-                mesh->pointL[i].pos[j]=lib3ds_io_read_float(io);
-              }
-            }
-            ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
-            ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
-          }
-        }
-        break;
-      case LIB3DS_POINT_FLAG_ARRAY:
-        {
-          unsigned i;
-          unsigned flags;
-          
-          lib3ds_mesh_free_flag_list(mesh);
-          flags=lib3ds_io_read_word(io);
-          if (flags) {
-            if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
-              LIB3DS_ERROR_LOG;
-              return(LIB3DS_FALSE);
-            }
-            for (i=0; i<mesh->flags; ++i) {
-              mesh->flagL[i]=lib3ds_io_read_word(io);
-            }
-            ASSERT((!mesh->points) || (mesh->flags==mesh->points));
-            ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
-          }
-        }
-        break;
-      case LIB3DS_FACE_ARRAY:
-        {
-          lib3ds_chunk_read_reset(&c, io);
-          if (!face_array_read(mesh, io)) {
-            return(LIB3DS_FALSE);
-          }
-        }
-        break;
-      case LIB3DS_MESH_TEXTURE_INFO:
-        {
-          int i,j;
-
-          for (i=0; i<2; ++i) {
-            mesh->map_data.tile[i]=lib3ds_io_read_float(io);
-          }
-          for (i=0; i<3; ++i) {
-            mesh->map_data.pos[i]=lib3ds_io_read_float(io);
-          }
-          mesh->map_data.scale=lib3ds_io_read_float(io);
-
-          lib3ds_matrix_identity(mesh->map_data.matrix);
-          for (i=0; i<4; i++) {
-            for (j=0; j<3; j++) {
-              mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io);
-            }
-          }
-          for (i=0; i<2; ++i) {
-            mesh->map_data.planar_size[i]=lib3ds_io_read_float(io);
-          }
-          mesh->map_data.cylinder_height=lib3ds_io_read_float(io);
-        }
-        break;
-      case LIB3DS_TEX_VERTS:
-        {
-          unsigned i;
-          unsigned texels;
-          
-          lib3ds_mesh_free_texel_list(mesh);
-          texels=lib3ds_io_read_word(io);
-          if (texels) {
-            if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
-              LIB3DS_ERROR_LOG;
-              return(LIB3DS_FALSE);
-            }
-            for (i=0; i<mesh->texels; ++i) {
-              mesh->texelL[i][0]=lib3ds_io_read_float(io);
-              mesh->texelL[i][1]=lib3ds_io_read_float(io);
-            }
-            ASSERT((!mesh->points) || (mesh->texels==mesh->points));
-            ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
-          }
-        }
-        break;
-      default:
-        lib3ds_chunk_unknown(chunk);
-    }
-  }
-  {
-    unsigned j;
-
-    for (j=0; j<mesh->faces; ++j) {
-      ASSERT(mesh->faceL[j].points[0]<mesh->points);
-      ASSERT(mesh->faceL[j].points[1]<mesh->points);
-      ASSERT(mesh->faceL[j].points[2]<mesh->points);
-      lib3ds_vector_normal(
-        mesh->faceL[j].normal,
-        mesh->pointL[mesh->faceL[j].points[0]].pos,
-        mesh->pointL[mesh->faceL[j].points[1]].pos,
-        mesh->pointL[mesh->faceL[j].points[2]].pos
-      );
-    }
-  }
-  
-  lib3ds_chunk_read_end(&c, io);
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  unsigned i;
-
-  if (!mesh->points || !mesh->pointL) {
-    return(LIB3DS_TRUE);
-  }
-  ASSERT(mesh->points<0x10000);
-  c.chunk=LIB3DS_POINT_ARRAY;
-  c.size=8+12*mesh->points;
-  lib3ds_chunk_write(&c, io);
-  
-  lib3ds_io_write_word(io, (Lib3dsWord)mesh->points);
-  for (i=0; i<mesh->points; ++i) {
-    lib3ds_io_write_vector(io, mesh->pointL[i].pos);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-flag_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  unsigned i;
-  
-  if (!mesh->flags || !mesh->flagL) {
-    return(LIB3DS_TRUE);
-  }
-  ASSERT(mesh->flags<0x10000);
-  c.chunk=LIB3DS_POINT_FLAG_ARRAY;
-  c.size=8+2*mesh->flags;
-  lib3ds_chunk_write(&c, io);
-  
-  lib3ds_io_write_word(io, (Lib3dsWord)mesh->flags);
-  for (i=0; i<mesh->flags; ++i) {
-    lib3ds_io_write_word(io, mesh->flagL[i]);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-static Lib3dsBool
-face_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  
-  if (!mesh->faces || !mesh->faceL) {
-    return(LIB3DS_TRUE);
-  }
-  ASSERT(mesh->faces<0x10000);
-  c.chunk=LIB3DS_FACE_ARRAY;
-  if (!lib3ds_chunk_write_start(&c, io)) {
-    return(LIB3DS_FALSE);
-  }
-  {
-    unsigned i;
-
-    lib3ds_io_write_word(io, (Lib3dsWord)mesh->faces);
-    for (i=0; i<mesh->faces; ++i) {
-      lib3ds_io_write_word(io, mesh->faceL[i].points[0]);
-      lib3ds_io_write_word(io, mesh->faceL[i].points[1]);
-      lib3ds_io_write_word(io, mesh->faceL[i].points[2]);
-      lib3ds_io_write_word(io, mesh->faceL[i].flags);
-    }
-  }
-
-  { /*---- MSH_MAT_GROUP ----*/
-    Lib3dsChunk c;
-    unsigned i,j;
-    Lib3dsWord num;
-    char *matf=calloc(sizeof(char), mesh->faces);
-    if (!matf) {
-      return(LIB3DS_FALSE);
-    }
-    
-    for (i=0; i<mesh->faces; ++i) {
-      if (!matf[i] && strlen(mesh->faceL[i].material)) {
-        matf[i]=1;
-        num=1;
-        
-        for (j=i+1; j<mesh->faces; ++j) {
-          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) ++num;
-        }
-        
-        c.chunk=LIB3DS_MSH_MAT_GROUP;
-        c.size=6+ strlen(mesh->faceL[i].material)+1 +2+2*num;
-        lib3ds_chunk_write(&c, io);
-        lib3ds_io_write_string(io, mesh->faceL[i].material);
-        lib3ds_io_write_word(io, num);
-        lib3ds_io_write_word(io, (Lib3dsWord)i);
-        
-        for (j=i+1; j<mesh->faces; ++j) {
-          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) {
-            lib3ds_io_write_word(io, (Lib3dsWord)j);
-            matf[j]=1;
-          }
-        }
-      }      
-    }
-    free(matf);
-  }
-
-  { /*---- SMOOTH_GROUP ----*/
-    Lib3dsChunk c;
-    unsigned i;
-    
-    c.chunk=LIB3DS_SMOOTH_GROUP;
-    c.size=6+4*mesh->faces;
-    lib3ds_chunk_write(&c, io);
-    
-    for (i=0; i<mesh->faces; ++i) {
-      lib3ds_io_write_dword(io, mesh->faceL[i].smoothing);
-    }
-  }
-  
-  { /*---- MSH_BOXMAP ----*/
-    Lib3dsChunk c;
-
-    if (strlen(mesh->box_map.front) ||
-      strlen(mesh->box_map.back) ||
-      strlen(mesh->box_map.left) ||
-      strlen(mesh->box_map.right) ||
-      strlen(mesh->box_map.top) ||
-      strlen(mesh->box_map.bottom)) {
-    
-      c.chunk=LIB3DS_MSH_BOXMAP;
-      if (!lib3ds_chunk_write_start(&c, io)) {
-        return(LIB3DS_FALSE);
-      }
-      
-      lib3ds_io_write_string(io, mesh->box_map.front);
-      lib3ds_io_write_string(io, mesh->box_map.back);
-      lib3ds_io_write_string(io, mesh->box_map.left);
-      lib3ds_io_write_string(io, mesh->box_map.right);
-      lib3ds_io_write_string(io, mesh->box_map.top);
-      lib3ds_io_write_string(io, mesh->box_map.bottom);
-      
-      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
-texel_array_write(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-  unsigned i;
-  
-  if (!mesh->texels || !mesh->texelL) {
-    return(LIB3DS_TRUE);
-  }
-  ASSERT(mesh->texels<0x10000);
-  c.chunk=LIB3DS_TEX_VERTS;
-  c.size=8+8*mesh->texels;
-  lib3ds_chunk_write(&c, io);
-  
-  lib3ds_io_write_word(io, (Lib3dsWord)mesh->texels);
-  for (i=0; i<mesh->texels; ++i) {
-    lib3ds_io_write_float(io, mesh->texelL[i][0]);
-    lib3ds_io_write_float(io, mesh->texelL[i][1]);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
- * \ingroup mesh
- */
-Lib3dsBool
-lib3ds_mesh_write(Lib3dsMesh *mesh, Lib3dsIo *io)
-{
-  Lib3dsChunk c;
-
-  c.chunk=LIB3DS_N_TRI_OBJECT;
-  if (!lib3ds_chunk_write_start(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  if (!point_array_write(mesh, io)) {
-    return(LIB3DS_FALSE);
-  }
-  if (!texel_array_write(mesh, io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  if (mesh->map_data.maptype!=LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/
-    Lib3dsChunk c;
-    int i,j;
-    
-    c.chunk=LIB3DS_MESH_TEXTURE_INFO;
-    c.size=92;
-    if (!lib3ds_chunk_write(&c,io)) {
-      return(LIB3DS_FALSE);
-    }
-
-    lib3ds_io_write_word(io, mesh->map_data.maptype);
-
-    for (i=0; i<2; ++i) {
-      lib3ds_io_write_float(io, mesh->map_data.tile[i]);
-    }
-    for (i=0; i<3; ++i) {
-      lib3ds_io_write_float(io, mesh->map_data.pos[i]);
-    }
-    lib3ds_io_write_float(io, mesh->map_data.scale);
-
-    for (i=0; i<4; i++) {
-      for (j=0; j<3; j++) {
-        lib3ds_io_write_float(io, mesh->map_data.matrix[i][j]);
-      }
-    }
-    for (i=0; i<2; ++i) {
-      lib3ds_io_write_float(io, mesh->map_data.planar_size[i]);
-    }
-    lib3ds_io_write_float(io, mesh->map_data.cylinder_height);
-  }
-
-  if (!flag_array_write(mesh, io)) {
-    return(LIB3DS_FALSE);
-  }
-  { /*---- LIB3DS_MESH_MATRIX ----*/
-    Lib3dsChunk c;
-    int i,j;
-
-    c.chunk=LIB3DS_MESH_MATRIX;
-    c.size=54;
-    if (!lib3ds_chunk_write(&c,io)) {
-      return(LIB3DS_FALSE);
-    }
-    for (i=0; i<4; i++) {
-      for (j=0; j<3; j++) {
-        lib3ds_io_write_float(io, mesh->matrix[i][j]);
-      }
-    }
-  }
-
-  if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/
-    Lib3dsChunk c;
-    
-    c.chunk=LIB3DS_MESH_COLOR;
-    c.size=7;
-    if (!lib3ds_chunk_write(&c,io)) {
-      return(LIB3DS_FALSE);
-    }
-    lib3ds_io_write_byte(io, mesh->color);
-  }
-  if (!face_array_write(mesh, io)) {
-    return(LIB3DS_FALSE);
-  }
-
-  if (!lib3ds_chunk_write_end(&c,io)) {
-    return(LIB3DS_FALSE);
-  }
-  return(LIB3DS_TRUE);
-}
-
-
-/*!
-
-\typedef Lib3dsFace
-  \ingroup mesh
-  \sa _Lib3dsFace
-
-*/
-/*!
-
-\typedef Lib3dsBoxMap
-  \ingroup mesh
-  \sa _Lib3dsBoxMap
-
-*/
-/*!
-
-\typedef Lib3dsMapData
-  \ingroup mesh
-  \sa _Lib3dsMapData
-
-*/
-/*!
-
-\typedef Lib3dsMesh
-  \ingroup mesh
-  \sa _Lib3dsMesh
-
-*/