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