From 157b9feb5f295c35ef1b33ba0f1bffa94ceb191c Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 6 Sep 2004 23:32:17 +0000 Subject: [PATCH] move setSmPos() etc. into C++ --- .../src/distributed/DistributedSmoothNode.py | 8 +- .../distributed/DistributedSmoothNodeAI.py | 2 + .../distributed/DistributedSmoothNodeBase.py | 191 +----------- direct/src/distributed/Sources.pp | 4 +- .../distributed/cDistributedSmoothNodeBase.I | 188 ++++++++++++ .../cDistributedSmoothNodeBase.cxx | 284 ++++++++++++++++++ .../distributed/cDistributedSmoothNodeBase.h | 98 ++++++ 7 files changed, 590 insertions(+), 185 deletions(-) create mode 100644 direct/src/distributed/cDistributedSmoothNodeBase.I create mode 100644 direct/src/distributed/cDistributedSmoothNodeBase.cxx create mode 100644 direct/src/distributed/cDistributedSmoothNodeBase.h diff --git a/direct/src/distributed/DistributedSmoothNode.py b/direct/src/distributed/DistributedSmoothNode.py index 8bf6e8fdfc..f964ceab48 100644 --- a/direct/src/distributed/DistributedSmoothNode.py +++ b/direct/src/distributed/DistributedSmoothNode.py @@ -85,6 +85,7 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, self.DistributedSmoothNode_initialized = 1 DistributedNode.DistributedNode.__init__(self, cr) DistributedSmoothNodeBase.DistributedSmoothNodeBase.__init__(self) + self.cnode.setRepository(cr, 0, 0) self.smoother = SmoothMover() self.smoothStarted = 0 @@ -308,11 +309,8 @@ class DistributedSmoothNode(DistributedNode.DistributedNode, DistributedNode.DistributedNode.d_setParent(self, parentToken) self.forceToTruePosition() - xyz = self.getPos() - hpr = self.getHpr() - x=xyz[0]; y=xyz[1]; z=xyz[2] - h=hpr[0]; p=hpr[1]; r=hpr[2] - self.d_setSmPosHpr(x,y,z,h,p,r) + self.cnode.initialize(self, self.dclass, self.doId) + self.cnode.sendEverything() ### Monitor clock sync ### diff --git a/direct/src/distributed/DistributedSmoothNodeAI.py b/direct/src/distributed/DistributedSmoothNodeAI.py index 4498a6e255..3ecddf421c 100755 --- a/direct/src/distributed/DistributedSmoothNodeAI.py +++ b/direct/src/distributed/DistributedSmoothNodeAI.py @@ -9,6 +9,8 @@ class DistributedSmoothNodeAI(DistributedNodeAI.DistributedNodeAI, DistributedNodeAI.DistributedNodeAI.__init__(self, air, name) DistributedSmoothNodeBase.DistributedSmoothNodeBase.__init__(self) + self.cnode.setRepository(air, 1, air.ourChannel) + def delete(self): DistributedSmoothNodeBase.DistributedSmoothNodeBase.delete(self) DistributedNodeAI.DistributedNodeAI.delete(self) diff --git a/direct/src/distributed/DistributedSmoothNodeBase.py b/direct/src/distributed/DistributedSmoothNodeBase.py index ad8c5b6163..33a7bf8c2a 100755 --- a/direct/src/distributed/DistributedSmoothNodeBase.py +++ b/direct/src/distributed/DistributedSmoothNodeBase.py @@ -10,46 +10,13 @@ class DistributedSmoothNodeBase: BroadcastTypes = Enum('FULL, XYH') def __init__(self): - pass + self.cnode = CDistributedSmoothNodeBase() + self.cnode.setClockDelta(globalClockDelta) def delete(self): # make sure our task is gone self.stopPosHprBroadcast() - ### distributed set pos and hpr functions ### - - ### These functions send the distributed update to set the - ### appropriate values on the remote side. These are - ### composite fields, with all the likely combinations - ### defined; each function maps (via the dc file) to one or - ### more component operations on the remote client. - - def d_setSmStop(self): - self.sendUpdate("setSmStop", [globalClockDelta.getFrameNetworkTime()]) - def d_setSmH(self, h): - self.sendUpdate("setSmH", [h, globalClockDelta.getFrameNetworkTime()]) - def d_setSmXY(self, x, y): - self.sendUpdate("setSmXY", [x, y, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmXZ(self, x, z): - self.sendUpdate("setSmXZ", [x, z, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmPos(self, x, y, z): - self.sendUpdate("setSmPos", [x, y, z, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmHpr(self, h, p, r): - self.sendUpdate("setSmHpr", [h, p, r, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmXYH(self, x, y, h): - self.sendUpdate("setSmXYH", [x, y, h, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmXYZH(self, x, y, z, h): - self.sendUpdate("setSmXYZH", [x, y, z, h, - globalClockDelta.getFrameNetworkTime()]) - def d_setSmPosHpr(self, x, y, z, h, p, r): - self.sendUpdate("setSmPosHpr", [x, y, z, h, p, r, - globalClockDelta.getFrameNetworkTime()]) - def b_clearSmoothing(self): self.d_clearSmoothing() self.clearSmoothing() @@ -68,6 +35,9 @@ class DistributedSmoothNodeBase: self.d_broadcastPosHpr = None def startPosHprBroadcast(self, period=.2, stagger=0, type=None): + if self.cnode == None: + self.initializeCnode() + BT = DistributedSmoothNodeBase.BroadcastTypes if type is None: type = BT.FULL @@ -75,8 +45,8 @@ class DistributedSmoothNodeBase: self.broadcastType = type broadcastFuncs = { - BT.FULL: self.d_broadcastPosHpr_FULL, - BT.XYH: self.d_broadcastPosHpr_XYH, + BT.FULL: self.cnode.broadcastPosHprFull, + BT.XYH: self.cnode.broadcastPosHprXyh, } self.d_broadcastPosHpr = broadcastFuncs[self.broadcastType] @@ -84,23 +54,15 @@ class DistributedSmoothNodeBase: # over 'period' seconds, to spread out task processing over time # when a large number of SmoothNodes are created simultaneously. taskName = self.getPosHprBroadcastTaskName() - # Set up telemetry optimization variables - xyz = self.getPos() - hpr = self.getHpr() - self.__storeX = xyz[0] - self.__storeY = xyz[1] - self.__storeZ = xyz[2] - self.__storeH = hpr[0] - self.__storeP = hpr[1] - self.__storeR = hpr[2] - self.__storeStop = 0 - self.__epsilon = 0.01 + # Set up telemetry optimization variables + self.cnode.initialize(self, self.dclass, self.doId) + self.__broadcastPeriod = period # Broadcast our initial position self.b_clearSmoothing() - self.d_setSmPosHpr(self.__storeX, self.__storeY, self.__storeZ, - self.__storeH, self.__storeP, self.__storeR) + self.cnode.sendEverything() + # remove any old tasks taskMgr.remove(taskName) # spawn the new task @@ -119,132 +81,3 @@ class DistributedSmoothNodeBase: taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName) return Task.done - - def d_broadcastPosHpr_FULL(self): - # send out the minimal bits to describe our new position - xyz = self.getPos() - hpr = self.getHpr() - - if abs(self.__storeX - xyz[0]) > self.__epsilon: - self.__storeX = xyz[0] - newX = 1 - else: - newX = 0 - - if abs(self.__storeY - xyz[1]) > self.__epsilon: - self.__storeY = xyz[1] - newY = 1 - else: - newY = 0 - - if abs(self.__storeZ - xyz[2]) > self.__epsilon: - self.__storeZ = xyz[2] - newZ = 1 - else: - newZ = 0 - - if abs(self.__storeH - hpr[0]) > self.__epsilon: - self.__storeH = hpr[0] - newH = 1 - else: - newH = 0 - - if abs(self.__storeP - hpr[1]) > self.__epsilon: - self.__storeP = hpr[1] - newP = 1 - else: - newP = 0 - - if abs(self.__storeR - hpr[2]) > self.__epsilon: - self.__storeR = hpr[2] - newR = 1 - else: - newR = 0 - - # Check for changes: - if not(newX or newY or newZ or newH or newP or newR): - # No change - # Send one and only one "stop" message. - if not self.__storeStop: - self.__storeStop = 1 - self.d_setSmStop() - # print 'no change' - elif (newH) and not(newX or newY or newZ or newP or newR): - # Only change in H - self.__storeStop = 0 - self.d_setSmH(self.__storeH) - # print ("H change") - elif (newX or newY) and not(newZ or newH or newP or newR): - # Only change in X, Y - self.__storeStop = 0 - self.d_setSmXY(self.__storeX, self.__storeY) - # print ("XY change") - elif (newX or newY or newZ) and not(newH or newP or newR): - # Only change in X, Y, Z - self.__storeStop = 0 - self.d_setSmPos(self.__storeX, self.__storeY, self.__storeZ) - # print ("XYZ change") - elif (newX or newY or newH) and not(newZ or newP or newR): - # Only change in X, Y, H - self.__storeStop = 0 - self.d_setSmXYH(self.__storeX, self.__storeY, self.__storeH) - # print ("XYH change") - elif (newX or newY or newZ or newH) and not(newP or newR): - # Only change in X, Y, Z, H - self.__storeStop = 0 - self.d_setSmXYZH(self.__storeX, self.__storeY, self.__storeZ, self.__storeH) - # print ("XYZH change") - else: - # Other changes - self.__storeStop = 0 - self.d_setSmPosHpr(self.__storeX, self.__storeY, self.__storeZ, - self.__storeH, self.__storeP, self.__storeR) - # print ("XYZHPR change") - - def d_broadcastPosHpr_XYH(self): - # send out the minimal bits to describe our new position - assert not self.isEmpty(), 'DistributedSmoothNode %s has been removed from graph?' % self.doId - xyz = self.getPos() - h = self.getH() - - if abs(self.__storeX - xyz[0]) > self.__epsilon: - self.__storeX = xyz[0] - newX = 1 - else: - newX = 0 - - if abs(self.__storeY - xyz[1]) > self.__epsilon: - self.__storeY = xyz[1] - newY = 1 - else: - newY = 0 - - if abs(self.__storeH - h) > self.__epsilon: - self.__storeH = h - newH = 1 - else: - newH = 0 - - # Check for changes: - if not(newX or newY or newH): - # No change - # Send one and only one "stop" message. - if not self.__storeStop: - self.__storeStop = 1 - self.d_setSmStop() - # print 'no change' - elif (newH) and not(newX or newY): - # Only change in H - self.__storeStop = 0 - self.d_setSmH(self.__storeH) - # print ("H change") - elif (newX or newY) and not(newH): - # Only change in X, Y - self.__storeStop = 0 - self.d_setSmXY(self.__storeX, self.__storeY) - # print ("XY change") - else: - # Only change in X, Y, H - self.__storeStop = 0 - self.d_setSmXYH(self.__storeX, self.__storeY, self.__storeH) - # print ("XYH change") diff --git a/direct/src/distributed/Sources.pp b/direct/src/distributed/Sources.pp index f468358110..370f6dfdd1 100644 --- a/direct/src/distributed/Sources.pp +++ b/direct/src/distributed/Sources.pp @@ -18,7 +18,9 @@ #define SOURCES \ config_distributed.cxx config_distributed.h \ cConnectionRepository.cxx cConnectionRepository.I \ - cConnectionRepository.h + cConnectionRepository.h \ + cDistributedSmoothNodeBase.cxx cDistributedSmoothNodeBase.I \ + cDistributedSmoothNodeBase.h #define IGATESCAN all #end lib_target diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.I b/direct/src/distributed/cDistributedSmoothNodeBase.I new file mode 100644 index 0000000000..b0862b932c --- /dev/null +++ b/direct/src/distributed/cDistributedSmoothNodeBase.I @@ -0,0 +1,188 @@ +// Filename: cDistributedSmoothNodeBase.I +// Created by: drose (03Sep04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::set_repository +// Access: Published, Static +// Description: Tells the C++ class definition about the AI or Client +// repository, used for sending datagrams. +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +set_repository(CConnectionRepository *repository, + bool is_ai, CHANNEL_TYPE ai_id) { + _repository = repository; + _is_ai = is_ai; + _ai_id = ai_id; +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::set_clock_delta +// Access: Published, Static +// Description: Tells the C++ class definition about the global +// ClockDelta object. +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +set_clock_delta(PyObject *clock_delta) { + _clock_delta = clock_delta; +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::only_changed +// Access: Private, Static +// Description: Returns true if at least some of the bits of compare +// are set in flags, but no bits outside of compare are +// set. That is to say, that the only things that are +// changed are the bits indicated in compare. +//////////////////////////////////////////////////////////////////// +INLINE bool CDistributedSmoothNodeBase:: +only_changed(int flags, int compare) { + return (flags & compare) != 0 && (flags & ~compare) == 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmStop +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmStop() { + DCPacker packer; + begin_send_update(packer, "setSmStop"); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmH +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmH(float h) { + DCPacker packer; + begin_send_update(packer, "setSmH"); + packer.pack_double(h); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmXY +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmXY(float x, float y) { + DCPacker packer; + begin_send_update(packer, "setSmXY"); + packer.pack_double(x); + packer.pack_double(y); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmXZ +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmXZ(float x, float z) { + DCPacker packer; + begin_send_update(packer, "setSmXZ"); + packer.pack_double(x); + packer.pack_double(z); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmPos +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmPos(float x, float y, float z) { + DCPacker packer; + begin_send_update(packer, "setSmPos"); + packer.pack_double(x); + packer.pack_double(y); + packer.pack_double(z); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmHpr +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmHpr(float h, float p, float r) { + DCPacker packer; + begin_send_update(packer, "setSmHpr"); + packer.pack_double(h); + packer.pack_double(p); + packer.pack_double(r); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmXYH +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmXYH(float x, float y, float h) { + DCPacker packer; + begin_send_update(packer, "setSmXYH"); + packer.pack_double(x); + packer.pack_double(y); + packer.pack_double(h); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmXYZH +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmXYZH(float x, float y, float z, float h) { + DCPacker packer; + begin_send_update(packer, "setSmXYZH"); + packer.pack_double(x); + packer.pack_double(y); + packer.pack_double(z); + packer.pack_double(h); + finish_send_update(packer); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::d_setSmPosHpr +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CDistributedSmoothNodeBase:: +d_setSmPosHpr(float x, float y, float z, float h, float p, float r) { + DCPacker packer; + begin_send_update(packer, "setSmPosHpr"); + packer.pack_double(x); + packer.pack_double(y); + packer.pack_double(z); + packer.pack_double(h); + packer.pack_double(p); + packer.pack_double(r); + finish_send_update(packer); +} diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.cxx b/direct/src/distributed/cDistributedSmoothNodeBase.cxx new file mode 100644 index 0000000000..266b45a087 --- /dev/null +++ b/direct/src/distributed/cDistributedSmoothNodeBase.cxx @@ -0,0 +1,284 @@ +// Filename: cDistributedSmoothNodeBase.cxx +// Created by: drose (03Sep04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "cDistributedSmoothNodeBase.h" +#include "cConnectionRepository.h" +#include "dcField.h" +#include "dcClass.h" +#include "dcmsgtypes.h" + +static const float smooth_node_epsilon = 0.01; +static const double network_time_precision = 100.0; // Matches ClockDelta.py + +CConnectionRepository *CDistributedSmoothNodeBase::_repository = NULL; +bool CDistributedSmoothNodeBase::_is_ai; +CHANNEL_TYPE CDistributedSmoothNodeBase::_ai_id; +PyObject *CDistributedSmoothNodeBase::_clock_delta = NULL; + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +CDistributedSmoothNodeBase:: +CDistributedSmoothNodeBase() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::Destructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +CDistributedSmoothNodeBase:: +~CDistributedSmoothNodeBase() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::initialize +// Access: Published +// Description: Initializes the internal structures from some +// constructs that are normally stored only in Python. +// Also reads the current node's pos & hpr values in +// preparation for transmitting them via one of the +// broadcast_pos_hpr_*() methods. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +initialize(const NodePath &node_path, DCClass *dclass, CHANNEL_TYPE do_id) { + _node_path = node_path; + _dclass = dclass; + _do_id = do_id; + + nassertv(!_node_path.is_empty()); + + _store_xyz = _node_path.get_pos(); + _store_hpr = _node_path.get_hpr(); + _store_stop = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::send_everything +// Access: Published +// Description: Broadcasts the current pos/hpr in its complete form. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +send_everything() { + d_setSmPosHpr(_store_xyz[0], _store_xyz[1], _store_xyz[2], + _store_hpr[0], _store_hpr[1], _store_hpr[2]); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::broadcast_pos_hpr_full +// Access: Published +// Description: Examines the complete pos/hpr information to see +// which of the six elements have changed, and +// broadcasts the appropriate messages. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +broadcast_pos_hpr_full() { + LPoint3f xyz = _node_path.get_pos(); + LVecBase3f hpr = _node_path.get_hpr(); + + int flags = 0; + + if (!IS_THRESHOLD_EQUAL(_store_xyz[0], xyz[0], smooth_node_epsilon)) { + _store_xyz[0] = xyz[0]; + flags |= F_new_x; + } + + if (!IS_THRESHOLD_EQUAL(_store_xyz[1], xyz[1], smooth_node_epsilon)) { + _store_xyz[1] = xyz[1]; + flags |= F_new_y; + } + + if (!IS_THRESHOLD_EQUAL(_store_xyz[2], xyz[2], smooth_node_epsilon)) { + _store_xyz[2] = xyz[2]; + flags |= F_new_z; + } + + if (!IS_THRESHOLD_EQUAL(_store_hpr[0], hpr[0], smooth_node_epsilon)) { + _store_hpr[0] = hpr[0]; + flags |= F_new_h; + } + + if (!IS_THRESHOLD_EQUAL(_store_hpr[1], hpr[1], smooth_node_epsilon)) { + _store_hpr[1] = hpr[1]; + flags |= F_new_p; + } + + if (!IS_THRESHOLD_EQUAL(_store_hpr[2], hpr[2], smooth_node_epsilon)) { + _store_hpr[2] = hpr[2]; + flags |= F_new_r; + } + + if (flags == 0) { + // No change. Send one and only one "stop" message. + if (!_store_stop) { + _store_stop = true; + d_setSmStop(); + } + + } else if (only_changed(flags, F_new_h)) { + // Only change in H. + _store_stop = false; + d_setSmH(_store_hpr[0]); + + } else if (only_changed(flags, F_new_x | F_new_y)) { + // Only change in X, Y + _store_stop = false; + d_setSmXY(_store_xyz[0], _store_xyz[1]); + + } else if (only_changed(flags, F_new_x | F_new_z)) { + // Only change in X, Z + _store_stop = false; + d_setSmXZ(_store_xyz[0], _store_xyz[2]); + + } else if (only_changed(flags, F_new_x | F_new_y | F_new_z)) { + // Only change in X, Y, Z + _store_stop = false; + d_setSmPos(_store_xyz[0], _store_xyz[1], _store_xyz[2]); + + } else if (only_changed(flags, F_new_h | F_new_p | F_new_r)) { + // Only change in H, P, R + _store_stop = false; + d_setSmHpr(_store_hpr[0], _store_hpr[1], _store_hpr[2]); + + } else if (only_changed(flags, F_new_x | F_new_y | F_new_h)) { + // Only change in X, Y, H + _store_stop = false; + d_setSmXYH(_store_xyz[0], _store_xyz[1], _store_hpr[0]); + + } else if (only_changed(flags, F_new_x | F_new_y | F_new_z | F_new_h)) { + // Only change in X, Y, Z, H + _store_stop = false; + d_setSmXYZH(_store_xyz[0], _store_xyz[1], _store_xyz[2], _store_hpr[0]); + + } else { + // Any other change + _store_stop = false; + d_setSmPosHpr(_store_xyz[0], _store_xyz[1], _store_xyz[2], + _store_hpr[0], _store_hpr[1], _store_hpr[2]); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::broadcast_pos_hpr_xyh +// Access: Published +// Description: Examines only X, Y, and H of the pos/hpr information, +// and broadcasts the appropriate messages. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +broadcast_pos_hpr_xyh() { + LPoint3f xyz = _node_path.get_pos(); + LVecBase3f hpr = _node_path.get_hpr(); + + int flags = 0; + + if (!IS_THRESHOLD_EQUAL(_store_xyz[0], xyz[0], smooth_node_epsilon)) { + _store_xyz[0] = xyz[0]; + flags |= F_new_x; + } + + if (!IS_THRESHOLD_EQUAL(_store_xyz[1], xyz[1], smooth_node_epsilon)) { + _store_xyz[1] = xyz[1]; + flags |= F_new_y; + } + + if (!IS_THRESHOLD_EQUAL(_store_hpr[0], hpr[0], smooth_node_epsilon)) { + _store_hpr[0] = hpr[0]; + flags |= F_new_h; + } + + if (flags == 0) { + // No change. Send one and only one "stop" message. + if (!_store_stop) { + _store_stop = true; + d_setSmStop(); + } + + } else if (only_changed(flags, F_new_h)) { + // Only change in H. + _store_stop = false; + d_setSmH(_store_hpr[0]); + + } else if (only_changed(flags, F_new_x | F_new_y)) { + // Only change in X, Y + _store_stop = false; + d_setSmXY(_store_xyz[0], _store_xyz[1]); + + } else { + // Any other change. + _store_stop = false; + d_setSmXYH(_store_xyz[0], _store_xyz[1], _store_hpr[0]); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::begin_send_update +// Access: Private +// Description: Fills up the packer with the data appropriate for +// sending an update on the indicated field name, up +// until the arguments. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +begin_send_update(DCPacker &packer, const string &field_name) { + DCField *field = _dclass->get_field_by_name(field_name); + nassertv(field != (DCField *)NULL); + + if (_is_ai) { + packer.RAW_PACK_CHANNEL(_do_id); + packer.RAW_PACK_CHANNEL(_ai_id); + packer.raw_pack_uint8('A'); + packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD); + packer.raw_pack_uint32(_do_id); + packer.raw_pack_uint16(field->get_number()); + + } else { + packer.raw_pack_uint16(CLIENT_OBJECT_UPDATE_FIELD); + packer.raw_pack_uint32(_do_id); + packer.raw_pack_uint16(field->get_number()); + } + + packer.begin_pack(field); + packer.push(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CDistributedSmoothNodeBase::finish_send_update +// Access: Private +// Description: Appends the timestamp and sends the update. +//////////////////////////////////////////////////////////////////// +void CDistributedSmoothNodeBase:: +finish_send_update(DCPacker &packer) { + PyObject *clock_delta = PyObject_GetAttrString(_clock_delta, "delta"); + nassertv(clock_delta != NULL); + double delta = PyFloat_AsDouble(clock_delta); + Py_DECREF(clock_delta); + + double local_time = ClockObject::get_global_clock()->get_frame_time(); + + short network_time = (short)(int)cfloor(((local_time - delta) * network_time_precision) + 0.5); + packer.pack_int(network_time); + + packer.pop(); + bool pack_ok = packer.end_pack(); + nassertv(pack_ok); + + Datagram dg(packer.get_data(), packer.get_length()); + _repository->send_datagram(dg); +} + diff --git a/direct/src/distributed/cDistributedSmoothNodeBase.h b/direct/src/distributed/cDistributedSmoothNodeBase.h new file mode 100644 index 0000000000..ac72d8af97 --- /dev/null +++ b/direct/src/distributed/cDistributedSmoothNodeBase.h @@ -0,0 +1,98 @@ +// Filename: cDistributedSmoothNodeBase.h +// Created by: drose (03Sep04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CDISTRIBUTEDSMOOTHNODEBASE_H +#define CDISTRIBUTEDSMOOTHNODEBASE_H + +#include "directbase.h" +#include "nodePath.h" +#include "dcbase.h" +#include "dcPacker.h" +#include "dcPython.h" // to pick up Python.h + +class DCClass; +class CConnectionRepository; + +//////////////////////////////////////////////////////////////////// +// Class : CDistributedSmoothNodeBase +// Description : This class defines some basic methods of +// DistributedSmoothNodeBase which have been moved into +// C++ as a performance optimization. +//////////////////////////////////////////////////////////////////// +class EXPCL_DIRECT CDistributedSmoothNodeBase { +PUBLISHED: + CDistributedSmoothNodeBase(); + ~CDistributedSmoothNodeBase(); + + INLINE static void + set_repository(CConnectionRepository *repository, + bool is_ai, CHANNEL_TYPE ai_id); + + INLINE static void + set_clock_delta(PyObject *clock_delta); + + void initialize(const NodePath &node_path, DCClass *dclass, + CHANNEL_TYPE do_id); + + void send_everything(); + + void broadcast_pos_hpr_full(); + void broadcast_pos_hpr_xyh(); + +private: + INLINE static bool only_changed(int flags, int compare); + + INLINE void d_setSmStop(); + INLINE void d_setSmH(float h); + INLINE void d_setSmXY(float x, float y); + INLINE void d_setSmXZ(float x, float z); + INLINE void d_setSmPos(float x, float y, float z); + INLINE void d_setSmHpr(float h, float p, float r); + INLINE void d_setSmXYH(float x, float y, float h); + INLINE void d_setSmXYZH(float x, float y, float z, float h); + INLINE void d_setSmPosHpr(float x, float y, float z, float h, float p, float r); + + void begin_send_update(DCPacker &packer, const string &field_name); + void finish_send_update(DCPacker &packer); + + enum Flags { + F_new_x = 0x01, + F_new_y = 0x02, + F_new_z = 0x04, + F_new_h = 0x08, + F_new_p = 0x10, + F_new_r = 0x20, + }; + + NodePath _node_path; + DCClass *_dclass; + CHANNEL_TYPE _do_id; + + static CConnectionRepository *_repository; + static bool _is_ai; + static CHANNEL_TYPE _ai_id; + static PyObject *_clock_delta; + + LPoint3f _store_xyz; + LVecBase3f _store_hpr; + bool _store_stop; +}; + +#include "cDistributedSmoothNodeBase.I" + +#endif // CDISTRIBUTEDSMOOTHNODEBASE_H