| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- from PandaObject import *
- from DirectGrid import DirectGrid
- class DirectCameraManipulation(PandaObject):
- def __init__():
- # Create the grid
- self.grid = DirectGrid(render)
- self.grid.hide()
- self.hitPt = Point3(0)
- self.iPoint = Point3(0)
- self.centerOfRotation = render.attachNewNode( NamedNode() )
- self.centerOfRotation.node().setName( 'centerOfRotation' )
- self.centerOfRotation.setPosHpr(Vec3(0), Vec3(0))
- self.orthoViewRoll = 0.0
- self.lastView = 0
- self.targetNodePath = render.attachNewNode(NamedNode('targetNode'))
- self.zeroBaseVec = VBase3(0)
- self.zeroVector = Vec3(0)
- self.centerVec = Vec3(0., 1., 0.)
- self.zeroPoint = Point3(0)
- def centerCam(chan):
- # Chan is a display region context
- self.centerCamIn(chan, 1.0)
-
- def centerCamNow(chan):
- self.centerCamIn(chan, 0.)
- def centerCamIn(chan,t):
- # Chan is a display region context
- taskMgr.removeTasksNamed('manipulateCamera')
- widgetToCam = direct.widget.getPos( chan.camera )
- dist = Vec3(widgetToCam - zeroPoint).length()
- scaledCenterVec = centerVec * dist.
- delta = widgetToCam - scaledCenterVec.
- relNodePath = render.attachNewNode(Node())
- relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0))
- ###
- [ chan camera setPos: relNodePath pos: delta t: t.
- ] spawnTaskNamed: 'manipulateCamera'
- uponDeath: [ relNodePath removeNode. ]
- ###
- def homeCam(chan):
- chan.camera.setMat(Mat4.identMat())
- def mouseFlyStart(chan):
- # Record starting mouse positions
- initMouseX = chan.mouseX
- initMouseY = chan.mouseY
- # Where are we in the channel?
- if ((initMouseX abs < 0.9) & (initMouseY abs < 0.9)):
- # Mouse is in central region
- # spawn task to determine mouse fly mode"
- self.determineMouseFlyMode()
- else:
- #Mouse is in outer frame, spawn mouseRotateTask
- self.spawnMouseRotateTask()
- def mouseFlyStop():
- taskMgr.removeTasksNamed('determineMouseFlyMode')
- taskMgr.removeTasksNamed('manipulateCamera')
- def removeManipulateCameraTask():
- taskMgr.removeTasksNamed('manipulateCamera')
- def enableMouseFly():
- self.enableMouseInteraction()
- self.enableHotKeys()
- def enableMouseInteraction():
- # disable C++ fly interface
- base.disableMouse()
- # Accept middle mouse events
- self.accept('mouse2', self.mouseFlyStart, [chanCenter])
- self.accept('mouse2-up' self.mouseFlyStop)
- def disableMouseFly():
- # Accept middle mouse events
- self.ignore('mouse2')
- self.ignore:'mouse2-up')
- self.ignore('u')
- self.ignore('c')
- self.ignore('h')
- for i in range(0,10):
- self.ignore(`i`)
- self.ignore('=')
- self.ignore('+')
- self.ignore('-')
- self.ignore('=')
- def enableHotKeys():
- self.accept('u', self.uprightCam, [chanCenter])
- self.accept('c', self.centerCamIn, [chanCenter, 0.5])
- self.accept('h', self.homeCam, [chanCenter])
- for i in range(1,8):
- self.accept(`i`, self.moveToView, [chanCenter, i])
- self.accept('9', self.swingCamAboutWidget, [chanCenter, -90.0, 1.0])
- self.accept('0', self.swingCamAboutWidget, [chanCenter, 90.0, 1.0])
- self.accept('8', self.removeManipulateCameraTask)
- self.accept('=', self.zoomCam, [chanCenter, 0.5, 1.0])
- self.accept('+', self.zoomCam, [chanCenter, 0.5, 1.0])
- self.accept('-', self.zoomCam, [chanCenter, -2.0, 1.0])
- self.accept('=', self.zoomCam, [chanCenter, -2.0, 1.0])
- def SpawnMoveToView(chan, view):
- # Kill any existing tasks
- taskMgr.removeTasksNamed('manipulateCamera')
- # Calc hprOffset
- hprOffset = VBase3()
- if view = 1:
- hprOffset.set(180., 0., 0.)
- elif view = 2:
- hprOffset set(0., 0., 0.)
- elif view = 3:
- hprOffset set(90., 0., 0.)
- elif view = 4:
- hprOffset set(-90., 0., 0.)
- elif view = 5:
- hprOffset set(0., -90., 0.)
- elif view = 6:
- hprOffset set(0., 90., 0.)
- elif view = 7:
- hprOffset set(135., -35.264, 0.)
- # Position target
- targetNodePath.setPosHpr(direct.widget,
- self.zeroBaseVec,
- hprOffset)
- # Scale center vec by current distance to target
- offsetDistance = Vec3(chan.camera.getPos(targetNodePath) - \
- zeroPoint).length()
- scaledCenterVec = centerVec * (-1.0 * offsetDistance).
- # Now put the targetNodePath at that point
- targetNodePath.setPosHpr(targetNodePath,
- scaledCenterVec,
- zeroBaseVec)
- # Start off with best view if change is to new view
- if (view != lastView):
- orthoViewRoll = 0.0
- lastView = view.
- [ chan camera setPosHpr: targetNodePath pos: zeroBaseVec
- hpr: (VBase3 new: 0.0 y: 0.0 z: orthoViewRoll)
- t: 1.0.
- "Try another roll next time"
- orthoViewRoll = (orthoViewRoll + 90.0) rem: 360.0.]
- spawnTaskNamed: #manipulateCamera.
-
- def determineMouseFlyMode():
- # Get mouse intersection point
- # TBS
- # Find this point to camera space
- gridToCamera = grid getMat: chanCenter camera.
- hitPt operatorAssign: (gridToCamera xformPoint: iPoint).
- "Make sure hitPt is in front of the camera"
- hitPt setY: (hitPt at: 1) abs.
- "Handle case of bad hit point (too close or too far)"
- hitDistance = (hitPt - zeroPoint) length.
- ((hitDistance < (1.1 * chanCenter near)) | (hitDistance > chanCenter far)) ifTrue: [
- "Just use grid origin"
- "hitPt operatorAssign: centerVec * (0.5 * (chanCenter far + chanCenter near))"
- hitPt operatorAssign: (grid getPos: chanCenter camera).
- ].
- (direct fShift) ifTrue: [ self.spawnHPPan. ]
- ifFalse: [
- [[deltaX = chanCenter mouseX - initMouseX.
- deltaY = chanCenter mouseY - initMouseY.
- ((deltaX abs < 0.1) & (deltaY abs < 0.1))] taskWhileTrue: [ nil ]
- ] spawnTaskNamed: #determineMouseFlyMode
- uponDeath: [
- (deltaY abs > 0.1) ifTrue: [
- self.spawnHPanYZoom]
- ifFalse: [
- self.spawnXZTranslate ].
- ].
- ].
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- spawnHPPan
- [[true] taskWhileTrue:
- [ chanCenter camera setHpr: chanCenter camera
- h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
- p: (-0.5 * chanCenter mouseDeltaY * chanCenter fovV)
- r: 0.0 ]]
- spawnTaskNamed: #manipulateCamera.
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- spawnHPanYZoom
- | targetVector distToMove |
- targetVector = Vec3 new: (hitPt at: 0) y: (hitPt at: 1) z: (hitPt at: 2).
- [[true] taskWhileTrue:
- [ distToMove = targetVector * (-1.0 * chanCenter mouseDeltaY).
- chanCenter camera setPosHpr: chanCenter camera
- x: (distToMove at: 0)
- y: (distToMove at: 1)
- z: (distToMove at: 2)
- h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
- p: 0.0 r: 0.0. ]]
- spawnTaskNamed: #manipulateCamera.
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- spawnMouseRotateTask
- | wrtMat |
- centerOfRotation setPos: grid pos: iPoint.
- centerOfRotation setHpr: chanCenter camera h: 0.0 p: 0.0 r: 0.0.
-
- wrtMat = chanCenter camera getMat: centerOfRotation.
- [[true] taskWhileTrue:
- [ centerOfRotation setHpr: centerOfRotation
- h: (-0.5 * chanCenter mouseDeltaX * 180.0)
- p: (0.5 * chanCenter mouseDeltaY * 180.0)
- r: 0.0.
- chanCenter camera setMat: centerOfRotation mat: wrtMat. ]]
- spawnTaskNamed: #manipulateCamera.
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- spawnXZTranslate
- | scaleFactor |
- scaleFactor = ((hitPt at: 1) / chanCenter near).
- [[true] taskWhileTrue:
- [ chanCenter camera setPos: chanCenter camera
- x: (-0.5 * chanCenter mouseDeltaX * chanCenter nearWidth * scaleFactor)
- y: 0.0
- z: (-0.5 * chanCenter mouseDeltaY * chanCenter nearHeight * scaleFactor) ] ]
- spawnTaskNamed: #manipulateCamera.
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- spawnXZTranslateOrHPPan
- | scaleFactor |
- scaleFactor = ((hitPt at: 1) / chanCenter near).
- [[true] taskWhileTrue:
- [ direct fShift
- ifTrue: [ chanCenter camera setHpr: chanCenter camera
- h: (0.5 * chanCenter mouseDeltaX * chanCenter fovH)
- p: (-0.5 * chanCenter mouseDeltaY * chanCenter fovV)
- r: 0.0 ]
- ifFalse: [ chanCenter camera setPos: chanCenter camera
- x: (-0.5 * chanCenter mouseDeltaX * chanCenter nearWidth * scaleFactor)
- y: 0.0
- z: (-0.5 * chanCenter mouseDeltaY * chanCenter nearHeight * scaleFactor)]
- ]]
- spawnTaskNamed: #manipulateCamera.
- ! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- swingCamAboutWidget: chan deg: degrees in: t
- | relNodePath parent |
- Task removeTasksNamed: #manipulateCamera.
-
- relNodePath = showBase render attachNewNode: (Node new).
- "Coincident with widget"
- relNodePath setPos: direct widget pos: (Point3 zero).
- "But aligned with render space"
- relNodePath setHpr: (Point3 zero).
- parent = chanCenter camera getParent.
- chanCenter camera wrtReparentTo: relNodePath.
- [ relNodePath setHpr: (VBase3 new: degrees y: 0.0 z: 0.0) t: t. ]
- spawnTaskNamed: #manipulateCamera
- uponDeath: [
- chanCenter camera wrtReparentTo: parent.
- relNodePath reparentTo: showBase hidden.
- relNodePath removeNode.
- ].! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- uprightCam: chan
- | currH |
- Task removeTasksNamed: #manipulateCamera.
- currH = chan camera getH.
- [ chan camera setHpr: showBase render h: currH p: 0.0 r: 0.0 t: 1.0.
- ] spawnTaskNamed: #manipulateCamera.! !
- !DirectCameraManipulation methodsFor: 'event handling' stamp: 'panda 00/00/0000 00:00'!
- zoomCam: chan zoom: zoom in: t
- | relNodePath zoomPtToCam |
- Task removeTasksNamed: #manipulateCamera.
- "Find a point zoom factor times the current separation of the widget and cam"
- zoomPtToCam = (direct widget getPos: chan camera) * zoom.
- "Put a target nodePath there"
- relNodePath = showBase render attachNewNode: (Node new).
- relNodePath setPos: chanCenter camera pos: zoomPtToCam.
-
- "Move to that point"
- [ chan camera setPos: relNodePath pos: (Point3 zero) t: t. ]
- spawnTaskNamed: #manipulateCamera
- uponDeath: [ relNodePath removeNode. ].! !
|