16 #include "fltHeader.h"
20 #include "fltVertexList.h"
21 #include "fltVertex.h"
22 #include "fltTexture.h"
23 #include "fltTransformTranslate.h"
24 #include "fltTransformRotateAboutEdge.h"
25 #include "fltTransformScale.h"
26 #include "fltTransformGeneralMatrix.h"
27 #include "eggPolygon.h"
29 #include "eggPrimitive.h"
30 #include "eggExternalReference.h"
32 #include "eggGroupNode.h"
33 #include "eggTexture.h"
34 #include "eggTransform.h"
36 #include "string_utils.h"
37 #include "vector_string.h"
49 set_binary_output(
true);
50 set_program_brief(
"convert files from .egg format to MultiGen .flt");
51 set_program_description
52 (
"egg2lt converts files from egg format to MultiGen .flt "
53 "format. It attempts to be as robust as possible, and matches "
54 "the capabilities of flt2egg. Generally, converting a model "
55 "from egg2lt and then back via flt2egg will result in essentially "
56 "the same egg file, within the limitations of what can be "
57 "represented in flt.");
60 (
"attr",
"none/new/all", 0,
61 "Specifies whether to write (or rewrite) .attr files for each "
62 "texture image. MultiGen stores texture properties like mipmapping "
63 "in a separate .attr file for each different texture image. "
64 "If this parameter is \"none\", these files will not be generated; "
65 "if this is \"new\", these files will only be generated if they "
66 "do not already exist (even if the properties have changed). "
67 "Specifying \"all\" causes these to be rewritten every time.",
68 &EggToFlt::dispatch_attr, NULL, &_auto_attr_update);
73 _coordinate_system = CS_zup_right;
74 _got_coordinate_system =
true;
75 _auto_attr_update = FltHeader::AU_if_missing;
85 _flt_header =
new FltHeader(_path_replace);
86 _flt_header->set_auto_attr_update(_auto_attr_update);
88 traverse(_data, _flt_header, FltGeometry::BT_none);
91 FltError result = _flt_header->write_flt(
get_output());
92 if (result != FE_ok) {
104 dispatch_attr(
const string &opt,
const string &arg,
void *var) {
105 FltHeader::AttrUpdate *ip = (FltHeader::AttrUpdate *)var;
107 if (cmp_nocase(arg,
"none") == 0) {
108 *ip = FltHeader::AU_none;
110 }
else if (cmp_nocase(arg,
"new") == 0) {
111 *ip = FltHeader::AU_if_missing;
113 }
else if (cmp_nocase(arg,
"all") == 0) {
114 *ip = FltHeader::AU_always;
118 <<
" requires either \"none\", \"new\", or \"all\".\n";
132 FltGeometry::BillboardType billboard) {
133 if (egg_node->
is_of_type(EggPolygon::get_class_type()) ||
134 egg_node->
is_of_type(EggPoint::get_class_type())) {
137 convert_primitive(egg_primitive, flt_node, billboard);
139 }
else if (egg_node->
is_of_type(EggExternalReference::get_class_type())) {
142 }
else if (egg_node->
is_of_type(EggGroup::get_class_type())) {
146 if (egg_group->get_group_type() == EggGroup::GT_joint) {
151 convert_group(egg_group, flt_node, billboard);
153 }
else if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
156 EggGroupNode::iterator ci;
157 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
158 traverse(*ci, flt_node, billboard);
172 FltGeometry::BillboardType billboard) {
176 flt_face->_billboard_type = billboard;
178 if (egg_primitive->has_color()) {
182 if (egg_primitive->
is_of_type(EggPoint::get_class_type())) {
184 flt_face->_draw_type = FltFace::DT_omni_light;
188 flt_face->_draw_type = FltFace::DT_solid_no_cull;
192 flt_face->_draw_type = FltFace::DT_solid_cull_backface;
197 FltTexture *flt_texture = get_flt_texture(egg_texture);
207 EggPrimitive::iterator vi;
208 bool all_verts_have_color =
true;
209 bool all_verts_have_normal =
true;
210 for (vi = egg_primitive->begin(); vi != egg_primitive->end(); ++vi) {
212 FltVertex *flt_vertex = get_flt_vertex(egg_vertex, egg_primitive);
215 if (!egg_vertex->has_color()) {
216 all_verts_have_color =
false;
218 if (!egg_vertex->has_normal()) {
219 all_verts_have_normal =
false;
222 if (all_verts_have_color) {
225 if (all_verts_have_normal) {
227 flt_face->_light_mode = FltFace::LM_vertex_with_normal;
229 flt_face->_light_mode = FltFace::LM_vertex_no_normal;
232 if (all_verts_have_normal) {
233 flt_face->_light_mode = FltFace::LM_face_with_normal;
235 flt_face->_light_mode = FltFace::LM_face_no_normal;
249 FltGeometry::BillboardType billboard) {
255 flt_group->
set_id(egg_group->get_name());
257 switch (egg_group->get_billboard_type()) {
260 case EggGroup::BT_axis:
261 billboard = FltGeometry::BT_axial;
264 case EggGroup::BT_point_world_relative:
265 billboard = FltGeometry::BT_point;
268 case EggGroup::BT_point_camera_relative:
270 billboard = FltGeometry::BT_fixed;
278 apply_transform(egg_group, flt_group);
281 if (egg_group->get_switch_flag()) {
282 if (egg_group->get_switch_fps() != 0.0) {
284 flt_group->_flags |= FltGroup::F_forward_animation;
286 <<
" <Scalar> fps { " << egg_group->get_switch_fps() <<
" }\n";
303 apply_egg_syntax(egg_syntax.str(), flt_group);
305 EggGroup::iterator ci;
306 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
307 traverse(*ci, flt_group, billboard);
321 bool components_ok =
true;
323 for (
int i = num_components - 1; i >= 0 && components_ok; i--) {
325 case EggTransform::CT_translate2d:
335 case EggTransform::CT_translate3d:
344 case EggTransform::CT_rotate2d:
354 case EggTransform::CT_rotx:
364 case EggTransform::CT_roty:
374 case EggTransform::CT_rotz:
384 case EggTransform::CT_rotate3d:
394 case EggTransform::CT_scale2d:
403 case EggTransform::CT_scale3d:
411 case EggTransform::CT_uniform_scale:
420 case EggTransform::CT_matrix3:
425 LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
426 m(1, 0), m(1, 1), 0.0, m(1, 2),
428 m(2, 0), m(2, 1), 0.0, m(2, 2));
434 case EggTransform::CT_matrix4:
445 components_ok =
false;
452 nout <<
"Incorrect transform! Expected:\n";
454 nout <<
"Computed:\n";
457 components_ok =
false;
461 if (!components_ok) {
477 apply_egg_syntax(
const string &egg_syntax,
FltRecord *flt_record) {
478 if (!egg_syntax.empty()) {
497 VertexMap &vertex_map = _vertex_map_per_frame[frame];
499 VertexMap::iterator vi = vertex_map.find(egg_vertex);
500 if (vi != vertex_map.end()) {
504 flt_vertex->_pos = egg_vertex->
get_pos3();
506 if (egg_vertex->has_color()) {
509 if (egg_vertex->has_normal()) {
510 flt_vertex->_normal = LCAST(PN_stdfloat, egg_vertex->get_normal());
511 flt_vertex->_has_normal =
true;
513 if (egg_vertex->
has_uv()) {
514 flt_vertex->_uv = LCAST(PN_stdfloat, egg_vertex->
get_uv());
515 flt_vertex->_has_uv =
true;
519 flt_vertex->_pos = flt_vertex->_pos * (*frame);
520 flt_vertex->_normal = flt_vertex->_normal * LCAST(PN_stdfloat, (*frame));
523 _flt_header->add_vertex(flt_vertex);
524 vertex_map[egg_vertex] = flt_vertex;
542 TextureMap::iterator vi = _texture_map.find(filename);
543 if (vi != _texture_map.end()) {
549 switch (egg_texture->get_minfilter()) {
550 case EggTexture::FT_nearest:
551 flt_texture->_min_filter = FltTexture::MN_point;
554 case EggTexture::FT_linear:
555 flt_texture->_min_filter = FltTexture::MN_bilinear;
558 case EggTexture::FT_nearest_mipmap_nearest:
559 flt_texture->_min_filter = FltTexture::MN_mipmap_point;
562 case EggTexture::FT_nearest_mipmap_linear:
563 flt_texture->_min_filter = FltTexture::MN_mipmap_linear;
566 case EggTexture::FT_linear_mipmap_nearest:
567 flt_texture->_min_filter = FltTexture::MN_mipmap_bilinear;
570 case EggTexture::FT_linear_mipmap_linear:
571 flt_texture->_min_filter = FltTexture::MN_mipmap_trilinear;
578 switch (egg_texture->get_magfilter()) {
579 case EggTexture::FT_nearest:
580 flt_texture->_mag_filter = FltTexture::MG_point;
583 case EggTexture::FT_linear:
584 flt_texture->_mag_filter = FltTexture::MG_bilinear;
591 switch (egg_texture->get_wrap_mode()) {
592 case EggTexture::WM_repeat:
593 flt_texture->_repeat = FltTexture::RT_repeat;
596 case EggTexture::WM_clamp:
597 flt_texture->_repeat = FltTexture::RT_clamp;
605 case EggTexture::WM_repeat:
606 flt_texture->_repeat_u = FltTexture::RT_repeat;
609 case EggTexture::WM_clamp:
610 flt_texture->_repeat_u = FltTexture::RT_clamp;
618 case EggTexture::WM_repeat:
619 flt_texture->_repeat_v = FltTexture::RT_repeat;
622 case EggTexture::WM_clamp:
623 flt_texture->_repeat_v = FltTexture::RT_clamp;
630 switch (egg_texture->get_env_type()) {
631 case EggTexture::ET_modulate:
632 flt_texture->_env_type = FltTexture::ET_modulate;
635 case EggTexture::ET_decal:
636 flt_texture->_env_type = FltTexture::ET_decal;
643 switch (egg_texture->get_format()) {
644 case EggTexture::F_luminance_alpha:
645 case EggTexture::F_luminance_alphamask:
646 flt_texture->_internal_format = FltTexture::IF_ia_8;
649 case EggTexture::F_rgb5:
650 case EggTexture::F_rgb332:
651 flt_texture->_internal_format = FltTexture::IF_rgb_5;
654 case EggTexture::F_rgba4:
655 case EggTexture::F_rgba5:
656 flt_texture->_internal_format = FltTexture::IF_rgba_4;
659 case EggTexture::F_rgba8:
660 case EggTexture::F_rgba:
661 case EggTexture::F_rgbm:
662 case EggTexture::F_rgb:
663 case EggTexture::F_rgb8:
664 flt_texture->_internal_format = FltTexture::IF_rgba_8;
667 case EggTexture::F_rgba12:
668 flt_texture->_internal_format = FltTexture::IF_rgba_12;
671 case EggTexture::F_alpha:
672 flt_texture->_internal_format = FltTexture::IF_i_16;
673 flt_texture->_intensity_is_alpha =
true;
676 case EggTexture::F_luminance:
677 flt_texture->_internal_format = FltTexture::IF_i_16;
680 case EggTexture::F_rgb12:
681 flt_texture->_internal_format = FltTexture::IF_rgb_12;
688 _flt_header->add_texture(flt_texture);
689 _texture_map[filename] = flt_texture;
696 int main(
int argc,
char *argv[]) {
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
This is the base class for all three-component vectors and points.
void set_transform(const LMatrix4d &mat)
Replaces the transform matrix on this bead.
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
This is a 4-by-4 transform matrix.
LColor get_color() const
Returns the color set on this particular attribute.
void set_comment(const string &comment)
Changes the comment for this record.
void set_color(const LColor &color)
Sets the color of the vertex, using the packed color convention.
bool get_bface_flag() const
Retrieves the backfacing flag of the polygon.
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
This is a two-component vector offset.
void set_texture_filename(const Filename &filename)
Changes the name of the texture image file.
A base class for nodes in the hierarchy that are not leaf nodes.
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
void add_transform_step(FltTransformRecord *record)
Applies the indicated transform step to the net transformation applied to the bead.
Defines a texture map that may be applied to geometry.
The main grouping bead of the flt file.
void set_color(const LColor &color)
Sets the primary color of the face, using the packed color convention.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
const LMatrix4d & get_transform() const
Returns the single-precision 4x4 matrix that represents the transform applied to this bead...
A base class for any of a broad family of flt records that represent particular beads in the hierarch...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
EggTexture * get_texture() const
Returns the first texture on the primitive, if any, or NULL if there are no textures on the primitive...
void add_child(FltRecord *child)
Adds a new child to the end of the list of children for this record.
void write_tags(ostream &out, int indent_level) const
Writes just the <Tag> entries, if any, to the indicated ostream.
void set_id(const string &id)
Changes the id (name) of this particular bead.
Filename get_output_filename() const
If has_output_filename() returns true, this is the filename that the user specified.
void add_vertex(FltVertex *vertex)
Adds a new vertex to the end of the vertex list.
void write_collide_flags(ostream &out, int indent_level) const
Writes just the <Collide> entry and related fields to the indicated ostream.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
void write_model_flags(ostream &out, int indent_level) const
Writes the <Model> flag and related flags to the indicated ostream.
WrapMode get_wrap_v() const
Returns the amount specified for V wrap.
This is a 3-by-3 transform matrix.
WrapMode get_wrap_u() const
Returns the amount specified for U wrap.
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
A list of vertices, typically added as a child of a face bead.
Represents a single texture in the texture palette.
The name of a file, such as a texture file or an Egg file.
A program to read an egg file and write a flt 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.
static const LPoint3d & zero()
Returns a zero-length point.
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
void clear_transform()
Removes any transform matrix and all transform steps on this bead.
void write_switch_flags(ostream &out, int indent_level) const
Writes the <Switch> flag and related flags to the indicated ostream.
const LMatrix4d * get_vertex_to_node_ptr() const
Returns either a NULL pointer or a unique pointer shared by nodes with the same get_vertex_to_node() ...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the general base class for a file-converter program that reads some model file format and gen...
A base class for things that may be directly added into the egg hierarchy.
void write_object_types(ostream &out, int indent_level) const
Writes just the <ObjectTypes> entries, if any, to the indicated ostream.
void write_render_mode(ostream &out, int indent_level) const
Writes the flags inherited from EggRenderMode and similar flags that control obscure render effects...
void write_decal_flags(ostream &out, int indent_level) const
Writes the flags related to decaling, if any.
void set_texture(FltTexture *texture)
Applies the indicated texture to this face, or if the texture is NULL, clears it. ...
bool has_texture() const
Returns true if the primitive has any textures specified, false otherwise.