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

Revision 10076, 30.2 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 "file.h"
24#include "chunk.h"
25#include "readwrite.h"
26#include "material.h"
27#include "mesh.h"
28#include "camera.h"
29#include "light.h"
30#include "node.h"
31#include "vector.h"
[8]32#include <stdlib.h>
33#include <string.h>
[151]34#include <math.h>
[1563]35#include "config.h"
[8]36#ifdef WITH_DMALLOC
37#include <dmalloc.h>
38#endif
39
[10076]40#include <istream>
41#include <stdio.h>
42//#include <strstream>
43#include <sstream>
44#include <fstream>
[151]45
[8]46/*!
47 * \defgroup file Files
48 *
49 * \author J.E. Hoffmann <je-h@gmx.net>
50 */
51
[151]52
[8]53/*!
[151]54 * Loads a .3DS file from disk into memory.
55 *
56 * \param filename  The filename of the .3DS file
57 *
58 * \return   A pointer to the Lib3dsFile structure containing the
59 *           data of the .3DS file.
60 *           If the .3DS file can not be loaded NULL is returned.
61 *
62 * \note     To free the returned pointer use lib3ds_free.
63 *
64 * \see lib3ds_file_save
65 * \see lib3ds_file_new
66 * \see lib3ds_file_free
67 *
[8]68 * \ingroup file
69 */
70Lib3dsFile*
[10076]71lib3ds_file_load(const char *filename, const osgDB::ReaderWriter::Options* options)
[8]72{
[10076]73  Lib3dsFile *file = NULL;
74  std::stringstream bufferedStream;
75  ifstream inputStream(filename,ios::in|ios::binary);
76  if (!inputStream.fail())
77  {
78        bufferedStream.operator<<(inputStream.rdbuf());               
79        bufferedStream.seekp(ios_base::beg);                   
80        file = lib3ds_stream_load(&bufferedStream);
81        inputStream.close();
82  }
83  return(file);
84}
[8]85
[10076]86Lib3dsFile*
87lib3ds_stream_load(iostream * strm)
88{
89  Lib3dsFile *file = NULL;
90  if (strm)
91  {   
92    file=lib3ds_file_new();
93    if (file)
94    {
95        if (!lib3ds_file_read(file,strm))
96        {
97            free(file);
98            file = NULL;
99        }
100    }
101    else 
102        file = NULL;
[151]103  }
104  return(file);
[8]105}
106
107
[10076]108
[8]109/*!
[151]110 * Saves a .3DS file from memory to disk.
111 *
112 * \param file      A pointer to a Lib3dsFile structure containing the
113 *                  the data that should be stored.
114 * \param filename  The filename of the .3DS file to store the data in.
115 *
116 * \return          TRUE on success, FALSE otherwise.
117 *
118 * \see lib3ds_file_load
119 *
[8]120 * \ingroup file
121 */
[151]122Lib3dsBool
123lib3ds_file_save(Lib3dsFile *file, const char *filename)
[8]124{
[10076]125  fstream strm;
[151]126
[10076]127  strm.open(filename,ios_base::out | ios_base::binary);
128  if (strm.fail()) return (LIB3DS_FALSE);
[151]129 
[10076]130  if (!lib3ds_file_write(file, &strm)) {
131      strm.close();
[151]132    return(LIB3DS_FALSE);
133  }
[10076]134  strm.close();
[151]135  return(LIB3DS_TRUE);
[8]136}
137
138
139/*!
140 * \ingroup file
141 */
142Lib3dsFile*
143lib3ds_file_new()
144{
[151]145  Lib3dsFile *file;
[8]146
[151]147  file=(Lib3dsFile*)calloc(sizeof(Lib3dsFile),1);
148  if (!file) {
149    return(0);
150  }
151  file->mesh_version=3;
152  file->master_scale=1.0f;
153  file->keyf_revision=5;
154  strcpy(file->name, "LIB3DS");
155  return(file);
[8]156}
157
158
159/*!
160 * \ingroup file
161 */
162void
163lib3ds_file_free(Lib3dsFile* file)
164{
[151]165  ASSERT(file);
166  lib3ds_viewport_set_views(&file->viewport,0);
167  {
168    Lib3dsMaterial *p,*q;
169   
170    for (p=file->materials; p; p=q) {
171      q=p->next;
172      lib3ds_material_free(p);
[8]173    }
[151]174    file->materials=0;
175  }
176  {
177    Lib3dsCamera *p,*q;
178   
179    for (p=file->cameras; p; p=q) {
180      q=p->next;
181      lib3ds_camera_free(p);
[8]182    }
[151]183    file->cameras=0;
184  }
185  {
186    Lib3dsLight *p,*q;
187   
188    for (p=file->lights; p; p=q) {
189      q=p->next;
190      lib3ds_light_free(p);
[8]191    }
[151]192    file->lights=0;
193  }
194  {
195    Lib3dsMesh *p,*q;
196   
197    for (p=file->meshes; p; p=q) {
198      q=p->next;
199      lib3ds_mesh_free(p);
[8]200    }
[151]201    file->meshes=0;
202  }
203  {
204    Lib3dsNode *p,*q;
205 
206    for (p=file->nodes; p; p=q) {
207      q=p->next;
208      lib3ds_node_free(p);
[8]209    }
[151]210  }
211  free(file);
[8]212}
213
214
215/*!
216 * \ingroup file
217 */
218void
219lib3ds_file_eval(Lib3dsFile *file, Lib3dsFloat t)
220{
[151]221  Lib3dsNode *p;
[8]222
[151]223  for (p=file->nodes; p!=0; p=p->next) {
224    lib3ds_node_eval(p, t);
225  }
[8]226}
227
228
229static Lib3dsBool
[10076]230named_object_read(Lib3dsFile *file, iostream *strm)
[8]231{
[151]232  Lib3dsChunk c;
233  char name[64];
234  Lib3dsWord chunk;
[8]235
[10076]236  if (!lib3ds_chunk_read_start(&c, LIB3DS_NAMED_OBJECT, strm)) {
[151]237    return(LIB3DS_FALSE);
238  }
[10076]239  if (!lib3ds_string_read(name, 64, strm)) {
[151]240    return(LIB3DS_FALSE);
241  }
242  lib3ds_chunk_dump_info("  NAME=%s", name);
[10076]243  lib3ds_chunk_read_tell(&c, strm);
[8]244
[10076]245  while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]246    switch (chunk) {
247      case LIB3DS_N_TRI_OBJECT:
[8]248        {
[151]249          Lib3dsMesh *mesh;
[8]250
[151]251          mesh=lib3ds_mesh_new(name);
252          if (!mesh) {
253            return(LIB3DS_FALSE);
254          }
[10076]255          lib3ds_chunk_read_reset(&c, strm);
256          if (!lib3ds_mesh_read(mesh, strm)) {
[151]257            return(LIB3DS_FALSE);
258          }
259          lib3ds_file_insert_mesh(file, mesh);
260        }
261        break;
262      case LIB3DS_N_CAMERA:
263        {
264          Lib3dsCamera *camera;
[8]265
[151]266          camera=lib3ds_camera_new(name);
267          if (!camera) {
268            return(LIB3DS_FALSE);
269          }
[10076]270          lib3ds_chunk_read_reset(&c, strm);
271          if (!lib3ds_camera_read(camera, strm)) {
[151]272            return(LIB3DS_FALSE);
273          }
274          lib3ds_file_insert_camera(file, camera);
275        }
276        break;
277      case LIB3DS_N_DIRECT_LIGHT:
278        {
279          Lib3dsLight *light;
[8]280
[151]281          light=lib3ds_light_new(name);
282          if (!light) {
283            return(LIB3DS_FALSE);
284          }
[10076]285          lib3ds_chunk_read_reset(&c, strm);
286          if (!lib3ds_light_read(light, strm)) {
[151]287            return(LIB3DS_FALSE);
288          }
289          lib3ds_file_insert_light(file, light);
[8]290        }
[151]291        break;
292      default:
293        lib3ds_chunk_unknown(chunk);
[8]294    }
[151]295  }
296 
[10076]297  lib3ds_chunk_read_end(&c, strm);
[151]298  return(LIB3DS_TRUE);
[8]299}
300
301
302static Lib3dsBool
[10076]303ambient_read(Lib3dsFile *file, iostream *strm)
[8]304{
[151]305  Lib3dsChunk c;
306  Lib3dsWord chunk;
307  Lib3dsBool have_lin=LIB3DS_FALSE;
[8]308
[10076]309  if (!lib3ds_chunk_read_start(&c, LIB3DS_AMBIENT_LIGHT, strm)) {
[151]310    return(LIB3DS_FALSE);
311  }
[8]312
[10076]313  while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]314    switch (chunk) {
315      case LIB3DS_LIN_COLOR_F:
[8]316        {
[151]317          int i;
318          for (i=0; i<3; ++i) {
[10076]319            file->ambient[i]=lib3ds_float_read(strm);
[151]320          }
321        }
322        have_lin=LIB3DS_TRUE;
323        break;
324      case LIB3DS_COLOR_F:
325        {
326          /* gamma corrected color chunk
327             replaced in 3ds R3 by LIN_COLOR_24 */
328          if (!have_lin) {
329            int i;
330            for (i=0; i<3; ++i) {
[10076]331              file->ambient[i]=lib3ds_float_read(strm);
[8]332            }
[151]333          }
[8]334        }
[151]335        break;
336      default:
337        lib3ds_chunk_unknown(chunk);
[8]338    }
[151]339  }
340 
[10076]341  lib3ds_chunk_read_end(&c, strm);
[151]342  return(LIB3DS_TRUE);
[8]343}
344
345
346static Lib3dsBool
[10076]347mdata_read(Lib3dsFile *file, iostream *strm)
[8]348{
[151]349  Lib3dsChunk c;
350  Lib3dsWord chunk;
[8]351
[10076]352  if (!lib3ds_chunk_read_start(&c, LIB3DS_MDATA, strm)) {
[151]353    return(LIB3DS_FALSE);
354  }
355 
[10076]356  while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]357    switch (chunk) {
358      case LIB3DS_MESH_VERSION:
[8]359        {
[10076]360          file->mesh_version=lib3ds_intd_read(strm);
[151]361        }
362        break;
363      case LIB3DS_MASTER_SCALE:
364        {
[10076]365          file->master_scale=lib3ds_float_read(strm);
[151]366        }
367        break;
368      case LIB3DS_SHADOW_MAP_SIZE:
369      case LIB3DS_LO_SHADOW_BIAS:
370      case LIB3DS_HI_SHADOW_BIAS:
371      case LIB3DS_SHADOW_SAMPLES:
372      case LIB3DS_SHADOW_RANGE:
373      case LIB3DS_SHADOW_FILTER:
374      case LIB3DS_RAY_BIAS:
375        {
[10076]376          lib3ds_chunk_read_reset(&c, strm);
377          if (!lib3ds_shadow_read(&file->shadow, strm)) {
[151]378            return(LIB3DS_FALSE);
379          }
380        }
381        break;
382      case LIB3DS_VIEWPORT_LAYOUT:
383      case LIB3DS_DEFAULT_VIEW:
384        {
[10076]385          lib3ds_chunk_read_reset(&c, strm);
386          if (!lib3ds_viewport_read(&file->viewport, strm)) {
[151]387            return(LIB3DS_FALSE);
388          }
389        }
390        break;
391      case LIB3DS_O_CONSTS:
392        {
393          int i;
394          for (i=0; i<3; ++i) {
[10076]395            file->construction_plane[i]=lib3ds_float_read(strm);
[151]396          }
397        }
398        break;
399      case LIB3DS_AMBIENT_LIGHT:
400        {
[10076]401          lib3ds_chunk_read_reset(&c, strm);
402          if (!ambient_read(file, strm)) {
[151]403            return(LIB3DS_FALSE);
404          }
405        }
406        break;
407      case LIB3DS_BIT_MAP:
408      case LIB3DS_SOLID_BGND:
409      case LIB3DS_V_GRADIENT:
410      case LIB3DS_USE_BIT_MAP:
411      case LIB3DS_USE_SOLID_BGND:
412      case LIB3DS_USE_V_GRADIENT:
413        {
[10076]414          lib3ds_chunk_read_reset(&c, strm);
415          if (!lib3ds_background_read(&file->background, strm)) {
[151]416            return(LIB3DS_FALSE);
417          }
418        }
419        break;
420      case LIB3DS_FOG:
421      case LIB3DS_LAYER_FOG:
422      case LIB3DS_DISTANCE_CUE:
423      case LIB3DS_USE_FOG:
424      case LIB3DS_USE_LAYER_FOG:
425      case LIB3DS_USE_DISTANCE_CUE:
426        {
[10076]427          lib3ds_chunk_read_reset(&c, strm);
428          if (!lib3ds_atmosphere_read(&file->atmosphere, strm)) {
[151]429            return(LIB3DS_FALSE);
430          }
431        }
432        break;
433      case LIB3DS_MAT_ENTRY:
434        {
435          Lib3dsMaterial *material;
[8]436
[151]437          material=lib3ds_material_new();
438          if (!material) {
439            return(LIB3DS_FALSE);
440          }
[10076]441          lib3ds_chunk_read_reset(&c, strm);
442          if (!lib3ds_material_read(material, strm)) {
[151]443            return(LIB3DS_FALSE);
444          }
445          lib3ds_file_insert_material(file, material);
[8]446        }
[151]447        break;
448      case LIB3DS_NAMED_OBJECT:
449        {
[10076]450          lib3ds_chunk_read_reset(&c, strm);
451          if (!named_object_read(file, strm)) {
[151]452            return(LIB3DS_FALSE);
453          }
454        }
455        break;
456      default:
457        lib3ds_chunk_unknown(chunk);
[8]458    }
[151]459  }
[8]460
[10076]461  lib3ds_chunk_read_end(&c, strm);
[151]462  return(LIB3DS_TRUE);
[8]463}
464
465
466static Lib3dsBool
[10076]467kfdata_read(Lib3dsFile *file, iostream *strm)
[8]468{
[151]469  Lib3dsChunk c;
470  Lib3dsWord chunk;
[8]471
[10076]472  if (!lib3ds_chunk_read_start(&c, LIB3DS_KFDATA, strm)) {
[151]473    return(LIB3DS_FALSE);
474  }
475 
[10076]476  while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]477    switch (chunk) {
478      case LIB3DS_KFHDR:
479        {
[10076]480          file->keyf_revision=lib3ds_word_read(strm);
481          if (!lib3ds_string_read(file->name, 12+1, strm)) {
[151]482            return(LIB3DS_FALSE);
483          }
[10076]484          file->frames=lib3ds_intd_read(strm);
[151]485        }
486        break;
487      case LIB3DS_KFSEG:
488        {
[10076]489          file->segment_from=lib3ds_intd_read(strm);
490          file->segment_to=lib3ds_intd_read(strm);
[151]491        }
492        break;
493      case LIB3DS_KFCURTIME:
494        {
[10076]495          file->current_frame=lib3ds_intd_read(strm);
[151]496        }
497        break;
498      case LIB3DS_VIEWPORT_LAYOUT:
499      case LIB3DS_DEFAULT_VIEW:
500        {
[10076]501          lib3ds_chunk_read_reset(&c, strm);
502          if (!lib3ds_viewport_read(&file->viewport_keyf, strm)) {
[151]503            return(LIB3DS_FALSE);
504          }
505        }
506        break;
507      case LIB3DS_AMBIENT_NODE_TAG:
508        {
509          Lib3dsNode *node;
[8]510
[151]511          node=lib3ds_node_new_ambient();
512          if (!node) {
513            return(LIB3DS_FALSE);
514          }
[10076]515          lib3ds_chunk_read_reset(&c, strm);
516          if (!lib3ds_node_read(node, file, strm)) {
[151]517            return(LIB3DS_FALSE);
518          }
519          lib3ds_file_insert_node(file, node);
520        }
521        break;
522      case LIB3DS_OBJECT_NODE_TAG:
[8]523        {
[151]524          Lib3dsNode *node;
[8]525
[151]526          node=lib3ds_node_new_object();
527          if (!node) {
528            return(LIB3DS_FALSE);
529          }
[10076]530          lib3ds_chunk_read_reset(&c, strm);
531          if (!lib3ds_node_read(node, file, strm)) {
[151]532            return(LIB3DS_FALSE);
533          }
534          lib3ds_file_insert_node(file, node);
535        }
536        break;
537      case LIB3DS_CAMERA_NODE_TAG:
538        {
539          Lib3dsNode *node;
[8]540
[151]541          node=lib3ds_node_new_camera();
542          if (!node) {
543            return(LIB3DS_FALSE);
544          }
[10076]545          lib3ds_chunk_read_reset(&c, strm);
546          if (!lib3ds_node_read(node, file, strm)) {
[151]547            return(LIB3DS_FALSE);
548          }
549          lib3ds_file_insert_node(file, node);
550        }
551        break;
552      case LIB3DS_TARGET_NODE_TAG:
553        {
554          Lib3dsNode *node;
[8]555
[151]556          node=lib3ds_node_new_target();
557          if (!node) {
558            return(LIB3DS_FALSE);
559          }
[10076]560          lib3ds_chunk_read_reset(&c, strm);
561          if (!lib3ds_node_read(node, file, strm)) {
[151]562            return(LIB3DS_FALSE);
563          }
564          lib3ds_file_insert_node(file, node);
565        }
566        break;
567      case LIB3DS_LIGHT_NODE_TAG:
568      case LIB3DS_SPOTLIGHT_NODE_TAG:
569        {
570          Lib3dsNode *node;
[8]571
[151]572          node=lib3ds_node_new_light();
573          if (!node) {
574            return(LIB3DS_FALSE);
575          }
[10076]576          lib3ds_chunk_read_reset(&c, strm);
577          if (!lib3ds_node_read(node, file, strm)) {
[151]578            return(LIB3DS_FALSE);
579          }
580          lib3ds_file_insert_node(file, node);
581        }
582        break;
583      case LIB3DS_L_TARGET_NODE_TAG:
584        {
585          Lib3dsNode *node;
[8]586
[151]587          node=lib3ds_node_new_spot();
588          if (!node) {
589            return(LIB3DS_FALSE);
590          }
[10076]591          lib3ds_chunk_read_reset(&c, strm);
592          if (!lib3ds_node_read(node, file, strm)) {
[151]593            return(LIB3DS_FALSE);
594          }
595          lib3ds_file_insert_node(file, node);
[8]596        }
[151]597        break;
598      default:
599        lib3ds_chunk_unknown(chunk);
[8]600    }
[151]601  }
[8]602
[10076]603  lib3ds_chunk_read_end(&c, strm);
[151]604  return(LIB3DS_TRUE);
[8]605}
606
607
608/*!
609 * \ingroup file
610 */
611Lib3dsBool
[10076]612lib3ds_file_read(Lib3dsFile *file, iostream *strm)
[8]613{
[151]614  Lib3dsChunk c;
615  Lib3dsWord chunk;
[8]616
[10076]617  if (!lib3ds_chunk_read_start(&c, 0, strm)) {
[151]618    return(LIB3DS_FALSE);
619  }
620  switch (c.chunk) {
621    case LIB3DS_MDATA:
622      {
[10076]623        lib3ds_chunk_read_reset(&c, strm);
624        if (!mdata_read(file, strm)) {
[151]625          return(LIB3DS_FALSE);
[8]626        }
[151]627      }
628      break;
629    case LIB3DS_M3DMAGIC:
630    case LIB3DS_MLIBMAGIC:
631    case LIB3DS_CMAGIC:
632      {
[10076]633        while ((chunk=lib3ds_chunk_read_next(&c, strm))!=0) {
[151]634          switch (chunk) {
635            case LIB3DS_M3D_VERSION:
636              {
[10076]637                file->mesh_version=lib3ds_dword_read(strm);
[151]638              }
639              break;
640            case LIB3DS_MDATA:
641              {
[10076]642                lib3ds_chunk_read_reset(&c, strm);
643                if (!mdata_read(file, strm)) {
[151]644                  return(LIB3DS_FALSE);
[8]645                }
[151]646              }
647              break;
648            case LIB3DS_KFDATA:
649              {
[10076]650                lib3ds_chunk_read_reset(&c, strm);
651                if (!kfdata_read(file, strm)) {
[151]652                  return(LIB3DS_FALSE);
653                }
654              }
655              break;
656            default:
657              lib3ds_chunk_unknown(chunk);
658          }
[8]659        }
[151]660      }
661      break;
662    default:
663      lib3ds_chunk_unknown(c.chunk);
664      return(LIB3DS_FALSE);
665  }
[8]666
[10076]667  lib3ds_chunk_read_end(&c, strm);
[151]668  return(LIB3DS_TRUE);
[8]669}
670
671
672static Lib3dsBool
[10076]673colorf_write(Lib3dsRgba rgb, iostream *strm)
[8]674{
[151]675  Lib3dsChunk c;
[8]676
[151]677  c.chunk=LIB3DS_COLOR_F;
678  c.size=18;
[10076]679  lib3ds_chunk_write(&c,strm);
680  lib3ds_rgb_write(rgb,strm);
[8]681
[151]682  c.chunk=LIB3DS_LIN_COLOR_F;
683  c.size=18;
[10076]684  lib3ds_chunk_write(&c,strm);
685  lib3ds_rgb_write(rgb,strm);
[151]686  return(LIB3DS_TRUE);
[8]687}
688
689
690static Lib3dsBool
[10076]691mdata_write(Lib3dsFile *file, iostream *strm)
[8]692{
[151]693  Lib3dsChunk c;
[8]694
[151]695  c.chunk=LIB3DS_MDATA;
[10076]696  if (!lib3ds_chunk_write_start(&c,strm)) {
[151]697    return(LIB3DS_FALSE);
698  }
[8]699
[151]700  { /*---- LIB3DS_MESH_VERSION ----*/
701    Lib3dsChunk c;
702    c.chunk=LIB3DS_MESH_VERSION;
703    c.size=10;
[10076]704    lib3ds_chunk_write(&c,strm);
705    lib3ds_intd_write(file->mesh_version,strm);
[151]706  }
707  { /*---- LIB3DS_MASTER_SCALE ----*/
708    Lib3dsChunk c;
709    c.chunk=LIB3DS_MASTER_SCALE;
710    c.size=10;
[10076]711    lib3ds_chunk_write(&c,strm);
712    lib3ds_float_write(file->master_scale,strm);
[151]713  }
714  { /*---- LIB3DS_O_CONSTS ----*/
715    int i;
716    for (i=0; i<3; ++i) {
717      if (fabs(file->construction_plane[i])>LIB3DS_EPSILON) {
718        break;
719      }
[8]720    }
[151]721    if (i<3) {
722      Lib3dsChunk c;
723      c.chunk=LIB3DS_O_CONSTS;
724      c.size=18;
[10076]725      lib3ds_chunk_write(&c,strm);
726      lib3ds_vector_write(file->construction_plane,strm);
[8]727    }
[151]728  }
729 
730  { /*---- LIB3DS_AMBIENT_LIGHT ----*/
731    int i;
732    for (i=0; i<3; ++i) {
733      if (fabs(file->ambient[i])>LIB3DS_EPSILON) {
734        break;
735      }
[8]736    }
[151]737    if (i<3) {
738      Lib3dsChunk c;
739      c.chunk=LIB3DS_AMBIENT_LIGHT;
740      c.size=42;
[10076]741      lib3ds_chunk_write(&c,strm);
742      colorf_write(file->ambient,strm);
[8]743    }
[151]744  }
[10076]745  lib3ds_background_write(&file->background, strm);
746  lib3ds_atmosphere_write(&file->atmosphere, strm);
747  lib3ds_shadow_write(&file->shadow, strm);
748  lib3ds_viewport_write(&file->viewport, strm);
[151]749  {
750    Lib3dsMaterial *p;
751    for (p=file->materials; p!=0; p=p->next) {
[10076]752      if (!lib3ds_material_write(p,strm)) {
[151]753        return(LIB3DS_FALSE);
754      }
[8]755    }
[151]756  }
757  {
758    Lib3dsCamera *p;
759    Lib3dsChunk c;
760   
761    for (p=file->cameras; p!=0; p=p->next) {
762      c.chunk=LIB3DS_NAMED_OBJECT;
[10076]763      if (!lib3ds_chunk_write_start(&c,strm)) {
[151]764        return(LIB3DS_FALSE);
765      }
[10076]766      lib3ds_string_write(p->name,strm);
767      lib3ds_camera_write(p,strm);
768      if (!lib3ds_chunk_write_end(&c,strm)) {
[151]769        return(LIB3DS_FALSE);
770      }
[8]771    }
[151]772  }
773  {
774    Lib3dsLight *p;
775    Lib3dsChunk c;
776   
777    for (p=file->lights; p!=0; p=p->next) {
778      c.chunk=LIB3DS_NAMED_OBJECT;
[10076]779      if (!lib3ds_chunk_write_start(&c,strm)) {
[151]780        return(LIB3DS_FALSE);
781      }
[10076]782      lib3ds_string_write(p->name,strm);
783      lib3ds_light_write(p,strm);
784      if (!lib3ds_chunk_write_end(&c,strm)) {
[151]785        return(LIB3DS_FALSE);
786      }
[8]787    }
[151]788  }
789  {
790    Lib3dsMesh *p;
791    Lib3dsChunk c;
792   
793    for (p=file->meshes; p!=0; p=p->next) {
794      c.chunk=LIB3DS_NAMED_OBJECT;
[10076]795      if (!lib3ds_chunk_write_start(&c,strm)) {
[8]796        return(LIB3DS_FALSE);
[151]797      }
[10076]798      lib3ds_string_write(p->name,strm);
799      lib3ds_mesh_write(p,strm);
800      if (!lib3ds_chunk_write_end(&c,strm)) {
[151]801        return(LIB3DS_FALSE);
802      }
[8]803    }
[151]804  }
805
[10076]806  if (!lib3ds_chunk_write_end(&c,strm)) {
[151]807    return(LIB3DS_FALSE);
808  }
809  return(LIB3DS_TRUE);
[8]810}
811
812
[151]813
[8]814static Lib3dsBool
[10076]815nodes_write(Lib3dsNode *node, Lib3dsFile *file, iostream *strm)
[8]816{
[151]817  {
818    Lib3dsNode *p;
819    for (p=node->childs; p!=0; p=p->next) {
[10076]820      if (!lib3ds_node_write(p, file, strm)) {
[151]821        return(LIB3DS_FALSE);
822      }
[10076]823      nodes_write(p, file, strm);
[8]824    }
[151]825  }
826  return(LIB3DS_TRUE);
[8]827}
828
829
830static Lib3dsBool
[10076]831kfdata_write(Lib3dsFile *file, iostream *strm)
[8]832{
[151]833  Lib3dsChunk c;
834 
835  c.chunk=LIB3DS_KFDATA;
[10076]836  if (!lib3ds_chunk_write_start(&c,strm)) {
[151]837    return(LIB3DS_FALSE);
838  }
839 
840  { /*---- LIB3DS_KFHDR ----*/
[8]841    Lib3dsChunk c;
[151]842    c.chunk=LIB3DS_KFHDR;
843    c.size=6 + 2 + strlen(file->name)+1 +4;
[10076]844    lib3ds_chunk_write(&c,strm);
845    lib3ds_intw_write(file->keyf_revision,strm);
846    lib3ds_string_write(file->name, strm);
847    lib3ds_intd_write(file->frames, strm);
[151]848  }
849  { /*---- LIB3DS_KFSEG ----*/
850    Lib3dsChunk c;
851    c.chunk=LIB3DS_KFSEG;
852    c.size=14;
[10076]853    lib3ds_chunk_write(&c,strm);
854    lib3ds_intd_write(file->segment_from,strm);
855    lib3ds_intd_write(file->segment_to,strm);
[151]856  }
857  { /*---- LIB3DS_KFCURTIME ----*/
858    Lib3dsChunk c;
859    c.chunk=LIB3DS_KFCURTIME;
860    c.size=10;
[10076]861    lib3ds_chunk_write(&c,strm);
862    lib3ds_intd_write(file->current_frame,strm);
[151]863  }
[10076]864  lib3ds_viewport_write(&file->viewport_keyf, strm);
[151]865 
866  {
867    Lib3dsNode *p;
868    for (p=file->nodes; p!=0; p=p->next) {
[10076]869      if (!lib3ds_node_write(p, file, strm)) {
[8]870        return(LIB3DS_FALSE);
[151]871      }
[10076]872      if (!nodes_write(p, file, strm)) {
[8]873        return(LIB3DS_FALSE);
[151]874      }
[8]875    }
[151]876  }
877 
[10076]878  if (!lib3ds_chunk_write_end(&c,strm)) {
[151]879    return(LIB3DS_FALSE);
880  }
881  return(LIB3DS_TRUE);
[8]882}
883
884
885/*!
886 * \ingroup file
887 */
888Lib3dsBool
[10076]889lib3ds_file_write(Lib3dsFile *file, iostream *strm)
[8]890{
[151]891  Lib3dsChunk c;
[8]892
[151]893  c.chunk=LIB3DS_M3DMAGIC;
[10076]894  if (!lib3ds_chunk_write_start(&c,strm)) {
[151]895    LIB3DS_ERROR_LOG;
896    return(LIB3DS_FALSE);
897  }
[8]898
[151]899  { /*---- LIB3DS_M3D_VERSION ----*/
900    Lib3dsChunk c;
[8]901
[151]902    c.chunk=LIB3DS_M3D_VERSION;
903    c.size=10;
[10076]904    lib3ds_chunk_write(&c,strm);
905    lib3ds_dword_write(file->mesh_version, strm);
[151]906  }
[8]907
[10076]908  if (!mdata_write(file, strm)) {
[151]909    return(LIB3DS_FALSE);
910  }
[10076]911  if (!kfdata_write(file, strm)) {
[151]912    return(LIB3DS_FALSE);
913  }
[8]914
[10076]915  if (!lib3ds_chunk_write_end(&c,strm)) {
[151]916    return(LIB3DS_FALSE);
917  }
918  return(LIB3DS_TRUE);
[8]919}
920
921
922/*!
923 * \ingroup file
924 */
925void
926lib3ds_file_insert_material(Lib3dsFile *file, Lib3dsMaterial *material)
927{
[151]928  Lib3dsMaterial *p,*q;
929 
930  ASSERT(file);
931  ASSERT(material);
932  ASSERT(!material->next);
[8]933
[151]934  q=0;
935  for (p=file->materials; p!=0; p=p->next) {
936    if (strcmp(material->name, p->name)<0) {
937      break;
[8]938    }
[151]939    q=p;
940  }
941  if (!q) {
942    material->next=file->materials;
943    file->materials=material;
944  }
945  else {
946    material->next=q->next;
947    q->next=material;
948  }
[8]949}
950
951
952/*!
953 * \ingroup file
954 */
955void
956lib3ds_file_remove_material(Lib3dsFile *file, Lib3dsMaterial *material)
957{
[151]958  Lib3dsMaterial *p,*q;
[8]959
[151]960  ASSERT(file);
961  ASSERT(material);
962  ASSERT(file->materials);
963  for (p=0,q=file->materials; q; p=q,q=q->next) {
964    if (q==material) {
965      break;
[8]966    }
[151]967  }
968  if (!q) {
969    ASSERT(LIB3DS_FALSE);
970    return;
971  }
972  if (!p) {
973    file->materials=material->next;
974  }
975  else {
976    p->next=q->next;
977  }
978  material->next=0;
[8]979}
980
981
982/*!
983 * \ingroup file
984 */
985Lib3dsMaterial*
986lib3ds_file_material_by_name(Lib3dsFile *file, const char *name)
987{
[151]988  Lib3dsMaterial *p;
[8]989
[151]990  ASSERT(file);
991  for (p=file->materials; p!=0; p=p->next) {
992    if (strcmp(p->name,name)==0) {
993      return(p);
[8]994    }
[151]995  }
996  return(0);
[8]997}
998
999
1000/*!
1001 * \ingroup file
1002 */
1003void
1004lib3ds_file_dump_materials(Lib3dsFile *file)
1005{
[151]1006  Lib3dsMaterial *p;
[8]1007
[151]1008  ASSERT(file);
1009  for (p=file->materials; p!=0; p=p->next) {
1010    lib3ds_material_dump(p);
1011  }
[8]1012}
1013
1014
1015/*!
1016 * \ingroup file
1017 */
1018void
1019lib3ds_file_insert_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
1020{
[151]1021  Lib3dsMesh *p,*q;
1022 
1023  ASSERT(file);
1024  ASSERT(mesh);
1025  ASSERT(!mesh->next);
[8]1026
[151]1027  q=0;
1028  for (p=file->meshes; p!=0; p=p->next) {
1029    if (strcmp(mesh->name, p->name)<0) {
1030      break;
[8]1031    }
[151]1032    q=p;
1033  }
1034  if (!q) {
1035    mesh->next=file->meshes;
1036    file->meshes=mesh;
1037  }
1038  else {
1039    mesh->next=q->next;
1040    q->next=mesh;
1041  }
[8]1042}
1043
1044
1045/*!
1046 * \ingroup file
1047 */
1048void
1049lib3ds_file_remove_mesh(Lib3dsFile *file, Lib3dsMesh *mesh)
1050{
[151]1051  Lib3dsMesh *p,*q;
[8]1052
[151]1053  ASSERT(file);
1054  ASSERT(mesh);
1055  ASSERT(file->meshes);
1056  for (p=0,q=file->meshes; q; p=q,q=q->next) {
1057    if (q==mesh) {
1058      break;
[8]1059    }
[151]1060  }
1061  if (!q) {
1062    ASSERT(LIB3DS_FALSE);
1063    return;
1064  }
1065  if (!p) {
1066    file->meshes=mesh->next;
1067  }
1068  else {
1069    p->next=q->next;
1070  }
1071  mesh->next=0;
[8]1072}
1073
1074
1075/*!
1076 * \ingroup file
1077 */
1078Lib3dsMesh*
1079lib3ds_file_mesh_by_name(Lib3dsFile *file, const char *name)
1080{
[151]1081  Lib3dsMesh *p;
[8]1082
[151]1083  ASSERT(file);
1084  for (p=file->meshes; p!=0; p=p->next) {
1085    if (strcmp(p->name,name)==0) {
1086      return(p);
[8]1087    }
[151]1088  }
1089  return(0);
[8]1090}
1091
1092
1093/*!
1094 * \ingroup file
1095 */
1096void
1097lib3ds_file_dump_meshes(Lib3dsFile *file)
1098{
[151]1099  Lib3dsMesh *p;
[8]1100
[151]1101  ASSERT(file);
1102  for (p=file->meshes; p!=0; p=p->next) {
1103    lib3ds_mesh_dump(p);
1104  }
[8]1105}
1106
1107
1108static void
1109dump_instances(Lib3dsNode *node, const char* parent)
1110{
[151]1111  Lib3dsNode *p;
1112  char name[255];
[8]1113
[151]1114  ASSERT(node);
1115  ASSERT(parent);
1116  strcpy(name, parent);
1117  strcat(name, ".");
1118  strcat(name, node->name);
1119  if (node->type==LIB3DS_OBJECT_NODE) {
1120    printf("  %s : %s\n", name, node->data.object.instance);
1121  }
1122  for (p=node->childs; p!=0; p=p->next) {
1123    dump_instances(p, parent);
1124  }
[8]1125}
1126
1127
1128/*!
1129 * \ingroup file
1130 */
1131void
1132lib3ds_file_dump_instances(Lib3dsFile *file)
1133{
[151]1134  Lib3dsNode *p;
[8]1135
[151]1136  ASSERT(file);
1137  for (p=file->nodes; p!=0; p=p->next) {
1138    dump_instances(p,"");
1139  }
[8]1140}
1141
1142
1143/*!
1144 * \ingroup file
1145 */
1146void
1147lib3ds_file_insert_camera(Lib3dsFile *file, Lib3dsCamera *camera)
1148{
[151]1149  Lib3dsCamera *p,*q;
1150 
1151  ASSERT(file);
1152  ASSERT(camera);
1153  ASSERT(!camera->next);
[8]1154
[151]1155  q=0;
1156  for (p=file->cameras; p!=0; p=p->next) {
1157    if (strcmp(camera->name, p->name)<0) {
1158      break;
[8]1159    }
[151]1160    q=p;
1161  }
1162  if (!q) {
1163    camera->next=file->cameras;
1164    file->cameras=camera;
1165  }
1166  else {
1167    camera->next=q->next;
1168    q->next=camera;
1169  }
[8]1170}
1171
1172
1173/*!
1174 * \ingroup file
1175 */
1176void
1177lib3ds_file_remove_camera(Lib3dsFile *file, Lib3dsCamera *camera)
1178{
[151]1179  Lib3dsCamera *p,*q;
[8]1180
[151]1181  ASSERT(file);
1182  ASSERT(camera);
1183  ASSERT(file->cameras);
1184  for (p=0,q=file->cameras; q; p=q,q=q->next) {
1185    if (q==camera) {
1186      break;
[8]1187    }
[151]1188  }
1189  if (!q) {
1190    ASSERT(LIB3DS_FALSE);
1191    return;
1192  }
1193  if (!p) {
1194    file->cameras=camera->next;
1195  }
1196  else {
1197    p->next=q->next;
1198  }
1199  camera->next=0;
[8]1200}
1201
1202
1203/*!
1204 * \ingroup file
1205 */
1206Lib3dsCamera*
1207lib3ds_file_camera_by_name(Lib3dsFile *file, const char *name)
1208{
[151]1209  Lib3dsCamera *p;
[8]1210
[151]1211  ASSERT(file);
1212  for (p=file->cameras; p!=0; p=p->next) {
1213    if (strcmp(p->name,name)==0) {
1214      return(p);
[8]1215    }
[151]1216  }
1217  return(0);
[8]1218}
1219
1220
1221/*!
1222 * \ingroup file
1223 */
1224void
1225lib3ds_file_dump_cameras(Lib3dsFile *file)
1226{
[151]1227  Lib3dsCamera *p;
[8]1228
[151]1229  ASSERT(file);
1230  for (p=file->cameras; p!=0; p=p->next) {
1231    lib3ds_camera_dump(p);
1232  }
[8]1233}
1234
1235
1236/*!
1237 * \ingroup file
1238 */
1239void
1240lib3ds_file_insert_light(Lib3dsFile *file, Lib3dsLight *light)
1241{
[151]1242  Lib3dsLight *p,*q;
1243 
1244  ASSERT(file);
1245  ASSERT(light);
1246  ASSERT(!light->next);
[8]1247
[151]1248  q=0;
1249  for (p=file->lights; p!=0; p=p->next) {
1250    if (strcmp(light->name, p->name)<0) {
1251      break;
[8]1252    }
[151]1253    q=p;
1254  }
1255  if (!q) {
1256    light->next=file->lights;
1257    file->lights=light;
1258  }
1259  else {
1260    light->next=q->next;
1261    q->next=light;
1262  }
[8]1263}
1264
1265
1266/*!
1267 * \ingroup file
1268 */
1269void
1270lib3ds_file_remove_light(Lib3dsFile *file, Lib3dsLight *light)
1271{
[151]1272  Lib3dsLight *p,*q;
[8]1273
[151]1274  ASSERT(file);
1275  ASSERT(light);
1276  ASSERT(file->lights);
1277  for (p=0,q=file->lights; q; p=q,q=q->next) {
1278    if (q==light) {
1279      break;
[8]1280    }
[151]1281  }
1282  if (!q) {
1283    ASSERT(LIB3DS_FALSE);
1284    return;
1285  }
1286  if (!p) {
1287    file->lights=light->next;
1288  }
1289  else {
1290    p->next=q->next;
1291  }
1292  light->next=0;
[8]1293}
1294
1295
1296/*!
1297 * \ingroup file
1298 */
1299Lib3dsLight*
1300lib3ds_file_light_by_name(Lib3dsFile *file, const char *name)
1301{
[151]1302  Lib3dsLight *p;
[8]1303
[151]1304  ASSERT(file);
1305  for (p=file->lights; p!=0; p=p->next) {
1306    if (strcmp(p->name,name)==0) {
1307      return(p);
[8]1308    }
[151]1309  }
1310  return(0);
[8]1311}
1312
1313
1314/*!
1315 * \ingroup file
1316 */
1317void
1318lib3ds_file_dump_lights(Lib3dsFile *file)
1319{
[151]1320  Lib3dsLight *p;
[8]1321
[151]1322  ASSERT(file);
1323  for (p=file->lights; p!=0; p=p->next) {
1324    lib3ds_light_dump(p);
1325  }
[8]1326}
1327
1328
1329/*!
1330 * \ingroup file
1331 */
[151]1332void
1333lib3ds_file_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
1334{
1335  Lib3dsBool init=LIB3DS_FALSE;
1336
1337  {
1338    Lib3dsVector lmin, lmax;
1339    Lib3dsMesh *p=file->meshes;
1340
1341    if (!init && p) {
1342      init = LIB3DS_TRUE;
1343      lib3ds_mesh_bounding_box(p, min, max);
1344      p = p->next; 
1345    }
1346    while (p) {
1347      lib3ds_mesh_bounding_box(p, lmin, lmax);
1348      lib3ds_vector_min(min, lmin);
1349      lib3ds_vector_max(max, lmax);
1350      p=p->next;
1351    }
1352  }
1353  {
1354    Lib3dsCamera *p=file->cameras;
1355    if (!init && p) {
1356      init = LIB3DS_TRUE;
1357      lib3ds_vector_copy(min, p->position);
1358      lib3ds_vector_copy(max, p->position);
1359    }
1360
1361    while (p) {
1362      lib3ds_vector_min(min, p->position);
1363      lib3ds_vector_max(max, p->position);
1364      lib3ds_vector_min(min, p->target);
1365      lib3ds_vector_max(max, p->target);
1366      p=p->next;
1367    }
1368  }
1369  {
1370    Lib3dsLight *p=file->lights;
1371    if (!init && p) {
1372      init = LIB3DS_TRUE;
1373      lib3ds_vector_copy(min, p->position);
1374      lib3ds_vector_copy(max, p->position);
1375    }
1376
1377    while (p) {
1378      lib3ds_vector_min(min, p->position);
1379      lib3ds_vector_max(max, p->position);
1380      if (p->spot_light) {
1381        lib3ds_vector_min(min, p->spot);
1382        lib3ds_vector_max(max, p->spot);
1383      }
1384      p=p->next;
1385    }
1386  }
1387
1388
1389
1390/*!
1391 * \ingroup file
1392 */
[8]1393Lib3dsNode*
1394lib3ds_file_node_by_name(Lib3dsFile *file, const char* name, Lib3dsNodeTypes type)
1395{
[151]1396  Lib3dsNode *p,*q;
[8]1397
[151]1398  ASSERT(file);
1399  for (p=file->nodes; p!=0; p=p->next) {
1400    if ((p->type==type) && (strcmp(p->name, name)==0)) {
1401      return(p);
[8]1402    }
[151]1403    q=lib3ds_node_by_name(p, name, type);
1404    if (q) {
1405      return(q);
1406    }
1407  }
1408  return(0);
[8]1409}
1410
1411
1412/*!
1413 * \ingroup file
1414 */
1415Lib3dsNode*
[151]1416lib3ds_file_node_by_id(Lib3dsFile *file, Lib3dsWord node_id)
[8]1417{
[151]1418  Lib3dsNode *p,*q;
[8]1419
[151]1420  ASSERT(file);
1421  for (p=file->nodes; p!=0; p=p->next) {
1422    if (p->node_id==node_id) {
1423      return(p);
[8]1424    }
[151]1425    q=lib3ds_node_by_id(p, node_id);
1426    if (q) {
1427      return(q);
1428    }
1429  }
1430  return(0);
[8]1431}
1432
1433
1434/*!
1435 * \ingroup file
1436 */
1437void
1438lib3ds_file_insert_node(Lib3dsFile *file, Lib3dsNode *node)
1439{
[151]1440  Lib3dsNode *parent,*p,*n;
1441 
1442  ASSERT(node);
1443  ASSERT(!node->next);
1444  ASSERT(!node->parent);
[8]1445
[151]1446  parent=0;
1447  if (node->parent_id!=LIB3DS_NO_PARENT) {
1448    parent=lib3ds_file_node_by_id(file, node->parent_id);
1449  }
1450  node->parent=parent;
1451 
1452  if (!parent) {
1453    for (p=0,n=file->nodes; n!=0; p=n,n=n->next) {
1454      if (strcmp(n->name, node->name)>0) {
1455        break;
1456      }
[8]1457    }
[151]1458    if (!p) {
1459      node->next=file->nodes;
1460      file->nodes=node;
[8]1461    }
[151]1462    else {
1463      node->next=p->next;
1464      p->next=node;
[8]1465    }
[151]1466  }
1467  else {
1468    for (p=0,n=parent->childs; n!=0; p=n,n=n->next) {
1469      if (strcmp(n->name, node->name)>0) {
1470        break;
1471      }
1472    }
1473    if (!p) {
1474      node->next=parent->childs;
1475      parent->childs=node;
1476    }
1477    else {
1478      node->next=p->next;
1479      p->next=node;
1480    }
1481  }
[8]1482
[151]1483  if (node->node_id!=LIB3DS_NO_PARENT) {
1484    for (n=file->nodes; n!=0; n=p) {
1485      p=n->next;
1486      if (n->parent_id==node->node_id) {
1487        lib3ds_file_remove_node(file, n);
1488        lib3ds_file_insert_node(file, n);
1489      }
[8]1490    }
[151]1491  }
[8]1492}
1493
1494
1495/*!
1496 * \ingroup file
1497 */
1498Lib3dsBool
1499lib3ds_file_remove_node(Lib3dsFile *file, Lib3dsNode *node)
1500{
[151]1501  Lib3dsNode *p,*n;
[8]1502
[151]1503  if (node->parent) {
1504    for (p=0,n=node->parent->childs; n; p=n,n=n->next) {
1505      if (n==node) {
1506        break;
1507      }
[8]1508    }
[151]1509    if (!n) {
1510      return(LIB3DS_FALSE);
[8]1511    }
[151]1512   
1513    if (!p) {
1514      node->parent->childs=n->next;
1515    }
1516    else {
1517      p->next=n->next;
1518    }
1519  }
1520  else {
1521    for (p=0,n=file->nodes; n; p=n,n=n->next) {
1522      if (n==node) {
1523        break;
1524      }
1525    }
1526    if (!n) {
1527      return(LIB3DS_FALSE);
1528    }
1529   
1530    if (!p) {
1531      file->nodes=n->next;
1532    }
1533    else {
1534      p->next=n->next;
1535    }
1536  }
1537  return(LIB3DS_TRUE);
[8]1538}
1539
1540
1541/*!
1542 * \ingroup file
1543 */
1544void
1545lib3ds_file_dump_nodes(Lib3dsFile *file)
1546{
[151]1547  Lib3dsNode *p;
[8]1548
[151]1549  ASSERT(file);
1550  for (p=file->nodes; p!=0; p=p->next) {
1551    lib3ds_node_dump(p,1);
1552  }
[8]1553}
1554
1555
1556/*!
1557
1558\typedef Lib3dsFile
1559  \ingroup file
1560  \sa _Lib3dsFile
1561
1562*/
Note: See TracBrowser for help on using the browser.