Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/fltegg/fltToEggLevelState.cxx

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

Generated on Fri May 2 03:19:54 2003 for Panda-Tool by doxygen1.3