Panda3D

fltToEggLevelState.cxx

00001 // Filename: fltToEggLevelState.cxx
00002 // Created by:  drose (18Apr01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "fltToEggLevelState.h"
00016 #include "fltToEggConverter.h"
00017 #include "fltTransformTranslate.h"
00018 #include "fltTransformRotateAboutPoint.h"
00019 #include "fltTransformRotateAboutEdge.h"
00020 #include "fltTransformScale.h"
00021 #include "fltTransformPut.h"
00022 #include "eggGroup.h"
00023 #include "dcast.h"
00024 #include "look_at.h"
00025 
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: FltToEggLevelState::Destructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 FltToEggLevelState::
00033 ~FltToEggLevelState() {
00034   Parents::iterator pi;
00035   for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
00036     delete (*pi).second;
00037   }
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: FltToEggLevelState::ParentNodes::Constructor
00042 //       Access: Public
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 FltToEggLevelState::ParentNodes::
00046 ParentNodes() {
00047   _axial_billboard = (EggGroup *)NULL;
00048   _point_billboard = (EggGroup *)NULL;
00049   _plain = (EggGroup *)NULL;
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: FltToEggLevelState::get_synthetic_group
00054 //       Access: Public
00055 //  Description: Sometimes it is necessary to synthesize a group
00056 //               within a particular EggGroup, for instance to insert
00057 //               a transform or billboard flag.  This function will
00058 //               synthesize a group as needed, or return an existing
00059 //               group (if the group need not be synthesized, or if a
00060 //               matching group was previously synthesized).
00061 //
00062 //               This collects together polygons that share the same
00063 //               billboard axis and/or transform space into the same
00064 //               group, rather than wastefully creating a group per
00065 //               polygon.
00066 ////////////////////////////////////////////////////////////////////
00067 EggGroupNode *FltToEggLevelState::
00068 get_synthetic_group(const string &name,
00069                     const FltBead *transform_bead,
00070                     FltGeometry::BillboardType type) {
00071   LMatrix4d transform = transform_bead->get_transform();
00072   bool is_identity = transform.almost_equal(LMatrix4d::ident_mat());
00073   if (is_identity && 
00074       (type != FltGeometry::BT_axial &&
00075        type != FltGeometry::BT_point)) {
00076     // Trivial case: the primitive belongs directly in its parent
00077     // group node.
00078     return _egg_parent;
00079   }
00080 
00081   // For other cases, we may have to create a subgroup to put the
00082   // primitive into.
00083   Parents::iterator pi;
00084   pi = _parents.find(transform);
00085   ParentNodes *nodes;
00086   if (pi != _parents.end()) {
00087     nodes = (*pi).second;
00088   } else {
00089     nodes = new ParentNodes;
00090     _parents.insert(Parents::value_type(transform, nodes));
00091   }
00092 
00093   switch (type) {
00094   case FltGeometry::BT_axial:
00095     if (nodes->_axial_billboard == (EggGroupNode *)NULL) {
00096       nodes->_axial_billboard = new EggGroup(name);
00097       _egg_parent->add_child(nodes->_axial_billboard);
00098       nodes->_axial_billboard->set_billboard_type(EggGroup::BT_axis);
00099       if (!is_identity) {
00100         set_transform(transform_bead, nodes->_axial_billboard);
00101         nodes->_axial_billboard->set_group_type(EggGroup::GT_instance);
00102       }
00103     }
00104     return nodes->_axial_billboard;
00105 
00106   case FltGeometry::BT_point:
00107     if (nodes->_point_billboard == (EggGroupNode *)NULL) {
00108       nodes->_point_billboard = new EggGroup(name);
00109       _egg_parent->add_child(nodes->_point_billboard);
00110       nodes->_point_billboard->set_billboard_type(EggGroup::BT_point_world_relative);
00111       if (!is_identity) {
00112         set_transform(transform_bead, nodes->_point_billboard);
00113         nodes->_point_billboard->set_group_type(EggGroup::GT_instance);
00114       }
00115     }
00116     return nodes->_point_billboard;
00117 
00118   default: // Normally, BT_none, although we've occasionally seen a
00119            // value of 3 come in here, whatever that's supposed to mean.
00120     if (nodes->_plain == (EggGroupNode *)NULL) {
00121       nodes->_plain = new EggGroup(name);
00122       _egg_parent->add_child(nodes->_plain);
00123       if (!is_identity) {
00124         set_transform(transform_bead, nodes->_plain);
00125         nodes->_plain->set_group_type(EggGroup::GT_instance);
00126       }
00127     }
00128     return nodes->_plain;
00129   }
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: FltToEggLevelState::set_transform
00134 //       Access: Public
00135 //  Description: Sets up the group to reflect the transform indicated
00136 //               by the given record, if any.
00137 ////////////////////////////////////////////////////////////////////
00138 void FltToEggLevelState::
00139 set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
00140   if (flt_bead->has_transform()) {
00141     egg_group->set_group_type(EggGroup::GT_instance);
00142 
00143     int num_steps = flt_bead->get_num_transform_steps();
00144     bool componentwise_ok = !_converter->_compose_transforms;
00145 
00146     if (num_steps == 0) {
00147       componentwise_ok = false;
00148     } else {
00149       // Walk through each transform step and store the individual
00150       // components in the egg file.  If we come across a step we
00151       // don't know how to interpret, just store the whole transform
00152       // matrix in the egg file.
00153       egg_group->clear_transform();
00154       for (int i = num_steps -1; i >= 0 && componentwise_ok; i--) {
00155         const FltTransformRecord *step = flt_bead->get_transform_step(i);
00156         if (step->is_exact_type(FltTransformTranslate::get_class_type())) {
00157           const FltTransformTranslate *trans;
00158           DCAST_INTO_V(trans, step);
00159           if (!trans->get_delta().almost_equal(LVector3d::zero())) {
00160             egg_group->add_translate3d(trans->get_delta());
00161           }
00162 
00163         } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) {
00164           const FltTransformRotateAboutPoint *rap;
00165           DCAST_INTO_V(rap, step); 
00166           if (!IS_NEARLY_ZERO(rap->get_angle())) {
00167             if (!rap->get_center().almost_equal(LVector3d::zero())) {
00168               egg_group->add_translate3d(-rap->get_center());
00169             }
00170             LVector3d axis = LCAST(double, rap->get_axis());
00171             egg_group->add_rotate3d(rap->get_angle(), axis);
00172             if (!rap->get_center().almost_equal(LVector3d::zero())) {
00173               egg_group->add_translate3d(rap->get_center());
00174             }
00175           }
00176 
00177         } else if (step->is_exact_type(FltTransformRotateAboutEdge::get_class_type())) {
00178           const FltTransformRotateAboutEdge *rae;
00179           DCAST_INTO_V(rae, step);
00180           if (!IS_NEARLY_ZERO(rae->get_angle())) {
00181             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
00182               egg_group->add_translate3d(-rae->get_point_a());
00183             }
00184             LVector3d axis = rae->get_point_b() - rae->get_point_a();
00185             egg_group->add_rotate3d(rae->get_angle(), axis);
00186             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
00187               egg_group->add_translate3d(rae->get_point_a());
00188             }
00189           }
00190 
00191         } else if (step->is_exact_type(FltTransformScale::get_class_type())) {
00192           const FltTransformScale *scale;
00193           DCAST_INTO_V(scale, step);
00194           if (!scale->get_scale().almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
00195             if (scale->has_center() && 
00196                 !scale->get_center().almost_equal(LVector3d::zero())) {
00197               egg_group->add_translate3d(-scale->get_center());
00198             }
00199             egg_group->add_scale3d(LCAST(double, scale->get_scale()));
00200             if (scale->has_center() && 
00201                 !scale->get_center().almost_equal(LVector3d::zero())) {
00202               egg_group->add_translate3d(scale->get_center());
00203             }
00204           }
00205 
00206         } else if (step->is_exact_type(FltTransformPut::get_class_type())) {
00207           const FltTransformPut *put;
00208           DCAST_INTO_V(put, step);
00209 
00210           if (!put->get_from_origin().almost_equal(LVector3d::zero())) {
00211             egg_group->add_translate3d(-put->get_from_origin());
00212           }
00213           LQuaterniond q1, q2;
00214           look_at(q1, put->get_from_align() - put->get_from_origin(),
00215                   put->get_from_track() - put->get_from_origin(),
00216                   CS_zup_right);
00217           look_at(q2, put->get_to_align() - put->get_to_origin(),
00218                   put->get_to_track() - put->get_to_origin(),
00219                   CS_zup_right);
00220 
00221           LQuaterniond q = invert(q1) * q2;
00222 
00223           if (!q.is_identity()) {
00224             egg_group->add_rotate3d(q);
00225           }
00226           if (!put->get_to_origin().almost_equal(LVector3d::zero())) {
00227             egg_group->add_translate3d(put->get_to_origin());
00228           }
00229 
00230         } else {
00231           // Here's a transform component we haven't implemented here.
00232           // Give up on storing the componentwise transform.
00233           componentwise_ok = false;
00234         }
00235       }
00236     }
00237 
00238     if (!componentwise_ok) {
00239       egg_group->set_transform3d(flt_bead->get_transform());
00240     }
00241   }
00242 }
 All Classes Functions Variables Enumerations