cDistributedSmoothNodeBase.cxx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // Filename: cDistributedSmoothNodeBase.cxx
  2. // Created by: drose (03Sep04)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "cDistributedSmoothNodeBase.h"
  19. #include "cConnectionRepository.h"
  20. #include "dcField.h"
  21. #include "dcClass.h"
  22. #include "dcmsgtypes.h"
  23. static const float smooth_node_epsilon = 0.01;
  24. static const double network_time_precision = 100.0; // Matches ClockDelta.py
  25. CConnectionRepository *CDistributedSmoothNodeBase::_repository = NULL;
  26. bool CDistributedSmoothNodeBase::_is_ai;
  27. CHANNEL_TYPE CDistributedSmoothNodeBase::_ai_id;
  28. PyObject *CDistributedSmoothNodeBase::_clock_delta = NULL;
  29. ////////////////////////////////////////////////////////////////////
  30. // Function: CDistributedSmoothNodeBase::Constructor
  31. // Access: Published
  32. // Description:
  33. ////////////////////////////////////////////////////////////////////
  34. CDistributedSmoothNodeBase::
  35. CDistributedSmoothNodeBase() {
  36. }
  37. ////////////////////////////////////////////////////////////////////
  38. // Function: CDistributedSmoothNodeBase::Destructor
  39. // Access: Published
  40. // Description:
  41. ////////////////////////////////////////////////////////////////////
  42. CDistributedSmoothNodeBase::
  43. ~CDistributedSmoothNodeBase() {
  44. }
  45. ////////////////////////////////////////////////////////////////////
  46. // Function: CDistributedSmoothNodeBase::initialize
  47. // Access: Published
  48. // Description: Initializes the internal structures from some
  49. // constructs that are normally stored only in Python.
  50. // Also reads the current node's pos & hpr values in
  51. // preparation for transmitting them via one of the
  52. // broadcast_pos_hpr_*() methods.
  53. ////////////////////////////////////////////////////////////////////
  54. void CDistributedSmoothNodeBase::
  55. initialize(const NodePath &node_path, DCClass *dclass, CHANNEL_TYPE do_id) {
  56. _node_path = node_path;
  57. _dclass = dclass;
  58. _do_id = do_id;
  59. nassertv(!_node_path.is_empty());
  60. _store_xyz = _node_path.get_pos();
  61. _store_hpr = _node_path.get_hpr();
  62. _store_stop = false;
  63. }
  64. ////////////////////////////////////////////////////////////////////
  65. // Function: CDistributedSmoothNodeBase::send_everything
  66. // Access: Published
  67. // Description: Broadcasts the current pos/hpr in its complete form.
  68. ////////////////////////////////////////////////////////////////////
  69. void CDistributedSmoothNodeBase::
  70. send_everything() {
  71. d_setSmPosHpr(_store_xyz[0], _store_xyz[1], _store_xyz[2],
  72. _store_hpr[0], _store_hpr[1], _store_hpr[2]);
  73. }
  74. ////////////////////////////////////////////////////////////////////
  75. // Function: CDistributedSmoothNodeBase::broadcast_pos_hpr_full
  76. // Access: Published
  77. // Description: Examines the complete pos/hpr information to see
  78. // which of the six elements have changed, and
  79. // broadcasts the appropriate messages.
  80. ////////////////////////////////////////////////////////////////////
  81. void CDistributedSmoothNodeBase::
  82. broadcast_pos_hpr_full() {
  83. LPoint3f xyz = _node_path.get_pos();
  84. LVecBase3f hpr = _node_path.get_hpr();
  85. int flags = 0;
  86. if (!IS_THRESHOLD_EQUAL(_store_xyz[0], xyz[0], smooth_node_epsilon)) {
  87. _store_xyz[0] = xyz[0];
  88. flags |= F_new_x;
  89. }
  90. if (!IS_THRESHOLD_EQUAL(_store_xyz[1], xyz[1], smooth_node_epsilon)) {
  91. _store_xyz[1] = xyz[1];
  92. flags |= F_new_y;
  93. }
  94. if (!IS_THRESHOLD_EQUAL(_store_xyz[2], xyz[2], smooth_node_epsilon)) {
  95. _store_xyz[2] = xyz[2];
  96. flags |= F_new_z;
  97. }
  98. if (!IS_THRESHOLD_EQUAL(_store_hpr[0], hpr[0], smooth_node_epsilon)) {
  99. _store_hpr[0] = hpr[0];
  100. flags |= F_new_h;
  101. }
  102. if (!IS_THRESHOLD_EQUAL(_store_hpr[1], hpr[1], smooth_node_epsilon)) {
  103. _store_hpr[1] = hpr[1];
  104. flags |= F_new_p;
  105. }
  106. if (!IS_THRESHOLD_EQUAL(_store_hpr[2], hpr[2], smooth_node_epsilon)) {
  107. _store_hpr[2] = hpr[2];
  108. flags |= F_new_r;
  109. }
  110. if (flags == 0) {
  111. // No change. Send one and only one "stop" message.
  112. if (!_store_stop) {
  113. _store_stop = true;
  114. d_setSmStop();
  115. }
  116. } else if (only_changed(flags, F_new_h)) {
  117. // Only change in H.
  118. _store_stop = false;
  119. d_setSmH(_store_hpr[0]);
  120. } else if (only_changed(flags, F_new_x | F_new_y)) {
  121. // Only change in X, Y
  122. _store_stop = false;
  123. d_setSmXY(_store_xyz[0], _store_xyz[1]);
  124. } else if (only_changed(flags, F_new_x | F_new_z)) {
  125. // Only change in X, Z
  126. _store_stop = false;
  127. d_setSmXZ(_store_xyz[0], _store_xyz[2]);
  128. } else if (only_changed(flags, F_new_x | F_new_y | F_new_z)) {
  129. // Only change in X, Y, Z
  130. _store_stop = false;
  131. d_setSmPos(_store_xyz[0], _store_xyz[1], _store_xyz[2]);
  132. } else if (only_changed(flags, F_new_h | F_new_p | F_new_r)) {
  133. // Only change in H, P, R
  134. _store_stop = false;
  135. d_setSmHpr(_store_hpr[0], _store_hpr[1], _store_hpr[2]);
  136. } else if (only_changed(flags, F_new_x | F_new_y | F_new_h)) {
  137. // Only change in X, Y, H
  138. _store_stop = false;
  139. d_setSmXYH(_store_xyz[0], _store_xyz[1], _store_hpr[0]);
  140. } else if (only_changed(flags, F_new_x | F_new_y | F_new_z | F_new_h)) {
  141. // Only change in X, Y, Z, H
  142. _store_stop = false;
  143. d_setSmXYZH(_store_xyz[0], _store_xyz[1], _store_xyz[2], _store_hpr[0]);
  144. } else {
  145. // Any other change
  146. _store_stop = false;
  147. d_setSmPosHpr(_store_xyz[0], _store_xyz[1], _store_xyz[2],
  148. _store_hpr[0], _store_hpr[1], _store_hpr[2]);
  149. }
  150. }
  151. ////////////////////////////////////////////////////////////////////
  152. // Function: CDistributedSmoothNodeBase::broadcast_pos_hpr_xyh
  153. // Access: Published
  154. // Description: Examines only X, Y, and H of the pos/hpr information,
  155. // and broadcasts the appropriate messages.
  156. ////////////////////////////////////////////////////////////////////
  157. void CDistributedSmoothNodeBase::
  158. broadcast_pos_hpr_xyh() {
  159. LPoint3f xyz = _node_path.get_pos();
  160. LVecBase3f hpr = _node_path.get_hpr();
  161. int flags = 0;
  162. if (!IS_THRESHOLD_EQUAL(_store_xyz[0], xyz[0], smooth_node_epsilon)) {
  163. _store_xyz[0] = xyz[0];
  164. flags |= F_new_x;
  165. }
  166. if (!IS_THRESHOLD_EQUAL(_store_xyz[1], xyz[1], smooth_node_epsilon)) {
  167. _store_xyz[1] = xyz[1];
  168. flags |= F_new_y;
  169. }
  170. if (!IS_THRESHOLD_EQUAL(_store_hpr[0], hpr[0], smooth_node_epsilon)) {
  171. _store_hpr[0] = hpr[0];
  172. flags |= F_new_h;
  173. }
  174. if (flags == 0) {
  175. // No change. Send one and only one "stop" message.
  176. if (!_store_stop) {
  177. _store_stop = true;
  178. d_setSmStop();
  179. }
  180. } else if (only_changed(flags, F_new_h)) {
  181. // Only change in H.
  182. _store_stop = false;
  183. d_setSmH(_store_hpr[0]);
  184. } else if (only_changed(flags, F_new_x | F_new_y)) {
  185. // Only change in X, Y
  186. _store_stop = false;
  187. d_setSmXY(_store_xyz[0], _store_xyz[1]);
  188. } else {
  189. // Any other change.
  190. _store_stop = false;
  191. d_setSmXYH(_store_xyz[0], _store_xyz[1], _store_hpr[0]);
  192. }
  193. }
  194. ////////////////////////////////////////////////////////////////////
  195. // Function: CDistributedSmoothNodeBase::begin_send_update
  196. // Access: Private
  197. // Description: Fills up the packer with the data appropriate for
  198. // sending an update on the indicated field name, up
  199. // until the arguments.
  200. ////////////////////////////////////////////////////////////////////
  201. void CDistributedSmoothNodeBase::
  202. begin_send_update(DCPacker &packer, const string &field_name) {
  203. DCField *field = _dclass->get_field_by_name(field_name);
  204. nassertv(field != (DCField *)NULL);
  205. if (_is_ai) {
  206. packer.RAW_PACK_CHANNEL(_do_id);
  207. packer.RAW_PACK_CHANNEL(_ai_id);
  208. packer.raw_pack_uint8('A');
  209. packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
  210. packer.raw_pack_uint32(_do_id);
  211. packer.raw_pack_uint16(field->get_number());
  212. } else {
  213. packer.raw_pack_uint16(CLIENT_OBJECT_UPDATE_FIELD);
  214. packer.raw_pack_uint32(_do_id);
  215. packer.raw_pack_uint16(field->get_number());
  216. }
  217. packer.begin_pack(field);
  218. packer.push();
  219. }
  220. ////////////////////////////////////////////////////////////////////
  221. // Function: CDistributedSmoothNodeBase::finish_send_update
  222. // Access: Private
  223. // Description: Appends the timestamp and sends the update.
  224. ////////////////////////////////////////////////////////////////////
  225. void CDistributedSmoothNodeBase::
  226. finish_send_update(DCPacker &packer) {
  227. PyObject *clock_delta = PyObject_GetAttrString(_clock_delta, "delta");
  228. nassertv(clock_delta != NULL);
  229. double delta = PyFloat_AsDouble(clock_delta);
  230. Py_DECREF(clock_delta);
  231. double local_time = ClockObject::get_global_clock()->get_frame_time();
  232. short network_time = (short)(int)cfloor(((local_time - delta) * network_time_precision) + 0.5);
  233. packer.pack_int(network_time);
  234. packer.pop();
  235. bool pack_ok = packer.end_pack();
  236. nassertv(pack_ok);
  237. Datagram dg(packer.get_data(), packer.get_length());
  238. _repository->send_datagram(dg);
  239. }