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...
const string & get_id() const
Returns the id (name) of this particular bead.
A base class for any of a broad family of flt beads that include an ID.
LColor get_color() const
Returns the color set on this particular attribute.
int get_num_subfaces() const
Returns the number of subface records of this record.
void set_pos(double pos)
Sets the vertex position.
A base class for nodes in the hierarchy that are not leaf nodes.
Defines a texture map that may be applied to geometry.
The main grouping bead of the flt file.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
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...
FltRecord * get_child(int n) const
Returns the nth child of this record.
Filename get_texture_filename() const
Returns the name of the texture image file.
This class supervises the construction of an EggData structure from the data represented by the FltHe...
This is a base class for both FltFace and FltMesh, which are two different kinds of geometric primiti...
bool has_texture() const
Returns true if the face has a texture applied, false otherwise.
A single point, or a collection of points as defined by a single <PointLight> entry.
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.
virtual bool supports_compressed() const
Returns true if this file type can transparently load compressed files (with a .pz extension)...
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...
void clear_error()
Resets the error flag to the no-error state.
virtual string get_extension() const
Returns the common extension of the file type this converter supports.
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.
FltTexture * get_texture() const
Returns the texture applied to this face, or NULL if no texture was applied.
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)...
bool had_error() const
Returns true if an error was detected during the conversion process (unless _allow_errors is true)...
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.
bool has_color() const
Returns true if the face has a primary color indicated, false otherwise.
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 ...
bool has_color() const
Returns true if the vertex has a primary color indicated, false otherwise.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
FltRecord * get_subface(int n) const
Returns the nth subface of this record.
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.
int get_num_children() const
Returns the number of child records of this record.
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 ...
virtual bool convert_file(const Filename &filename)
Handles the reading of the input file and converting it to egg.
LColor get_color() const
Returns the primary color of the face, as a four-component value (including alpha as the transparency...
LColor get_color() const
If has_color() indicates true, returns the color of the vertex, as a four-component value...
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...
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. ...
virtual string get_name() const
Returns the English name of the file type this converter supports.