Panda3D
Loading...
Searching...
No Matches
lwoToEggConverter.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file lwoToEggConverter.cxx
10 * @author drose
11 * @date 2001-04-25
12 */
13
14#include "lwoToEggConverter.h"
15#include "cLwoLayer.h"
16#include "cLwoClip.h"
17#include "cLwoPoints.h"
18#include "cLwoPolygons.h"
19#include "cLwoSurface.h"
20
21#include "eggData.h"
22#include "lwoHeader.h"
23#include "lwoLayer.h"
24#include "lwoClip.h"
25#include "lwoPoints.h"
26#include "lwoPolygons.h"
27#include "lwoVertexMap.h"
29#include "lwoTags.h"
30#include "lwoPolygonTags.h"
31#include "lwoInputFile.h"
32#include "dcast.h"
33
34
35/**
36 *
37 */
38LwoToEggConverter::
39LwoToEggConverter() {
40 _generic_layer = nullptr;
41 _make_materials = true;
42}
43
44/**
45 *
46 */
47LwoToEggConverter::
48LwoToEggConverter(const LwoToEggConverter &copy) :
50{
51}
52
53/**
54 *
55 */
56LwoToEggConverter::
57~LwoToEggConverter() {
58 cleanup();
59}
60
61/**
62 * Allocates and returns a new copy of the converter.
63 */
68
69/**
70 * Returns the English name of the file type this converter supports.
71 */
73get_name() const {
74 return "Lightwave";
75}
76
77/**
78 * Returns the common extension of the file type this converter supports.
79 */
81get_extension() const {
82 return "lwo";
83}
84
85/**
86 * Returns true if this file type can transparently load compressed files
87 * (with a .pz extension), false otherwise.
88 */
90supports_compressed() const {
91 return true;
92}
93
94/**
95 * Handles the reading of the input file and converting it to egg. Returns
96 * true if successful, false otherwise.
97 *
98 * This is designed to be as generic as possible, generally in support of run-
99 * time loading. Command-line converters may choose to use convert_lwo()
100 * instead, as it provides more control.
101 */
103convert_file(const Filename &filename) {
104 LwoInputFile in;
105
106 nout << "Reading " << filename << "\n";
107 if (!in.open_read(filename)) {
108 nout << "Unable to open " << filename << "\n";
109 return false;
110 }
111
112 PT(IffChunk) chunk = in.get_chunk();
113 if (chunk == nullptr) {
114 nout << "Unable to read " << filename << "\n";
115 return false;
116 }
117
118 if (!chunk->is_of_type(LwoHeader::get_class_type())) {
119 nout << "File " << filename << " is not a Lightwave Object file.\n";
120 return false;
121 }
122
123 LwoHeader *header = DCAST(LwoHeader, chunk);
124 if (!header->is_valid()) {
125 nout << "File " << filename
126 << " is not recognized as a Lightwave Object file. "
127 << "Perhaps the version is too recent.\n";
128 return false;
129 }
130
131 return convert_lwo(header);
132}
133
134/**
135 * Fills up the egg_data structure according to the indicated lwo structure.
136 */
138convert_lwo(const LwoHeader *lwo_header) {
139 if (_egg_data->get_coordinate_system() == CS_default) {
140 _egg_data->set_coordinate_system(CS_yup_left);
141 }
142
143 _error = false;
144 _lwo_header = lwo_header;
145
146 collect_lwo();
147 make_egg();
148 connect_egg();
149
150 _egg_data->remove_unused_vertices(true);
151 cleanup();
152
153 return !had_error();
154}
155
156/**
157 * Returns a pointer to the layer with the given index number, or NULL if
158 * there is no such layer.
159 */
161get_layer(int number) const {
162 if (number >= 0 && number < (int)_layers.size()) {
163 return _layers[number];
164 }
165 return nullptr;
166}
167
168/**
169 * Returns a pointer to the clip with the given index number, or NULL if there
170 * is no such clip.
171 */
173get_clip(int number) const {
174 if (number >= 0 && number < (int)_clips.size()) {
175 return _clips[number];
176 }
177 return nullptr;
178}
179
180/**
181 * Returns a pointer to the surface definition with the given name, or NULL if
182 * there is no such surface.
183 */
185get_surface(const std::string &name) const {
186 Surfaces::const_iterator si;
187 si = _surfaces.find(name);
188 if (si != _surfaces.end()) {
189 return (*si).second;
190 }
191 return nullptr;
192}
193
194/**
195 * Frees all the internal data structures after we're done converting, and
196 * resets the converter to its initial state.
197 */
198void LwoToEggConverter::
199cleanup() {
200 _lwo_header.clear();
201
202 if (_generic_layer != nullptr) {
203 delete _generic_layer;
204 _generic_layer = nullptr;
205 }
206
207 Layers::iterator li;
208 for (li = _layers.begin(); li != _layers.end(); ++li) {
209 CLwoLayer *layer = (*li);
210 if (layer != nullptr) {
211 delete layer;
212 }
213 }
214 _layers.clear();
215
216 Clips::iterator ci;
217 for (ci = _clips.begin(); ci != _clips.end(); ++ci) {
218 CLwoClip *clip = (*ci);
219 if (clip != nullptr) {
220 delete clip;
221 }
222 }
223 _clips.clear();
224
225 Points::iterator pi;
226 for (pi = _points.begin(); pi != _points.end(); ++pi) {
227 CLwoPoints *points = (*pi);
228 delete points;
229 }
230 _points.clear();
231
232 Polygons::iterator gi;
233 for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
234 CLwoPolygons *polygons = (*gi);
235 delete polygons;
236 }
237 _polygons.clear();
238
239 Surfaces::iterator si;
240 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
241 CLwoSurface *surface = (*si).second;
242 delete surface;
243 }
244 _surfaces.clear();
245}
246
247/**
248 * Walks through the chunks in the Lightwave data and creates wrapper objects
249 * for each relevant piece.
250 */
251void LwoToEggConverter::
252collect_lwo() {
253 CLwoLayer *last_layer = nullptr;
254 CLwoPoints *last_points = nullptr;
255 CLwoPolygons *last_polygons = nullptr;
256
257 const LwoTags *tags = nullptr;
258
259 int num_chunks = _lwo_header->get_num_chunks();
260 for (int i = 0; i < num_chunks; i++) {
261 const IffChunk *chunk = _lwo_header->get_chunk(i);
262
263 if (chunk->is_of_type(LwoLayer::get_class_type())) {
264 const LwoLayer *lwo_layer = DCAST(LwoLayer, chunk);
265 CLwoLayer *layer = new CLwoLayer(this, lwo_layer);
266 int number = layer->get_number();
267 slot_layer(number);
268
269 if (_layers[number] != nullptr) {
270 nout << "Warning: multiple layers with number " << number << "\n";
271 }
272 _layers[number] = layer;
273 last_layer = layer;
274 last_points = nullptr;
275 last_polygons = nullptr;
276
277 } else if (chunk->is_of_type(LwoClip::get_class_type())) {
278 const LwoClip *lwo_clip = DCAST(LwoClip, chunk);
279 CLwoClip *clip = new CLwoClip(this, lwo_clip);
280
281 int index = clip->get_index();
282 slot_clip(index);
283
284 if (_clips[index] != nullptr) {
285 nout << "Warning: multiple clips with index " << index << "\n";
286 }
287 _clips[index] = clip;
288
289 } else if (chunk->is_of_type(LwoPoints::get_class_type())) {
290 if (last_layer == nullptr) {
291 last_layer = make_generic_layer();
292 }
293
294 const LwoPoints *lwo_points = DCAST(LwoPoints, chunk);
295 CLwoPoints *points = new CLwoPoints(this, lwo_points, last_layer);
296 _points.push_back(points);
297 last_points = points;
298
299 } else if (chunk->is_of_type(LwoVertexMap::get_class_type())) {
300 if (last_points == nullptr) {
301 nout << "Vertex map chunk encountered without a preceding points chunk.\n";
302 } else {
303 const LwoVertexMap *lwo_vmap = DCAST(LwoVertexMap, chunk);
304 last_points->add_vmap(lwo_vmap);
305 }
306
307 } else if (chunk->is_of_type(LwoDiscontinuousVertexMap::get_class_type())) {
308 if (last_polygons == nullptr) {
309 nout << "Discontinous vertex map chunk encountered without a preceding polygons chunk.\n";
310 } else {
311 const LwoDiscontinuousVertexMap *lwo_vmad = DCAST(LwoDiscontinuousVertexMap, chunk);
312 last_polygons->add_vmad(lwo_vmad);
313 }
314
315 } else if (chunk->is_of_type(LwoTags::get_class_type())) {
316 tags = DCAST(LwoTags, chunk);
317
318 } else if (chunk->is_of_type(LwoPolygons::get_class_type())) {
319 if (last_points == nullptr) {
320 nout << "Polygon chunk encountered without a preceding points chunk.\n";
321 } else {
322 const LwoPolygons *lwo_polygons = DCAST(LwoPolygons, chunk);
323 CLwoPolygons *polygons =
324 new CLwoPolygons(this, lwo_polygons, last_points);
325 _polygons.push_back(polygons);
326 last_polygons = polygons;
327 }
328
329 } else if (chunk->is_of_type(LwoPolygonTags::get_class_type())) {
330 if (last_polygons == nullptr) {
331 nout << "Polygon tags chunk encountered without a preceding polygons chunk.\n";
332 } else if (tags == nullptr) {
333 nout << "Polygon tags chunk encountered without a preceding tags chunk.\n";
334 } else {
335 const LwoPolygonTags *lwo_ptags = DCAST(LwoPolygonTags, chunk);
336 last_polygons->add_ptags(lwo_ptags, tags);
337 }
338
339 } else if (chunk->is_of_type(LwoSurface::get_class_type())) {
340 if (last_layer == nullptr) {
341 last_layer = make_generic_layer();
342 }
343
344 const LwoSurface *lwo_surface = DCAST(LwoSurface, chunk);
345 CLwoSurface *surface = new CLwoSurface(this, lwo_surface);
346
347 bool inserted = _surfaces.insert(Surfaces::value_type(surface->get_name(), surface)).second;
348 if (!inserted) {
349 nout << "Multiple surface definitions named " << surface->get_name() << "\n";
350 delete surface;
351 }
352 }
353 }
354}
355
356/**
357 * Makes egg structures for all of the conversion wrapper objects.
358 */
359void LwoToEggConverter::
360make_egg() {
361 if (_generic_layer != nullptr) {
362 _generic_layer->make_egg();
363 }
364
365 Layers::iterator li;
366 for (li = _layers.begin(); li != _layers.end(); ++li) {
367 CLwoLayer *layer = (*li);
368 if (layer != nullptr) {
369 layer->make_egg();
370 }
371 }
372
373 Points::iterator pi;
374 for (pi = _points.begin(); pi != _points.end(); ++pi) {
375 CLwoPoints *points = (*pi);
376 points->make_egg();
377 }
378
379 Polygons::iterator gi;
380 for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
381 CLwoPolygons *polygons = (*gi);
382 polygons->make_egg();
383 }
384}
385
386/**
387 * Connects together all of the egg structures.
388 */
389void LwoToEggConverter::
390connect_egg() {
391 if (_generic_layer != nullptr) {
392 _generic_layer->connect_egg();
393 }
394
395 Layers::iterator li;
396 for (li = _layers.begin(); li != _layers.end(); ++li) {
397 CLwoLayer *layer = (*li);
398 if (layer != nullptr) {
399 layer->connect_egg();
400 }
401 }
402
403 Points::iterator pi;
404 for (pi = _points.begin(); pi != _points.end(); ++pi) {
405 CLwoPoints *points = (*pi);
406 points->connect_egg();
407 }
408
409 Polygons::iterator gi;
410 for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) {
411 CLwoPolygons *polygons = (*gi);
412 polygons->connect_egg();
413 }
414}
415
416/**
417 * Ensures that there is space in the _layers array to store an element at
418 * position number.
419 */
420void LwoToEggConverter::
421slot_layer(int number) {
422 nassertv(number - (int)_layers.size() < 1000);
423 while (number >= (int)_layers.size()) {
424 _layers.push_back(nullptr);
425 }
426 nassertv(number >= 0 && number < (int)_layers.size());
427}
428
429/**
430 * Ensures that there is space in the _clips array to store an element at
431 * position number.
432 */
433void LwoToEggConverter::
434slot_clip(int number) {
435 nassertv(number - (int)_clips.size() < 1000);
436 while (number >= (int)_clips.size()) {
437 _clips.push_back(nullptr);
438 }
439 nassertv(number >= 0 && number < (int)_clips.size());
440}
441
442/**
443 * If a geometry definition is encountered in the Lightwave file before a
444 * layer definition, we should make a generic layer to hold the geometry.
445 * This makes and returns a single layer for this purpose. It should not be
446 * called twice.
447 */
448CLwoLayer *LwoToEggConverter::
449make_generic_layer() {
450 nassertr(_generic_layer == nullptr, _generic_layer);
451
452 PT(LwoLayer) layer = new LwoLayer;
453 layer->make_generic();
454
455 _generic_layer = new CLwoLayer(this, layer);
456 return _generic_layer;
457}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class is a wrapper around LwoClip and stores additional information useful during the conversion...
Definition cLwoClip.h:29
int get_index() const
Returns the index number of this clip.
Definition cLwoClip.I:19
This class is a wrapper around LwoLayer and stores additional information useful during the conversio...
Definition cLwoLayer.h:29
void make_egg()
Creates the egg structures associated with this Lightwave object.
Definition cLwoLayer.cxx:24
int get_number() const
Returns the index number associated with this particular layer.
Definition cLwoLayer.I:29
void connect_egg()
Connects all the egg structures together.
Definition cLwoLayer.cxx:39
This class is a wrapper around LwoPoints and stores additional information useful during the conversi...
Definition cLwoPoints.h:33
void make_egg()
Creates the egg structures associated with this Lightwave object.
void add_vmap(const LwoVertexMap *lwo_vmap)
Associates the indicated VertexMap with the points set.
void connect_egg()
Connects all the egg structures together.
This class is a wrapper around LwoPolygons and stores additional information useful during the conver...
void make_egg()
Creates the egg structures associated with this Lightwave object.
void connect_egg()
Connects all the egg structures together.
void add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad)
Associates the indicated DiscontinousVertexMap with the polygons.
void add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags)
Associates the indicated PolygonTags and Tags with the polygons in this chunk.
This class is a wrapper around LwoSurface and stores additional information useful during the convers...
Definition cLwoSurface.h:39
const std::string & get_name() const
Returns the name of the surface.
Definition cLwoSurface.I:19
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
The basic kind of record in an EA "IFF" file, which the LightWave object file is based on.
Definition iffChunk.h:30
bool open_read(Filename filename)
Attempts to open the indicated filename for reading.
A single image file, or a numbered sequence of images (e.g.
Definition lwoClip.h:25
A mapping of floating-point values per integer index.
The first chunk in a Lightwave Object file.
Definition lwoHeader.h:24
bool is_valid() const
Returns true if the header represents a valid and recognized Lightwave header, false otherwise.
Definition lwoHeader.I:19
A specialization of IffInputFile to handle reading a Lightwave Object file.
Signals the start of a new layer.
Definition lwoLayer.h:28
An array of points that will be referenced by later chunks.
Definition lwoPoints.h:26
An association of polygons defined in the most recent LwoPolygons chunk to tag ids defined in the mos...
An array of polygons that will be referenced by later chunks.
Definition lwoPolygons.h:29
Describes the shading attributes of a surface.
Definition lwoSurface.h:25
An array of tag strings that will be referenced by later chunks.
Definition lwoTags.h:31
This class supervises the construction of an EggData structure from the data represented by the LwoHe...
CLwoSurface * get_surface(const std::string &name) const
Returns a pointer to the surface definition with the given name, or NULL if there is no such surface.
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz extension),...
CLwoClip * get_clip(int number) const
Returns a pointer to the clip with the given index number, or NULL if there is no such clip.
virtual std::string get_name() const
Returns the English name of the file type this converter supports.
virtual SomethingToEggConverter * make_copy()
Allocates and returns a new copy of the converter.
virtual std::string get_extension() const
Returns the common extension of the file type this converter supports.
CLwoLayer * get_layer(int number) const
Returns a pointer to the layer with the given index number, or NULL if there is no such layer.
virtual bool convert_file(const Filename &filename)
Handles the reading of the input file and converting it to egg.
bool convert_lwo(const LwoHeader *lwo_header)
Fills up the egg_data structure according to the indicated lwo structure.
A mapping of floating-point values per integer index.
This is a base class for a family of converter classes that manage a conversion from some file type t...
bool had_error() const
Returns true if an error was detected during the conversion process (unless _allow_errors is true),...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.