diff --git a/pandatool/src/flt/fltBead.cxx b/pandatool/src/flt/fltBead.cxx index c711cf4ae1..1f5b75c28b 100644 --- a/pandatool/src/flt/fltBead.cxx +++ b/pandatool/src/flt/fltBead.cxx @@ -129,6 +129,20 @@ get_transform_step(int n) { return _transform_steps[n]; } +//////////////////////////////////////////////////////////////////// +// Function: FltBead::get_transform_step +// Access: Public +// Description: Returns the nth individual step that defines +// the net transform on this bead. See +// get_num_transform_steps(). +//////////////////////////////////////////////////////////////////// +const FltTransformRecord *FltBead:: +get_transform_step(int n) const { + nassertr(n >= 0 && n < (int)_transform_steps.size(), + (const FltTransformRecord *)NULL); + return _transform_steps[n]; +} + //////////////////////////////////////////////////////////////////// // Function: FltBead::add_transform_step // Access: Public diff --git a/pandatool/src/flt/fltBead.h b/pandatool/src/flt/fltBead.h index d5fa955b83..e89fb0a143 100644 --- a/pandatool/src/flt/fltBead.h +++ b/pandatool/src/flt/fltBead.h @@ -45,6 +45,7 @@ public: int get_num_transform_steps() const; FltTransformRecord *get_transform_step(int n); + const FltTransformRecord *get_transform_step(int n) const; void add_transform_step(FltTransformRecord *record); int get_replicate_count() const; diff --git a/pandatool/src/fltegg/fltToEggConverter.cxx b/pandatool/src/fltegg/fltToEggConverter.cxx index 56ebf18555..7e6887d6fb 100644 --- a/pandatool/src/fltegg/fltToEggConverter.cxx +++ b/pandatool/src/fltegg/fltToEggConverter.cxx @@ -251,7 +251,7 @@ convert_lod(const FltLOD *flt_lod, FltToEggLevelState &state) { flt_lod->_transition_range); egg_group->set_lod(lod); - set_transform(flt_lod, egg_group); + state.set_transform(flt_lod, egg_group); parse_comment(flt_lod, egg_group); FltToEggLevelState next_state(state); @@ -275,7 +275,7 @@ convert_group(const FltGroup *flt_group, FltToEggLevelState &state) { egg_group->set_switch_fps(24.0); } - set_transform(flt_group, egg_group); + state.set_transform(flt_group, egg_group); parse_comment(flt_group, egg_group); ///*** replicate count. @@ -295,7 +295,7 @@ convert_object(const FltObject *flt_object, FltToEggLevelState &state) { EggGroup *egg_group = new EggGroup(flt_object->get_id()); state._egg_parent->add_child(egg_group); - set_transform(flt_object, egg_group); + state.set_transform(flt_object, egg_group); parse_comment(flt_object, egg_group); FltToEggLevelState next_state(state); @@ -317,7 +317,7 @@ convert_bead_id(const FltBeadID *flt_bead, FltToEggLevelState &state) { EggGroup *egg_group = new EggGroup(flt_bead->get_id()); state._egg_parent->add_child(egg_group); - set_transform(flt_bead, egg_group); + state.set_transform(flt_bead, egg_group); parse_comment(flt_bead, egg_group); FltToEggLevelState next_state(state); @@ -338,7 +338,7 @@ convert_bead(const FltBead *flt_bead, FltToEggLevelState &state) { EggGroup *egg_group = new EggGroup; state._egg_parent->add_child(egg_group); - set_transform(flt_bead, egg_group); + state.set_transform(flt_bead, egg_group); parse_comment(flt_bead, egg_group); FltToEggLevelState next_state(state); @@ -404,7 +404,7 @@ void FltToEggConverter:: convert_ext_ref(const FltExternalReference *flt_ext, FltToEggLevelState &state) { // Get a group node to put the reference into. EggGroupNode *egg_parent = - state.get_synthetic_group("", flt_ext->get_transform()); + state.get_synthetic_group("", flt_ext); handle_external_reference(egg_parent, flt_ext->_filename, _flt_header->get_model_path()); @@ -426,7 +426,7 @@ setup_geometry(const FltGeometry *flt_geom, FltToEggLevelState &state, // Determine what the appropriate parent will be. EggGroupNode *egg_parent = - state.get_synthetic_group(flt_geom->get_id(), flt_geom->get_transform(), + state.get_synthetic_group(flt_geom->get_id(), flt_geom, flt_geom->_billboard_type); // Create a new state to reflect the new parent. @@ -579,20 +579,6 @@ convert_subfaces(const FltRecord *flt_record, FltToEggLevelState &state) { } } -//////////////////////////////////////////////////////////////////// -// Function: FltToEggConverter::set_transform -// Access: Private -// Description: Sets up the group to reflect the transform indicated -// by the given record, if any. -//////////////////////////////////////////////////////////////////// -void FltToEggConverter:: -set_transform(const FltBead *flt_bead, EggGroup *egg_group) { - if (flt_bead->has_transform()) { - egg_group->set_transform(flt_bead->get_transform()); - egg_group->set_group_type(EggGroup::GT_instance); - } -} - //////////////////////////////////////////////////////////////////// // Function: FltToEggConverter::parse_comment // Access: Private diff --git a/pandatool/src/fltegg/fltToEggConverter.h b/pandatool/src/fltegg/fltToEggConverter.h index 84c59a404e..013a03424a 100644 --- a/pandatool/src/fltegg/fltToEggConverter.h +++ b/pandatool/src/fltegg/fltToEggConverter.h @@ -88,7 +88,6 @@ private: void convert_subfaces(const FltRecord *flt_record, FltToEggLevelState &state); - void set_transform(const FltBead *flt_bead, EggGroup *egg_group); bool parse_comment(const FltBeadID *flt_bead, EggNode *egg_node); bool parse_comment(const FltBead *flt_bead, EggNode *egg_node); bool parse_comment(const FltTexture *flt_texture, EggNode *egg_node); diff --git a/pandatool/src/fltegg/fltToEggLevelState.cxx b/pandatool/src/fltegg/fltToEggLevelState.cxx index 74f71e222d..5f665c9e1b 100644 --- a/pandatool/src/fltegg/fltToEggLevelState.cxx +++ b/pandatool/src/fltegg/fltToEggLevelState.cxx @@ -17,8 +17,14 @@ //////////////////////////////////////////////////////////////////// #include "fltToEggLevelState.h" - -#include +#include "fltTransformTranslate.h" +#include "fltTransformRotateAboutPoint.h" +#include "fltTransformRotateAboutEdge.h" +#include "fltTransformScale.h" +#include "fltTransformPut.h" +#include "eggGroup.h" +#include "dcast.h" +#include "look_at.h" //////////////////////////////////////////////////////////////////// @@ -63,9 +69,9 @@ ParentNodes() { //////////////////////////////////////////////////////////////////// EggGroupNode *FltToEggLevelState:: get_synthetic_group(const string &name, - const LMatrix4d &transform, + const FltBead *transform_bead, FltGeometry::BillboardType type) { - + LMatrix4d transform = transform_bead->get_transform(); bool is_identity = transform.almost_equal(LMatrix4d::ident_mat()); if (is_identity && (type != FltGeometry::BT_axial && @@ -94,7 +100,7 @@ get_synthetic_group(const string &name, _egg_parent->add_child(nodes->_axial_billboard); nodes->_axial_billboard->set_billboard_type(EggGroup::BT_axis); if (!is_identity) { - nodes->_axial_billboard->set_transform(transform); + set_transform(transform_bead, nodes->_axial_billboard); nodes->_axial_billboard->set_group_type(EggGroup::GT_instance); } } @@ -106,7 +112,7 @@ get_synthetic_group(const string &name, _egg_parent->add_child(nodes->_point_billboard); nodes->_point_billboard->set_billboard_type(EggGroup::BT_point_world_relative); if (!is_identity) { - nodes->_point_billboard->set_transform(transform); + set_transform(transform_bead, nodes->_point_billboard); nodes->_point_billboard->set_group_type(EggGroup::GT_instance); } } @@ -118,10 +124,121 @@ get_synthetic_group(const string &name, nodes->_plain = new EggGroup(name); _egg_parent->add_child(nodes->_plain); if (!is_identity) { - nodes->_plain->set_transform(transform); + set_transform(transform_bead, nodes->_plain); nodes->_plain->set_group_type(EggGroup::GT_instance); } } return nodes->_plain; } } + +//////////////////////////////////////////////////////////////////// +// Function: FltToEggLevelState::set_transform +// Access: Public, Static +// Description: Sets up the group to reflect the transform indicated +// by the given record, if any. +//////////////////////////////////////////////////////////////////// +void FltToEggLevelState:: +set_transform(const FltBead *flt_bead, EggGroup *egg_group) { + if (flt_bead->has_transform()) { + egg_group->set_group_type(EggGroup::GT_instance); + + int num_steps = flt_bead->get_num_transform_steps(); + bool componentwise_ok = true; + + if (num_steps == 0) { + componentwise_ok = false; + } else { + // Walk through each transform step and store the individual + // components in the egg file. If we come across a step we + // don't know how to interpret, just store the whole transform + // matrix in the egg file. + egg_group->clear_transform(); + + for (int i = 0; i < num_steps && componentwise_ok; i++) { + const FltTransformRecord *step = flt_bead->get_transform_step(i); + if (step->is_exact_type(FltTransformTranslate::get_class_type())) { + const FltTransformTranslate *trans; + DCAST_INTO_V(trans, step); + if (!trans->get_delta().almost_equal(LVector3d::zero())) { + egg_group->add_translate(trans->get_delta()); + } + + } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) { + const FltTransformRotateAboutPoint *rap; + DCAST_INTO_V(rap, step); + if (!IS_NEARLY_ZERO(rap->get_angle())) { + if (!rap->get_center().almost_equal(LVector3d::zero())) { + egg_group->add_translate(-rap->get_center()); + } + LVector3d axis = LCAST(double, rap->get_axis()); + egg_group->add_rotate(rap->get_angle(), axis); + if (!rap->get_center().almost_equal(LVector3d::zero())) { + egg_group->add_translate(rap->get_center()); + } + } + + } else if (step->is_exact_type(FltTransformRotateAboutEdge::get_class_type())) { + const FltTransformRotateAboutEdge *rae; + DCAST_INTO_V(rae, step); + if (!IS_NEARLY_ZERO(rae->get_angle())) { + if (!rae->get_point_a().almost_equal(LVector3d::zero())) { + egg_group->add_translate(-rae->get_point_a()); + } + LVector3d axis = rae->get_point_b() - rae->get_point_a(); + egg_group->add_rotate(rae->get_angle(), axis); + if (!rae->get_point_a().almost_equal(LVector3d::zero())) { + egg_group->add_translate(rae->get_point_a()); + } + } + + } else if (step->is_exact_type(FltTransformScale::get_class_type())) { + const FltTransformScale *scale; + DCAST_INTO_V(scale, step); + if (!scale->get_scale().almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) { + if (!scale->get_center().almost_equal(LVector3d::zero())) { + egg_group->add_translate(-scale->get_center()); + } + egg_group->add_scale(LCAST(double, scale->get_scale())); + if (!scale->get_center().almost_equal(LVector3d::zero())) { + egg_group->add_translate(scale->get_center()); + } + } + + } else if (step->is_exact_type(FltTransformPut::get_class_type())) { + const FltTransformPut *put; + DCAST_INTO_V(put, step); + + if (!put->get_from_origin().almost_equal(LVector3d::zero())) { + egg_group->add_translate(-put->get_from_origin()); + } + LQuaterniond q1, q2; + look_at(q1, put->get_from_align() - put->get_from_origin(), + put->get_from_track() - put->get_from_origin(), + CS_zup_right); + look_at(q2, put->get_to_align() - put->get_to_origin(), + put->get_to_track() - put->get_to_origin(), + CS_zup_right); + + LQuaterniond q = invert(q1) * q2; + + if (!q.is_identity()) { + egg_group->add_rotate(q); + } + if (!put->get_to_origin().almost_equal(LVector3d::zero())) { + egg_group->add_translate(put->get_to_origin()); + } + + } else { + // Here's a transform component we haven't implemented here. + // Give up on storing the componentwise transform. + componentwise_ok = false; + } + } + } + + if (!componentwise_ok) { + egg_group->set_transform(flt_bead->get_transform()); + } + } +} diff --git a/pandatool/src/fltegg/fltToEggLevelState.h b/pandatool/src/fltegg/fltToEggLevelState.h index 9491c0c1b9..669801383b 100644 --- a/pandatool/src/fltegg/fltToEggLevelState.h +++ b/pandatool/src/fltegg/fltToEggLevelState.h @@ -19,11 +19,11 @@ #ifndef FLTTOEGGLEVELSTATE_H #define FLTTOEGGLEVELSTATE_H -#include - -#include +#include "pandatoolbase.h" +#include "fltGeometry.h" class FltObject; +class FltBead; class EggGroupNode; class EggGroup; @@ -40,9 +40,11 @@ public: ~FltToEggLevelState(); EggGroupNode *get_synthetic_group(const string &name, - const LMatrix4d &transform, + const FltBead *transform_bead, FltGeometry::BillboardType type = FltGeometry::BT_none); + static void set_transform(const FltBead *flt_bead, EggGroup *egg_group); + const FltObject *_flt_object; EggGroupNode *_egg_parent;