wrt.I 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // Filename: wrt.cxx
  2. // Created by: drose (26Oct98)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "wrt.h"
  6. #include "nodeRelation.h"
  7. #include "node.h"
  8. #include "config_graph.h"
  9. ////////////////////////////////////////////////////////////////////
  10. // Function: get_cached_net_transition
  11. // Description: Returns the net transition from the root of the
  12. // graph, or the nearest ancestor with multiple parents,
  13. // to and including the indicated arc. This is a
  14. // support function for wrt() and should not be called
  15. // directly.
  16. //
  17. // This flavor of get_cached_net_transition() gets the
  18. // transition up to an arc, instead of a node, and does
  19. // not necessarily start at the root of the scene graph.
  20. // By starting at the nearest ancestor with multiple
  21. // parents, we allow ambiguous paths in the scene graph
  22. // without interfering with state caching. Since there
  23. // are no nodes with multiple parents in the chain of
  24. // transitions returned by this function, the result is
  25. // always unambiguous; any wrt() ambiguity is resolved
  26. // later.
  27. ////////////////////////////////////////////////////////////////////
  28. template<class TransitionWrapper>
  29. void
  30. get_cached_net_transition(NodeRelation *arc, Node *&root, UpdateSeq now,
  31. TransitionWrapper &net, TypeHandle graph_type) {
  32. TransitionWrapper cur_cache = TransitionWrapper::init_from(net);
  33. Node *top_subtree = cur_cache.extract_from_cache(arc);
  34. if (cur_cache.is_cache_verified(now)) {
  35. // This arc's cached value has recently been verified, so we don't
  36. // even need to go anywhere--we trust it's still good.
  37. root = top_subtree;
  38. net = cur_cache;
  39. } else {
  40. // This arc's cache hasn't recently been verified, and we need to
  41. // verify it now. This will entail at least walking up the scene
  42. // graph to the root, and possibly recomputing the cache as we go.
  43. // Get the node above the arc.
  44. Node *node = arc->get_parent();
  45. UpRelations::const_iterator uri;
  46. uri = node->_parents.find(graph_type);
  47. if (uri == node->_parents.end() || (*uri).second.size() != 1) {
  48. // The node has zero or multiple parents. It's thus either the
  49. // top of the scene graph, or it's the first ancestor with
  50. // multiple parents; in either case, it's as far as we can take
  51. // the caching. Stop here.
  52. if (uri == node->_parents.end() || (*uri).second.empty()) {
  53. // The node is the very top of the scene graph. We'll treat
  54. // this as a special case by setting the node to NULL. This
  55. // will tell our calling function that there's no need to look
  56. // further.
  57. node = NULL;
  58. }
  59. root = node;
  60. net.extract_from(arc);
  61. net.set_computed_verified(now);
  62. net.store_to_cache(arc, node);
  63. } else {
  64. // The node has exactly one parent. Carry on.
  65. NodeRelation *parent = *(*uri).second.begin();
  66. get_cached_net_transition(parent, root, now, net, graph_type);
  67. // Now recompute our own cache.
  68. TransitionWrapper cur_value = TransitionWrapper::init_from(net);
  69. cur_value.extract_from(arc);
  70. net.cached_compose(cur_cache, cur_value, now);
  71. net.store_to_cache(arc, root);
  72. }
  73. }
  74. }
  75. ////////////////////////////////////////////////////////////////////
  76. // Function: get_cached_net_transition
  77. // Description: Returns the net transition from the root of the graph
  78. // to the indicated node. This is a support function
  79. // for wrt() and should not be called directly.
  80. //
  81. // If [arc_list_begin..arc_list_end) is nonempty, it
  82. // contains a list of NodeRelation pointers to resolve
  83. // ambiguities when a node with multiple parents is
  84. // encountered.
  85. ////////////////////////////////////////////////////////////////////
  86. template<class InputIterator, class TransitionWrapper>
  87. void
  88. get_cached_net_transition(const Node *node,
  89. InputIterator arc_list_begin,
  90. InputIterator arc_list_end,
  91. UpdateSeq now,
  92. TransitionWrapper &result,
  93. TypeHandle graph_type) {
  94. if (node == NULL) {
  95. // the NULL node is by convention equivalent to the root.
  96. result.make_identity();
  97. return;
  98. }
  99. UpRelations::const_iterator uri;
  100. uri = node->_parents.find(graph_type);
  101. if (uri == node->_parents.end()) {
  102. // This node has no parents. Stop here.
  103. result.make_identity();
  104. return;
  105. }
  106. const UpRelationPointers &urp = (*uri).second;
  107. if (urp.empty()) {
  108. // Again, this node has no parents.
  109. result.make_identity();
  110. return;
  111. }
  112. const NodeRelation *parent_arc = (const NodeRelation *)NULL;
  113. if (urp.size() == 1) {
  114. // There is only one parent, so there's no doubt as to which arc
  115. // to choose.
  116. parent_arc = *(urp.begin());
  117. } else {
  118. // The node has multiple parents, and we have a list of arcs in
  119. // arc_list_begin .. arc_list_end. If any of the parents is
  120. // mentioned in the list, we must choose that parent.
  121. for (InputIterator ri = arc_list_begin;
  122. parent_arc == (NodeRelation *)NULL && ri != arc_list_end;
  123. ++ri) {
  124. if ((*ri)->get_child() == node) {
  125. parent_arc = (*ri);
  126. }
  127. }
  128. if (parent_arc == (NodeRelation *)NULL) {
  129. // No, it wasn't mentioned. Issue a warning and use the first
  130. // one.
  131. graph_cat.warning()
  132. << *node << " has multiple parents; wrt() ambiguous.\n";
  133. parent_arc = *(urp.begin());
  134. }
  135. }
  136. // Get the net transition leading into this node.
  137. Node *root;
  138. get_cached_net_transition((NodeRelation *)parent_arc, root, now, result,
  139. graph_type);
  140. if (root != NULL) {
  141. // There's more to get. The above function call was forced to
  142. // stop at a node with multiple parents.
  143. TransitionWrapper more = TransitionWrapper::init_from(result);
  144. get_cached_net_transition(root, arc_list_begin, arc_list_end,
  145. now, more, graph_type);
  146. more.compose_in_place(result);
  147. result = more;
  148. }
  149. }
  150. ////////////////////////////////////////////////////////////////////
  151. // Function: get_uncached_net_transition
  152. // Description: Returns the net transition from the root of the graph
  153. // to the indicated node. This is a support function
  154. // for wrt() and should not be called directly.
  155. //
  156. // If [arc_list_begin..arc_list_end) is nonempty, it
  157. // contains a list of NodeRelation pointers to resolve
  158. // ambiguities when a node with multiple parents is
  159. // encountered.
  160. //
  161. // This variant of get_cached_net_transition() does not
  162. // respect or update the cache values stored in the
  163. // arcs. It's intended only as a debugging doublecheck
  164. // against the normal get_cached_net_transition()
  165. // function that does do this.
  166. ////////////////////////////////////////////////////////////////////
  167. template<class InputIterator, class TransitionWrapper>
  168. void
  169. get_uncached_net_transition(const Node *node,
  170. InputIterator arc_list_begin,
  171. InputIterator arc_list_end,
  172. TransitionWrapper &result,
  173. TypeHandle graph_type) {
  174. if (node == NULL) {
  175. // the NULL node is by convention equivalent to the root.
  176. result.make_identity();
  177. return;
  178. }
  179. UpRelations::const_iterator uri;
  180. uri = node->_parents.find(graph_type);
  181. if (uri == node->_parents.end()) {
  182. // This node has no parents. Stop here.
  183. result.make_identity();
  184. return;
  185. }
  186. const UpRelationPointers &urp = (*uri).second;
  187. if (urp.empty()) {
  188. // Again, this node has no parents.
  189. result.make_identity();
  190. return;
  191. }
  192. const NodeRelation *parent_arc = (const NodeRelation *)NULL;
  193. if (urp.size() == 1) {
  194. // There is only one parent, so there's no doubt as to which arc
  195. // to choose.
  196. parent_arc = *(urp.begin());
  197. } else {
  198. // The node has multiple parents, and we have a list of arcs in
  199. // arc_list_begin .. arc_list_end. If any of the parents is
  200. // mentioned in the list, we must choose that parent.
  201. for (InputIterator ri = arc_list_begin;
  202. parent_arc == (NodeRelation *)NULL && ri != arc_list_end;
  203. ++ri) {
  204. if ((*ri)->get_child() == node) {
  205. parent_arc = (*ri);
  206. }
  207. }
  208. if (parent_arc == (NodeRelation *)NULL) {
  209. // No, it wasn't mentioned. Issue a warning and use the first
  210. // one.
  211. graph_cat.warning()
  212. << *node << " has multiple parents; wrt() ambiguous.\n";
  213. parent_arc = *(urp.begin());
  214. }
  215. }
  216. get_uncached_net_transition(parent_arc->get_parent(),
  217. arc_list_begin, arc_list_end,
  218. result,
  219. graph_type);
  220. TransitionWrapper next = TransitionWrapper::init_from(result);
  221. next.extract_from(parent_arc);
  222. result.compose_in_place(next);
  223. }
  224. ////////////////////////////////////////////////////////////////////
  225. // Function: cached_wrt_base
  226. // Description: The implementation of wrt_base, below, but always
  227. // uses the cached value. This is the normal behavior.
  228. ////////////////////////////////////////////////////////////////////
  229. template<class InputIterator1, class InputIterator2, class TransitionWrapper>
  230. void
  231. cached_wrt_base(const Node *from,
  232. InputIterator1 from_arcs_begin, InputIterator1 from_arcs_end,
  233. const Node *to,
  234. InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end,
  235. TransitionWrapper &result,
  236. TypeHandle graph_type) {
  237. UpdateSeq now = last_graph_update[graph_type];
  238. TransitionWrapper net_from_trans = TransitionWrapper::init_from(result);
  239. get_cached_net_transition(from, from_arcs_begin, from_arcs_end, now,
  240. net_from_trans, graph_type);
  241. get_cached_net_transition(to, to_arcs_begin, to_arcs_end, now,
  242. result, graph_type);
  243. #ifndef NDEBUG
  244. if (paranoid_wrt) {
  245. // We don't entirely trust the caching to work flawlessly. Go
  246. // ahead and compute the uncached transition just to doublecheck.
  247. TransitionWrapper check_from_trans =
  248. TransitionWrapper::init_from(result);
  249. TransitionWrapper check_to_trans =
  250. TransitionWrapper::init_from(result);
  251. get_uncached_net_transition(from, from_arcs_begin, from_arcs_end,
  252. check_from_trans, graph_type);
  253. if (check_from_trans.compare_to(net_from_trans) != 0) {
  254. graph_cat.warning()
  255. << "WRT cache from " << *from << " is invalid!\n"
  256. << " cached value is " << net_from_trans << "\n"
  257. << " should be " << check_from_trans << "\n";
  258. net_from_trans = check_from_trans;
  259. }
  260. get_uncached_net_transition(to, to_arcs_begin, to_arcs_end,
  261. check_to_trans, graph_type);
  262. if (check_to_trans.compare_to(result) != 0) {
  263. graph_cat.warning()
  264. << "WRT cache to " << *to << " is invalid!\n"
  265. << " cached value is " << result << "\n"
  266. << " should be " << check_to_trans << "\n";
  267. result = check_to_trans;
  268. }
  269. }
  270. #endif
  271. result.invert_compose_in_place(net_from_trans);
  272. }
  273. ////////////////////////////////////////////////////////////////////
  274. // Function: uncached_wrt_base
  275. // Description: The implementation of wrt_base, below, but never
  276. // cached.
  277. ////////////////////////////////////////////////////////////////////
  278. template<class InputIterator1, class InputIterator2, class TransitionWrapper>
  279. void
  280. uncached_wrt_base(const Node *from,
  281. InputIterator1 from_arcs_begin, InputIterator1 from_arcs_end,
  282. const Node *to,
  283. InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end,
  284. TransitionWrapper &result,
  285. TypeHandle graph_type) {
  286. // UpdateSeq now = last_graph_update[graph_type];
  287. TransitionWrapper net_from_trans = TransitionWrapper::init_from(result);
  288. get_uncached_net_transition(from, from_arcs_begin, from_arcs_end,
  289. net_from_trans, graph_type);
  290. get_uncached_net_transition(to, to_arcs_begin, to_arcs_end,
  291. result, graph_type);
  292. result.invert_compose_in_place(net_from_trans);
  293. }
  294. ////////////////////////////////////////////////////////////////////
  295. // Function: wrt_base
  296. // Description: Returns the net transition from the node "to"
  297. // to the node "from".
  298. //
  299. // If [from_arcs_begin..from_arcs_end) is nonempty, it
  300. // contains a list of NodeRelation pointers to resolve
  301. // ambiguities when a node with multiple parents is
  302. // encountered as an ancestor of the from node. If any
  303. // of the parents is listed, that parent will be chosen.
  304. //
  305. // Similarly with [to_arcs_begin..to_arcs_end).
  306. //
  307. // wrt_base() is a low-level implementation; use the
  308. // various wrt() wrappers instead.
  309. ////////////////////////////////////////////////////////////////////
  310. template<class InputIterator1, class InputIterator2, class TransitionWrapper>
  311. INLINE void
  312. wrt_base(const Node *from,
  313. InputIterator1 from_arcs_begin, InputIterator1 from_arcs_end,
  314. const Node *to,
  315. InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end,
  316. TransitionWrapper &result,
  317. TypeHandle graph_type) {
  318. if (cache_wrt) {
  319. cached_wrt_base(from, from_arcs_begin, from_arcs_end,
  320. to, to_arcs_begin, to_arcs_end,
  321. result, graph_type);
  322. } else {
  323. uncached_wrt_base(from, from_arcs_begin, from_arcs_end,
  324. to, to_arcs_begin, to_arcs_end,
  325. result, graph_type);
  326. }
  327. }
  328. template<class TransitionWrapper>
  329. INLINE void
  330. wrt(const Node *from, const Node *to,
  331. TransitionWrapper &result, TypeHandle graph_type) {
  332. // In the normal wrt() interface, we have no from_arcs or to_arcs
  333. // list. Supply empty lists for both.
  334. const NodeRelation *arc = NULL;
  335. wrt_base(from, &arc, &arc, to, &arc, &arc, result, graph_type);
  336. }
  337. template<class InputIterator, class TransitionWrapper>
  338. INLINE void
  339. wrt(const Node *from,
  340. InputIterator from_arcs_begin, InputIterator from_arcs_end,
  341. const Node *to,
  342. TransitionWrapper &result, TypeHandle graph_type) {
  343. const NodeRelation *arc = NULL;
  344. wrt_base(from, from_arcs_begin, from_arcs_end, to, &arc, &arc,
  345. result, graph_type);
  346. }
  347. template<class InputIterator, class TransitionWrapper>
  348. INLINE void
  349. wrt(const Node *from,
  350. const Node *to,
  351. InputIterator to_arcs_begin, InputIterator to_arcs_end,
  352. TransitionWrapper &result, TypeHandle graph_type) {
  353. const NodeRelation *arc = NULL;
  354. wrt_base(from, &arc, &arc, to, to_arcs_begin, to_arcs_end,
  355. result, graph_type);
  356. }
  357. template<class InputIterator1, class InputIterator2, class TransitionWrapper>
  358. INLINE void
  359. wrt(const Node *from,
  360. InputIterator1 from_arcs_begin, InputIterator1 from_arcs_end,
  361. const Node *to,
  362. InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end,
  363. TransitionWrapper &result, TypeHandle graph_type) {
  364. wrt_base(from, from_arcs_begin, from_arcs_end,
  365. to, to_arcs_begin, to_arcs_end,
  366. result, graph_type);
  367. }
  368. template<class TransitionWrapper>
  369. INLINE void
  370. uncached_wrt(const Node *from, const Node *to,
  371. TransitionWrapper &result, TypeHandle graph_type) {
  372. const NodeRelation *arc = NULL;
  373. uncached_wrt_base(from, &arc, &arc, to, &arc, &arc, result, graph_type);
  374. }
  375. template<class InputIterator, class TransitionWrapper>
  376. INLINE void
  377. uncached_wrt(const Node *from,
  378. InputIterator from_arcs_begin, InputIterator from_arcs_end,
  379. const Node *to,
  380. TransitionWrapper &result, TypeHandle graph_type) {
  381. const NodeRelation *arc = NULL;
  382. uncached_wrt_base(from, from_arcs_begin, from_arcs_end, to, &arc, &arc,
  383. result, graph_type);
  384. }
  385. template<class InputIterator, class TransitionWrapper>
  386. INLINE void
  387. uncached_wrt(const Node *from,
  388. const Node *to,
  389. InputIterator to_arcs_begin, InputIterator to_arcs_end,
  390. TransitionWrapper &result, TypeHandle graph_type) {
  391. const NodeRelation *arc = NULL;
  392. uncached_wrt_base(from, &arc, &arc, to, to_arcs_begin, to_arcs_end,
  393. result, graph_type);
  394. }
  395. template<class InputIterator1, class InputIterator2, class TransitionWrapper>
  396. INLINE void
  397. uncached_wrt(const Node *from,
  398. InputIterator1 from_arcs_begin, InputIterator1 from_arcs_end,
  399. const Node *to,
  400. InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end,
  401. TransitionWrapper &result, TypeHandle graph_type) {
  402. uncached_wrt_base(from, from_arcs_begin, from_arcs_end,
  403. to, to_arcs_begin, to_arcs_end,
  404. result, graph_type);
  405. }
  406. template<class TransitionWrapper>
  407. Node *
  408. wrt_subtree(NodeRelation *arc, Node *to, TransitionWrapper &result,
  409. TypeHandle graph_type) {
  410. if (!cache_wrt) {
  411. // If we aren't caching wrt, do this the hard way.
  412. uncached_wrt(arc->get_child(), &arc, &arc + 1, to, result, graph_type);
  413. return to;
  414. }
  415. UpdateSeq now = last_graph_update[graph_type];
  416. // First, determine the net transition up to the top of the current
  417. // subtree.
  418. Node *top_subtree;
  419. get_cached_net_transition(arc, top_subtree, now, result, graph_type);
  420. if (top_subtree == to || to == (Node *)NULL) {
  421. // If the top of the subtree is the node we asked to wrt to,
  422. // excellent! Stop here.
  423. } else {
  424. // Otherwise, it must be the case that the node we want to wrt to is
  425. // some descendent of the top_subtree node. It also therefore
  426. // follows that this node has exactly one parent.
  427. nassertr(to->get_num_parents(graph_type) == 1, NULL);
  428. NodeRelation *to_arc = to->get_parent(graph_type, 0);
  429. // Save the result from the first pass.
  430. TransitionWrapper net_from_trans = result;
  431. // Now determine the net transition to the top of the subtree from
  432. // this arc. It had better be the same subtree!
  433. Node *top_subtree_2;
  434. get_cached_net_transition(to_arc, top_subtree_2, now, result, graph_type);
  435. nassertr(top_subtree == top_subtree_2, NULL);
  436. // And now compute the actual wrt.
  437. result.invert_compose_in_place(net_from_trans);
  438. }
  439. #ifndef NDEBUG
  440. if (paranoid_wrt) {
  441. // Now check the results.
  442. TransitionWrapper check_trans =
  443. TransitionWrapper::init_from(result);
  444. uncached_wrt(arc->get_child(), &arc, &arc + 1, to, check_trans,
  445. graph_type);
  446. if (check_trans.compare_to(result) != 0) {
  447. graph_cat.warning()
  448. << "WRT subtree cache from " << *arc->get_child() << " to ";
  449. if (to == (Node *)NULL) {
  450. graph_cat.warning(false) << "(top)";
  451. } else {
  452. graph_cat.warning(false) << *to;
  453. }
  454. graph_cat.warning(false)
  455. << " is invalid!\n"
  456. << " cached value is " << result << "\n"
  457. << " should be " << check_trans << "\n";
  458. result = check_trans;
  459. }
  460. }
  461. #endif
  462. return top_subtree;
  463. }