| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- """ClusterMsgs module: Message types for Cluster rendering"""
- # This module is intended to supply routines and dataformats common to
- # both ClusterClient and ClusterServer.
- from panda3d.core import *
- from direct.distributed.PyDatagram import PyDatagram
- from direct.distributed.PyDatagramIterator import PyDatagramIterator
- import time
- #these are the types of messages that are currently supported.
- CLUSTER_NONE = 0
- CLUSTER_CAM_OFFSET = 1
- CLUSTER_CAM_FRUSTUM = 2
- CLUSTER_CAM_MOVEMENT = 3
- CLUSTER_SWAP_READY = 4
- CLUSTER_SWAP_NOW = 5
- CLUSTER_COMMAND_STRING = 6
- CLUSTER_SELECTED_MOVEMENT = 7
- CLUSTER_TIME_DATA = 8
- CLUSTER_NAMED_OBJECT_MOVEMENT = 9
- CLUSTER_NAMED_MOVEMENT_DONE = 10
- CLUSTER_EXIT = 100
- #Port number for cluster rendering
- # DAEMON PORT IS PORT USED FOR STARTUP MESSAGE EXCHANGE
- # CAN BE OVERRIDEN WITH cluster-daemon-client-port for client
- # and cluster-daemon-server-port for server
- CLUSTER_DAEMON_PORT = 8001
- # THIS IS THE TCP PORT USED FOR EXCHANGE OF DATA ONCE STARTUP IS COMPLETE
- CLUSTER_SERVER_PORT = 1970
- # Precede command string with ! to tell server to execute command string
- # NOTE: Had to stick with the import __builtin__ scheme, at startup,
- # __builtins__ is a module, not a dictionary, like it is inside of a module
- # Note, this startup string obviates the need to set any cluster related
- # config variables in the client Configrc files
- SERVER_STARTUP_STRING = (
- '!bash ppython -c ' +
- '"import __builtin__; ' +
- '__builtin__.clusterMode = \'server\';' +
- '__builtin__.clusterServerPort = %s;' +
- '__builtin__.clusterSyncFlag = %d;' +
- '__builtin__.clusterDaemonClient = \'%s\';' +
- '__builtin__.clusterDaemonPort = %d;'
- 'from direct.directbase.DirectStart import *; run()"')
- class ClusterMsgHandler:
- """ClusterMsgHandler: wrapper for PC clusters/multi-piping networking"""
- def __init__(self, packetStart, notify):
- # packetStart can be used to distinguish which ClusterMsgHandler
- # sends a given packet.
- self.packetNumber = packetStart
- self.notify = notify
- def nonBlockingRead(self, qcr):
- """
- Return a datagram iterator and type if data is available on the
- queued connection reader
- """
- if qcr.dataAvailable():
- datagram = NetDatagram()
- if qcr.getData(datagram):
- (dgi, type) = self.readHeader(datagram)
- else:
- dgi = None
- type = CLUSTER_NONE
- self.notify.warning("getData returned false")
- else:
- datagram = None
- dgi = None
- type = CLUSTER_NONE
- # Note, return datagram to keep a handle on the data
- return (datagram, dgi, type)
- def blockingRead(self, qcr):
- """
- Block until data is available on the queued connection reader.
- Returns a datagram iterator and type
- """
- while not qcr.dataAvailable():
- # The following may not be necessary.
- # I just wanted some
- # time given to the operating system while
- # busy waiting.
- time.sleep(0.002)
- # Data is available, create a datagram iterator
- datagram = NetDatagram()
- if qcr.getData(datagram):
- (dgi, type) = self.readHeader(datagram)
- else:
- (dgi, type) = (None, CLUSTER_NONE)
- self.notify.warning("getData returned false")
- # Note, return datagram to keep a handle on the data
- return (datagram, dgi, type)
- def readHeader(self, datagram):
- dgi = PyDatagramIterator(datagram)
- number = dgi.getUint32()
- type = dgi.getUint8()
- self.notify.debug("Packet %d type %d received" % (number, type))
- return (dgi, type)
- def makeCamOffsetDatagram(self, xyz, hpr):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_CAM_OFFSET)
- datagram.addFloat32(xyz[0])
- datagram.addFloat32(xyz[1])
- datagram.addFloat32(xyz[2])
- datagram.addFloat32(hpr[0])
- datagram.addFloat32(hpr[1])
- datagram.addFloat32(hpr[2])
- return datagram
- def parseCamOffsetDatagram(self, dgi):
- x=dgi.getFloat32()
- y=dgi.getFloat32()
- z=dgi.getFloat32()
- h=dgi.getFloat32()
- p=dgi.getFloat32()
- r=dgi.getFloat32()
- self.notify.debug('new offset=%f %f %f %f %f %f' % (x, y, z, h, p, r))
- return (x, y, z, h, p, r)
- def makeCamFrustumDatagram(self, focalLength, filmSize, filmOffset):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_CAM_FRUSTUM)
- datagram.addFloat32(focalLength)
- datagram.addFloat32(filmSize[0])
- datagram.addFloat32(filmSize[1])
- datagram.addFloat32(filmOffset[0])
- datagram.addFloat32(filmOffset[1])
- return datagram
- def parseCamFrustumDatagram(self, dgi):
- focalLength = dgi.getFloat32()
- filmSize = (dgi.getFloat32(), dgi.getFloat32())
- filmOffset = (dgi.getFloat32(), dgi.getFloat32())
- self.notify.debug('fl, fs, fo=%f, (%f, %f), (%f, %f)' %
- (focalLength, filmSize[0], filmSize[1],
- filmOffset[0], filmOffset[1]))
- return (focalLength, filmSize, filmOffset)
- def makeCamMovementDatagram(self, xyz, hpr):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_CAM_MOVEMENT)
- datagram.addFloat32(xyz[0])
- datagram.addFloat32(xyz[1])
- datagram.addFloat32(xyz[2])
- datagram.addFloat32(hpr[0])
- datagram.addFloat32(hpr[1])
- datagram.addFloat32(hpr[2])
- return datagram
- def makeNamedMovementDone(self):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_NAMED_MOVEMENT_DONE)
- return datagram
-
- def makeNamedObjectMovementDatagram(self, xyz, hpr, scale, color, hidden, name):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_NAMED_OBJECT_MOVEMENT)
- datagram.addString(name)
- datagram.addFloat32(xyz[0])
- datagram.addFloat32(xyz[1])
- datagram.addFloat32(xyz[2])
- datagram.addFloat32(hpr[0])
- datagram.addFloat32(hpr[1])
- datagram.addFloat32(hpr[2])
- datagram.addFloat32(scale[0])
- datagram.addFloat32(scale[1])
- datagram.addFloat32(scale[2])
- datagram.addFloat32(color[0])
- datagram.addFloat32(color[1])
- datagram.addFloat32(color[2])
- datagram.addFloat32(color[3])
- datagram.addBool(hidden)
- return datagram
- def parseCamMovementDatagram(self, dgi):
- x=dgi.getFloat32()
- y=dgi.getFloat32()
- z=dgi.getFloat32()
- h=dgi.getFloat32()
- p=dgi.getFloat32()
- r=dgi.getFloat32()
- self.notify.debug((' new position=%f %f %f %f %f %f' %
- (x, y, z, h, p, r)))
- return (x, y, z, h, p, r)
- def parseNamedMovementDatagram(self, dgi):
- name = dgi.getString()
- x=dgi.getFloat32()
- y=dgi.getFloat32()
- z=dgi.getFloat32()
- h=dgi.getFloat32()
- p=dgi.getFloat32()
- r=dgi.getFloat32()
- sx = dgi.getFloat32()
- sy = dgi.getFloat32()
- sz = dgi.getFloat32()
- red = dgi.getFloat32()
- g = dgi.getFloat32()
- b = dgi.getFloat32()
- a = dgi.getFloat32()
- hidden = dgi.getBool()
- return (name,x, y, z, h, p, r, sx, sy, sz, red, g, b, a, hidden)
- def makeSelectedMovementDatagram(self, xyz, hpr, scale):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_SELECTED_MOVEMENT)
- datagram.addFloat32(xyz[0])
- datagram.addFloat32(xyz[1])
- datagram.addFloat32(xyz[2])
- datagram.addFloat32(hpr[0])
- datagram.addFloat32(hpr[1])
- datagram.addFloat32(hpr[2])
- datagram.addFloat32(scale[0])
- datagram.addFloat32(scale[1])
- datagram.addFloat32(scale[2])
- #datagram.addBool(hidden)
- return datagram
- def parseSelectedMovementDatagram(self, dgi):
- x=dgi.getFloat32()
- y=dgi.getFloat32()
- z=dgi.getFloat32()
- h=dgi.getFloat32()
- p=dgi.getFloat32()
- r=dgi.getFloat32()
- sx=dgi.getFloat32()
- sy=dgi.getFloat32()
- sz=dgi.getFloat32()
- self.notify.debug(' new position=%f %f %f %f %f %f %f %f %f' %
- (x, y, z, h, p, r, sx, sy, sz))
- return (x, y, z, h, p, r, sx, sy, sz)
- def makeCommandStringDatagram(self, commandString):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_COMMAND_STRING)
- datagram.addString(commandString)
- return datagram
- def parseCommandStringDatagram(self, dgi):
- command = dgi.getString()
- return command
- def makeSwapNowDatagram(self):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_SWAP_NOW)
- return datagram
- def makeSwapReadyDatagram(self):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_SWAP_READY)
- return datagram
- def makeExitDatagram(self):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_EXIT)
- return datagram
- def makeTimeDataDatagram(self, frameCount, frameTime, dt):
- datagram = PyDatagram()
- datagram.addUint32(self.packetNumber)
- self.packetNumber = self.packetNumber + 1
- datagram.addUint8(CLUSTER_TIME_DATA)
- datagram.addUint32(frameCount)
- datagram.addFloat32(frameTime)
- datagram.addFloat32(dt)
- return datagram
- def parseTimeDataDatagram(self, dgi):
- frameCount=dgi.getUint32()
- frameTime=dgi.getFloat32()
- dt=dgi.getFloat32()
- self.notify.debug('time data=%f %f' % (frameTime, dt))
- return (frameCount, frameTime, dt)
|