I am trying to write a scene navigation camera that enables the user to do many more things including seamless switching from the standard trackball (base.trackball.node()) to the standard camera (base.camera). My requirement here is that when the user switches modes (Drive versus Trackball) that the apparent viewer state remain the same … that is … the viewer retains its position and orientation between mode switches.
There is no problem when I switch from trackball mode to drive mode. The viewer state (base.camera.getPos(), base.camera.getHpr()) does not change. However, if I switch to drive mode and move the camera position, then switch back to trackball mode, the trackball remembers the last position it was before I changed to drive mode and plops me right back at that point.
I see that the trackball has both an origin and an offset from that origin but I am having difficulty figuring out how tofix this problem. Any ideas?
My code so far follows … The methods of interest here are switchToDriveMode and switchToTrackballMode in class Camera. You can see some of the ideas I have been experimenting with in the commented out code sections in these methods.
Notes On Controlling Camera:
Starts out in standard Panda3D trackball mode. The ‘n’ key cycles the mode from camera to drive and back.
‘+’ - Increases the translation gain (speeds up motion)
‘-’ - Decreases the translation gain (slows down motion)
‘mouse1’ - When depressed, slides the camera laterally in trackball mode, changes the heading angle in drive mode.
‘mouse2’ - When depressed, slides the camera forward/backward in trackball mode, changes the pitch angle in drive mode.
When in trackball mode, the following keys are ignored. They function in drive mode.
‘d’ - Drive forward
‘c’ - Drive backward
‘s’ - Slide left
‘f’ - Slide right
‘e’ - Slide up
‘v’ - Slide down
Thx,
Paul
Code for Camera.py
# Camera.py
""" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Description: Dual mode (FPS / Trackball) Camera.
$Author: pleopard $
$Modtime: 10/19/06 8:46p $
$Revision: 1 $
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """
# Standard imports
import sys
from math import fabs
# Panda imports
from pandac.PandaModules import *
from direct.showbase import DirectObject
from direct.showbase.DirectObject import DirectObject
import direct.directbase.DirectStart
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Internal stuff
def Sign(x):
if x<0:
return -1
return 1
def ComputeMapping(a0,a1,b0,b1) :
if (a1-a0)==0 :
slope = 0
intercept = 0
else :
slope = (b1-b0)/(a1-a0)
intercept = b1 - slope*a1
return [slope,intercept]
class CameraControlDefs:
def getDriveForwardEvent(self):
return 'd'
def getDriveReverseEvent(self):
return 'c'
def getSlideLeftEvent(self):
return 's'
def getSlideRightEvent(self):
return 'f'
def getSlideUpEvent(self):
return 'e'
def getSlideDownEvent(self):
return 'v'
def getModeCyclingEvent(self):
return 'n'
def getMotionGainIncreaseEvent(self):
return '+'
def getMotionGainDecreaseEvent(self):
return '-'
def getTurboBoostEvent(self):
return 'space'
def getHeadingAngleEvent(self):
return 'mouse1'
def getPitchAngleEvent(self):
return 'mouse2'
def getRollAngleEvent(self):
return 'mouse3'
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
class Camera(DirectObject):
TrackBallMode = 0
DriveMode = 1
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def __init__(self,msgDisplay,camControlsDef):
# *** Get controls definitions
self.mDriveForwardEvent = camControlsDef.getDriveForwardEvent()
self.mDriveReverseEvent = camControlsDef.getDriveReverseEvent()
self.mSlideLeftEvent = camControlsDef.getSlideLeftEvent()
self.mSlideRightEvent = camControlsDef.getSlideRightEvent()
self.mSlideUpEvent = camControlsDef.getSlideUpEvent()
self.mSlideDownEvent = camControlsDef.getSlideDownEvent()
self.mModeCyclingEvent = camControlsDef.getModeCyclingEvent()
self.mTurboBoostEvent = camControlsDef.getTurboBoostEvent()
self.mMotionGainIncreaseEvent = \
camControlsDef.getMotionGainIncreaseEvent()
self.mMotionGainDecreaseEvent = \
camControlsDef.getMotionGainDecreaseEvent()
self.mHeadingAngleEvent = camControlsDef.getHeadingAngleEvent()
self.mPitchAngleEvent = camControlsDef.getPitchAngleEvent()
self.mRollAngleEvent = camControlsDef.getRollAngleEvent()
# *** Setup static controls
self.accept(self.mModeCyclingEvent,self.cycleMode)
control = self.mMotionGainIncreaseEvent
self.accept(control,self.motionGainIncrease)
control = control + '-repeat'
self.accept(control,self.motionGainIncrease)
control = self.mMotionGainDecreaseEvent
self.accept(control,self.motionGainDecrease)
control = control + '-repeat'
self.accept(control,self.motionGainDecrease)
control = self.mTurboBoostEvent
self.accept(control,self.turboBoostOn)
control = control + '-up'
self.accept(control,self.turboBoostOff)
# *** Note current position
self.mLastPos = base.camera.getPos()
self.mLastHpr = base.camera.getHpr()
# *** Other setup
self.mStatusDisplay = msgDisplay
self.mCameraMode = Camera.TrackBallMode
base.useTrackball()
self.mMotionGain = 1
self.mHeadingGain = 5
self.mPitchGain = 5
self.mRollGain = 12
self.mDriveDir = 0
self.mLateralSlideDir = 0
self.mVerticalSlideDir = 0
self.mDevButtons = [\
Camera.__DeviceButton(),
Camera.__DeviceButton(),
Camera.__DeviceButton()
]
self.mTrackBallScale = base.trackball.node().getForwardScale()
self.mLastTime = globalClock.getFrameTime()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def tickUpdate(self):
if self.mCameraMode == Camera.TrackBallMode:
return
# Get time differential
dt = globalClock.getFrameTime() - self.mLastTime
self.mLastTime = globalClock.getFrameTime()
# Get window size
wp = base.win.getProperties()
winWidth = wp.getXSize()
winWidth2 = winWidth/2
winHeight = wp.getYSize()
winHeight2 = winHeight/2
# Compute mapping from (0,W-1) onto (-W/2,W/2)
xTrans = \
ComputeMapping(\
0.0,float(winWidth-1), \
-float(winWidth2), float(winWidth2) \
)
# Compute mapping from (0,H-1) onto (-H/2,H/2)
yTrans = \
ComputeMapping(\
0.0,float(winHeight-1), \
-float(winHeight2), float(winHeight2) \
)
# Get cursor coordinates
md = base.win.getPointer(0)
cursorX = md.getX()
cursorY = md.getY()
# Convert using transform
xCursor = xTrans[0]*float(cursorX)+xTrans[1]
yCursor = yTrans[0]*float(cursorY)+yTrans[1]
aButtonIsDown = False
# Init delta angles
dHeading = 0
dPitch = 0
dRoll = 0
# Heading and pitch (mouse)
mouseButton0Down = self.mDevButtons[0].mIsPressed
if mouseButton0Down :
delx = float(self.mDevButtons[0].mCoordinates[0]) - xCursor
dely = float(self.mDevButtons[0].mCoordinates[1]) - yCursor
delx = xCursor*dt
dely = yCursor*dt
sx = Sign(delx)
sy = Sign(dely)
dx = delx*delx*sx*self.mHeadingGain
dy = dely*dely*sy*self.mPitchGain
dHeading += -dx
dPitch += dy
aButtonIsDown = True
# Roll
mouseButton2Down = self.mDevButtons[2].mIsPressed
if mouseButton2Down :
delx = float(self.mDevButtons[0].mCoordinates[0]) - xCursor
# dely = float(self.mDevButtons[0].mCoordinates[1]) - yCursor
delx = xCursor*dt
# dely = yCursor*dt
dir = Sign(delx)
da = fabs(delx*delx)*dir*self.mRollGain
dPitch += da
aButtonIsDown = True
# Get direction of travel
mouseButton1Down = self.mDevButtons[1].mIsPressed
direction = 1
if mouseButton1Down :
aButtonIsDown = True
direction = -1
dPos = Vec3(0,0,0)*direction
# Update camera
if self.mDriveDir != 0:
quat = base.camera.getQuat()
fw = quat.getForward()
cPos = base.camera.getPos()
dPos = dPos + fw*self.mMotionGain*self.mDriveDir
if self.mLateralSlideDir != 0:
quat = base.camera.getQuat()
rt = quat.getRight()
cPos = base.camera.getPos()
dPos = dPos + rt*self.mMotionGain*self.mLateralSlideDir
if self.mVerticalSlideDir != 0:
quat = base.camera.getQuat()
up = quat.getUp()
cPos = base.camera.getPos()
dPos = dPos + up*self.mMotionGain*self.mVerticalSlideDir
dPos = dPos*self.mMotionGain*dt
cPos = base.camera.getPos() + dPos
base.camera.setPos(cPos)
dHpr = Vec3(dHeading,dPitch,dRoll)*dt
cHpr = base.camera.getHpr() + dHpr
base.camera.setHpr(cHpr)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def getPos(self):
return base.camera.getPos()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def getHpr(self):
return base.camera.getHpr()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def __str__(self):
if self.mCameraMode == Camera.DriveMode:
s = "Drive"
elif self.mCameraMode == Camera.TrackBallMode:
s = "TrackBall"
pos = base.camera.getPos()
hpr = base.camera.getHpr()
s1 = " Pos(%7.2f,%7.2f,%7.2f)" % (pos[0],pos[1],pos[2])
s2 = " Hpr(%7.2f,%7.2f,%7.2f)" % (hpr[0],hpr[1],hpr[2])
s = s + s1 + s2
return s
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Internal utility class
class __DeviceButton :
def __init__(self) :
self.mIsPressed = False
self.mCoordinates = [0,0]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Internal function
def __SetDeviceButton(self, button, newState):
md = base.win.getPointer(0)
cursorX = md.getX()
cursorY = md.getY()
self.mDevButtons[button].mIsPressed = newState
self.mDevButtons[button].mCoordinates = [cursorX,cursorY]
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def motionGainIncrease(self):
if self.mCameraMode == Camera.DriveMode:
self.mMotionGain = self.mMotionGain*1.05
print "Motion Gain : ",self.mMotionGain
elif self.mCameraMode == Camera.TrackBallMode:
scale = base.trackball.node().getForwardScale()*1.05
base.trackball.node().setForwardScale(scale)
print "Trackball Gain : ",scale
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def motionGainDecrease(self):
if self.mCameraMode == Camera.DriveMode:
self.mMotionGain = self.mMotionGain*0.95
print "Motion Gain : ",self.mMotionGain
elif self.mCameraMode == Camera.TrackBallMode:
self.mTrackBallScale = base.trackball.node().getForwardScale()*0.95
base.trackball.node().setForwardScale(self.mTrackBallScale)
print "Trackball Gain : ",self.mTrackBallScale
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def turboBoostOn(self):
self.mMotionGain *= 10.0
self.mTrackBallScale *= 10.0
base.trackball.node().setForwardScale(self.mTrackBallScale)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def turboBoostOff(self):
self.mMotionGain *= 0.10
self.mTrackBallScale *= 0.10
base.trackball.node().setForwardScale(self.mTrackBallScale)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def driveReverse(self):
self.mDriveDir = -1
def driveForward(self):
self.mDriveDir = 1
def stopDriving(self):
self.mDriveDir = 0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def lateralSlideRight(self):
self.mLateralSlideDir = 1
def lateralSlideLeft(self):
self.mLateralSlideDir = -1
def stopLateralSliding(self):
self.mLateralSlideDir = 0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def verticalSlideDown(self):
self.mVerticalSlideDir = -1
def verticalSlideUp(self):
self.mVerticalSlideDir = 1
def stopVerticalSliding(self):
self.mVerticalSlideDir = 0
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def switchToDriveMode(self):
self.mLastPos = base.camera.getPos()
self.mLastHpr = base.camera.getHpr()
self.mCameraMode = Camera.DriveMode
base.useDrive()
base.disableMouse()
# base.camera.setPos(self.mLastPos)
# base.camera.setHpr(self.mLastHpr)
# xPos = self.mLastPos*-1.0
# xHpr = self.mLastHpr*-1.0
# base.trackball.node().setPos(self.mLastPos)
# base.trackball.node().setHpr(self.mLastHpr)
# base.camera.setPos(xPos)
# base.camera.setHpr(xHpr)
self.mDriveDir = 0
self.mLateralSlideDir = 0
self.mVerticalSlideDir = 0
control = self.mDriveForwardEvent
self.accept(control,self.driveForward)
control = control + '-up'
self.accept(control,self.stopDriving)
control = self.mDriveReverseEvent
self.accept(control,self.driveReverse)
control = control + '-up'
self.accept(control,self.stopDriving)
control = self.mSlideLeftEvent
self.accept(control,self.lateralSlideLeft)
control = control + '-up'
self.accept(control,self.stopLateralSliding)
control = self.mSlideRightEvent
self.accept(control,self.lateralSlideRight)
control = control + '-up'
self.accept(control,self.stopLateralSliding)
control = self.mSlideUpEvent
self.accept(control,self.verticalSlideUp)
control = control + '-up'
self.accept(control,self.stopVerticalSliding)
control = self.mSlideDownEvent
self.accept(control,self.verticalSlideDown)
control = control + '-up'
self.accept(control,self.stopVerticalSliding)
control = self.mHeadingAngleEvent
self.accept(control,self.__SetDeviceButton, [0, 1])
control = control + '-up'
self.accept(control,self.__SetDeviceButton, [0, 0])
control = self.mPitchAngleEvent
self.accept(control,self.__SetDeviceButton, [1, 1])
control = control + '-up'
self.accept(control,self.__SetDeviceButton, [1, 0])
control = self.mRollAngleEvent
self.accept(control,self.__SetDeviceButton, [2, 1])
control = control + '-up'
self.accept(control,self.__SetDeviceButton, [2, 0])
self.mStatusDisplay.postStatusMessage("Camera Mode : Drive")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def switchToTrackBallMode(self):
self.mLastPos = base.camera.getPos()
self.mLastHpr = base.camera.getHpr()
self.mCameraMode = Camera.TrackBallMode
base.useTrackball()
base.enableMouse()
# xPos = self.mLastPos*-1.0
# xHpr = self.mLastHpr*-1.0
# base.trackball.node().setPos(xPos)
# base.trackball.node().setHpr(xHpr)
# base.camera.setPos(self.mLastPos)
# base.camera.setHpr(self.mLastHpr)
control = self.mDriveForwardEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
control = self.mDriveReverseEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
control = self.mSlideLeftEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
control = self.mSlideRightEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
control = self.mSlideUpEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
control = self.mSlideDownEvent
self.ignore(control)
control = control + '-up'
self.ignore(control)
self.mDriveDir = 0
self.mLateralSlideDir = 0
self.mVerticalSlideDir = 0
self.ignore('mouse1')
self.ignore('mouse1-up')
self.ignore('mouse2')
self.ignore('mouse2-up')
self.ignore('mouse3')
self.ignore('mouse3-up')
self.mStatusDisplay.postStatusMessage("Camera Mode : Trackball")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def cycleMode(self):
if self.mCameraMode == 0:
self.switchToDriveMode()
elif self.mCameraMode == 1:
self.switchToTrackBallMode()
Code for Main.py
# Main.py
""" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Description: Test harness for the Camera class.
$Author: pleopard $
$Modtime: 10/19/06 8:46p $
$Revision: 1 $
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """
# Standard imports
import sys
# Panda imports
from pandac.PandaModules import *
loadPrcFile("CameraTester.prc")
from direct.gui.OnscreenText import OnscreenText
from direct.showbase import DirectObject
from direct.showbase.DirectObject import DirectObject
import direct.directbase.DirectStart
from direct.task import Task
from direct.showbase import Audio3DManager
# Local imports
from Camera import *
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def Max(a,b):
if a>b:
return a
return b
def CreateTextLabel(\
text,
color,
i,
xStart=-1.3,
yStart=0.95,
yOffset = 0.1,
tFont=None
):
if tFont==None:
return OnscreenText(\
text = text,
pos = (xStart, yStart-yOffset*i),
fg=color,
mayChange = True,
align=TextNode.ALeft
)
else:
return OnscreenText(\
text = text,
pos = (xStart, yStart-yOffset*i),
fg=color,
mayChange = True,
align=TextNode.ALeft,
font=tFont
)
def P3DCreateGridXY(xCellCount=10,yCellCount=10,lineThickness=1,doCenter=True):
if doCenter==True:
offset = -0.5
else:
offset = 0
ls = LineSegs()
ls.setThickness(lineThickness)
offset = -0.5
deltaX = 1.0/float(xCellCount)
deltaY = 1.0/float(yCellCount)
for i in range(xCellCount):
x0 = float(i)*deltaX + offset
x1 = float(i+1)*deltaX + offset
for j in range(yCellCount):
y0 = float(j)*deltaY + offset
y1 = float(j+1)*deltaY + offset
ls.moveTo(x0,y0,0)
ls.drawTo(x0,y1,0)
ls.drawTo(x1,y1,0)
ls.drawTo(x1,y0,0)
ls.drawTo(x0,y0,0)
node = ls.create()
return NodePath(node)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
class World(DirectObject):
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def timeUpdate(self,task):
self.mCamera.tickUpdate()
s = str(self.mCamera)
self.mCamDisplay.setText(s)
return Task.cont
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def __init__(self):
# *** Set program inputs
worldDims = (1000.0,1000.0,100.0)
bkgColor = (0.0,0.05,0.1,1.0)
titleColor = (1.0,1.0,0.0,1.0)
msgColor = (0.0,1.0,0.0,1.0)
messageColor = (1,1,0,1)
windowTitle = 'Test harness for the Camera class.'
gridColor = (0,0.4,0.4)
cursorHidden = False
axesScale = .25
textXStart = -1.3
textYStart = 0.95
textYOffset = 0.1
verbose = False
lightLevel = 0.7
lightPos = (0.0,-10.0,10.0)
lightHpr = (0.0,-26.0,0.0)
backgroundMusicFile = "None"
# *** Setup basics
wp = WindowProperties()
wp.setTitle(windowTitle)
wp.setCursorHidden(cursorHidden)
base.win.requestProperties(wp)
# *** Setup text displays
self.mTitleDisplay = \
CreateTextLabel(
windowTitle,
titleColor,
1,
textXStart,
textYStart,
textYOffset,
None
)
self.mMessageDisplay = \
CreateTextLabel(
'> ',
msgColor,
2,
textXStart,
textYStart,
textYOffset,
None
)
self.mCamDisplay = \
CreateTextLabel(
'',
msgColor,
3,
textXStart,
textYStart,
textYOffset,
None
)
# *** Setup world dimensions
self.mWorldDims = worldDims
maxWorldDim = \
Max(\
Max(self.mWorldDims[0],self.mWorldDims[1]),
self.mWorldDims[2]
)
base.camLens.setNearFar(0.1,2.5*maxWorldDim)
# *** Setup lighting
dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(lightLevel, lightLevel, lightLevel, 1))
dlnp = render.attachNewNode(dlight.upcastToPandaNode())
dlnp.setHpr(lightHpr[0],lightHpr[1],lightHpr[2])
dlnp.setPos(lightPos[0],lightPos[1],lightPos[2])
render.setLight(dlnp)
alight = AmbientLight('alight')
alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
alnp = render.attachNewNode(alight.upcastToPandaNode())
# *** Setup camera stuff
self.mCamera = Camera(self,CameraControlDefs())
# *** Setup scene
base.setBackgroundColor(\
bkgColor[0],
bkgColor[1],
bkgColor[2],
bkgColor[3]
)
self.mGrid = P3DCreateGridXY(50,50,1,True)
self.mGrid.setColor(gridColor[0],gridColor[1],gridColor[2])
self.mGrid.setScale(\
self.mWorldDims[0],
self.mWorldDims[1],
self.mWorldDims[2]
)
self.mGrid.setPos(0,0,0)
self.mGrid.setLightOff()
self.mGrid.setTwoSided(True)
self.mGrid.reparentTo(render)
self.mGridVisible = True
aScale = axesScale*maxWorldDim
self.mAxes = loader.loadModel("Axes3D.egg")
if self.mAxes==None:
self.mAxes = P3DCreateAxes()
self.mAxes.setScale(aScale,aScale,aScale)
self.mAxes.reparentTo(render)
self.mAxesVisible = True
# *** Setup events
self.setupKeyBindings()
# *** Setup basic audio
self.mFxMgr = base.sfxManagerList[0]
self.m3DAudioMgr = Audio3DManager.Audio3DManager(self.mFxMgr, camera)
self.m3DAudioMgr.setDropOffFactor( 0.7 )
if backgroundMusicFile=="None":
self.mBkgMusic = None
else:
self.mBkgMusic = self.mFxMgr.getSound("T2-Ice.mp3")
self.mBkgMusic.setLoop(True)
self.mBkgMusic.setVolume(1.0)
# *** Done, setup time update task
taskMgr.add(self.timeUpdate,'TimeUpdate')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def snapShot(self):
base.screenshot('Snap')
self.postStatusMessage("Snapshot Saved")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def getBoundingVolume(self):
return BoundingVolume(\
0,0,0,\
self.mWorldDims[0],\
self.mWorldDims[1],\
self.mWorldDims[2]
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def getElevation(self,x,y):
return 0;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def postStatusMessage(self,msg):
print msg
self.mMessageDisplay.setText("> "+msg)
taskMgr.doMethodLater(
1.2,
self.clearStatusDisplay,
'',extraArgs =[]
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def clearStatusDisplay(self):
self.mMessageDisplay.setText("> ")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Method name : setupKeyBindings
#
# Description:
#
# Load and register key bindings
#
# Input(s):
#
# None
#
# Output(s):
#
# None
#
def setupKeyBindings(self) :
self.accept('p',self.snapShot)
self.accept('escape',sys.exit)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
world = World()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Run the program
run()