root/OpenSceneGraph/trunk/src/osgPlugins/3ds/mesh.cpp @ 10076

Revision 10076, 21.6 kB (checked in by robert, 5 years ago)

From Neil Hughes, converted across to use istream for reading data from file to enable reading .3ds files over http (use OSG's libcurl plugin).

From Robert Osfield, ammendments of the above to better support reading of files from local directories.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[8]1/*
2 * The 3D Studio File Format Library
3 * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
4 * All rights reserved.
5 *
6 * This program is  free  software;  you can redistribute it and/or modify it
[151]7 * under the terms of the  GNU Lesser General Public License  as published by
8 * the  Free Software Foundation;  either version 2.1 of the License,  or (at
[8]9 * your option) any later version.
10 *
11 * This  program  is  distributed in  the  hope that it will  be useful,  but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
[151]13 * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public 
[8]14 * License for more details.
15 *
16 * You should  have received  a copy of the GNU Lesser General Public License
17 * along with  this program;  if not, write to the  Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id$
21 */
22#define LIB3DS_EXPORT
[1563]23#include "mesh.h"
24#include "readwrite.h"
25#include "chunk.h"
26#include "vector.h"
27#include "matrix.h"
[8]28#include <stdlib.h>
29#include <string.h>
[151]30#include <math.h>
[1563]31#include "config.h"
[8]32#ifdef WITH_DMALLOC
33#include <dmalloc.h>
34#endif
35
[151]36
[8]37/*!
38 * \defgroup mesh Meshes
39 *
40 * \author J.E. Hoffmann <je-h@gmx.net>
41 */
42
[151]43
[8]44static Lib3dsBool
[10076]45face_array_read(Lib3dsMesh *mesh, iostream *strm)
[8]46{
[151]47  Lib3dsChunk c;
48  Lib3dsWord chunk;
49  int i;
50  int faces;
[8]51
[10076]52  if (!lib3ds_chunk_read_start(&c, LIB3DS_FACE_ARRAY, strm)) {
[151]53    return(LIB3DS_FALSE);
54  }
55  lib3ds_mesh_free_face_list(mesh);
56 
[10076]57  faces=lib3ds_word_read(strm);
[151]58  if (faces) {
59    if (!lib3ds_mesh_new_face_list(mesh, faces)) {
60      LIB3DS_ERROR_LOG;
61      return(LIB3DS_FALSE);
[8]62    }
[151]63    for (i=0; i<faces; ++i) {
64      strcpy(mesh->faceL[i].material, "");
[10076]65      mesh->faceL[i].points[0]=lib3ds_word_read(strm);
66      mesh->faceL[i].points[1]=lib3ds_word_read(strm);
67      mesh->faceL[i].points[2]=lib3ds_word_read(strm);
68      mesh->faceL[i].flags=lib3ds_word_read(strm);
[151]69    }
[10076]70    lib3ds_chunk_read_tell(&c, strm);
[8]71
[10076]72    while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]73      switch (chunk) {
74        case LIB3DS_SMOOTH_GROUP:
75          {
76            unsigned i;
[8]77
[151]78            for (i=0; i<mesh->faces; ++i) {
[10076]79              mesh->faceL[i].smoothing=lib3ds_dword_read(strm);
[151]80            }
81          }
82          break;
83        case LIB3DS_MSH_MAT_GROUP:
84          {
85            char name[64];
86            unsigned faces;
87            unsigned i;
88            unsigned index;
[8]89
[10076]90            if (!lib3ds_string_read(name, 64, strm)) {
[151]91              return(LIB3DS_FALSE);
92            }
[10076]93            faces=lib3ds_word_read(strm);
[151]94            for (i=0; i<faces; ++i) {
[10076]95              index=lib3ds_word_read(strm);
[151]96              ASSERT(index<mesh->faces);
97              strcpy(mesh->faceL[index].material, name);
98            }
99          }
100          break;
101        case LIB3DS_MSH_BOXMAP:
102          {
103            char name[64];
[8]104
[10076]105            if (!lib3ds_string_read(name, 64, strm)) {
[151]106              return(LIB3DS_FALSE);
[8]107            }
[151]108            strcpy(mesh->box_map.front, name);
[10076]109            if (!lib3ds_string_read(name, 64, strm)) {
[151]110              return(LIB3DS_FALSE);
111            }
112            strcpy(mesh->box_map.back, name);
[10076]113            if (!lib3ds_string_read(name, 64, strm)) {
[151]114              return(LIB3DS_FALSE);
115            }
116            strcpy(mesh->box_map.left, name);
[10076]117            if (!lib3ds_string_read(name, 64, strm)) {
[151]118              return(LIB3DS_FALSE);
119            }
120            strcpy(mesh->box_map.right, name);
[10076]121            if (!lib3ds_string_read(name, 64, strm)) {
[151]122              return(LIB3DS_FALSE);
123            }
124            strcpy(mesh->box_map.top, name);
[10076]125            if (!lib3ds_string_read(name, 64, strm)) {
[151]126              return(LIB3DS_FALSE);
127            }
128            strcpy(mesh->box_map.bottom, name);
129          }
130          break;
131        default:
132          lib3ds_chunk_unknown(chunk);
133      }
[8]134    }
[151]135   
136  }
[10076]137  lib3ds_chunk_read_end(&c, strm);
[151]138  return(LIB3DS_TRUE);
[8]139}
140
141
142/*!
143 * \ingroup mesh
144 */
145Lib3dsMesh*
146lib3ds_mesh_new(const char *name)
147{
[151]148  Lib3dsMesh *mesh;
[8]149
[151]150  ASSERT(name);
151  ASSERT(strlen(name)<64);
152 
153  mesh=(Lib3dsMesh*)calloc(sizeof(Lib3dsMesh), 1);
154  if (!mesh) {
155    return(0);
156  }
157  strcpy(mesh->name, name);
158  lib3ds_matrix_identity(mesh->matrix);
159  mesh->map_data.maptype=LIB3DS_MAP_NONE;
160  return(mesh);
[8]161}
162
163
164/*!
165 * \ingroup mesh
166 */
167void
168lib3ds_mesh_free(Lib3dsMesh *mesh)
169{
[151]170  lib3ds_mesh_free_point_list(mesh);
171  lib3ds_mesh_free_flag_list(mesh);
172  lib3ds_mesh_free_texel_list(mesh);
173  lib3ds_mesh_free_face_list(mesh);
174  memset(mesh, 0, sizeof(Lib3dsMesh));
175  free(mesh);
[8]176}
177
178
179/*!
180 * \ingroup mesh
181 */
182Lib3dsBool
183lib3ds_mesh_new_point_list(Lib3dsMesh *mesh, Lib3dsDword points)
184{
[151]185  ASSERT(mesh);
186  if (mesh->pointL) {
187    ASSERT(mesh->points);
188    lib3ds_mesh_free_point_list(mesh);
189  }
190  ASSERT(!mesh->pointL && !mesh->points);
191  mesh->points=0;
192  mesh->pointL=(Lib3dsPoint*)calloc(sizeof(Lib3dsPoint)*points,1);
193  if (!mesh->pointL) {
194    LIB3DS_ERROR_LOG;
195    return(LIB3DS_FALSE);
196  }
197  mesh->points=points;
198  return(LIB3DS_TRUE);
[8]199}
200
201
202/*!
203 * \ingroup mesh
204 */
205void
206lib3ds_mesh_free_point_list(Lib3dsMesh *mesh)
207{
[151]208  ASSERT(mesh);
209  if (mesh->pointL) {
210    ASSERT(mesh->points);
211    free(mesh->pointL);
212    mesh->pointL=0;
213    mesh->points=0;
214  }
215  else {
216    ASSERT(!mesh->points);
217  }
[8]218}
219
220
221/*!
222 * \ingroup mesh
223 */
224Lib3dsBool
225lib3ds_mesh_new_flag_list(Lib3dsMesh *mesh, Lib3dsDword flags)
226{
[151]227  ASSERT(mesh);
228  if (mesh->flagL) {
229    ASSERT(mesh->flags);
230    lib3ds_mesh_free_flag_list(mesh);
231  }
232  ASSERT(!mesh->flagL && !mesh->flags);
233  mesh->flags=0;
234  mesh->flagL=(Lib3dsWord*)calloc(sizeof(Lib3dsWord)*flags,1);
235  if (!mesh->flagL) {
236    LIB3DS_ERROR_LOG;
237    return(LIB3DS_FALSE);
238  }
239  mesh->flags=flags;
240  return(LIB3DS_TRUE);
[8]241}
242
243
244/*!
245 * \ingroup mesh
246 */
247void
248lib3ds_mesh_free_flag_list(Lib3dsMesh *mesh)
249{
[151]250  ASSERT(mesh);
251  if (mesh->flagL) {
252    ASSERT(mesh->flags);
253    free(mesh->flagL);
254    mesh->flagL=0;
255    mesh->flags=0;
256  }
257  else {
258    ASSERT(!mesh->flags);
259  }
[8]260}
261
262
263/*!
264 * \ingroup mesh
265 */
266Lib3dsBool
267lib3ds_mesh_new_texel_list(Lib3dsMesh *mesh, Lib3dsDword texels)
268{
[151]269  ASSERT(mesh);
270  if (mesh->texelL) {
271    ASSERT(mesh->texels);
272    lib3ds_mesh_free_texel_list(mesh);
273  }
274  ASSERT(!mesh->texelL && !mesh->texels);
275  mesh->texels=0;
276  mesh->texelL=(Lib3dsTexel*) calloc(sizeof(Lib3dsTexel)*texels,1);
277  if (!mesh->texelL) {
278    LIB3DS_ERROR_LOG;
279    return(LIB3DS_FALSE);
280  }
281  mesh->texels=texels;
282  return(LIB3DS_TRUE);
[8]283}
284
285
286/*!
287 * \ingroup mesh
288 */
289void
290lib3ds_mesh_free_texel_list(Lib3dsMesh *mesh)
291{
[151]292  ASSERT(mesh);
293  if (mesh->texelL) {
294    ASSERT(mesh->texels);
295    free(mesh->texelL);
296    mesh->texelL=0;
297    mesh->texels=0;
298  }
299  else {
300    ASSERT(!mesh->texels);
301  }
[8]302}
303
304
305/*!
306 * \ingroup mesh
307 */
308Lib3dsBool
309lib3ds_mesh_new_face_list(Lib3dsMesh *mesh, Lib3dsDword faces)
310{
[151]311  ASSERT(mesh);
312  if (mesh->faceL) {
313    ASSERT(mesh->faces);
314    lib3ds_mesh_free_face_list(mesh);
315  }
316  ASSERT(!mesh->faceL && !mesh->faces);
317  mesh->faces=0;
318  mesh->faceL=(Lib3dsFace*)calloc(sizeof(Lib3dsFace)*faces,1);
319  if (!mesh->faceL) {
320    LIB3DS_ERROR_LOG;
321    return(LIB3DS_FALSE);
322  }
323  mesh->faces=faces;
324  return(LIB3DS_TRUE);
[8]325}
326
327
328/*!
329 * \ingroup mesh
330 */
331void
332lib3ds_mesh_free_face_list(Lib3dsMesh *mesh)
333{
[151]334  ASSERT(mesh);
335  if (mesh->faceL) {
336    ASSERT(mesh->faces);
337    free(mesh->faceL);
338    mesh->faceL=0;
339    mesh->faces=0;
340  }
341  else {
342    ASSERT(!mesh->faces);
343  }
[8]344}
345
346
[151]347typedef struct _Lib3dsFaces Lib3dsFaces;
348
349struct _Lib3dsFaces {
350  Lib3dsFaces *next;
351  Lib3dsFace *face;
352};
353
354
355
356
[8]357/*!
358 * \ingroup mesh
359 */
360void
361lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max)
362{
[151]363  unsigned i,j;
364  Lib3dsFloat v;
[8]365
[151]366  if (!mesh->points) {
367    lib3ds_vector_zero(min);
368    lib3ds_vector_zero(max);
369    return;
370  }
371 
372  lib3ds_vector_copy(min, mesh->pointL[0].pos);
373  lib3ds_vector_copy(max, mesh->pointL[0].pos);
374  for (i=1; i<mesh->points; ++i) {
375    for (j=0; j<3; ++j) {
376      v=mesh->pointL[i].pos[j];
377      if (v<min[j]) {
378        min[j]=v;
379      }
380      if (v>max[j]) {
381        max[j]=v;
382      }
[8]383    }
[151]384  };
385}
[8]386
[151]387
388/*!
389 * Calculates the vertex normals corresponding to the smoothing group
390 * settings for each face of a mesh.
391 *
392 * \param mesh      A pointer to the mesh to calculate the normals for.
393 * \param normalL   A pointer to a buffer to store the calculated
394 *                  normals. The buffer must have the size:
395 *                  3*sizeof(Lib3dsVector)*mesh->faces.
396 *
397 * To allocate the normal buffer do for example the following:
398 * \code
399 *  Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces);
400 * \endcode
401 *
402 * To access the normal of the i-th vertex of the j-th face do the
403 * following:
404 * \code
405 *   normalL[3*j+i]
406 * \endcode
407 */
408void
409lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
410{
411  Lib3dsFaces **fl;
412  Lib3dsFaces *fa;
413  unsigned i,j,k;
414
415  if (!mesh->faces) {
416    return;
417  }
418
419  fl=(Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*),mesh->points);
420  ASSERT(fl);
421  fa=(Lib3dsFaces*)calloc(sizeof(Lib3dsFaces),3*mesh->faces);
422  ASSERT(fa);
423  k=0;
424  for (i=0; i<mesh->faces; ++i) {
425    Lib3dsFace *f=&mesh->faceL[i];
426    for (j=0; j<3; ++j) {
427      Lib3dsFaces* l=&fa[k++];
428      ASSERT(f->points[j]<mesh->points);
429      l->face=f;
430      l->next=fl[f->points[j]];
431      fl[f->points[j]]=l;
432    }
433  }
434 
435  for (i=0; i<mesh->faces; ++i) {
436    Lib3dsFace *f=&mesh->faceL[i];
437    for (j=0; j<3; ++j) {
438      Lib3dsVector n,N[32];
439      Lib3dsFaces *p;
440      int k,l;
441      int found;
442
443      ASSERT(f->points[j]<mesh->points);
444
445      if (f->smoothing) {
446        lib3ds_vector_zero(n);
447        k=0;
448        for (p=fl[f->points[j]]; p; p=p->next) {
449          found=0;
450          for (l=0; l<k; ++l) {
451            if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
452              found=1;
453              break;
[8]454            }
[151]455          }
456          if (!found) {
457            if (f->smoothing & p->face->smoothing) {
458              lib3ds_vector_add(n,n, p->face->normal);
459              lib3ds_vector_copy(N[k], p->face->normal);
460              ++k;
[8]461            }
[151]462          }
[8]463        }
[151]464      }
465      else {
466        lib3ds_vector_copy(n, f->normal);
467      }
468      lib3ds_vector_normalize(n);
469
470      lib3ds_vector_copy(normalL[3*i+j], n);
471    }
472  }
473
474  free(fa);
475  free(fl);
[8]476}
477
478
479/*!
[151]480 * This function prints data associated with the specified mesh such as
481 * vertex and point lists.
482 *
483 * \param mesh  Points to a mesh that you wish to view the data for.
484 *
485 * \return None
486 *
487 * \warning WIN32: Should only be used in a console window not in a GUI.
488 *
[8]489 * \ingroup mesh
490 */
491void
492lib3ds_mesh_dump(Lib3dsMesh *mesh)
493{
[151]494  unsigned i;
495  Lib3dsVector p;
[8]496
[151]497  ASSERT(mesh);
[5453]498  printf("  %s vertices=%d faces=%d\n",
[151]499    mesh->name,
500    mesh->points,
501    mesh->faces
502  );
503  printf("  matrix:\n");
504  lib3ds_matrix_dump(mesh->matrix);
505  printf("  point list:\n");
506  for (i=0; i<mesh->points; ++i) {
507    lib3ds_vector_copy(p, mesh->pointL[i].pos);
508    printf ("    %8f %8f %8f\n", p[0], p[1], p[2]);
509  }
510  printf("  facelist:\n");
511  for (i=0; i<mesh->points; ++i) {
512    printf ("    %4d %4d %4d  smoothing:%X\n",
513      mesh->faceL[i].points[0],
514      mesh->faceL[i].points[1],
515      mesh->faceL[i].points[2],
[576]516      static_cast<int>(mesh->faceL[i].smoothing)
[151]517    );
518  }
[8]519}
520
521
522/*!
523 * \ingroup mesh
524 */
525Lib3dsBool
[10076]526lib3ds_mesh_read(Lib3dsMesh *mesh, iostream *strm)
[8]527{
[151]528  Lib3dsChunk c;
529  Lib3dsWord chunk;
[8]530
[10076]531  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, strm)) {
[151]532    return(LIB3DS_FALSE);
533  }
[8]534
[10076]535  while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]536    switch (chunk) {
537      case LIB3DS_MESH_MATRIX:
[8]538        {
[151]539          int i,j;
540         
541          lib3ds_matrix_identity(mesh->matrix);
542          for (i=0; i<4; i++) {
543            for (j=0; j<3; j++) {
[10076]544              mesh->matrix[i][j]=lib3ds_float_read(strm);
[8]545            }
[151]546          }
547        }
548        break;
549      case LIB3DS_MESH_COLOR:
550        {
[10076]551          mesh->color=lib3ds_byte_read(strm);
[151]552        }
553        break;
554      case LIB3DS_POINT_ARRAY:
555        {
556          unsigned i,j;
557          unsigned points;
558         
559          lib3ds_mesh_free_point_list(mesh);
[10076]560          points=lib3ds_word_read(strm);
[151]561          if (points) {
562            if (!lib3ds_mesh_new_point_list(mesh, points)) {
563              LIB3DS_ERROR_LOG;
564              return(LIB3DS_FALSE);
[8]565            }
[151]566            for (i=0; i<mesh->points; ++i) {
567              for (j=0; j<3; ++j) {
[10076]568                mesh->pointL[i].pos[j]=lib3ds_float_read(strm);
[151]569              }
[8]570            }
[151]571            ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
572            ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
573          }
574        }
575        break;
576      case LIB3DS_POINT_FLAG_ARRAY:
577        {
578          unsigned i;
579          unsigned flags;
580         
581          lib3ds_mesh_free_flag_list(mesh);
[10076]582          flags=lib3ds_word_read(strm);
[151]583          if (flags) {
584            if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
585              LIB3DS_ERROR_LOG;
586              return(LIB3DS_FALSE);
[8]587            }
[151]588            for (i=0; i<mesh->flags; ++i) {
[10076]589              mesh->flagL[i]=lib3ds_word_read(strm);
[8]590            }
[151]591            ASSERT((!mesh->points) || (mesh->flags==mesh->points));
592            ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
593          }
594        }
595        break;
596      case LIB3DS_FACE_ARRAY:
597        {
[10076]598          lib3ds_chunk_read_reset(&c, strm);
599          if (!face_array_read(mesh, strm)) {
[151]600            return(LIB3DS_FALSE);
601          }
602        }
603        break;
604      case LIB3DS_MESH_TEXTURE_INFO:
605        {
606          int i,j;
[8]607
[151]608          for (i=0; i<2; ++i) {
[10076]609            mesh->map_data.tile[i]=lib3ds_float_read(strm);
[151]610          }
611          for (i=0; i<3; ++i) {
[10076]612            mesh->map_data.pos[i]=lib3ds_float_read(strm);
[151]613          }
[10076]614          mesh->map_data.scale=lib3ds_float_read(strm);
[8]615
[151]616          lib3ds_matrix_identity(mesh->map_data.matrix);
617          for (i=0; i<4; i++) {
618            for (j=0; j<3; j++) {
[10076]619              mesh->map_data.matrix[i][j]=lib3ds_float_read(strm);
[8]620            }
[151]621          }
622          for (i=0; i<2; ++i) {
[10076]623            mesh->map_data.planar_size[i]=lib3ds_float_read(strm);
[151]624          }
[10076]625          mesh->map_data.cylinder_height=lib3ds_float_read(strm);
[151]626        }
627        break;
628      case LIB3DS_TEX_VERTS:
629        {
630          unsigned i;
631          unsigned texels;
632         
633          lib3ds_mesh_free_texel_list(mesh);
[10076]634          texels=lib3ds_word_read(strm);
[151]635          if (texels) {
636            if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
637              LIB3DS_ERROR_LOG;
638              return(LIB3DS_FALSE);
[8]639            }
[151]640            for (i=0; i<mesh->texels; ++i) {
[10076]641              mesh->texelL[i][0]=lib3ds_float_read(strm);
642              mesh->texelL[i][1]=lib3ds_float_read(strm);
[151]643            }
644            ASSERT((!mesh->points) || (mesh->texels==mesh->points));
645            ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
646          }
[8]647        }
[151]648        break;
649      default:
650        lib3ds_chunk_unknown(chunk);
[8]651    }
[151]652  }
653  {
654    unsigned j;
[8]655
[151]656    for (j=0; j<mesh->faces; ++j) {
657      ASSERT(mesh->faceL[j].points[0]<mesh->points);
658      ASSERT(mesh->faceL[j].points[1]<mesh->points);
659      ASSERT(mesh->faceL[j].points[2]<mesh->points);
660      lib3ds_vector_normal(
661        mesh->faceL[j].normal,
662        mesh->pointL[mesh->faceL[j].points[0]].pos,
663        mesh->pointL[mesh->faceL[j].points[1]].pos,
664        mesh->pointL[mesh->faceL[j].points[2]].pos
665      );
[8]666    }
[151]667  }
668 
[10076]669  lib3ds_chunk_read_end(&c, strm);
[151]670  return(LIB3DS_TRUE);
[8]671}
672
673
674static Lib3dsBool
[10076]675point_array_write(Lib3dsMesh *mesh, iostream *strm)
[8]676{
[151]677  Lib3dsChunk c;
678  unsigned i;
[8]679
[151]680  if (!mesh->points || !mesh->pointL) {
[8]681    return(LIB3DS_TRUE);
[151]682  }
683  ASSERT(mesh->points<0x10000);
684  c.chunk=LIB3DS_POINT_ARRAY;
685  c.size=8+12*mesh->points;
[10076]686  lib3ds_chunk_write(&c, strm);
[151]687 
[10076]688  lib3ds_word_write((Lib3dsWord)mesh->points, strm);
[151]689  for (i=0; i<mesh->points; ++i) {
[10076]690    lib3ds_vector_write(mesh->pointL[i].pos, strm);
[151]691  }
692  return(LIB3DS_TRUE);
[8]693}
694
695
696static Lib3dsBool
[10076]697flag_array_write(Lib3dsMesh *mesh, iostream *strm)
[8]698{
[151]699  Lib3dsChunk c;
700  unsigned i;
701 
702  if (!mesh->flags || !mesh->flagL) {
[8]703    return(LIB3DS_TRUE);
[151]704  }
705  ASSERT(mesh->flags<0x10000);
706  c.chunk=LIB3DS_POINT_FLAG_ARRAY;
707  c.size=8+2*mesh->flags;
[10076]708  lib3ds_chunk_write(&c, strm);
[151]709 
[10076]710  lib3ds_word_write((Lib3dsWord)mesh->flags, strm);
[151]711  for (i=0; i<mesh->flags; ++i) {
[10076]712    lib3ds_word_write(mesh->flagL[i], strm);
[151]713  }
714  return(LIB3DS_TRUE);
[8]715}
716
717
718static Lib3dsBool
[10076]719face_array_write(Lib3dsMesh *mesh, iostream *strm)
[8]720{
[151]721  Lib3dsChunk c;
722 
723  if (!mesh->faces || !mesh->faceL) {
724    return(LIB3DS_TRUE);
725  }
726  ASSERT(mesh->faces<0x10000);
727  c.chunk=LIB3DS_FACE_ARRAY;
[10076]728  if (!lib3ds_chunk_write_start(&c, strm)) {
[151]729    return(LIB3DS_FALSE);
730  }
731  {
732    unsigned i;
[8]733
[10076]734    lib3ds_word_write((Lib3dsWord)mesh->faces, strm);
[151]735    for (i=0; i<mesh->faces; ++i) {
[10076]736      lib3ds_word_write(mesh->faceL[i].points[0], strm);
737      lib3ds_word_write(mesh->faceL[i].points[1], strm);
738      lib3ds_word_write(mesh->faceL[i].points[2], strm);
739      lib3ds_word_write(mesh->faceL[i].flags, strm);
[8]740    }
[151]741  }
[8]742
[151]743  { /*---- MSH_MAT_GROUP ----*/
744    Lib3dsChunk c;
745    unsigned i,j;
746    Lib3dsWord num;
747    char *matf=(char*)calloc(sizeof(char), mesh->faces);
748    if (!matf) {
749      return(LIB3DS_FALSE);
[8]750    }
[151]751   
752    for (i=0; i<mesh->faces; ++i) {
753      if (!matf[i] && strlen(mesh->faceL[i].material)) {
754        matf[i]=1;
755        num=1;
756       
757        for (j=i+1; j<mesh->faces; ++j) {
758          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) ++num;
[8]759        }
[151]760       
761        c.chunk=LIB3DS_MSH_MAT_GROUP;
762        c.size=6+ strlen(mesh->faceL[i].material)+1 +2+2*num;
[10076]763        lib3ds_chunk_write(&c, strm);
764        lib3ds_string_write(mesh->faceL[i].material, strm);
765        lib3ds_word_write(num, strm);
766        lib3ds_word_write((Lib3dsWord)i, strm);
[151]767       
768        for (j=i+1; j<mesh->faces; ++j) {
769          if (strcmp(mesh->faceL[i].material, mesh->faceL[j].material)==0) {
[10076]770            lib3ds_word_write((Lib3dsWord)j, strm);
[151]771            matf[j]=1;
772          }
[8]773        }
[151]774      }     
[8]775    }
[151]776    free(matf);
777  }
[8]778
[151]779  { /*---- SMOOTH_GROUP ----*/
780    Lib3dsChunk c;
781    unsigned i;
782   
783    c.chunk=LIB3DS_SMOOTH_GROUP;
784    c.size=6+4*mesh->faces;
[10076]785    lib3ds_chunk_write(&c, strm);
[151]786   
787    for (i=0; i<mesh->faces; ++i) {
[10076]788      lib3ds_dword_write(mesh->faceL[i].smoothing, strm);
[8]789    }
[151]790  }
791 
792  { /*---- MSH_BOXMAP ----*/
793    Lib3dsChunk c;
[8]794
[151]795    if (strlen(mesh->box_map.front) ||
796      strlen(mesh->box_map.back) ||
797      strlen(mesh->box_map.left) ||
798      strlen(mesh->box_map.right) ||
799      strlen(mesh->box_map.top) ||
800      strlen(mesh->box_map.bottom)) {
801   
802      c.chunk=LIB3DS_MSH_BOXMAP;
[10076]803      if (!lib3ds_chunk_write_start(&c, strm)) {
[8]804        return(LIB3DS_FALSE);
[151]805      }
806     
[10076]807      lib3ds_string_write(mesh->box_map.front, strm);
808      lib3ds_string_write(mesh->box_map.back, strm);
809      lib3ds_string_write(mesh->box_map.left, strm);
810      lib3ds_string_write(mesh->box_map.right, strm);
811      lib3ds_string_write(mesh->box_map.top, strm);
812      lib3ds_string_write(mesh->box_map.bottom, strm);
[151]813     
[10076]814      if (!lib3ds_chunk_write_end(&c, strm)) {
[151]815        return(LIB3DS_FALSE);
816      }
[8]817    }
[151]818  }
819
[10076]820  if (!lib3ds_chunk_write_end(&c, strm)) {
[151]821    return(LIB3DS_FALSE);
822  }
823  return(LIB3DS_TRUE);
[8]824}
825
826
827static Lib3dsBool
[10076]828texel_array_write(Lib3dsMesh *mesh, iostream *strm)
[8]829{
[151]830  Lib3dsChunk c;
831  unsigned i;
832 
833  if (!mesh->texels || !mesh->texelL) {
[8]834    return(LIB3DS_TRUE);
[151]835  }
836  ASSERT(mesh->texels<0x10000);
837  c.chunk=LIB3DS_TEX_VERTS;
838  c.size=8+8*mesh->texels;
[10076]839  lib3ds_chunk_write(&c, strm);
[151]840 
[10076]841  lib3ds_word_write((Lib3dsWord)mesh->texels, strm);
[151]842  for (i=0; i<mesh->texels; ++i) {
[10076]843    lib3ds_float_write(mesh->texelL[i][0], strm);
844    lib3ds_float_write(mesh->texelL[i][1], strm);
[151]845  }
846  return(LIB3DS_TRUE);
[8]847}
848
849
850/*!
851 * \ingroup mesh
852 */
853Lib3dsBool
[10076]854lib3ds_mesh_write(Lib3dsMesh *mesh, iostream *strm)
[8]855{
[151]856  Lib3dsChunk c;
857
858  c.chunk=LIB3DS_N_TRI_OBJECT;
[10076]859  if (!lib3ds_chunk_write_start(&c,strm)) {
[151]860    return(LIB3DS_FALSE);
861  }
[10076]862  if (!point_array_write(mesh, strm)) {
[151]863    return(LIB3DS_FALSE);
864  }
[10076]865  if (!texel_array_write(mesh, strm)) {
[151]866    return(LIB3DS_FALSE);
867  }
868
869  if (mesh->map_data.maptype!=LIB3DS_MAP_NONE) { /*---- LIB3DS_MESH_TEXTURE_INFO ----*/
[8]870    Lib3dsChunk c;
[151]871    int i,j;
872   
873    c.chunk=LIB3DS_MESH_TEXTURE_INFO;
874    c.size=92;
[10076]875    if (!lib3ds_chunk_write(&c,strm)) {
[151]876      return(LIB3DS_FALSE);
877    }
[8]878
[10076]879    lib3ds_word_write(mesh->map_data.maptype, strm);
[151]880
881    for (i=0; i<2; ++i) {
[10076]882      lib3ds_float_write(mesh->map_data.tile[i], strm);
[8]883    }
[151]884    for (i=0; i<3; ++i) {
[10076]885      lib3ds_float_write(mesh->map_data.pos[i], strm);
[8]886    }
[10076]887    lib3ds_float_write(mesh->map_data.scale, strm);
[151]888
889    for (i=0; i<4; i++) {
890      for (j=0; j<3; j++) {
[10076]891        lib3ds_float_write(mesh->map_data.matrix[i][j], strm);
[151]892      }
[8]893    }
[151]894    for (i=0; i<2; ++i) {
[10076]895      lib3ds_float_write(mesh->map_data.planar_size[i], strm);
[8]896    }
[10076]897    lib3ds_float_write(mesh->map_data.cylinder_height, strm);
[151]898  }
[8]899
[10076]900  if (!flag_array_write(mesh, strm)) {
[151]901    return(LIB3DS_FALSE);
902  }
903  { /*---- LIB3DS_MESH_MATRIX ----*/
904    Lib3dsChunk c;
905    int i,j;
[8]906
[151]907    c.chunk=LIB3DS_MESH_MATRIX;
908    c.size=54;
[10076]909    if (!lib3ds_chunk_write(&c,strm)) {
[151]910      return(LIB3DS_FALSE);
[8]911    }
[151]912    for (i=0; i<4; i++) {
913      for (j=0; j<3; j++) {
[10076]914        lib3ds_float_write(mesh->matrix[i][j], strm);
[151]915      }
916    }
917  }
[8]918
[151]919  if (mesh->color) { /*---- LIB3DS_MESH_COLOR ----*/
920    Lib3dsChunk c;
921   
922    c.chunk=LIB3DS_MESH_COLOR;
923    c.size=7;
[10076]924    if (!lib3ds_chunk_write(&c,strm)) {
[151]925      return(LIB3DS_FALSE);
[8]926    }
[10076]927    lib3ds_byte_write(mesh->color, strm);
[151]928  }
[10076]929  if (!face_array_write(mesh, strm)) {
[151]930    return(LIB3DS_FALSE);
931  }
[8]932
[10076]933  if (!lib3ds_chunk_write_end(&c,strm)) {
[151]934    return(LIB3DS_FALSE);
935  }
936  return(LIB3DS_TRUE);
[8]937}
938
939
940/*!
941
942\typedef Lib3dsFace
943  \ingroup mesh
944  \sa _Lib3dsFace
945
946*/
947/*!
948
949\typedef Lib3dsBoxMap
950  \ingroup mesh
951  \sa _Lib3dsBoxMap
952
953*/
954/*!
955
956\typedef Lib3dsMapData
957  \ingroup mesh
958  \sa _Lib3dsMapData
959
960*/
961/*!
962
963\typedef Lib3dsMesh
964  \ingroup mesh
965  \sa _Lib3dsMesh
966
967*/
Note: See TracBrowser for help on using the browser.