45 set_binary_output(
true);
46 set_program_brief(
"convert files from .egg format to MultiGen .flt");
47 set_program_description
48 (
"egg2lt converts files from egg format to MultiGen .flt "
49 "format. It attempts to be as robust as possible, and matches "
50 "the capabilities of flt2egg. Generally, converting a model "
51 "from egg2lt and then back via flt2egg will result in essentially "
52 "the same egg file, within the limitations of what can be "
53 "represented in flt.");
56 (
"attr",
"none/new/all", 0,
57 "Specifies whether to write (or rewrite) .attr files for each "
58 "texture image. MultiGen stores texture properties like mipmapping "
59 "in a separate .attr file for each different texture image. "
60 "If this parameter is \"none\", these files will not be generated; "
61 "if this is \"new\", these files will only be generated if they "
62 "do not already exist (even if the properties have changed). "
63 "Specifying \"all\" causes these to be rewritten every time.",
64 &EggToFlt::dispatch_attr,
nullptr, &_auto_attr_update);
69 _coordinate_system = CS_zup_right;
70 _got_coordinate_system =
true;
71 _auto_attr_update = FltHeader::AU_if_missing;
79 _flt_header =
new FltHeader(_path_replace);
80 _flt_header->set_auto_attr_update(_auto_attr_update);
82 traverse(_data, _flt_header, FltGeometry::BT_none);
85 FltError result = _flt_header->write_flt(
get_output());
86 if (result != FE_ok) {
96 dispatch_attr(
const std::string &opt,
const std::string &arg,
void *var) {
97 FltHeader::AttrUpdate *ip = (FltHeader::AttrUpdate *)var;
99 if (cmp_nocase(arg,
"none") == 0) {
100 *ip = FltHeader::AU_none;
102 }
else if (cmp_nocase(arg,
"new") == 0) {
103 *ip = FltHeader::AU_if_missing;
105 }
else if (cmp_nocase(arg,
"all") == 0) {
106 *ip = FltHeader::AU_always;
110 <<
" requires either \"none\", \"new\", or \"all\".\n";
122 FltGeometry::BillboardType billboard) {
123 if (egg_node->
is_of_type(EggPolygon::get_class_type()) ||
124 egg_node->
is_of_type(EggPoint::get_class_type())) {
127 convert_primitive(egg_primitive, flt_node, billboard);
129 }
else if (egg_node->
is_of_type(EggExternalReference::get_class_type())) {
132 }
else if (egg_node->
is_of_type(EggGroup::get_class_type())) {
136 if (egg_group->get_group_type() == EggGroup::GT_joint) {
141 convert_group(egg_group, flt_node, billboard);
143 }
else if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
146 EggGroupNode::iterator ci;
147 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
148 traverse(*ci, flt_node, billboard);
159 FltGeometry::BillboardType billboard) {
163 flt_face->_billboard_type = billboard;
165 if (egg_primitive->has_color()) {
169 if (egg_primitive->
is_of_type(EggPoint::get_class_type())) {
171 flt_face->_draw_type = FltFace::DT_omni_light;
175 flt_face->_draw_type = FltFace::DT_solid_no_cull;
179 flt_face->_draw_type = FltFace::DT_solid_cull_backface;
184 FltTexture *flt_texture = get_flt_texture(egg_texture);
194 EggPrimitive::iterator vi;
195 bool all_verts_have_color =
true;
196 bool all_verts_have_normal =
true;
197 for (vi = egg_primitive->begin(); vi != egg_primitive->end(); ++vi) {
199 FltVertex *flt_vertex = get_flt_vertex(egg_vertex, egg_primitive);
202 if (!egg_vertex->has_color()) {
203 all_verts_have_color =
false;
205 if (!egg_vertex->has_normal()) {
206 all_verts_have_normal =
false;
209 if (all_verts_have_color) {
212 if (all_verts_have_normal) {
214 flt_face->_light_mode = FltFace::LM_vertex_with_normal;
216 flt_face->_light_mode = FltFace::LM_vertex_no_normal;
219 if (all_verts_have_normal) {
220 flt_face->_light_mode = FltFace::LM_face_with_normal;
222 flt_face->_light_mode = FltFace::LM_face_no_normal;
233 FltGeometry::BillboardType billboard) {
234 std::ostringstream egg_syntax;
239 flt_group->
set_id(egg_group->get_name());
241 switch (egg_group->get_billboard_type()) {
244 case EggGroup::BT_axis:
245 billboard = FltGeometry::BT_axial;
248 case EggGroup::BT_point_world_relative:
249 billboard = FltGeometry::BT_point;
252 case EggGroup::BT_point_camera_relative:
254 billboard = FltGeometry::BT_fixed;
262 apply_transform(egg_group, flt_group);
265 if (egg_group->get_switch_flag()) {
266 if (egg_group->get_switch_fps() != 0.0) {
268 flt_group->_flags |= FltGroup::F_forward_animation;
270 <<
" <Scalar> fps { " << egg_group->get_switch_fps() <<
" }\n";
286 apply_egg_syntax(egg_syntax.str(), flt_group);
288 EggGroup::iterator ci;
289 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
290 traverse(*ci, flt_group, billboard);
301 bool components_ok =
true;
303 for (
int i = num_components - 1; i >= 0 && components_ok; i--) {
305 case EggTransform::CT_translate2d:
310 translate->
set(LPoint3d::zero(), LVector3d(v2[0], v2[1], 0.0));
315 case EggTransform::CT_translate3d:
324 case EggTransform::CT_rotate2d:
328 rotate->
set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0),
334 case EggTransform::CT_rotx:
338 rotate->
set(LPoint3d::zero(), LPoint3d(1.0, 0.0, 0.0),
344 case EggTransform::CT_roty:
348 rotate->
set(LPoint3d::zero(), LPoint3d(0.0, 1.0, 0.0),
354 case EggTransform::CT_rotz:
358 rotate->
set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0),
364 case EggTransform::CT_rotate3d:
374 case EggTransform::CT_scale2d:
378 scale->set(LPoint3d::zero(), LVector3(v2[0], v2[1], 1.0f));
383 case EggTransform::CT_scale3d:
386 scale->set(LPoint3d::zero(), LCAST(PN_stdfloat, egg_transform->
get_component_vec3(i)));
391 case EggTransform::CT_uniform_scale:
395 scale->set(LPoint3d::zero(), LVecBase3(factor, factor, factor));
400 case EggTransform::CT_matrix3:
405 LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
406 m(1, 0), m(1, 1), 0.0, m(1, 2),
408 m(2, 0), m(2, 1), 0.0, m(2, 2));
414 case EggTransform::CT_matrix4:
425 components_ok =
false;
432 nout <<
"Incorrect transform! Expected:\n";
434 nout <<
"Computed:\n";
437 components_ok =
false;
441 if (!components_ok) {
453 apply_egg_syntax(
const std::string &egg_syntax,
FltRecord *flt_record) {
454 if (!egg_syntax.empty()) {
455 std::ostringstream out;
471 VertexMap &vertex_map = _vertex_map_per_frame[frame];
473 VertexMap::iterator vi = vertex_map.find(egg_vertex);
474 if (vi != vertex_map.end()) {
478 flt_vertex->_pos = egg_vertex->
get_pos3();
480 if (egg_vertex->has_color()) {
483 if (egg_vertex->has_normal()) {
484 flt_vertex->_normal = LCAST(PN_stdfloat, egg_vertex->get_normal());
485 flt_vertex->_has_normal =
true;
487 if (egg_vertex->
has_uv()) {
488 flt_vertex->_uv = LCAST(PN_stdfloat, egg_vertex->
get_uv());
489 flt_vertex->_has_uv =
true;
492 if (frame !=
nullptr) {
493 flt_vertex->_pos = flt_vertex->_pos * (*frame);
494 flt_vertex->_normal = flt_vertex->_normal * LCAST(PN_stdfloat, (*frame));
497 _flt_header->add_vertex(flt_vertex);
498 vertex_map[egg_vertex] = flt_vertex;
513 TextureMap::iterator vi = _texture_map.find(filename);
514 if (vi != _texture_map.end()) {
520 switch (egg_texture->get_minfilter()) {
521 case EggTexture::FT_nearest:
522 flt_texture->_min_filter = FltTexture::MN_point;
525 case EggTexture::FT_linear:
526 flt_texture->_min_filter = FltTexture::MN_bilinear;
529 case EggTexture::FT_nearest_mipmap_nearest:
530 flt_texture->_min_filter = FltTexture::MN_mipmap_point;
533 case EggTexture::FT_nearest_mipmap_linear:
534 flt_texture->_min_filter = FltTexture::MN_mipmap_linear;
537 case EggTexture::FT_linear_mipmap_nearest:
538 flt_texture->_min_filter = FltTexture::MN_mipmap_bilinear;
541 case EggTexture::FT_linear_mipmap_linear:
542 flt_texture->_min_filter = FltTexture::MN_mipmap_trilinear;
549 switch (egg_texture->get_magfilter()) {
550 case EggTexture::FT_nearest:
551 flt_texture->_mag_filter = FltTexture::MG_point;
554 case EggTexture::FT_linear:
555 flt_texture->_mag_filter = FltTexture::MG_bilinear;
562 switch (egg_texture->get_wrap_mode()) {
563 case EggTexture::WM_repeat:
564 flt_texture->_repeat = FltTexture::RT_repeat;
567 case EggTexture::WM_clamp:
568 flt_texture->_repeat = FltTexture::RT_clamp;
576 case EggTexture::WM_repeat:
577 flt_texture->_repeat_u = FltTexture::RT_repeat;
580 case EggTexture::WM_clamp:
581 flt_texture->_repeat_u = FltTexture::RT_clamp;
589 case EggTexture::WM_repeat:
590 flt_texture->_repeat_v = FltTexture::RT_repeat;
593 case EggTexture::WM_clamp:
594 flt_texture->_repeat_v = FltTexture::RT_clamp;
601 switch (egg_texture->get_env_type()) {
602 case EggTexture::ET_modulate:
603 flt_texture->_env_type = FltTexture::ET_modulate;
606 case EggTexture::ET_decal:
607 flt_texture->_env_type = FltTexture::ET_decal;
614 switch (egg_texture->get_format()) {
615 case EggTexture::F_luminance_alpha:
616 case EggTexture::F_luminance_alphamask:
617 flt_texture->_internal_format = FltTexture::IF_ia_8;
620 case EggTexture::F_rgb5:
621 case EggTexture::F_rgb332:
622 flt_texture->_internal_format = FltTexture::IF_rgb_5;
625 case EggTexture::F_rgba4:
626 case EggTexture::F_rgba5:
627 flt_texture->_internal_format = FltTexture::IF_rgba_4;
630 case EggTexture::F_rgba8:
631 case EggTexture::F_rgba:
632 case EggTexture::F_rgbm:
633 case EggTexture::F_rgb:
634 case EggTexture::F_rgb8:
635 flt_texture->_internal_format = FltTexture::IF_rgba_8;
638 case EggTexture::F_rgba12:
639 flt_texture->_internal_format = FltTexture::IF_rgba_12;
642 case EggTexture::F_alpha:
643 flt_texture->_internal_format = FltTexture::IF_i_16;
644 flt_texture->_intensity_is_alpha =
true;
647 case EggTexture::F_luminance:
648 flt_texture->_internal_format = FltTexture::IF_i_16;
651 case EggTexture::F_rgb12:
652 flt_texture->_internal_format = FltTexture::IF_rgb_12;
659 _flt_header->add_texture(flt_texture);
660 _texture_map[filename] = flt_texture;
667 int main(
int argc,
char *argv[]) {