15 #include "fltToEggConverter.h" 17 #include "fltRecord.h" 20 #include "fltObject.h" 21 #include "fltBeadID.h" 24 #include "fltVertex.h" 25 #include "fltVertexList.h" 26 #include "fltExternalReference.h" 30 #include "eggSwitchCondition.h" 31 #include "eggPrimitive.h" 32 #include "eggPolygon.h" 34 #include "eggVertex.h" 35 #include "eggVertexPool.h" 36 #include "eggExternalReference.h" 37 #include "string_utils.h" 47 _compose_transforms =
false;
48 _flt_units = DU_invalid;
59 _compose_transforms(copy._compose_transforms)
69 ~FltToEggConverter() {
134 nout <<
"Reading " << filename <<
"\n";
135 FltError result = header->read_flt(filename);
136 if (result != FE_ok) {
137 nout <<
"Unable to read: " << result <<
"\n";
141 header->check_version();
143 _flt_units = header->get_units();
170 if (_egg_data->get_coordinate_system() == CS_default) {
171 _egg_data->set_coordinate_system(CS_zup_right);
175 _flt_header = flt_header;
179 _egg_data->add_child(_main_egg_vpool.p());
188 state._egg_parent = _egg_data;
189 convert_record(_flt_header, state);
191 if (_main_egg_vpool->empty()) {
194 _egg_data->remove_child(_main_egg_vpool.p());
209 void FltToEggConverter::
212 _main_egg_vpool.clear();
221 void FltToEggConverter::
225 for (
int i = 0; i < num_children; i++) {
227 dispatch_record(child, state);
237 void FltToEggConverter::
239 if (flt_record->
is_of_type(FltLOD::get_class_type())) {
240 convert_lod(DCAST(
FltLOD, flt_record), state);
242 }
else if (flt_record->
is_of_type(FltGroup::get_class_type())) {
243 convert_group(DCAST(
FltGroup, flt_record), state);
245 }
else if (flt_record->
is_of_type(FltObject::get_class_type())) {
246 convert_object(DCAST(
FltObject, flt_record), state);
248 }
else if (flt_record->
is_of_type(FltFace::get_class_type())) {
249 convert_face(DCAST(
FltFace, flt_record), state);
251 }
else if (flt_record->
is_of_type(FltExternalReference::get_class_type())) {
255 }
else if (flt_record->
is_of_type(FltBeadID::get_class_type())) {
256 convert_bead_id(DCAST(
FltBeadID, flt_record), state);
258 }
else if (flt_record->
is_of_type(FltBead::get_class_type())) {
259 convert_bead(DCAST(
FltBead, flt_record), state);
262 convert_record(flt_record, state);
271 void FltToEggConverter::
277 (flt_lod->_switch_in, flt_lod->_switch_out,
278 LPoint3d(flt_lod->_center_x, flt_lod->_center_y, flt_lod->_center_z),
279 flt_lod->_transition_range);
280 egg_group->set_lod(lod);
283 parse_comment(flt_lod, egg_group);
286 next_state._egg_parent = egg_group;
287 convert_record(flt_lod, next_state);
295 void FltToEggConverter::
300 if ((flt_group->_flags & FltGroup::F_forward_animation) != 0) {
302 egg_group->set_switch_flag(
true);
303 egg_group->set_switch_fps(24.0);
307 parse_comment(flt_group, egg_group);
312 next_state._egg_parent = egg_group;
313 convert_record(flt_group, next_state);
321 void FltToEggConverter::
327 parse_comment(flt_object, egg_group);
330 next_state._flt_object = flt_object;
331 next_state._egg_parent = egg_group;
332 convert_record(flt_object, next_state);
341 void FltToEggConverter::
343 nout <<
"Don't know how to convert beads of type " << flt_bead->get_type()
349 parse_comment(flt_bead, egg_group);
352 next_state._egg_parent = egg_group;
353 convert_record(flt_bead, next_state);
362 void FltToEggConverter::
364 nout <<
"Don't know how to convert beads of type " << flt_bead->get_type()
370 parse_comment(flt_bead, egg_group);
373 next_state._egg_parent = egg_group;
374 convert_record(flt_bead, next_state);
382 void FltToEggConverter::
385 switch (flt_face->_draw_type) {
386 case FltGeometry::DT_omni_light:
387 case FltGeometry::DT_uni_light:
388 case FltGeometry::DT_bi_light:
408 for (
int i = 0; i < num_children && vlist == (
FltVertexList *)NULL; i++) {
410 if (child->
is_of_type(FltVertexList::get_class_type())) {
416 int num_vertices = vlist->get_num_vertices();
417 for (
int i = 0; i < num_vertices; i++) {
418 FltVertex *flt_vertex = vlist->get_vertex(i);
419 vertices.push_back(make_egg_vertex(flt_vertex));
423 setup_geometry(flt_face, state, egg_prim, _main_egg_vpool, vertices);
431 void FltToEggConverter::
449 void FltToEggConverter::
457 flt_geom->_billboard_type);
461 next_state._egg_parent = egg_parent;
464 convert_subfaces(flt_geom, next_state);
467 next_state._egg_parent->
add_child(egg_prim);
470 EggVertices::const_iterator vi;
472 bool use_vertex_color =
true;
473 bool keep_normals =
true;
474 switch (flt_geom->_light_mode) {
475 case FltGeometry::LM_face_no_normal:
476 use_vertex_color =
false;
477 keep_normals =
false;
480 case FltGeometry::LM_vertex_no_normal:
481 use_vertex_color =
true;
482 keep_normals =
false;
485 case FltGeometry::LM_face_with_normal:
486 use_vertex_color =
false;
490 case FltGeometry::LM_vertex_with_normal:
491 use_vertex_color =
true;
498 if (state._flt_object != (
FltObject *)NULL) {
501 PN_stdfloat alpha = 1.0 - (state._flt_object->_transparency / 65535.0);
502 face_color[3] *= alpha;
505 egg_prim->set_color(face_color);
511 if (flt_geom->_texwhite) {
514 use_vertex_color =
false;
518 if (use_vertex_color) {
521 egg_prim->clear_color();
525 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
527 if (vertex->has_color()) {
529 vertex_color[3] = face_color[3];
530 vertex->set_color(vertex_color);
535 vertex->set_color(face_color);
543 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
544 (*vi)->clear_color();
550 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
551 (*vi)->clear_normal();
555 if (flt_geom->_draw_type == FltGeometry::DT_solid_no_cull) {
560 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
565 parse_comment(flt_geom, egg_prim);
580 void FltToEggConverter::
583 if (num_subfaces == 0) {
591 state._egg_parent = egg_group;
593 egg_group->set_decal_flag(
true);
598 egg_group = decal_group;
601 next_state._egg_parent = decal_group;
603 for (
int i = 0; i < num_subfaces; i++) {
605 dispatch_record(subface, next_state);
618 bool FltToEggConverter::
632 bool FltToEggConverter::
634 return parse_comment(flt_bead->
get_comment(),
"anonymous", egg_node);
646 bool FltToEggConverter::
661 bool FltToEggConverter::
662 parse_comment(
const string &comment,
const string &name,
664 if (comment.empty()) {
670 static const string egg_str =
"<egg>";
674 while (p < comment.length() &&
675 cmp_nocase(comment.substr(p, 5), egg_str) != 0) {
679 if (p >= comment.length()) {
686 while (p < comment.length() && isspace(comment[p])) {
689 if (p >= comment.length() || comment[p] !=
'{') {
690 nout <<
"No opening brace in comment for " 699 size_t q = comment.length() - 1;
700 while (q > p && comment[q] !=
'}') {
704 nout <<
"No closing brace in comment for " 710 string egg_syntax = comment.substr(p, q - p);
713 nout <<
"Syntax error in comment for " 730 PT_EggVertex FltToEggConverter::
731 make_egg_vertex(
const FltVertex *flt_vertex) {
733 egg_vertex->
set_pos(flt_vertex->_pos);
735 if (flt_vertex->_has_normal) {
736 egg_vertex->set_normal(LCAST(
double, flt_vertex->_normal));
739 if (flt_vertex->_has_uv) {
740 egg_vertex->set_uv(LCAST(
double, flt_vertex->_uv));
744 egg_vertex->set_color(flt_vertex->
get_color());
757 PT_EggTexture FltToEggConverter::
758 make_egg_texture(
const FltTexture *flt_texture) {
759 Textures::const_iterator ti;
760 ti = _textures.find(flt_texture);
761 if (ti != _textures.end()) {
767 string tref_name = format_string(flt_texture->_pattern_index);
770 PT_EggTexture egg_texture =
new EggTexture(tref_name, filename);
772 _textures.insert(Textures::value_type(flt_texture, egg_texture));
776 switch (flt_texture->_min_filter) {
777 case FltTexture::MN_point:
778 egg_texture->set_minfilter(EggTexture::FT_nearest);
781 case FltTexture::MN_bilinear:
782 egg_texture->set_minfilter(EggTexture::FT_linear);
785 case FltTexture::MN_mipmap_point:
786 egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_nearest);
789 case FltTexture::MN_mipmap_linear:
790 egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_linear);
793 case FltTexture::MN_mipmap_bilinear:
794 egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_nearest);
797 case FltTexture::MN_mipmap_trilinear:
798 case FltTexture::MN_OB_mipmap:
799 egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_linear);
802 case FltTexture::MN_bicubic:
803 case FltTexture::MN_bilinear_gequal:
804 case FltTexture::MN_bilinear_lequal:
805 case FltTexture::MN_bicubic_gequal:
806 case FltTexture::MN_bicubic_lequal:
811 switch (flt_texture->_mag_filter) {
812 case FltTexture::MG_point:
813 egg_texture->set_magfilter(EggTexture::FT_nearest);
816 case FltTexture::MG_bilinear:
817 egg_texture->set_magfilter(EggTexture::FT_linear);
820 case FltTexture::MG_bicubic:
821 case FltTexture::MG_sharpen:
822 case FltTexture::MG_add_detail:
823 case FltTexture::MG_modulate_detail:
824 case FltTexture::MG_bilinear_gequal:
825 case FltTexture::MG_bilinear_lequal:
826 case FltTexture::MG_bicubic_gequal:
827 case FltTexture::MG_bicubic_lequal:
832 switch (flt_texture->_repeat) {
833 case FltTexture::RT_repeat:
834 egg_texture->set_wrap_mode(EggTexture::WM_repeat);
837 case FltTexture::RT_clamp:
838 egg_texture->set_wrap_mode(EggTexture::WM_clamp);
842 switch (flt_texture->_repeat_u) {
843 case FltTexture::RT_repeat:
844 egg_texture->set_wrap_u(EggTexture::WM_repeat);
847 case FltTexture::RT_clamp:
848 egg_texture->set_wrap_u(EggTexture::WM_clamp);
852 switch (flt_texture->_repeat_v) {
853 case FltTexture::RT_repeat:
854 egg_texture->set_wrap_v(EggTexture::WM_repeat);
857 case FltTexture::RT_clamp:
858 egg_texture->set_wrap_v(EggTexture::WM_clamp);
862 switch (flt_texture->_env_type) {
863 case FltTexture::ET_modulate:
864 egg_texture->set_env_type(EggTexture::ET_modulate);
867 case FltTexture::ET_decal:
868 egg_texture->set_env_type(EggTexture::ET_decal);
871 case FltTexture::ET_blend:
872 case FltTexture::ET_color:
877 switch (flt_texture->_internal_format) {
878 case FltTexture::IF_default:
881 case FltTexture::IF_i_12a_4:
882 case FltTexture::IF_ia_12:
883 case FltTexture::IF_ia_8:
884 egg_texture->set_format(EggTexture::F_luminance_alpha);
887 case FltTexture::IF_rgb_5:
888 egg_texture->set_format(EggTexture::F_rgb5);
891 case FltTexture::IF_rgba_4:
892 egg_texture->set_format(EggTexture::F_rgba4);
896 case FltTexture::IF_rgba_8:
897 egg_texture->set_format(EggTexture::F_rgba8);
900 case FltTexture::IF_rgba_12:
901 egg_texture->set_format(EggTexture::F_rgba12);
904 case FltTexture::IF_i_16:
905 if (flt_texture->_intensity_is_alpha) {
906 egg_texture->set_format(EggTexture::F_alpha);
908 egg_texture->set_format(EggTexture::F_luminance);
912 case FltTexture::IF_rgb_12:
913 egg_texture->set_format(EggTexture::F_rgb12);
917 parse_comment(flt_texture, egg_texture);
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
bool parse_egg(const string &egg_syntax)
Parses the egg syntax given in the indicate string as if it had been read from the egg file within th...
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz extension)...
A base class for any of a broad family of flt beads that include an ID.
Filename get_texture_filename() const
Returns the name of the texture image file.
bool had_error() const
Returns true if an error was detected during the conversion process (unless _allow_errors is true)...
void set_pos(double pos)
Sets the vertex position.
A base class for nodes in the hierarchy that are not leaf nodes.
int get_num_children() const
Returns the number of child records of this record.
Defines a texture map that may be applied to geometry.
The main grouping bead of the flt file.
bool handle_external_reference(EggGroupNode *egg_parent, const Filename &ref_filename)
Handles an external reference in the source file.
void set_texture(EggTexture *texture)
Replaces the current list of textures with the indicated texture.
A base class for any of a broad family of flt records that represent particular beads in the hierarch...
const string & get_id() const
Returns the id (name) of this particular bead.
This class supervises the construction of an EggData structure from the data represented by the FltHe...
LColor get_color() const
Returns the color set on this particular attribute.
bool has_color() const
Returns true if the vertex has a primary color indicated, false otherwise.
This is a base class for both FltFace and FltMesh, which are two different kinds of geometric primiti...
A single point, or a collection of points as defined by a single <PointLight> entry.
bool has_color() const
Returns true if the face has a primary color indicated, false otherwise.
virtual string get_name() const
Returns the English name of the file type this converter supports.
This keeps track of relevant things about the traversal as we walk through the flt hierarchy...
This is our own Panda specialization on the default STL vector.
void set_bface_flag(bool flag)
Sets the backfacing flag of the polygon.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
virtual DistanceUnit get_input_units()
This may be called after convert_file() has been called and returned true, indicating a successful co...
FltRecord * get_subface(int n) const
Returns the nth subface of this record.
void clear_error()
Resets the error flag to the no-error state.
A list of vertices, typically added as a child of a face bead.
const string & get_comment() const
Retrieves the comment for this record, or empty string if the record has no comment.
Represents a single texture in the texture palette.
The name of a file, such as a texture file or an Egg file.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
The base class for all kinds of records in a MultiGen OpenFlight file.
Represents a single vertex in the vertex palette.
An external reference to another flt file (possibly to a specific bead within the flt file)...
virtual string get_extension() const
Returns the common extension of the file type this converter supports.
The main objecting bead of the flt file.
bool convert_flt(const FltHeader *flt_header)
Fills up the egg_data structure according to the indicated lwo structure.
FltRecord * get_child(int n) const
Returns the nth child of this record.
This is the base class for all three-component vectors and points.
Filename get_ref_filename() const
Returns the name of the referenced file.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
LColor get_color() const
Returns the primary color of the face, as a four-component value (including alpha as the transparency...
A base class for things that may be directly added into the egg hierarchy.
virtual SomethingToEggConverter * make_copy()
Allocates and returns a new copy of the converter.
EggGroupNode * get_synthetic_group(const string &name, const FltBead *transform_bead, FltGeometry::BillboardType type=FltGeometry::BT_none)
Sometimes it is necessary to synthesize a group within a particular EggGroup, for instance to insert ...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
virtual bool convert_file(const Filename &filename)
Handles the reading of the input file and converting it to egg.
LColor get_color() const
If has_color() indicates true, returns the color of the vertex, as a four-component value...
bool has_texture() const
Returns true if the face has a texture applied, false otherwise.
A Level-of-Detail record.
This is a base class for a family of converter classes that manage a conversion from some file type t...
FltTexture * get_texture() const
Returns the texture applied to this face, or NULL if no texture was applied.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it...
A SwitchCondition that switches the levels-of-detail based on distance from the camera's eyepoint...
void set_transform(const FltBead *flt_bead, EggGroup *egg_group)
Sets up the group to reflect the transform indicated by the given record, if any. ...
int get_num_subfaces() const
Returns the number of subface records of this record.