lightAttrib.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. // Filename: lightAttrib.cxx
  2. // Created by: drose (26Mar02)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "lightAttrib.h"
  19. #include "pandaNode.h"
  20. #include "graphicsStateGuardianBase.h"
  21. #include "bamReader.h"
  22. #include "bamWriter.h"
  23. #include "datagram.h"
  24. #include "datagramIterator.h"
  25. TypeHandle LightAttrib::_type_handle;
  26. ////////////////////////////////////////////////////////////////////
  27. // Function: LightAttrib::make_all_off
  28. // Access: Published, Static
  29. // Description: Constructs a new LightAttrib object that turns off
  30. // all lights (and hence disables lighting).
  31. ////////////////////////////////////////////////////////////////////
  32. CPT(RenderAttrib) LightAttrib::
  33. make_all_off() {
  34. LightAttrib *attrib = new LightAttrib;
  35. attrib->_operation = O_set;
  36. return return_new(attrib);
  37. }
  38. ////////////////////////////////////////////////////////////////////
  39. // Function: LightAttrib::make
  40. // Access: Published, Static
  41. // Description: Constructs a new LightAttrib object that turns on (or
  42. // off, according to op) the indicate light(s).
  43. ////////////////////////////////////////////////////////////////////
  44. CPT(RenderAttrib) LightAttrib::
  45. make(LightAttrib::Operation op, Light *light) {
  46. LightAttrib *attrib = new LightAttrib;
  47. attrib->_operation = op;
  48. attrib->_lights.push_back(light);
  49. return return_new(attrib);
  50. }
  51. ////////////////////////////////////////////////////////////////////
  52. // Function: LightAttrib::make
  53. // Access: Published, Static
  54. // Description: Constructs a new LightAttrib object that turns on (or
  55. // off, according to op) the indicate light(s).
  56. ////////////////////////////////////////////////////////////////////
  57. CPT(RenderAttrib) LightAttrib::
  58. make(LightAttrib::Operation op, Light *light1, Light *light2) {
  59. LightAttrib *attrib = new LightAttrib;
  60. attrib->_operation = op;
  61. attrib->_lights.push_back(light1);
  62. attrib->_lights.push_back(light2);
  63. attrib->_lights.sort();
  64. return return_new(attrib);
  65. }
  66. ////////////////////////////////////////////////////////////////////
  67. // Function: LightAttrib::make
  68. // Access: Published, Static
  69. // Description: Constructs a new LightAttrib object that turns on (or
  70. // off, according to op) the indicate light(s).
  71. ////////////////////////////////////////////////////////////////////
  72. CPT(RenderAttrib) LightAttrib::
  73. make(LightAttrib::Operation op, Light *light1, Light *light2,
  74. Light *light3) {
  75. LightAttrib *attrib = new LightAttrib;
  76. attrib->_operation = op;
  77. attrib->_lights.push_back(light1);
  78. attrib->_lights.push_back(light2);
  79. attrib->_lights.push_back(light3);
  80. attrib->_lights.sort();
  81. return return_new(attrib);
  82. }
  83. ////////////////////////////////////////////////////////////////////
  84. // Function: LightAttrib::make
  85. // Access: Published, Static
  86. // Description: Constructs a new LightAttrib object that turns on (or
  87. // off, according to op) the indicate light(s).
  88. ////////////////////////////////////////////////////////////////////
  89. CPT(RenderAttrib) LightAttrib::
  90. make(LightAttrib::Operation op, Light *light1, Light *light2,
  91. Light *light3, Light *light4) {
  92. LightAttrib *attrib = new LightAttrib;
  93. attrib->_operation = op;
  94. attrib->_lights.push_back(light1);
  95. attrib->_lights.push_back(light2);
  96. attrib->_lights.push_back(light3);
  97. attrib->_lights.push_back(light4);
  98. attrib->_lights.sort();
  99. return return_new(attrib);
  100. }
  101. ////////////////////////////////////////////////////////////////////
  102. // Function: LightAttrib::has_light
  103. // Access: Published
  104. // Description: Returns true if the indicated light is listed in the
  105. // attrib, false otherwise.
  106. ////////////////////////////////////////////////////////////////////
  107. bool LightAttrib::
  108. has_light(Light *light) const {
  109. return _lights.find(light) != _lights.end();
  110. }
  111. ////////////////////////////////////////////////////////////////////
  112. // Function: LightAttrib::issue
  113. // Access: Public, Virtual
  114. // Description: Calls the appropriate method on the indicated GSG
  115. // to issue the graphics commands appropriate to the
  116. // given attribute. This is normally called
  117. // (indirectly) only from
  118. // GraphicsStateGuardian::set_state() or modify_state().
  119. ////////////////////////////////////////////////////////////////////
  120. void LightAttrib::
  121. issue(GraphicsStateGuardianBase *gsg) const {
  122. gsg->issue_light(this);
  123. }
  124. ////////////////////////////////////////////////////////////////////
  125. // Function: LightAttrib::output
  126. // Access: Public, Virtual
  127. // Description:
  128. ////////////////////////////////////////////////////////////////////
  129. void LightAttrib::
  130. output(ostream &out) const {
  131. out << get_type() << ":";
  132. if (_operation == O_set && _lights.empty()) {
  133. out << "all off";
  134. } else {
  135. switch (_operation) {
  136. case O_set:
  137. out << "set";
  138. break;
  139. case O_add:
  140. out << "add";
  141. break;
  142. case O_remove:
  143. out << "remove";
  144. break;
  145. }
  146. Lights::const_iterator li;
  147. for (li = _lights.begin(); li != _lights.end(); ++li) {
  148. Light *light = (*li);
  149. out << " " << light->get_type();
  150. }
  151. }
  152. }
  153. ////////////////////////////////////////////////////////////////////
  154. // Function: LightAttrib::compare_to_impl
  155. // Access: Protected, Virtual
  156. // Description: Intended to be overridden by derived LightAttrib
  157. // types to return a unique number indicating whether
  158. // this LightAttrib is equivalent to the other one.
  159. //
  160. // This should return 0 if the two LightAttrib objects
  161. // are equivalent, a number less than zero if this one
  162. // should be sorted before the other one, and a number
  163. // greater than zero otherwise.
  164. //
  165. // This will only be called with two LightAttrib
  166. // objects whose get_type() functions return the same.
  167. ////////////////////////////////////////////////////////////////////
  168. int LightAttrib::
  169. compare_to_impl(const RenderAttrib *other) const {
  170. const LightAttrib *ta;
  171. DCAST_INTO_R(ta, other, 0);
  172. if (_operation != ta->_operation) {
  173. return (int)_operation - (int)ta->_operation;
  174. }
  175. Lights::const_iterator li = _lights.begin();
  176. Lights::const_iterator oli = ta->_lights.begin();
  177. while (li != _lights.end() && oli != ta->_lights.end()) {
  178. Light *light = (*li);
  179. Light *other_light = (*oli);
  180. if (light != other_light) {
  181. return light < other_light ? -1 : 1;
  182. }
  183. ++li;
  184. ++oli;
  185. }
  186. if (li != _lights.end()) {
  187. return 1;
  188. }
  189. if (oli != ta->_lights.end()) {
  190. return -1;
  191. }
  192. return 0;
  193. }
  194. ////////////////////////////////////////////////////////////////////
  195. // Function: LightAttrib::compose_impl
  196. // Access: Protected, Virtual
  197. // Description: Intended to be overridden by derived RenderAttrib
  198. // types to specify how two consecutive RenderAttrib
  199. // objects of the same type interact.
  200. //
  201. // This should return the result of applying the other
  202. // RenderAttrib to a node in the scene graph below this
  203. // RenderAttrib, which was already applied. In most
  204. // cases, the result is the same as the other
  205. // RenderAttrib (that is, a subsequent RenderAttrib
  206. // completely replaces the preceding one). On the other
  207. // hand, some kinds of RenderAttrib (for instance,
  208. // ColorTransformAttrib) might combine in meaningful
  209. // ways.
  210. ////////////////////////////////////////////////////////////////////
  211. CPT(RenderAttrib) LightAttrib::
  212. compose_impl(const RenderAttrib *other) const {
  213. const LightAttrib *ta;
  214. DCAST_INTO_R(ta, other, 0);
  215. if (ta->_operation == O_set) {
  216. // If the other type is O_set, it doesn't matter what we are.
  217. return ta;
  218. }
  219. if (_operation == ta->_operation) {
  220. // If the operation types match, the composition is simply the
  221. // union.
  222. return do_add(ta, _operation);
  223. } else if (ta->_operation == O_remove) {
  224. // If the other operation type is remove, and our type is add or
  225. // set, then remove.
  226. return do_remove(ta, _operation);
  227. } else if (_operation == O_remove) {
  228. // If our type is remove, then the other one wins.
  229. return ta;
  230. } else {
  231. // Otherwise, the result is the union.
  232. return do_add(ta, _operation);
  233. }
  234. }
  235. ////////////////////////////////////////////////////////////////////
  236. // Function: LightAttrib::invert_compose_impl
  237. // Access: Protected, Virtual
  238. // Description: Intended to be overridden by derived RenderAttrib
  239. // types to specify how two consecutive RenderAttrib
  240. // objects of the same type interact.
  241. //
  242. // See invert_compose() and compose_impl().
  243. ////////////////////////////////////////////////////////////////////
  244. CPT(RenderAttrib) LightAttrib::
  245. invert_compose_impl(const RenderAttrib *other) const {
  246. // I think in this case the other attrib always wins. Maybe this
  247. // needs a bit more thought. It's hard to imagine that it's even
  248. // important to compute this properly.
  249. return other;
  250. }
  251. ////////////////////////////////////////////////////////////////////
  252. // Function: LightAttrib::make_default_impl
  253. // Access: Protected, Virtual
  254. // Description: Intended to be overridden by derived LightAttrib
  255. // types to specify what the default property for a
  256. // LightAttrib of this type should be.
  257. //
  258. // This should return a newly-allocated LightAttrib of
  259. // the same type that corresponds to whatever the
  260. // standard default for this kind of LightAttrib is.
  261. ////////////////////////////////////////////////////////////////////
  262. RenderAttrib *LightAttrib::
  263. make_default_impl() const {
  264. return new LightAttrib;
  265. }
  266. ////////////////////////////////////////////////////////////////////
  267. // Function: LightAttrib::do_add
  268. // Access: Private
  269. // Description: Returns a new LightAttrib that represents all the
  270. // lights of this attrib, with those of the other one
  271. // added in.
  272. ////////////////////////////////////////////////////////////////////
  273. CPT(RenderAttrib) LightAttrib::
  274. do_add(const LightAttrib *other, LightAttrib::Operation op) const {
  275. Lights::const_iterator ai = _lights.begin();
  276. Lights::const_iterator bi = other->_lights.begin();
  277. // Create a new LightAttrib that will hold the result.
  278. LightAttrib *new_attrib = new LightAttrib;
  279. new_attrib->_operation = op;
  280. back_insert_iterator<Lights> result =
  281. back_inserter(new_attrib->_lights);
  282. while (ai != _lights.end() && bi != other->_lights.end()) {
  283. if ((*ai) < (*bi)) {
  284. // Here is a light that we have in the original, which is not
  285. // present in the secondary.
  286. *result = *ai;
  287. ++ai;
  288. ++result;
  289. } else if ((*bi) < (*ai)) {
  290. // Here is a new light we have in the secondary, that was not
  291. // present in the original.
  292. *result = *bi;
  293. ++bi;
  294. ++result;
  295. } else {
  296. // Here is a light we have in both.
  297. *result = *ai;
  298. ++ai;
  299. ++bi;
  300. ++result;
  301. }
  302. }
  303. while (ai != _lights.end()) {
  304. *result = *ai;
  305. ++ai;
  306. ++result;
  307. }
  308. while (bi != other->_lights.end()) {
  309. *result = *bi;
  310. ++bi;
  311. ++result;
  312. }
  313. return return_new(new_attrib);
  314. }
  315. ////////////////////////////////////////////////////////////////////
  316. // Function: LightAttrib::do_remove
  317. // Access: Private
  318. // Description: Returns a new LightAttrib that represents all the
  319. // lights of this attrib, with those of the other one
  320. // removed.
  321. ////////////////////////////////////////////////////////////////////
  322. CPT(RenderAttrib) LightAttrib::
  323. do_remove(const LightAttrib *other, LightAttrib::Operation op) const {
  324. Lights::const_iterator ai = _lights.begin();
  325. Lights::const_iterator bi = other->_lights.begin();
  326. // Create a new LightAttrib that will hold the result.
  327. LightAttrib *new_attrib = new LightAttrib;
  328. new_attrib->_operation = op;
  329. back_insert_iterator<Lights> result =
  330. back_inserter(new_attrib->_lights);
  331. while (ai != _lights.end() && bi != other->_lights.end()) {
  332. if ((*ai) < (*bi)) {
  333. // Here is a light that we have in the original, which is
  334. // not present in the secondary. Keep it.
  335. *result = *ai;
  336. ++ai;
  337. ++result;
  338. } else if ((*bi) < (*ai)) {
  339. // Here is a new light we have in the secondary, that was
  340. // not present in the original. Ignore it.
  341. ++bi;
  342. } else {
  343. // Here is a light we have in both. Drop it.
  344. ++ai;
  345. ++bi;
  346. }
  347. }
  348. while (ai != _lights.end()) {
  349. *result = *ai;
  350. ++ai;
  351. ++result;
  352. }
  353. return return_new(new_attrib);
  354. }
  355. ////////////////////////////////////////////////////////////////////
  356. // Function: LightAttrib::register_with_read_factory
  357. // Access: Public, Static
  358. // Description: Tells the BamReader how to create objects of type
  359. // LightAttrib.
  360. ////////////////////////////////////////////////////////////////////
  361. void LightAttrib::
  362. register_with_read_factory() {
  363. BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
  364. }
  365. ////////////////////////////////////////////////////////////////////
  366. // Function: LightAttrib::write_datagram
  367. // Access: Public, Virtual
  368. // Description: Writes the contents of this object to the datagram
  369. // for shipping out to a Bam file.
  370. ////////////////////////////////////////////////////////////////////
  371. void LightAttrib::
  372. write_datagram(BamWriter *manager, Datagram &dg) {
  373. RenderAttrib::write_datagram(manager, dg);
  374. dg.add_int8((int)_operation);
  375. PN_uint16 num_lights = _lights.size();
  376. nassertv(num_lights == _lights.size());
  377. dg.add_uint16(num_lights);
  378. Lights::const_iterator li;
  379. for (li = _lights.begin(); li != _lights.end(); ++li) {
  380. Light *light = (*li);
  381. manager->write_pointer(dg, light->as_node());
  382. }
  383. }
  384. ////////////////////////////////////////////////////////////////////
  385. // Function: LightAttrib::complete_pointers
  386. // Access: Public, Virtual
  387. // Description: Receives an array of pointers, one for each time
  388. // manager->read_pointer() was called in fillin().
  389. // Returns the number of pointers processed.
  390. ////////////////////////////////////////////////////////////////////
  391. int LightAttrib::
  392. complete_pointers(TypedWritable **p_list, BamReader *manager) {
  393. int pi = RenderAttrib::complete_pointers(p_list, manager);
  394. Lights::iterator li;
  395. for (li = _lights.begin(); li != _lights.end(); ++li) {
  396. PandaNode *node;
  397. DCAST_INTO_R(node, p_list[pi++], pi);
  398. (*li) = node->as_light();
  399. }
  400. return pi;
  401. }
  402. ////////////////////////////////////////////////////////////////////
  403. // Function: LightAttrib::make_from_bam
  404. // Access: Protected, Static
  405. // Description: This function is called by the BamReader's factory
  406. // when a new object of type LightAttrib is encountered
  407. // in the Bam file. It should create the LightAttrib
  408. // and extract its information from the file.
  409. ////////////////////////////////////////////////////////////////////
  410. TypedWritable *LightAttrib::
  411. make_from_bam(const FactoryParams &params) {
  412. LightAttrib *attrib = new LightAttrib;
  413. DatagramIterator scan;
  414. BamReader *manager;
  415. parse_params(params, scan, manager);
  416. attrib->fillin(scan, manager);
  417. return attrib;
  418. }
  419. ////////////////////////////////////////////////////////////////////
  420. // Function: LightAttrib::fillin
  421. // Access: Protected
  422. // Description: This internal function is called by make_from_bam to
  423. // read in all of the relevant data from the BamFile for
  424. // the new LightAttrib.
  425. ////////////////////////////////////////////////////////////////////
  426. void LightAttrib::
  427. fillin(DatagramIterator &scan, BamReader *manager) {
  428. RenderAttrib::fillin(scan, manager);
  429. _operation = (Operation)scan.get_int8();
  430. int num_lights = scan.get_uint16();
  431. for (int i = 0; i < num_lights; i++) {
  432. manager->read_pointer(scan);
  433. _lights.push_back(NULL);
  434. }
  435. }