Panda3D
 All Classes Functions Variables Enumerations
texMatrixAttrib.cxx
00001 // Filename: texMatrixAttrib.cxx
00002 // Created by:  drose (14Mar02)
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 "texMatrixAttrib.h"
00016 #include "graphicsStateGuardianBase.h"
00017 #include "dcast.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "datagram.h"
00021 #include "datagramIterator.h"
00022 #include "textureStagePool.h"
00023 
00024 CPT(RenderAttrib) TexMatrixAttrib::_empty_attrib;
00025 TypeHandle TexMatrixAttrib::_type_handle;
00026 int TexMatrixAttrib::_attrib_slot;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: TexMatrixAttrib::Destructor
00030 //       Access: Public, Virtual
00031 //  Description: 
00032 ////////////////////////////////////////////////////////////////////
00033 TexMatrixAttrib::
00034 ~TexMatrixAttrib() {
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: TexMatrixAttrib::make
00039 //       Access: Published, Static
00040 //  Description: Constructs a TexMatrixAttrib that applies
00041 //               no stages at all.
00042 ////////////////////////////////////////////////////////////////////
00043 CPT(RenderAttrib) TexMatrixAttrib::
00044 make() {
00045   // We make it a special case and store a pointer to the empty attrib
00046   // forever once we find it the first time, as an optimization.
00047   if (_empty_attrib == (RenderAttrib *)NULL) {
00048     _empty_attrib = return_new(new TexMatrixAttrib);
00049   }
00050 
00051   return _empty_attrib;
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: TexMatrixAttrib::make
00056 //       Access: Published, Static
00057 //  Description: Constructs a TexMatrixAttrib that applies the
00058 //               indicated matrix to the default texture stage.  This
00059 //               interface is deprecated.
00060 ////////////////////////////////////////////////////////////////////
00061 CPT(RenderAttrib) TexMatrixAttrib::
00062 make(const LMatrix4 &mat) {
00063   pgraph_cat.warning()
00064     << "Using deprecated TexMatrixAttrib interface.\n";
00065   if (mat == LMatrix4::ident_mat()) {
00066     return make();
00067   }
00068   CPT(TransformState) transform = TransformState::make_mat(mat);
00069   return make(TextureStage::get_default(), transform);
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: TexMatrixAttrib::make
00074 //       Access: Published, Static
00075 //  Description: Constructs a TexMatrixAttrib that applies the
00076 //               indicated transform to the named texture stage.
00077 ////////////////////////////////////////////////////////////////////
00078 CPT(RenderAttrib) TexMatrixAttrib::
00079 make(TextureStage *stage, const TransformState *transform) {
00080   return DCAST(TexMatrixAttrib, make())->add_stage(stage, transform);
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: TexMatrixAttrib::make_default
00085 //       Access: Published, Static
00086 //  Description: Returns a RenderAttrib that corresponds to whatever
00087 //               the standard default properties for render attributes
00088 //               of this type ought to be.
00089 ////////////////////////////////////////////////////////////////////
00090 CPT(RenderAttrib) TexMatrixAttrib::
00091 make_default() {
00092   return return_new(new TexMatrixAttrib);
00093 }
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 //     Function: TexMatrixAttrib::add_stage
00097 //       Access: Published, Static
00098 //  Description: Returns a new TexMatrixAttrib just like this one,
00099 //               with the indicated transform for the given stage.  If
00100 //               this stage already exists, its transform is replaced.
00101 ////////////////////////////////////////////////////////////////////
00102 CPT(RenderAttrib) TexMatrixAttrib::
00103 add_stage(TextureStage *stage, const TransformState *transform,
00104           int override) const {
00105   TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
00106   Stages::iterator si = attrib->_stages.insert(StageNode(stage)).first;
00107   (*si)._transform = transform;
00108   (*si)._override = override;
00109 
00110   return return_new(attrib);
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: TexMatrixAttrib::remove_stage
00115 //       Access: Published, Static
00116 //  Description: Returns a new TexMatrixAttrib just like this one,
00117 //               with the indicated stage removed.
00118 ////////////////////////////////////////////////////////////////////
00119 CPT(RenderAttrib) TexMatrixAttrib::
00120 remove_stage(TextureStage *stage) const {
00121   TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
00122   attrib->_stages.erase(StageNode(stage));
00123   return return_new(attrib);
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: TexMatrixAttrib::get_mat
00128 //       Access: Published
00129 //  Description: Returns the transformation matrix associated with
00130 //               the default texture stage.
00131 ////////////////////////////////////////////////////////////////////
00132 const LMatrix4 &TexMatrixAttrib::
00133 get_mat() const {
00134   return get_mat(TextureStage::get_default());
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: TexMatrixAttrib::is_empty
00139 //       Access: Published
00140 //  Description: Returns true if no stages are defined in the
00141 //               TexMatrixAttrib, false if at least one is.
00142 ////////////////////////////////////////////////////////////////////
00143 bool TexMatrixAttrib::
00144 is_empty() const {
00145   return _stages.empty();
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: TexMatrixAttrib::has_stage
00150 //       Access: Published
00151 //  Description: Returns true if there is a transform associated with
00152 //               the indicated stage, or false otherwise (in which
00153 //               case get_transform(stage) will return the identity
00154 //               transform).
00155 ////////////////////////////////////////////////////////////////////
00156 bool TexMatrixAttrib::
00157 has_stage(TextureStage *stage) const {
00158   Stages::const_iterator mi = _stages.find(StageNode(stage));
00159   return (mi != _stages.end());
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: TexMatrixAttrib::get_num_stages
00164 //       Access: Published
00165 //  Description: Returns the number of stages that are represented by
00166 //               this attrib.
00167 ////////////////////////////////////////////////////////////////////
00168 int TexMatrixAttrib::
00169 get_num_stages() const {
00170   return _stages.size();
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: TexMatrixAttrib::get_stage
00175 //       Access: Published
00176 //  Description: Returns the nth stage that is represented by this
00177 //               attrib.  The TextureStages are in no particular
00178 //               order.
00179 ////////////////////////////////////////////////////////////////////
00180 TextureStage *TexMatrixAttrib::
00181 get_stage(int n) const {
00182   nassertr(n >= 0 && n < (int)_stages.size(), NULL);
00183   return _stages[n]._stage;
00184 }
00185 
00186 ////////////////////////////////////////////////////////////////////
00187 //     Function: TexMatrixAttrib::get_mat
00188 //       Access: Published
00189 //  Description: Returns the transformation matrix associated with
00190 //               the indicated texture stage, or identity matrix if
00191 //               nothing is associated with the indicated stage.
00192 ////////////////////////////////////////////////////////////////////
00193 const LMatrix4 &TexMatrixAttrib::
00194 get_mat(TextureStage *stage) const {
00195   return get_transform(stage)->get_mat();
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: TexMatrixAttrib::get_transform
00200 //       Access: Published
00201 //  Description: Returns the transformation associated with
00202 //               the indicated texture stage, or identity matrix if
00203 //               nothing is associated with the indicated stage.
00204 ////////////////////////////////////////////////////////////////////
00205 CPT(TransformState) TexMatrixAttrib::
00206 get_transform(TextureStage *stage) const {
00207   Stages::const_iterator mi = _stages.find(StageNode(stage));
00208   if (mi != _stages.end()) {
00209     return (*mi)._transform;
00210   }
00211   return TransformState::make_identity();
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: TexMatrixAttrib::output
00216 //       Access: Public, Virtual
00217 //  Description: 
00218 ////////////////////////////////////////////////////////////////////
00219 void TexMatrixAttrib::
00220 output(ostream &out) const {
00221   out << get_type() << ":";
00222 
00223   Stages::const_iterator mi;
00224   for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
00225     const StageNode &sn = (*mi);
00226     out << " " << sn._stage->get_name() << "(" << *sn._transform << ")";
00227     if (sn._override != 0) {
00228       out << "^" << sn._override;
00229     }
00230   }
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: TexMatrixAttrib::compare_to_impl
00235 //       Access: Protected, Virtual
00236 //  Description: Intended to be overridden by derived TexMatrixAttrib
00237 //               types to return a unique number indicating whether
00238 //               this TexMatrixAttrib is equivalent to the other one.
00239 //
00240 //               This should return 0 if the two TexMatrixAttrib objects
00241 //               are equivalent, a number less than zero if this one
00242 //               should be sorted before the other one, and a number
00243 //               greater than zero otherwise.
00244 //
00245 //               This will only be called with two TexMatrixAttrib
00246 //               objects whose get_type() functions return the same.
00247 ////////////////////////////////////////////////////////////////////
00248 int TexMatrixAttrib::
00249 compare_to_impl(const RenderAttrib *other) const {
00250   const TexMatrixAttrib *ta;
00251   DCAST_INTO_R(ta, other, 0);
00252   
00253   Stages::const_iterator ai, bi;
00254   ai = _stages.begin();
00255   bi = ta->_stages.begin();
00256   while (ai != _stages.end() && bi != ta->_stages.end()) {
00257     if ((*ai) < (*bi)) {
00258       // This stage is in a but not in b.
00259       return -1;
00260 
00261     } else if ((*bi) < (*ai)) {
00262       // This stage is in b but not in a.
00263       return 1;
00264 
00265     } else {
00266       // This stage is in both.
00267       ++ai;
00268       ++bi;
00269     }
00270   }
00271 
00272   if (bi != ta->_stages.end()) {
00273     // a ran out first; b was longer.
00274     return -1;
00275   }
00276 
00277   if (ai != _stages.end()) {
00278     // b ran out first; a was longer.
00279     return 1;
00280   }
00281 
00282   return 0;
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: TexMatrixAttrib::get_hash_impl
00287 //       Access: Protected, Virtual
00288 //  Description: Intended to be overridden by derived RenderAttrib
00289 //               types to return a unique hash for these particular
00290 //               properties.  RenderAttribs that compare the same with
00291 //               compare_to_impl(), above, should return the same
00292 //               hash; RenderAttribs that compare differently should
00293 //               return a different hash.
00294 ////////////////////////////////////////////////////////////////////
00295 size_t TexMatrixAttrib::
00296 get_hash_impl() const {
00297   size_t hash = 0;
00298   Stages::const_iterator si;
00299   for (si = _stages.begin(); si != _stages.end(); ++si) {
00300     const StageNode &sn = (*si);
00301 
00302     hash = pointer_hash::add_hash(hash, sn._stage);
00303     hash = pointer_hash::add_hash(hash, sn._transform);
00304     hash = int_hash::add_hash(hash, sn._override);
00305   }
00306 
00307   return hash;
00308 }
00309 
00310 ////////////////////////////////////////////////////////////////////
00311 //     Function: TexMatrixAttrib::compose_impl
00312 //       Access: Protected, Virtual
00313 //  Description: Intended to be overridden by derived RenderAttrib
00314 //               types to specify how two consecutive RenderAttrib
00315 //               objects of the same type interact.
00316 //
00317 //               This should return the result of applying the other
00318 //               RenderAttrib to a node in the scene graph below this
00319 //               RenderAttrib, which was already applied.  In most
00320 //               cases, the result is the same as the other
00321 //               RenderAttrib (that is, a subsequent RenderAttrib
00322 //               completely replaces the preceding one).  On the other
00323 //               hand, some kinds of RenderAttrib (for instance,
00324 //               ColorTransformAttrib) might combine in meaningful
00325 //               ways.
00326 ////////////////////////////////////////////////////////////////////
00327 CPT(RenderAttrib) TexMatrixAttrib::
00328 compose_impl(const RenderAttrib *other) const {
00329   const TexMatrixAttrib *ta;
00330   DCAST_INTO_R(ta, other, 0);
00331 
00332   // The composition is the union of the two attribs.  In the case
00333   // when a stage is in both attribs, we compose the stages.
00334 
00335   TexMatrixAttrib *attrib = new TexMatrixAttrib;
00336 
00337   Stages::const_iterator ai, bi;
00338   ai = _stages.begin();
00339   bi = ta->_stages.begin();
00340   while (ai != _stages.end() && bi != ta->_stages.end()) {
00341     if ((*ai)._stage < (*bi)._stage) {
00342       // This stage is in a but not in b.
00343       attrib->_stages.insert(attrib->_stages.end(), *ai);
00344       ++ai;
00345 
00346     } else if ((*bi)._stage < (*ai)._stage) {
00347       // This stage is in b but not in a.
00348       attrib->_stages.insert(attrib->_stages.end(), *bi);
00349       ++bi;
00350 
00351     } else {
00352       // This stage is in both.
00353       if ((*ai)._override == (*bi)._override) {
00354         // Same override; compose them.
00355         CPT(TransformState) new_transform = (*ai)._transform->compose((*bi)._transform);
00356         StageNode sn((*ai)._stage);
00357         sn._transform = new_transform;
00358         sn._override = (*ai)._override;
00359         attrib->_stages.insert(attrib->_stages.end(), sn);
00360       } else if ((*ai)._override < (*bi)._override) {
00361         // Override b wins.
00362         attrib->_stages.insert(attrib->_stages.end(), *bi);
00363       } else {
00364         // Override a wins.
00365         attrib->_stages.insert(attrib->_stages.end(), *ai);
00366       }
00367 
00368       ++ai;
00369       ++bi;
00370     }
00371   }
00372 
00373   while (ai != _stages.end()) {
00374     // This stage is in a but not in b.
00375     attrib->_stages.insert(attrib->_stages.end(), *ai);
00376     ++ai;
00377   }
00378 
00379   while (bi != ta->_stages.end()) {
00380     // This stage is in b but not in a.
00381     attrib->_stages.insert(attrib->_stages.end(), *bi);
00382     ++bi;
00383   }
00384 
00385   return return_new(attrib);
00386 }
00387 
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: TexMatrixAttrib::invert_compose_impl
00390 //       Access: Protected, Virtual
00391 //  Description: Intended to be overridden by derived RenderAttrib
00392 //               types to specify how two consecutive RenderAttrib
00393 //               objects of the same type interact.
00394 //
00395 //               See invert_compose() and compose_impl().
00396 ////////////////////////////////////////////////////////////////////
00397 CPT(RenderAttrib) TexMatrixAttrib::
00398 invert_compose_impl(const RenderAttrib *other) const {
00399   const TexMatrixAttrib *ta;
00400   DCAST_INTO_R(ta, other, 0);
00401 
00402   // The inverse composition works a lot like the composition, except
00403   // we invert the ai stages.
00404 
00405   TexMatrixAttrib *attrib = new TexMatrixAttrib;
00406 
00407   Stages::const_iterator ai, bi;
00408   ai = _stages.begin();
00409   bi = ta->_stages.begin();
00410   while (ai != _stages.end() && bi != ta->_stages.end()) {
00411     if ((*ai)._stage < (*bi)._stage) {
00412       // This stage is in a but not in b.
00413       CPT(TransformState) inv_a = 
00414         (*ai)._transform->invert_compose(TransformState::make_identity());
00415       StageNode sn((*ai)._stage);
00416       sn._transform = inv_a;
00417       sn._override = (*ai)._override;
00418       attrib->_stages.insert(attrib->_stages.end(), sn);
00419       ++ai;
00420 
00421     } else if ((*bi)._stage < (*ai)._stage) {
00422       // This stage is in b but not in a.
00423       attrib->_stages.insert(attrib->_stages.end(), *bi);
00424       ++bi;
00425 
00426     } else {
00427       // This stage is in both.
00428       if ((*ai)._override == (*bi)._override) {
00429         // Same override; compose them.
00430         CPT(TransformState) new_transform = (*ai)._transform->invert_compose((*bi)._transform);
00431         StageNode sn((*ai)._stage);
00432         sn._transform = new_transform;
00433         sn._override = (*ai)._override;
00434         attrib->_stages.insert(attrib->_stages.end(), sn);
00435 
00436       } else if ((*ai)._override < (*bi)._override) {
00437         // Override b wins.
00438         attrib->_stages.insert(attrib->_stages.end(), *bi);
00439 
00440       } else {
00441         // Override a wins.
00442         CPT(TransformState) inv_a = 
00443           (*ai)._transform->invert_compose(TransformState::make_identity());
00444         StageNode sn((*ai)._stage);
00445         sn._transform = inv_a;
00446         sn._override = (*ai)._override;
00447         attrib->_stages.insert(attrib->_stages.end(), sn);
00448       }
00449 
00450       ++ai;
00451       ++bi;
00452     }
00453   }
00454 
00455   while (ai != _stages.end()) {
00456     // This stage is in a but not in b.
00457     CPT(TransformState) inv_a = 
00458       (*ai)._transform->invert_compose(TransformState::make_identity());
00459     StageNode sn((*ai)._stage);
00460     sn._transform = inv_a;
00461     sn._override = (*ai)._override;
00462     attrib->_stages.insert(attrib->_stages.end(), sn);
00463     ++ai;
00464   }
00465 
00466   while (bi != ta->_stages.end()) {
00467     // This stage is in b but not in a.
00468     attrib->_stages.insert(attrib->_stages.end(), *bi);
00469     ++bi;
00470   }
00471 
00472   return return_new(attrib);
00473 }
00474 
00475 ////////////////////////////////////////////////////////////////////
00476 //     Function: TexMatrixAttrib::get_auto_shader_attrib_impl
00477 //       Access: Protected, Virtual
00478 //  Description: 
00479 ////////////////////////////////////////////////////////////////////
00480 CPT(RenderAttrib) TexMatrixAttrib::
00481 get_auto_shader_attrib_impl(const RenderState *state) const {
00482   // For a TexMatrixAttrib, the particular matrix per TextureStage
00483   // isn't important, just whether there is a matrix at all.  So we
00484   // create a new state with an identity matrix everywhere there is a
00485   // matrix at all in the original.
00486 
00487   TexMatrixAttrib *attrib = new TexMatrixAttrib;
00488 
00489   Stages::const_iterator ai;
00490   for (ai = _stages.begin(); ai != _stages.end(); ++ai) {
00491     StageNode sn((*ai)._stage);
00492     sn._transform = TransformState::make_identity();
00493     attrib->_stages.insert(attrib->_stages.end(), sn);
00494   }
00495 
00496   return return_new(attrib);
00497 }
00498 
00499 ////////////////////////////////////////////////////////////////////
00500 //     Function: TexMatrixAttrib::register_with_read_factory
00501 //       Access: Public, Static
00502 //  Description: Tells the BamReader how to create objects of type
00503 //               TexMatrixAttrib.
00504 ////////////////////////////////////////////////////////////////////
00505 void TexMatrixAttrib::
00506 register_with_read_factory() {
00507   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00508 }
00509 
00510 ////////////////////////////////////////////////////////////////////
00511 //     Function: TexMatrixAttrib::write_datagram
00512 //       Access: Public, Virtual
00513 //  Description: Writes the contents of this object to the datagram
00514 //               for shipping out to a Bam file.
00515 ////////////////////////////////////////////////////////////////////
00516 void TexMatrixAttrib::
00517 write_datagram(BamWriter *manager, Datagram &dg) {
00518   RenderAttrib::write_datagram(manager, dg);
00519 
00520   dg.add_uint16(_stages.size());
00521 
00522   Stages::const_iterator si;
00523   for (si = _stages.begin(); si != _stages.end(); ++si) {
00524     const StageNode &sn = (*si);
00525 
00526     manager->write_pointer(dg, sn._stage);
00527     manager->write_pointer(dg, sn._transform);
00528     dg.add_int32(sn._override);
00529   }
00530 }
00531 
00532 ////////////////////////////////////////////////////////////////////
00533 //     Function: TexMatrixAttrib::complete_pointers
00534 //       Access: Public, Virtual
00535 //  Description: Receives an array of pointers, one for each time
00536 //               manager->read_pointer() was called in fillin().
00537 //               Returns the number of pointers processed.
00538 ////////////////////////////////////////////////////////////////////
00539 int TexMatrixAttrib::
00540 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00541   int pi = RenderAttrib::complete_pointers(p_list, manager);
00542 
00543   for (size_t sni = 0; sni < _stages.size(); ++sni) {
00544     // Filter the TextureStage through the TextureStagePool.
00545     PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]);
00546     ts = TextureStagePool::get_stage(ts);
00547 
00548     const TransformState *transform = DCAST(TransformState, p_list[pi++]);
00549     
00550     StageNode &sn = _stages[sni];
00551     sn._stage = ts;
00552     sn._transform = transform;
00553   }
00554   _stages.sort();
00555 
00556   return pi;
00557 }
00558 
00559 ////////////////////////////////////////////////////////////////////
00560 //     Function: TexMatrixAttrib::make_from_bam
00561 //       Access: Protected, Static
00562 //  Description: This function is called by the BamReader's factory
00563 //               when a new object of type TexMatrixAttrib is encountered
00564 //               in the Bam file.  It should create the TexMatrixAttrib
00565 //               and extract its information from the file.
00566 ////////////////////////////////////////////////////////////////////
00567 TypedWritable *TexMatrixAttrib::
00568 make_from_bam(const FactoryParams &params) {
00569   TexMatrixAttrib *attrib = new TexMatrixAttrib;
00570   DatagramIterator scan;
00571   BamReader *manager;
00572 
00573   parse_params(params, scan, manager);
00574   attrib->fillin(scan, manager);
00575 
00576   return attrib;
00577 }
00578 
00579 ////////////////////////////////////////////////////////////////////
00580 //     Function: TexMatrixAttrib::fillin
00581 //       Access: Protected
00582 //  Description: This internal function is called by make_from_bam to
00583 //               read in all of the relevant data from the BamFile for
00584 //               the new TexMatrixAttrib.
00585 ////////////////////////////////////////////////////////////////////
00586 void TexMatrixAttrib::
00587 fillin(DatagramIterator &scan, BamReader *manager) {
00588   RenderAttrib::fillin(scan, manager);
00589 
00590   size_t num_stages = scan.get_uint16();
00591   for (size_t i = 0; i < num_stages; i++) {
00592     manager->read_pointer(scan);
00593     manager->read_pointer(scan);
00594     int override = 0;
00595     if (manager->get_file_minor_ver() >= 24) {
00596       override = scan.get_int32();
00597     }
00598 
00599     StageNode sn(NULL);
00600     sn._override = override;
00601     _stages.push_back(sn);
00602   }
00603 }
 All Classes Functions Variables Enumerations