00001 // Filename: lightAttrib.cxx 00002 // Created by: drose (26Mar02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "lightAttrib.h" 00020 #include "pandaNode.h" 00021 #include "graphicsStateGuardianBase.h" 00022 #include "bamReader.h" 00023 #include "bamWriter.h" 00024 #include "datagram.h" 00025 #include "datagramIterator.h" 00026 00027 TypeHandle LightAttrib::_type_handle; 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: LightAttrib::make_all_off 00031 // Access: Published, Static 00032 // Description: Constructs a new LightAttrib object that turns off 00033 // all lights (and hence disables lighting). 00034 //////////////////////////////////////////////////////////////////// 00035 CPT(RenderAttrib) LightAttrib:: 00036 make_all_off() { 00037 LightAttrib *attrib = new LightAttrib; 00038 attrib->_operation = O_set; 00039 return return_new(attrib); 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: LightAttrib::make 00044 // Access: Published, Static 00045 // Description: Constructs a new LightAttrib object that turns on (or 00046 // off, according to op) the indicate light(s). 00047 //////////////////////////////////////////////////////////////////// 00048 CPT(RenderAttrib) LightAttrib:: 00049 make(LightAttrib::Operation op, Light *light) { 00050 LightAttrib *attrib = new LightAttrib; 00051 attrib->_operation = op; 00052 attrib->_lights.push_back(light); 00053 return return_new(attrib); 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: LightAttrib::make 00058 // Access: Published, Static 00059 // Description: Constructs a new LightAttrib object that turns on (or 00060 // off, according to op) the indicate light(s). 00061 //////////////////////////////////////////////////////////////////// 00062 CPT(RenderAttrib) LightAttrib:: 00063 make(LightAttrib::Operation op, Light *light1, Light *light2) { 00064 LightAttrib *attrib = new LightAttrib; 00065 attrib->_operation = op; 00066 attrib->_lights.push_back(light1); 00067 attrib->_lights.push_back(light2); 00068 00069 attrib->_lights.sort(); 00070 return return_new(attrib); 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: LightAttrib::make 00075 // Access: Published, Static 00076 // Description: Constructs a new LightAttrib object that turns on (or 00077 // off, according to op) the indicate light(s). 00078 //////////////////////////////////////////////////////////////////// 00079 CPT(RenderAttrib) LightAttrib:: 00080 make(LightAttrib::Operation op, Light *light1, Light *light2, 00081 Light *light3) { 00082 LightAttrib *attrib = new LightAttrib; 00083 attrib->_operation = op; 00084 attrib->_lights.push_back(light1); 00085 attrib->_lights.push_back(light2); 00086 attrib->_lights.push_back(light3); 00087 00088 attrib->_lights.sort(); 00089 return return_new(attrib); 00090 } 00091 00092 //////////////////////////////////////////////////////////////////// 00093 // Function: LightAttrib::make 00094 // Access: Published, Static 00095 // Description: Constructs a new LightAttrib object that turns on (or 00096 // off, according to op) the indicate light(s). 00097 //////////////////////////////////////////////////////////////////// 00098 CPT(RenderAttrib) LightAttrib:: 00099 make(LightAttrib::Operation op, Light *light1, Light *light2, 00100 Light *light3, Light *light4) { 00101 LightAttrib *attrib = new LightAttrib; 00102 attrib->_operation = op; 00103 attrib->_lights.push_back(light1); 00104 attrib->_lights.push_back(light2); 00105 attrib->_lights.push_back(light3); 00106 attrib->_lights.push_back(light4); 00107 00108 attrib->_lights.sort(); 00109 return return_new(attrib); 00110 } 00111 00112 //////////////////////////////////////////////////////////////////// 00113 // Function: LightAttrib::has_light 00114 // Access: Published 00115 // Description: Returns true if the indicated light is listed in the 00116 // attrib, false otherwise. 00117 //////////////////////////////////////////////////////////////////// 00118 bool LightAttrib:: 00119 has_light(Light *light) const { 00120 return _lights.find(light) != _lights.end(); 00121 } 00122 00123 //////////////////////////////////////////////////////////////////// 00124 // Function: LightAttrib::issue 00125 // Access: Public, Virtual 00126 // Description: Calls the appropriate method on the indicated GSG 00127 // to issue the graphics commands appropriate to the 00128 // given attribute. This is normally called 00129 // (indirectly) only from 00130 // GraphicsStateGuardian::set_state() or modify_state(). 00131 //////////////////////////////////////////////////////////////////// 00132 void LightAttrib:: 00133 issue(GraphicsStateGuardianBase *gsg) const { 00134 gsg->issue_light(this); 00135 } 00136 00137 //////////////////////////////////////////////////////////////////// 00138 // Function: LightAttrib::output 00139 // Access: Public, Virtual 00140 // Description: 00141 //////////////////////////////////////////////////////////////////// 00142 void LightAttrib:: 00143 output(ostream &out) const { 00144 out << get_type() << ":"; 00145 if (_operation == O_set && _lights.empty()) { 00146 out << "all off"; 00147 } else { 00148 switch (_operation) { 00149 case O_set: 00150 out << "set"; 00151 break; 00152 case O_add: 00153 out << "add"; 00154 break; 00155 case O_remove: 00156 out << "remove"; 00157 break; 00158 } 00159 00160 Lights::const_iterator li; 00161 for (li = _lights.begin(); li != _lights.end(); ++li) { 00162 Light *light = (*li); 00163 out << " " << light->get_type(); 00164 } 00165 } 00166 } 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: LightAttrib::compare_to_impl 00170 // Access: Protected, Virtual 00171 // Description: Intended to be overridden by derived LightAttrib 00172 // types to return a unique number indicating whether 00173 // this LightAttrib is equivalent to the other one. 00174 // 00175 // This should return 0 if the two LightAttrib objects 00176 // are equivalent, a number less than zero if this one 00177 // should be sorted before the other one, and a number 00178 // greater than zero otherwise. 00179 // 00180 // This will only be called with two LightAttrib 00181 // objects whose get_type() functions return the same. 00182 //////////////////////////////////////////////////////////////////// 00183 int LightAttrib:: 00184 compare_to_impl(const RenderAttrib *other) const { 00185 const LightAttrib *ta; 00186 DCAST_INTO_R(ta, other, 0); 00187 00188 if (_operation != ta->_operation) { 00189 return (int)_operation - (int)ta->_operation; 00190 } 00191 00192 Lights::const_iterator li = _lights.begin(); 00193 Lights::const_iterator oli = ta->_lights.begin(); 00194 00195 while (li != _lights.end() && oli != ta->_lights.end()) { 00196 Light *light = (*li); 00197 Light *other_light = (*oli); 00198 00199 if (light != other_light) { 00200 return light < other_light ? -1 : 1; 00201 } 00202 00203 ++li; 00204 ++oli; 00205 } 00206 00207 if (li != _lights.end()) { 00208 return 1; 00209 } 00210 if (oli != ta->_lights.end()) { 00211 return -1; 00212 } 00213 00214 return 0; 00215 } 00216 00217 //////////////////////////////////////////////////////////////////// 00218 // Function: LightAttrib::compose_impl 00219 // Access: Protected, Virtual 00220 // Description: Intended to be overridden by derived RenderAttrib 00221 // types to specify how two consecutive RenderAttrib 00222 // objects of the same type interact. 00223 // 00224 // This should return the result of applying the other 00225 // RenderAttrib to a node in the scene graph below this 00226 // RenderAttrib, which was already applied. In most 00227 // cases, the result is the same as the other 00228 // RenderAttrib (that is, a subsequent RenderAttrib 00229 // completely replaces the preceding one). On the other 00230 // hand, some kinds of RenderAttrib (for instance, 00231 // ColorTransformAttrib) might combine in meaningful 00232 // ways. 00233 //////////////////////////////////////////////////////////////////// 00234 CPT(RenderAttrib) LightAttrib:: 00235 compose_impl(const RenderAttrib *other) const { 00236 const LightAttrib *ta; 00237 DCAST_INTO_R(ta, other, 0); 00238 00239 if (ta->_operation == O_set) { 00240 // If the other type is O_set, it doesn't matter what we are. 00241 return ta; 00242 } 00243 00244 if (_operation == ta->_operation) { 00245 // If the operation types match, the composition is simply the 00246 // union. 00247 return do_add(ta, _operation); 00248 00249 } else if (ta->_operation == O_remove) { 00250 // If the other operation type is remove, and our type is add or 00251 // set, then remove. 00252 return do_remove(ta, _operation); 00253 00254 } else if (_operation == O_remove) { 00255 // If our type is remove, then the other one wins. 00256 return ta; 00257 00258 } else { 00259 // Otherwise, the result is the union. 00260 return do_add(ta, _operation); 00261 } 00262 } 00263 00264 //////////////////////////////////////////////////////////////////// 00265 // Function: LightAttrib::invert_compose_impl 00266 // Access: Protected, Virtual 00267 // Description: Intended to be overridden by derived RenderAttrib 00268 // types to specify how two consecutive RenderAttrib 00269 // objects of the same type interact. 00270 // 00271 // See invert_compose() and compose_impl(). 00272 //////////////////////////////////////////////////////////////////// 00273 CPT(RenderAttrib) LightAttrib:: 00274 invert_compose_impl(const RenderAttrib *other) const { 00275 // I think in this case the other attrib always wins. Maybe this 00276 // needs a bit more thought. It's hard to imagine that it's even 00277 // important to compute this properly. 00278 return other; 00279 } 00280 00281 //////////////////////////////////////////////////////////////////// 00282 // Function: LightAttrib::make_default_impl 00283 // Access: Protected, Virtual 00284 // Description: Intended to be overridden by derived LightAttrib 00285 // types to specify what the default property for a 00286 // LightAttrib of this type should be. 00287 // 00288 // This should return a newly-allocated LightAttrib of 00289 // the same type that corresponds to whatever the 00290 // standard default for this kind of LightAttrib is. 00291 //////////////////////////////////////////////////////////////////// 00292 RenderAttrib *LightAttrib:: 00293 make_default_impl() const { 00294 return new LightAttrib; 00295 } 00296 00297 //////////////////////////////////////////////////////////////////// 00298 // Function: LightAttrib::do_add 00299 // Access: Private 00300 // Description: Returns a new LightAttrib that represents all the 00301 // lights of this attrib, with those of the other one 00302 // added in. 00303 //////////////////////////////////////////////////////////////////// 00304 CPT(RenderAttrib) LightAttrib:: 00305 do_add(const LightAttrib *other, LightAttrib::Operation op) const { 00306 Lights::const_iterator ai = _lights.begin(); 00307 Lights::const_iterator bi = other->_lights.begin(); 00308 00309 // Create a new LightAttrib that will hold the result. 00310 LightAttrib *new_attrib = new LightAttrib; 00311 new_attrib->_operation = op; 00312 back_insert_iterator<Lights> result = 00313 back_inserter(new_attrib->_lights); 00314 00315 while (ai != _lights.end() && bi != other->_lights.end()) { 00316 if ((*ai) < (*bi)) { 00317 // Here is a light that we have in the original, which is not 00318 // present in the secondary. 00319 *result = *ai; 00320 ++ai; 00321 ++result; 00322 } else if ((*bi) < (*ai)) { 00323 // Here is a new light we have in the secondary, that was not 00324 // present in the original. 00325 *result = *bi; 00326 ++bi; 00327 ++result; 00328 } else { 00329 // Here is a light we have in both. 00330 *result = *ai; 00331 ++ai; 00332 ++bi; 00333 ++result; 00334 } 00335 } 00336 00337 while (ai != _lights.end()) { 00338 *result = *ai; 00339 ++ai; 00340 ++result; 00341 } 00342 00343 while (bi != other->_lights.end()) { 00344 *result = *bi; 00345 ++bi; 00346 ++result; 00347 } 00348 00349 return return_new(new_attrib); 00350 } 00351 00352 //////////////////////////////////////////////////////////////////// 00353 // Function: LightAttrib::do_remove 00354 // Access: Private 00355 // Description: Returns a new LightAttrib that represents all the 00356 // lights of this attrib, with those of the other one 00357 // removed. 00358 //////////////////////////////////////////////////////////////////// 00359 CPT(RenderAttrib) LightAttrib:: 00360 do_remove(const LightAttrib *other, LightAttrib::Operation op) const { 00361 Lights::const_iterator ai = _lights.begin(); 00362 Lights::const_iterator bi = other->_lights.begin(); 00363 00364 // Create a new LightAttrib that will hold the result. 00365 LightAttrib *new_attrib = new LightAttrib; 00366 new_attrib->_operation = op; 00367 back_insert_iterator<Lights> result = 00368 back_inserter(new_attrib->_lights); 00369 00370 while (ai != _lights.end() && bi != other->_lights.end()) { 00371 if ((*ai) < (*bi)) { 00372 // Here is a light that we have in the original, which is 00373 // not present in the secondary. Keep it. 00374 *result = *ai; 00375 ++ai; 00376 ++result; 00377 } else if ((*bi) < (*ai)) { 00378 // Here is a new light we have in the secondary, that was 00379 // not present in the original. Ignore it. 00380 ++bi; 00381 } else { 00382 // Here is a light we have in both. Drop it. 00383 ++ai; 00384 ++bi; 00385 } 00386 } 00387 00388 while (ai != _lights.end()) { 00389 *result = *ai; 00390 ++ai; 00391 ++result; 00392 } 00393 00394 return return_new(new_attrib); 00395 } 00396 00397 //////////////////////////////////////////////////////////////////// 00398 // Function: LightAttrib::register_with_read_factory 00399 // Access: Public, Static 00400 // Description: Tells the BamReader how to create objects of type 00401 // LightAttrib. 00402 //////////////////////////////////////////////////////////////////// 00403 void LightAttrib:: 00404 register_with_read_factory() { 00405 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00406 } 00407 00408 //////////////////////////////////////////////////////////////////// 00409 // Function: LightAttrib::write_datagram 00410 // Access: Public, Virtual 00411 // Description: Writes the contents of this object to the datagram 00412 // for shipping out to a Bam file. 00413 //////////////////////////////////////////////////////////////////// 00414 void LightAttrib:: 00415 write_datagram(BamWriter *manager, Datagram &dg) { 00416 RenderAttrib::write_datagram(manager, dg); 00417 00418 dg.add_int8((int)_operation); 00419 PN_uint16 num_lights = _lights.size(); 00420 nassertv(num_lights == _lights.size()); 00421 dg.add_uint16(num_lights); 00422 00423 Lights::const_iterator li; 00424 for (li = _lights.begin(); li != _lights.end(); ++li) { 00425 Light *light = (*li); 00426 manager->write_pointer(dg, light->as_node()); 00427 } 00428 } 00429 00430 //////////////////////////////////////////////////////////////////// 00431 // Function: LightAttrib::complete_pointers 00432 // Access: Public, Virtual 00433 // Description: Receives an array of pointers, one for each time 00434 // manager->read_pointer() was called in fillin(). 00435 // Returns the number of pointers processed. 00436 //////////////////////////////////////////////////////////////////// 00437 int LightAttrib:: 00438 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00439 int pi = RenderAttrib::complete_pointers(p_list, manager); 00440 00441 Lights::iterator li; 00442 for (li = _lights.begin(); li != _lights.end(); ++li) { 00443 PandaNode *node; 00444 DCAST_INTO_R(node, p_list[pi++], pi); 00445 (*li) = node->as_light(); 00446 } 00447 00448 return pi; 00449 } 00450 00451 //////////////////////////////////////////////////////////////////// 00452 // Function: LightAttrib::make_from_bam 00453 // Access: Protected, Static 00454 // Description: This function is called by the BamReader's factory 00455 // when a new object of type LightAttrib is encountered 00456 // in the Bam file. It should create the LightAttrib 00457 // and extract its information from the file. 00458 //////////////////////////////////////////////////////////////////// 00459 TypedWritable *LightAttrib:: 00460 make_from_bam(const FactoryParams ¶ms) { 00461 LightAttrib *attrib = new LightAttrib; 00462 DatagramIterator scan; 00463 BamReader *manager; 00464 00465 parse_params(params, scan, manager); 00466 attrib->fillin(scan, manager); 00467 00468 return attrib; 00469 } 00470 00471 //////////////////////////////////////////////////////////////////// 00472 // Function: LightAttrib::fillin 00473 // Access: Protected 00474 // Description: This internal function is called by make_from_bam to 00475 // read in all of the relevant data from the BamFile for 00476 // the new LightAttrib. 00477 //////////////////////////////////////////////////////////////////// 00478 void LightAttrib:: 00479 fillin(DatagramIterator &scan, BamReader *manager) { 00480 RenderAttrib::fillin(scan, manager); 00481 00482 _operation = (Operation)scan.get_int8(); 00483 int num_lights = scan.get_uint16(); 00484 00485 for (int i = 0; i < num_lights; i++) { 00486 manager->read_pointer(scan); 00487 _lights.push_back(NULL); 00488 } 00489 }