Panda3D
|
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 ¶ms) { 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 }