Panda3D
|
00001 // Filename: compassEffect.cxx 00002 // Created by: drose (16Jul02) 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 "compassEffect.h" 00016 #include "cullTraverserData.h" 00017 #include "config_pgraph.h" 00018 #include "nodePath.h" 00019 #include "bamReader.h" 00020 #include "bamWriter.h" 00021 #include "datagram.h" 00022 #include "datagramIterator.h" 00023 00024 TypeHandle CompassEffect::_type_handle; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: CompassEffect::make 00028 // Access: Published, Static 00029 // Description: Constructs a new CompassEffect object. If the 00030 // reference is an empty NodePath, it means the 00031 // CompassEffect is relative to the root of the scene 00032 // graph; otherwise, it's relative to the indicated 00033 // node. The properties bitmask specifies the set of 00034 // properties that the compass node inherits from the 00035 // reference instead of from its parent. 00036 //////////////////////////////////////////////////////////////////// 00037 CPT(RenderEffect) CompassEffect:: 00038 make(const NodePath &reference, int properties) { 00039 CompassEffect *effect = new CompassEffect; 00040 effect->_reference = reference; 00041 effect->_properties = (properties & P_all); 00042 return return_new(effect); 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: CompassEffect::safe_to_transform 00047 // Access: Public, Virtual 00048 // Description: Returns true if it is generally safe to transform 00049 // this particular kind of RenderEffect by calling the 00050 // xform() method, false otherwise. 00051 //////////////////////////////////////////////////////////////////// 00052 bool CompassEffect:: 00053 safe_to_transform() const { 00054 return false; 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: CompassEffect::output 00059 // Access: Public, Virtual 00060 // Description: 00061 //////////////////////////////////////////////////////////////////// 00062 void CompassEffect:: 00063 output(ostream &out) const { 00064 out << get_type() << ":"; 00065 if (_properties == 0) { 00066 out << " none"; 00067 } 00068 if ((_properties & P_pos) == P_pos) { 00069 out << " xyz"; 00070 } else { 00071 if ((_properties & P_x) != 0) { 00072 out << " x"; 00073 } 00074 if ((_properties & P_y) != 0) { 00075 out << " y"; 00076 } 00077 if ((_properties & P_z) != 0) { 00078 out << " z"; 00079 } 00080 } 00081 if ((_properties & P_rot) != 0) { 00082 out << " rot"; 00083 } 00084 if ((_properties & P_scale) == P_scale) { 00085 out << " scale"; 00086 } else { 00087 if ((_properties & P_sx) != 0) { 00088 out << " sx"; 00089 } 00090 if ((_properties & P_sy) != 0) { 00091 out << " sy"; 00092 } 00093 if ((_properties & P_sz) != 0) { 00094 out << " sz"; 00095 } 00096 } 00097 if (!_reference.is_empty()) { 00098 out << " reference " << _reference; 00099 } 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: CompassEffect::has_cull_callback 00104 // Access: Public, Virtual 00105 // Description: Should be overridden by derived classes to return 00106 // true if cull_callback() has been defined. Otherwise, 00107 // returns false to indicate cull_callback() does not 00108 // need to be called for this effect during the cull 00109 // traversal. 00110 //////////////////////////////////////////////////////////////////// 00111 bool CompassEffect:: 00112 has_cull_callback() const { 00113 return true; 00114 } 00115 00116 //////////////////////////////////////////////////////////////////// 00117 // Function: CompassEffect::cull_callback 00118 // Access: Public, Virtual 00119 // Description: If has_cull_callback() returns true, this function 00120 // will be called during the cull traversal to perform 00121 // any additional operations that should be performed at 00122 // cull time. This may include additional manipulation 00123 // of render state or additional visible/invisible 00124 // decisions, or any other arbitrary operation. 00125 // 00126 // At the time this function is called, the current 00127 // node's transform and state have not yet been applied 00128 // to the net_transform and net_state. This callback 00129 // may modify the node_transform and node_state to apply 00130 // an effective change to the render state at this 00131 // level. 00132 //////////////////////////////////////////////////////////////////// 00133 void CompassEffect:: 00134 cull_callback(CullTraverser *trav, CullTraverserData &data, 00135 CPT(TransformState) &node_transform, 00136 CPT(RenderState) &) const { 00137 if (_properties == 0) { 00138 // Nothing to do. 00139 return; 00140 } 00141 00142 CPT(TransformState) true_net_transform = data.get_net_transform(trav); 00143 CPT(TransformState) want_net_transform = true_net_transform; 00144 adjust_transform(want_net_transform, node_transform, data.node()); 00145 00146 // Now compute the transform that will convert true_net_transform to 00147 // want_transform. This is inv(true_net_transform) * want_transform. 00148 CPT(TransformState) compass_transform = 00149 true_net_transform->invert_compose(want_net_transform); 00150 00151 // And modify our local node's apparent transform so that 00152 // true_net_transform->compose(new_node_transform) produces the same 00153 // result we would have gotten had we actually computed 00154 // want_transform->compose(orig_node_transform). 00155 node_transform = compass_transform->compose(node_transform); 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: CompassEffect::has_adjust_transform 00160 // Access: Public, Virtual 00161 // Description: Should be overridden by derived classes to return 00162 // true if adjust_transform() has been defined, and 00163 // therefore the RenderEffect has some effect on the 00164 // node's apparent local and net transforms. 00165 //////////////////////////////////////////////////////////////////// 00166 bool CompassEffect:: 00167 has_adjust_transform() const { 00168 return (_properties != 0); 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: CompassEffect::adjust_transform 00173 // Access: Public, Virtual 00174 // Description: Performs some operation on the node's apparent net 00175 // and/or local transforms. This will only be called if 00176 // has_adjust_transform() is redefined to return true. 00177 // 00178 // Both parameters are in/out. The original transforms 00179 // will be passed in, and they may (or may not) be 00180 // modified in-place by the RenderEffect. 00181 //////////////////////////////////////////////////////////////////// 00182 void CompassEffect:: 00183 adjust_transform(CPT(TransformState) &net_transform, 00184 CPT(TransformState) &node_transform, 00185 PandaNode *) const { 00186 if (_properties == 0) { 00187 // Nothing to do. 00188 return; 00189 } 00190 00191 // The reference transform: where we are acting as if we inherit 00192 // from. Either the root node (identity) or the specified reference 00193 // node. 00194 CPT(TransformState) ref_transform; 00195 if (_reference.is_empty()) { 00196 ref_transform = TransformState::make_identity(); 00197 } else { 00198 ref_transform = _reference.get_net_transform(); 00199 } 00200 00201 // Now compute the net transform we actually want to achieve. This 00202 // is all of the components from the net transform we want to 00203 // inherit normally from our parent, with all of the components from 00204 // the ref transform we want to inherit from our reference. 00205 CPT(TransformState) want_net_transform; 00206 if (_properties == P_all) { 00207 // If we want to steal the whole transform, that's easy. 00208 want_net_transform = ref_transform; 00209 00210 } else { 00211 // How much of the pos do we want to steal? We can always 00212 // determine a transform's pos, even if it's nondecomposable. 00213 LVecBase3 want_pos = net_transform->get_pos(); 00214 const LVecBase3 &ref_pos = ref_transform->get_pos(); 00215 if ((_properties & P_x) != 0) { 00216 want_pos[0] = ref_pos[0]; 00217 } 00218 if ((_properties & P_y) != 0) { 00219 want_pos[1] = ref_pos[1]; 00220 } 00221 if ((_properties & P_z) != 0) { 00222 want_pos[2] = ref_pos[2]; 00223 } 00224 00225 if ((_properties & ~P_pos) == 0) { 00226 // If we only want to steal the pos, that's pretty easy. 00227 want_net_transform = net_transform->set_pos(want_pos); 00228 00229 } else if ((_properties & (P_rot | P_scale)) == (P_rot | P_scale)) { 00230 // If we want to steal everything *but* the pos, also easy. 00231 want_net_transform = ref_transform->set_pos(want_pos); 00232 00233 } else { 00234 // For any other combination, we have to be able to decompose both 00235 // transforms. 00236 if (!net_transform->has_components() || 00237 !ref_transform->has_components()) { 00238 // If we can't decompose, just do the best we can: steal 00239 // everything but the pos. 00240 want_net_transform = ref_transform->set_pos(want_pos); 00241 00242 } else { 00243 // If we can decompose, then take only the components we want. 00244 LQuaternion want_quat = net_transform->get_quat(); 00245 if ((_properties & P_rot) != 0) { 00246 want_quat = ref_transform->get_quat(); 00247 } 00248 00249 LVecBase3 want_scale = net_transform->get_scale(); 00250 const LVecBase3 &ref_scale = ref_transform->get_scale(); 00251 if ((_properties & P_sx) != 0) { 00252 want_scale[0] = ref_scale[0]; 00253 } 00254 if ((_properties & P_sy) != 0) { 00255 want_scale[1] = ref_scale[1]; 00256 } 00257 if ((_properties & P_sz) != 0) { 00258 want_scale[2] = ref_scale[2]; 00259 } 00260 00261 want_net_transform = 00262 TransformState::make_pos_quat_scale(want_pos, want_quat, want_scale); 00263 } 00264 } 00265 } 00266 00267 net_transform = want_net_transform; 00268 } 00269 00270 //////////////////////////////////////////////////////////////////// 00271 // Function: CompassEffect::compare_to_impl 00272 // Access: Protected, Virtual 00273 // Description: Intended to be overridden by derived CompassEffect 00274 // types to return a unique number indicating whether 00275 // this CompassEffect is equivalent to the other one. 00276 // 00277 // This should return 0 if the two CompassEffect objects 00278 // are equivalent, a number less than zero if this one 00279 // should be sorted before the other one, and a number 00280 // greater than zero otherwise. 00281 // 00282 // This will only be called with two CompassEffect 00283 // objects whose get_type() functions return the same. 00284 //////////////////////////////////////////////////////////////////// 00285 int CompassEffect:: 00286 compare_to_impl(const RenderEffect *other) const { 00287 const CompassEffect *ta; 00288 DCAST_INTO_R(ta, other, 0); 00289 00290 if (_properties != ta->_properties) { 00291 return _properties - ta->_properties; 00292 } 00293 int compare = _reference.compare_to(ta->_reference); 00294 if (compare != 0) { 00295 return compare; 00296 } 00297 return 0; 00298 } 00299 00300 //////////////////////////////////////////////////////////////////// 00301 // Function: CompassEffect::register_with_read_factory 00302 // Access: Public, Static 00303 // Description: Tells the BamReader how to create objects of type 00304 // CompassEffect. 00305 //////////////////////////////////////////////////////////////////// 00306 void CompassEffect:: 00307 register_with_read_factory() { 00308 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00309 } 00310 00311 //////////////////////////////////////////////////////////////////// 00312 // Function: CompassEffect::write_datagram 00313 // Access: Public, Virtual 00314 // Description: Writes the contents of this object to the datagram 00315 // for shipping out to a Bam file. 00316 //////////////////////////////////////////////////////////////////// 00317 void CompassEffect:: 00318 write_datagram(BamWriter *manager, Datagram &dg) { 00319 RenderEffect::write_datagram(manager, dg); 00320 dg.add_uint16(_properties); 00321 // *** We don't write out the _reference NodePath right now. Maybe 00322 // we should. 00323 } 00324 00325 //////////////////////////////////////////////////////////////////// 00326 // Function: CompassEffect::make_from_bam 00327 // Access: Protected, Static 00328 // Description: This function is called by the BamReader's factory 00329 // when a new object of type CompassEffect is encountered 00330 // in the Bam file. It should create the CompassEffect 00331 // and extract its information from the file. 00332 //////////////////////////////////////////////////////////////////// 00333 TypedWritable *CompassEffect:: 00334 make_from_bam(const FactoryParams ¶ms) { 00335 CompassEffect *effect = new CompassEffect; 00336 DatagramIterator scan; 00337 BamReader *manager; 00338 00339 parse_params(params, scan, manager); 00340 effect->fillin(scan, manager); 00341 00342 return effect; 00343 } 00344 00345 //////////////////////////////////////////////////////////////////// 00346 // Function: CompassEffect::fillin 00347 // Access: Protected 00348 // Description: This internal function is called by make_from_bam to 00349 // read in all of the relevant data from the BamFile for 00350 // the new CompassEffect. 00351 //////////////////////////////////////////////////////////////////// 00352 void CompassEffect:: 00353 fillin(DatagramIterator &scan, BamReader *manager) { 00354 RenderEffect::fillin(scan, manager); 00355 _properties = scan.get_uint16(); 00356 }