Hi All, thanks in advance for any help anyone can offer.
I’m modifying the rts scroller camera from this post:
[Real-Time Strategy Camera)
I’ve got it setup almost entirely except for one problem. I am scrolling over a 3d mesh (flat plane for now) that is 128X128 and centered on the origin. Scrolling works fine, zooming works fine, but my clamping system needs to be improved. I obviously don’t want to over scroll the mesh, so I calculate the center of my scene and clamp my X and Y camera position to be within the map size, shifted by the distance of my zoom and angle of camera view. This works fine. I am clamping successfully, but only based on the coordinate at the center of my screen. What I really need to do is clamp based when my viewable area will display outside of my ground plane. This number can be thought of my as current clamp coords minus 1/2 of a screen in any direction.
Basically I need to know how to calculate how many units in 3d space == 1/2 a 2d screen, or I need a new approach for clamping to my groundplane.
Here is my code:
from direct.showbase.DirectObject import DirectObject from pandac.PandaModules import VBase3, Point2, Point3 from math import tan, radians class gamecam(DirectObject): def __init__(self): self._gameCam = base.cam base.camLens.setFov(40.0) base.camLens.setFocalLength(35.0) self._gameCam.setPos(0,0,30) self.tolerance = 35 # How many pixels from the edge of the window self.cameraMoveDist = 14 # How many units to move the camera self.cameraZBounds = [25, 60] self.cameraXBounds = [-64,64] self.cameraYBounds = [-64,64] #base.disableMouse() self._gameCam.lookAt(0,15,0) # Make the camera look at the floater (creates angle) taskMgr.add(self.handleMouseInput,"mouse_scroll") self.accept( 'wheel_up', self.zoom,  ) # Listen for mouse scrolling self.accept( 'wheel_down', self.zoom, [-1] ) # for zooming def handleMouseInput(self, task): # Get the position of the cursor if it is in the window if( base.mouseWatcherNode.hasMouse() ): movementDirection = VBase3(0, 0, 0) # Which direction to move the camera md = base.win.getPointer(0) x = md.getX() y = md.getY() # If the cursor is on the edges, move the camera if( x + self.tolerance > 640 ): movementDirection.setX(1) elif( x < self.tolerance ): movementDirection.setX(-1) if( y + self.tolerance > 480 ): movementDirection.setY(-1) elif( y < self.tolerance ): movementDirection.setY(1) if movementDirection.x != 0 or movementDirection.y !=0: self.moveCamera( movementDirection ) return task.cont def moveCamera(self, dir): deltaPos = dir * self.cameraMoveDist * globalClock.getDt() cpos = self._gameCam.getPos() + deltaPos zoomModifiedBound = tan(radians(26.5651)) * self._gameCam.getPos().getZ() #This num is specific to this: self._gameCam.lookAt(0,15,0). cpos.x = min (max(cpos.x, self.cameraXBounds),self.cameraXBounds) cpos.y = min (max(cpos.y, self.cameraYBounds - zoomModifiedBound),self.cameraYBounds - zoomModifiedBound) self._gameCam.setPos( cpos ) # Determines the vector from the camera to the floater and moves the # camera closer to or farther from the floater along the vector def zoom(self, dir): camToFloater = VBase3(0, 0.15,0) - VBase3(0,0,0.30) camToFloater *= dir newPos = self._gameCam.getPos() + camToFloater z = newPos.getZ() if( z < self.cameraZBounds and z > self.cameraZBounds): self._gameCam.setPos(newPos) def setXBounds(self, arr2): self.cameraXBounds = arr2 def setYBounds(self, arr2): self.cameraYBounds = arr2