X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2F3dengfx%2Flibs%2Flib3ds%2Fmesh.c;fp=src%2F3dengfx%2Flibs%2Flib3ds%2Fmesh.c;h=f0e5b3e0c22ae6777f674a966efed560c5ee00ac;hb=6e23259dbabaeb1711a2a5ca25b9cb421f693759;hp=0000000000000000000000000000000000000000;hpb=fe068fa879814784c45e0cb2e65dac489e8f5594;p=summerhack diff --git a/src/3dengfx/libs/lib3ds/mesh.c b/src/3dengfx/libs/lib3ds/mesh.c new file mode 100644 index 0000000..f0e5b3e --- /dev/null +++ b/src/3dengfx/libs/lib3ds/mesh.c @@ -0,0 +1,1063 @@ +/* + * The 3D Studio File Format Library + * Copyright (C) 1996-2001 by J.E. Hoffmann + * 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 +#include +#include +#include +#include +#include +#include +#include +#ifdef WITH_DMALLOC +#include +#endif + + +/*! + * \defgroup mesh Meshes + * + * \author J.E. Hoffmann + */ + + +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; ifaceL[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; ifaces; ++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; ifaces); + 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; ipoints; ++i) { + for (j=0; j<3; ++j) { + v=mesh->pointL[i].pos[j]; + if (vmax[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; ifaces; ++i) { + Lib3dsFace *f=&mesh->faceL[i]; + for (j=0; j<3; ++j) { + Lib3dsFaces* l=&fa[k++]; + ASSERT(f->points[j]points); + l->face=f; + l->next=fl[f->points[j]]; + fl[f->points[j]]=l; + } + } + + for (i=0; ifaces; ++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]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= 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; ipoints; ++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; ifaces; ++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; ipoints; ++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; iflags; ++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; itexels; ++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; jfaces; ++j) { + ASSERT(mesh->faceL[j].points[0]points); + ASSERT(mesh->faceL[j].points[1]points); + ASSERT(mesh->faceL[j].points[2]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; ipoints; ++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; iflags; ++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; ifaces; ++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; ifaces; ++i) { + if (!matf[i] && strlen(mesh->faceL[i].material)) { + matf[i]=1; + num=1; + + for (j=i+1; jfaces; ++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; jfaces; ++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; ifaces; ++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; itexels; ++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 + +*/