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 LMatrix4f &mat) { 00063 pgraph_cat.warning() 00064 << "Using deprecated TexMatrixAttrib interface.\n"; 00065 if (mat == LMatrix4f::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 LMatrix4f &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 LMatrix4f &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::compose_impl 00287 // Access: Protected, Virtual 00288 // Description: Intended to be overridden by derived RenderAttrib 00289 // types to specify how two consecutive RenderAttrib 00290 // objects of the same type interact. 00291 // 00292 // This should return the result of applying the other 00293 // RenderAttrib to a node in the scene graph below this 00294 // RenderAttrib, which was already applied. In most 00295 // cases, the result is the same as the other 00296 // RenderAttrib (that is, a subsequent RenderAttrib 00297 // completely replaces the preceding one). On the other 00298 // hand, some kinds of RenderAttrib (for instance, 00299 // ColorTransformAttrib) might combine in meaningful 00300 // ways. 00301 //////////////////////////////////////////////////////////////////// 00302 CPT(RenderAttrib) TexMatrixAttrib:: 00303 compose_impl(const RenderAttrib *other) const { 00304 const TexMatrixAttrib *ta; 00305 DCAST_INTO_R(ta, other, 0); 00306 00307 // The composition is the union of the two attribs. In the case 00308 // when a stage is in both attribs, we compose the stages. 00309 00310 TexMatrixAttrib *attrib = new TexMatrixAttrib; 00311 00312 Stages::const_iterator ai, bi; 00313 ai = _stages.begin(); 00314 bi = ta->_stages.begin(); 00315 while (ai != _stages.end() && bi != ta->_stages.end()) { 00316 if ((*ai)._stage < (*bi)._stage) { 00317 // This stage is in a but not in b. 00318 attrib->_stages.insert(attrib->_stages.end(), *ai); 00319 ++ai; 00320 00321 } else if ((*bi)._stage < (*ai)._stage) { 00322 // This stage is in b but not in a. 00323 attrib->_stages.insert(attrib->_stages.end(), *bi); 00324 ++bi; 00325 00326 } else { 00327 // This stage is in both. 00328 if ((*ai)._override == (*bi)._override) { 00329 // Same override; compose them. 00330 CPT(TransformState) new_transform = (*ai)._transform->compose((*bi)._transform); 00331 StageNode sn((*ai)._stage); 00332 sn._transform = new_transform; 00333 sn._override = (*ai)._override; 00334 attrib->_stages.insert(attrib->_stages.end(), sn); 00335 } else if ((*ai)._override < (*bi)._override) { 00336 // Override b wins. 00337 attrib->_stages.insert(attrib->_stages.end(), *bi); 00338 } else { 00339 // Override a wins. 00340 attrib->_stages.insert(attrib->_stages.end(), *ai); 00341 } 00342 00343 ++ai; 00344 ++bi; 00345 } 00346 } 00347 00348 while (ai != _stages.end()) { 00349 // This stage is in a but not in b. 00350 attrib->_stages.insert(attrib->_stages.end(), *ai); 00351 ++ai; 00352 } 00353 00354 while (bi != ta->_stages.end()) { 00355 // This stage is in b but not in a. 00356 attrib->_stages.insert(attrib->_stages.end(), *bi); 00357 ++bi; 00358 } 00359 00360 return return_new(attrib); 00361 } 00362 00363 //////////////////////////////////////////////////////////////////// 00364 // Function: TexMatrixAttrib::invert_compose_impl 00365 // Access: Protected, Virtual 00366 // Description: Intended to be overridden by derived RenderAttrib 00367 // types to specify how two consecutive RenderAttrib 00368 // objects of the same type interact. 00369 // 00370 // See invert_compose() and compose_impl(). 00371 //////////////////////////////////////////////////////////////////// 00372 CPT(RenderAttrib) TexMatrixAttrib:: 00373 invert_compose_impl(const RenderAttrib *other) const { 00374 const TexMatrixAttrib *ta; 00375 DCAST_INTO_R(ta, other, 0); 00376 00377 // The inverse composition works a lot like the composition, except 00378 // we invert the ai stages. 00379 00380 TexMatrixAttrib *attrib = new TexMatrixAttrib; 00381 00382 Stages::const_iterator ai, bi; 00383 ai = _stages.begin(); 00384 bi = ta->_stages.begin(); 00385 while (ai != _stages.end() && bi != ta->_stages.end()) { 00386 if ((*ai)._stage < (*bi)._stage) { 00387 // This stage is in a but not in b. 00388 CPT(TransformState) inv_a = 00389 (*ai)._transform->invert_compose(TransformState::make_identity()); 00390 StageNode sn((*ai)._stage); 00391 sn._transform = inv_a; 00392 sn._override = (*ai)._override; 00393 attrib->_stages.insert(attrib->_stages.end(), sn); 00394 ++ai; 00395 00396 } else if ((*bi)._stage < (*ai)._stage) { 00397 // This stage is in b but not in a. 00398 attrib->_stages.insert(attrib->_stages.end(), *bi); 00399 ++bi; 00400 00401 } else { 00402 // This stage is in both. 00403 if ((*ai)._override == (*bi)._override) { 00404 // Same override; compose them. 00405 CPT(TransformState) new_transform = (*ai)._transform->invert_compose((*bi)._transform); 00406 StageNode sn((*ai)._stage); 00407 sn._transform = new_transform; 00408 sn._override = (*ai)._override; 00409 attrib->_stages.insert(attrib->_stages.end(), sn); 00410 00411 } else if ((*ai)._override < (*bi)._override) { 00412 // Override b wins. 00413 attrib->_stages.insert(attrib->_stages.end(), *bi); 00414 00415 } else { 00416 // Override a wins. 00417 CPT(TransformState) inv_a = 00418 (*ai)._transform->invert_compose(TransformState::make_identity()); 00419 StageNode sn((*ai)._stage); 00420 sn._transform = inv_a; 00421 sn._override = (*ai)._override; 00422 attrib->_stages.insert(attrib->_stages.end(), sn); 00423 } 00424 00425 ++ai; 00426 ++bi; 00427 } 00428 } 00429 00430 while (ai != _stages.end()) { 00431 // This stage is in a but not in b. 00432 CPT(TransformState) inv_a = 00433 (*ai)._transform->invert_compose(TransformState::make_identity()); 00434 StageNode sn((*ai)._stage); 00435 sn._transform = inv_a; 00436 sn._override = (*ai)._override; 00437 attrib->_stages.insert(attrib->_stages.end(), sn); 00438 ++ai; 00439 } 00440 00441 while (bi != ta->_stages.end()) { 00442 // This stage is in b but not in a. 00443 attrib->_stages.insert(attrib->_stages.end(), *bi); 00444 ++bi; 00445 } 00446 00447 return return_new(attrib); 00448 } 00449 00450 //////////////////////////////////////////////////////////////////// 00451 // Function: TexMatrixAttrib::register_with_read_factory 00452 // Access: Public, Static 00453 // Description: Tells the BamReader how to create objects of type 00454 // TexMatrixAttrib. 00455 //////////////////////////////////////////////////////////////////// 00456 void TexMatrixAttrib:: 00457 register_with_read_factory() { 00458 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00459 } 00460 00461 //////////////////////////////////////////////////////////////////// 00462 // Function: TexMatrixAttrib::write_datagram 00463 // Access: Public, Virtual 00464 // Description: Writes the contents of this object to the datagram 00465 // for shipping out to a Bam file. 00466 //////////////////////////////////////////////////////////////////// 00467 void TexMatrixAttrib:: 00468 write_datagram(BamWriter *manager, Datagram &dg) { 00469 RenderAttrib::write_datagram(manager, dg); 00470 00471 dg.add_uint16(_stages.size()); 00472 00473 Stages::const_iterator si; 00474 for (si = _stages.begin(); si != _stages.end(); ++si) { 00475 const StageNode &sn = (*si); 00476 00477 manager->write_pointer(dg, sn._stage); 00478 manager->write_pointer(dg, sn._transform); 00479 dg.add_int32(sn._override); 00480 } 00481 } 00482 00483 //////////////////////////////////////////////////////////////////// 00484 // Function: TexMatrixAttrib::complete_pointers 00485 // Access: Public, Virtual 00486 // Description: Receives an array of pointers, one for each time 00487 // manager->read_pointer() was called in fillin(). 00488 // Returns the number of pointers processed. 00489 //////////////////////////////////////////////////////////////////// 00490 int TexMatrixAttrib:: 00491 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00492 int pi = RenderAttrib::complete_pointers(p_list, manager); 00493 00494 for (size_t sni = 0; sni < _stages.size(); ++sni) { 00495 // Filter the TextureStage through the TextureStagePool. 00496 PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]); 00497 ts = TextureStagePool::get_stage(ts); 00498 00499 const TransformState *transform = DCAST(TransformState, p_list[pi++]); 00500 00501 StageNode &sn = _stages[sni]; 00502 sn._stage = ts; 00503 sn._transform = transform; 00504 } 00505 _stages.sort(); 00506 00507 return pi; 00508 } 00509 00510 //////////////////////////////////////////////////////////////////// 00511 // Function: TexMatrixAttrib::make_from_bam 00512 // Access: Protected, Static 00513 // Description: This function is called by the BamReader's factory 00514 // when a new object of type TexMatrixAttrib is encountered 00515 // in the Bam file. It should create the TexMatrixAttrib 00516 // and extract its information from the file. 00517 //////////////////////////////////////////////////////////////////// 00518 TypedWritable *TexMatrixAttrib:: 00519 make_from_bam(const FactoryParams ¶ms) { 00520 TexMatrixAttrib *attrib = new TexMatrixAttrib; 00521 DatagramIterator scan; 00522 BamReader *manager; 00523 00524 parse_params(params, scan, manager); 00525 attrib->fillin(scan, manager); 00526 00527 return attrib; 00528 } 00529 00530 //////////////////////////////////////////////////////////////////// 00531 // Function: TexMatrixAttrib::fillin 00532 // Access: Protected 00533 // Description: This internal function is called by make_from_bam to 00534 // read in all of the relevant data from the BamFile for 00535 // the new TexMatrixAttrib. 00536 //////////////////////////////////////////////////////////////////// 00537 void TexMatrixAttrib:: 00538 fillin(DatagramIterator &scan, BamReader *manager) { 00539 RenderAttrib::fillin(scan, manager); 00540 00541 size_t num_stages = scan.get_uint16(); 00542 for (size_t i = 0; i < num_stages; i++) { 00543 manager->read_pointer(scan); 00544 manager->read_pointer(scan); 00545 int override = 0; 00546 if (manager->get_file_minor_ver() >= 24) { 00547 override = scan.get_int32(); 00548 } 00549 00550 StageNode sn(NULL); 00551 sn._override = override; 00552 _stages.push_back(sn); 00553 } 00554 }