Panda3D
|
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 }