Pārlūkot izejas kodu

convert flt files with componentwise transforms

David Rose 23 gadi atpakaļ
vecāks
revīzija
3ab477ccbf

+ 14 - 0
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

+ 1 - 0
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;

+ 7 - 21
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

+ 0 - 1
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);

+ 124 - 7
pandatool/src/fltegg/fltToEggLevelState.cxx

@@ -17,8 +17,14 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "fltToEggLevelState.h"
-
-#include <eggGroup.h>
+#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());
+    }
+  }
+}

+ 6 - 4
pandatool/src/fltegg/fltToEggLevelState.h

@@ -19,11 +19,11 @@
 #ifndef FLTTOEGGLEVELSTATE_H
 #define FLTTOEGGLEVELSTATE_H
 
-#include <pandatoolbase.h>
-
-#include <fltGeometry.h>
+#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;