Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/lwoegg/lwoToEggConverter.cxx

Go to the documentation of this file.
00001 // Filename: lwoToEggConverter.cxx
00002 // Created by:  drose (25Apr01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "lwoToEggConverter.h"
00020 #include "cLwoLayer.h"
00021 #include "cLwoClip.h"
00022 #include "cLwoPoints.h"
00023 #include "cLwoPolygons.h"
00024 #include "cLwoSurface.h"
00025 
00026 #include "eggData.h"
00027 #include "lwoHeader.h"
00028 #include "lwoLayer.h"
00029 #include "lwoClip.h"
00030 #include "lwoPoints.h"
00031 #include "lwoPolygons.h"
00032 #include "lwoVertexMap.h"
00033 #include "lwoDiscontinuousVertexMap.h"
00034 #include "lwoTags.h"
00035 #include "lwoPolygonTags.h"
00036 #include "lwoInputFile.h"
00037 #include "dcast.h"
00038 
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: LwoToEggConverter::Constructor
00042 //       Access: Public
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 LwoToEggConverter::
00046 LwoToEggConverter() {
00047   _generic_layer = (CLwoLayer *)NULL;
00048   _make_materials = true;
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: LwoToEggConverter::Copy Constructor
00053 //       Access: Public
00054 //  Description:
00055 ////////////////////////////////////////////////////////////////////
00056 LwoToEggConverter::
00057 LwoToEggConverter(const LwoToEggConverter &copy) :
00058   SomethingToEggConverter(copy)
00059 {
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: LwoToEggConverter::Destructor
00064 //       Access: Public, Virtual
00065 //  Description:
00066 ////////////////////////////////////////////////////////////////////
00067 LwoToEggConverter::
00068 ~LwoToEggConverter() {
00069   cleanup();
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: LwoToEggConverter::make_copy
00074 //       Access: Public, Virtual
00075 //  Description: Allocates and returns a new copy of the converter.
00076 ////////////////////////////////////////////////////////////////////
00077 SomethingToEggConverter *LwoToEggConverter::
00078 make_copy() {
00079   return new LwoToEggConverter(*this);
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: LwoToEggConverter::get_name
00084 //       Access: Public, Virtual
00085 //  Description: Returns the English name of the file type this
00086 //               converter supports.
00087 ////////////////////////////////////////////////////////////////////
00088 string LwoToEggConverter::
00089 get_name() const {
00090   return "Lightwave";
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: LwoToEggConverter::get_extension
00095 //       Access: Public, Virtual
00096 //  Description: Returns the common extension of the file type this
00097 //               converter supports.
00098 ////////////////////////////////////////////////////////////////////
00099 string LwoToEggConverter::
00100 get_extension() const {
00101   return "lwo";
00102 }
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: LwoToEggConverter::convert_file
00106 //       Access: Public, Virtual
00107 //  Description: Handles the reading of the input file and converting
00108 //               it to egg.  Returns true if successful, false
00109 //               otherwise.
00110 //
00111 //               This is designed to be as generic as possible,
00112 //               generally in support of run-time loading.
00113 //               Command-line converters may choose to use
00114 //               convert_lwo() instead, as it provides more control.
00115 ////////////////////////////////////////////////////////////////////
00116 bool LwoToEggConverter::
00117 convert_file(const Filename &filename) {
00118   LwoInputFile in;
00119 
00120   nout << "Reading " << filename << "\n";
00121   if (!in.open_read(filename)) {
00122     nout << "Unable to open " << filename << "\n";
00123     return false;
00124   }
00125 
00126   PT(IffChunk) chunk = in.get_chunk();
00127   if (chunk == (IffChunk *)NULL) {
00128     nout << "Unable to read " << filename << "\n";
00129     return false;
00130   }
00131 
00132   if (!chunk->is_of_type(LwoHeader::get_class_type())) {
00133     nout << "File " << filename << " is not a Lightwave Object file.\n";
00134     return false;
00135   }
00136 
00137   LwoHeader *header = DCAST(LwoHeader, chunk);
00138   if (!header->is_valid()) {
00139     nout << "File " << filename
00140          << " is not recognized as a Lightwave Object file.  "
00141          << "Perhaps the version is too recent.\n";
00142     return false;
00143   }
00144 
00145   return convert_lwo(header);
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: LwoToEggConverter::convert_lwo
00150 //       Access: Public
00151 //  Description: Fills up the egg_data structure according to the
00152 //               indicated lwo structure.
00153 ////////////////////////////////////////////////////////////////////
00154 bool LwoToEggConverter::
00155 convert_lwo(const LwoHeader *lwo_header) {
00156   if (_egg_data->get_coordinate_system() == CS_default) {
00157     _egg_data->set_coordinate_system(CS_yup_left);
00158   }
00159 
00160   _error = false;
00161   _lwo_header = lwo_header;
00162 
00163   collect_lwo();
00164   make_egg();
00165   connect_egg();
00166 
00167   _egg_data->remove_unused_vertices();
00168   cleanup();
00169 
00170   return !_error;
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: LwoToEggConverter::get_layer
00175 //       Access: Public
00176 //  Description: Returns a pointer to the layer with the given index
00177 //               number, or NULL if there is no such layer.
00178 ////////////////////////////////////////////////////////////////////
00179 CLwoLayer *LwoToEggConverter::
00180 get_layer(int number) const {
00181   if (number >= 0 && number < (int)_layers.size()) {
00182     return _layers[number];
00183   }
00184   return (CLwoLayer *)NULL;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: LwoToEggConverter::get_clip
00189 //       Access: Public
00190 //  Description: Returns a pointer to the clip with the given index
00191 //               number, or NULL if there is no such clip.
00192 ////////////////////////////////////////////////////////////////////
00193 CLwoClip *LwoToEggConverter::
00194 get_clip(int number) const {
00195   if (number >= 0 && number < (int)_clips.size()) {
00196     return _clips[number];
00197   }
00198   return (CLwoClip *)NULL;
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: LwoToEggConverter::get_surface
00203 //       Access: Public
00204 //  Description: Returns a pointer to the surface definition with the
00205 //               given name, or NULL if there is no such surface.
00206 ////////////////////////////////////////////////////////////////////
00207 CLwoSurface *LwoToEggConverter::
00208 get_surface(const string &name) const {
00209   Surfaces::const_iterator si;
00210   si = _surfaces.find(name);
00211   if (si != _surfaces.end()) {
00212     return (*si).second;
00213   }
00214   return (CLwoSurface *)NULL;
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: LwoToEggConverter::cleanup
00219 //       Access: Private
00220 //  Description: Frees all the internal data structures after we're
00221 //               done converting, and resets the converter to its
00222 //               initial state.
00223 ////////////////////////////////////////////////////////////////////
00224 void LwoToEggConverter::
00225 cleanup() {
00226   _lwo_header.clear();
00227 
00228   if (_generic_layer != (CLwoLayer *)NULL) {
00229     delete _generic_layer;
00230     _generic_layer = (CLwoLayer *)NULL;
00231   }
00232 
00233   Layers::iterator li;
00234   for (li = _layers.begin(); li != _layers.end(); ++li) {
00235     CLwoLayer *layer = (*li);
00236     if (layer != (CLwoLayer *)NULL) {
00237       delete layer;
00238     }
00239   }
00240   _layers.clear();
00241 
00242   Clips::iterator ci;
00243   for (ci = _clips.begin(); ci != _clips.end(); ++ci) {
00244     CLwoClip *clip = (*ci);
00245     if (clip != (CLwoClip *)NULL) {
00246       delete clip;
00247     }
00248   }
00249   _clips.clear();
00250 
00251   Points::iterator pi;
00252   for (pi = _points.begin(); pi != _points.end(); ++pi) {
00253     CLwoPoints *points = (*pi);
00254     delete points;
00255   }
00256   _points.clear();
00257 
00258   Polygons::iterator gi;
00259   for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
00260     CLwoPolygons *polygons = (*gi);
00261     delete polygons;
00262   }
00263   _polygons.clear();
00264 
00265   Surfaces::iterator si;
00266   for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
00267     CLwoSurface *surface = (*si).second;
00268     delete surface;
00269   }
00270   _surfaces.clear();
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: LwoToEggConverter::collect_lwo
00275 //       Access: Private
00276 //  Description: Walks through the chunks in the Lightwave data and
00277 //               creates wrapper objects for each relevant piece.
00278 ////////////////////////////////////////////////////////////////////
00279 void LwoToEggConverter::
00280 collect_lwo() {
00281   CLwoLayer *last_layer = (CLwoLayer *)NULL;
00282   CLwoPoints *last_points = (CLwoPoints *)NULL;
00283   CLwoPolygons *last_polygons = (CLwoPolygons *)NULL;
00284 
00285   const LwoTags *tags = (const LwoTags *)NULL;
00286 
00287   int num_chunks = _lwo_header->get_num_chunks();
00288   for (int i = 0; i < num_chunks; i++) {
00289     const IffChunk *chunk = _lwo_header->get_chunk(i);
00290 
00291     if (chunk->is_of_type(LwoLayer::get_class_type())) {
00292       const LwoLayer *lwo_layer = DCAST(LwoLayer, chunk);
00293       CLwoLayer *layer = new CLwoLayer(this, lwo_layer);
00294       int number = layer->get_number();
00295       slot_layer(number);
00296 
00297       if (_layers[number] != (CLwoLayer *)NULL) {
00298         nout << "Warning: multiple layers with number " << number << "\n";
00299       }
00300       _layers[number] = layer;
00301       last_layer = layer;
00302       last_points = (CLwoPoints *)NULL;
00303       last_polygons = (CLwoPolygons *)NULL;
00304 
00305     } else if (chunk->is_of_type(LwoClip::get_class_type())) {
00306       const LwoClip *lwo_clip = DCAST(LwoClip, chunk);
00307       CLwoClip *clip = new CLwoClip(this, lwo_clip);
00308 
00309       int index = clip->get_index();
00310       slot_clip(index);
00311 
00312       if (_clips[index] != (CLwoClip *)NULL) {
00313         nout << "Warning: multiple clips with index " << index << "\n";
00314       }
00315       _clips[index] = clip;
00316 
00317     } else if (chunk->is_of_type(LwoPoints::get_class_type())) {
00318       if (last_layer == (CLwoLayer *)NULL) {
00319         last_layer = make_generic_layer();
00320       }
00321 
00322       const LwoPoints *lwo_points = DCAST(LwoPoints, chunk);
00323       CLwoPoints *points = new CLwoPoints(this, lwo_points, last_layer);
00324       _points.push_back(points);
00325       last_points = points;
00326 
00327     } else if (chunk->is_of_type(LwoVertexMap::get_class_type())) {
00328       if (last_points == (CLwoPoints *)NULL) {
00329         nout << "Vertex map chunk encountered without a preceding points chunk.\n";
00330       } else {
00331         const LwoVertexMap *lwo_vmap = DCAST(LwoVertexMap, chunk);
00332         last_points->add_vmap(lwo_vmap);
00333       }
00334 
00335     } else if (chunk->is_of_type(LwoDiscontinuousVertexMap::get_class_type())) {
00336       if (last_polygons == (CLwoPolygons *)NULL) {
00337         nout << "Discontinous vertex map chunk encountered without a preceding polygons chunk.\n";
00338       } else {
00339         const LwoDiscontinuousVertexMap *lwo_vmad = DCAST(LwoDiscontinuousVertexMap, chunk);
00340         last_polygons->add_vmad(lwo_vmad);
00341       }
00342 
00343     } else if (chunk->is_of_type(LwoTags::get_class_type())) {
00344       tags = DCAST(LwoTags, chunk);
00345 
00346     } else if (chunk->is_of_type(LwoPolygons::get_class_type())) {
00347       if (last_points == (CLwoPoints *)NULL) {
00348         nout << "Polygon chunk encountered without a preceding points chunk.\n";
00349       } else {
00350         const LwoPolygons *lwo_polygons = DCAST(LwoPolygons, chunk);
00351         CLwoPolygons *polygons =
00352           new CLwoPolygons(this, lwo_polygons, last_points);
00353         _polygons.push_back(polygons);
00354         last_polygons = polygons;
00355       }
00356 
00357     } else if (chunk->is_of_type(LwoPolygonTags::get_class_type())) {
00358       if (last_polygons == (CLwoPolygons *)NULL) {
00359         nout << "Polygon tags chunk encountered without a preceding polygons chunk.\n";
00360       } else if (tags == (LwoTags *)NULL) {
00361         nout << "Polygon tags chunk encountered without a preceding tags chunk.\n";
00362       } else {
00363         const LwoPolygonTags *lwo_ptags = DCAST(LwoPolygonTags, chunk);
00364         last_polygons->add_ptags(lwo_ptags, tags);
00365       }
00366 
00367     } else if (chunk->is_of_type(LwoSurface::get_class_type())) {
00368       if (last_layer == (CLwoLayer *)NULL) {
00369         last_layer = make_generic_layer();
00370       }
00371 
00372       const LwoSurface *lwo_surface = DCAST(LwoSurface, chunk);
00373       CLwoSurface *surface = new CLwoSurface(this, lwo_surface);
00374 
00375       bool inserted = _surfaces.insert(Surfaces::value_type(surface->get_name(), surface)).second;
00376       if (!inserted) {
00377         nout << "Multiple surface definitions named " << surface->get_name() << "\n";
00378         delete surface;
00379       }
00380     }
00381   }
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: LwoToEggConverter::make_egg
00386 //       Access: Private
00387 //  Description: Makes egg structures for all of the conversion
00388 //               wrapper objects.
00389 ////////////////////////////////////////////////////////////////////
00390 void LwoToEggConverter::
00391 make_egg() {
00392   if (_generic_layer != (CLwoLayer *)NULL) {
00393     _generic_layer->make_egg();
00394   }
00395 
00396   Layers::iterator li;
00397   for (li = _layers.begin(); li != _layers.end(); ++li) {
00398     CLwoLayer *layer = (*li);
00399     if (layer != (CLwoLayer *)NULL) {
00400       layer->make_egg();
00401     }
00402   }
00403 
00404   Points::iterator pi;
00405   for (pi = _points.begin(); pi != _points.end(); ++pi) {
00406     CLwoPoints *points = (*pi);
00407     points->make_egg();
00408   }
00409 
00410   Polygons::iterator gi;
00411   for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
00412     CLwoPolygons *polygons = (*gi);
00413     polygons->make_egg();
00414   }
00415 }
00416 
00417 ////////////////////////////////////////////////////////////////////
00418 //     Function: LwoToEggConverter::connect_egg
00419 //       Access: Private
00420 //  Description: Connects together all of the egg structures.
00421 ////////////////////////////////////////////////////////////////////
00422 void LwoToEggConverter::
00423 connect_egg() {
00424   if (_generic_layer != (CLwoLayer *)NULL) {
00425     _generic_layer->connect_egg();
00426   }
00427 
00428   Layers::iterator li;
00429   for (li = _layers.begin(); li != _layers.end(); ++li) {
00430     CLwoLayer *layer = (*li);
00431     if (layer != (CLwoLayer *)NULL) {
00432       layer->connect_egg();
00433     }
00434   }
00435 
00436   Points::iterator pi;
00437   for (pi = _points.begin(); pi != _points.end(); ++pi) {
00438     CLwoPoints *points = (*pi);
00439     points->connect_egg();
00440   }
00441 
00442   Polygons::iterator gi;
00443   for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
00444     CLwoPolygons *polygons = (*gi);
00445     polygons->connect_egg();
00446   }
00447 }
00448 
00449 ////////////////////////////////////////////////////////////////////
00450 //     Function: LwoToEggConverter::slot_layer
00451 //       Access: Private
00452 //  Description: Ensures that there is space in the _layers array to
00453 //               store an element at position number.
00454 ////////////////////////////////////////////////////////////////////
00455 void LwoToEggConverter::
00456 slot_layer(int number) {
00457   nassertv(number - (int)_layers.size() < 1000);
00458   while (number >= (int)_layers.size()) {
00459     _layers.push_back((CLwoLayer *)NULL);
00460   }
00461   nassertv(number >= 0 && number < (int)_layers.size());
00462 }
00463 
00464 ////////////////////////////////////////////////////////////////////
00465 //     Function: LwoToEggConverter::slot_clip
00466 //       Access: Private
00467 //  Description: Ensures that there is space in the _clips array to
00468 //               store an element at position number.
00469 ////////////////////////////////////////////////////////////////////
00470 void LwoToEggConverter::
00471 slot_clip(int number) {
00472   nassertv(number - (int)_clips.size() < 1000);
00473   while (number >= (int)_clips.size()) {
00474     _clips.push_back((CLwoClip *)NULL);
00475   }
00476   nassertv(number >= 0 && number < (int)_clips.size());
00477 }
00478 
00479 ////////////////////////////////////////////////////////////////////
00480 //     Function: LwoToEggConverter::make_generic_layer
00481 //       Access: Private
00482 //  Description: If a geometry definition is encountered in the
00483 //               Lightwave file before a layer definition, we should
00484 //               make a generic layer to hold the geometry.  This
00485 //               makes and returns a single layer for this purpose.
00486 //               It should not be called twice.
00487 ////////////////////////////////////////////////////////////////////
00488 CLwoLayer *LwoToEggConverter::
00489 make_generic_layer() {
00490   nassertr(_generic_layer == (CLwoLayer *)NULL, _generic_layer);
00491 
00492   PT(LwoLayer) layer = new LwoLayer;
00493   layer->make_generic();
00494 
00495   _generic_layer = new CLwoLayer(this, layer);
00496   return _generic_layer;
00497 }

Generated on Fri May 2 03:21:14 2003 for Panda-Tool by doxygen1.3