class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if not np in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
class NodeRaycaster: def __init__(self, renderer): self.log = logging.getLogger('pano.raycaster') self.renderer = renderer #Stores the collisions of the camera ray with the cubemap self.collisionsQueue = None #Variables for setting up collision detection in Panda self.pickerNP = None self.pickerNode = None self.pickerRay = None self.traverser = None def initialize(self): """ To setup collision detection we need: a. A CollisionNode having a ray as its solid and placed at the position of the camera while also having the same orientation as the camera. b. A new nodepath placed in the scenegraph as an immediate child of the camera. It will be used to insert the collision node in the scenegraph. c. A CollisionRay for firing rays based on mouse clicks. d. A collisions traverser. e. A collisions queue where all found collisions will be stored for later processing. """ self.traverser = CollisionTraverser('Hotspots collision traverser') self.collisionsQueue = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.pickerNP = self.renderer.getCamera().attachNewNode( self.pickerNode) self.traverser.addCollider(self.pickerNP, self.collisionsQueue) def dispose(self): if self.pickerNP is not None: self.traverser.removeCollider(self.pickerNP) self.pickerNode.clearSolids() self.pickerNP.removeNode() def raycastWindow(self, x, y, returnAll=False): ''' Casts a camera ray, whose origin is implicitly defined by the given window coordinates, against the rendered scene returns information regarding the hit point, if any. @param x: The x window coordinate of the ray's origin in render2d space. @param y: The y window coordinate of the ray's origin in render2d space @param returnAll: If set to False then only the closest collided geometry is returned, otherwise all nodepaths whose collision nodes were intersected by the camera ray will be returned. @return: If returnAll was False, then a list containing a tuple of the form (topmost intersected NodePath, contact point Point3f). if returnAll was set to True, a list of tuples in the same form as above, one tuple for each intersection. None if no collision occurred. ''' #This makes the ray's origin the camera and makes the ray point #to the screen coordinates of the mouse self.pickerRay.setFromLens(self.renderer.getCamera().node(), x, y) #Check for collision only with the node self.traverser.traverse(self.renderer.getSceneRoot()) if self.collisionsQueue.getNumEntries() > 0: if not returnAll: self.collisionsQueue.sortEntries() cEntry = self.collisionsQueue.getEntry(0) if cEntry.hasInto(): return [(cEntry.getIntoNodePath(), cEntry.getSurfacePoint())] else: return None else: nodepaths = [] for i in xrange(self.collisionsQueue.getNumEntries()): cEntry = self.collisionsQueue.getEntry(i) if cEntry.hasInto(): # self.log.debug('adding collision into-nodepath: %s' % str(cEntry.getIntoNodePath())) intoNP = cEntry.getIntoNodePath() nodepaths.append( (intoNP, cEntry.getSurfacePoint(intoNP))) return nodepaths
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ( (levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2]), ) self._lookAtZ = self._toon.getHeight() + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath("CamParent") self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath("CameraLookAt") self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode("CameraToonRay") camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask( OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask ) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath("trans") self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin("fixed", 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / (maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E ** (dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr(smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find("col_") >= 0: np = entry.getIntoNodePath().getParent() if not nodesInBetween.has_key(np): nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if self._betweenCamAndToon.has_key(np): del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").hide() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").show() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").show() self._betweenCamAndToon = nodesInBetween