#!/usr/bin/env python from PyOSG import osg from PyOSG import osgGA import math class TestManipulator(osgGA.MatrixManipulator): def __init__(self): osgGA.MatrixManipulator.__init__(self) self._ga_t1 = osg.ref() self._ga_t0 = osg.ref() self._node = None self._modelScale = 0.01 self._minimumZoomScale = 0.05 self._thrown = False self._center = osg.Vec3(0.0, 0.0, 0.0) self._rotation = osg.Quat() self._distance = 1.0 def __del__(self): pass def setNode(self, node): self._node = node if self._node: boundingSphere=self._node.getBound() self._modelScale = boundingSphere.radius() def getNode(self): return self._node def home(self, ea, us): if self._node: boundingSphere=self._node.getBound() self.computePosition(boundingSphere.center()+osg.Vec3(0.0, 0.0, 20.0), osg.Vec3(0.0, 1.0, 0.0), osg.Vec3(0.0, 0.0, 1.0)) us.requestRedraw() def init(self, ea, us): self.flushMouseEventStack() def handle(self, ea, us): eType = ea.getEventType() if eType == osgGA.GUIEventAdapter.PUSH: self.flushMouseEventStack() self.addMouseEvent(ea) if self.calcMovement(): us.requestRedraw() us.requestContinuousUpdate(False) self._thrown = False return True elif eType == osgGA.GUIEventAdapter.RELEASE: if ea.getButtonMask() == 0: if self.isMouseMoving(): if self.calcMovement(): us.requestRedraw() us.requestContinuousUpdate(True) self._thrown = True else: self.flushMouseEventStack() self.addMouseEvent(ea) if self.calcMovement(): us.requestRedraw() us.requestContinuousUpdate(False) self._thrown = False else: self.flushMouseEventStack() self.addMouseEvent(ea) if self.calcMovement(): us.requestRedraw() us.requestContinuousUpdate(False) self._thrown = False return True elif eType == osgGA.GUIEventAdapter.DRAG: self.addMouseEvent(ea) if (self.calcMovement()): us.requestRedraw() us.requestContinuousUpdate(False) self._thrown = False return True elif eType == osgGA.GUIEventAdapter.MOVE: return False elif eType == osgGA.GUIEventAdapter.KEYDOWN: if ea.getKey()==ord(' '): self.flushMouseEventStack() self._thrown = False self.home(ea,us) us.requestRedraw() us.requestContinuousUpdate(False) return True return False elif eType == osgGA.GUIEventAdapter.FRAME: if self._thrown: if self.calcMovement(): us.requestRedraw() return True return False else: return False def isMouseMoving(self): if self._ga_t0() == None or self._ga_t1() == None: return False velocity = 0.1 dx = self._ga_t0().getXnormalized()-self._ga_t1().getXnormalized() dy = self._ga_t0().getYnormalized()-self._ga_t1().getYnormalized() ln = math.sqrt(dx*dx+dy*dy) dt = self._ga_t0().time()-self._ga_t1().time() return ln>dt*velocity def flushMouseEventStack(self): """Reset the internal GUIEvent stack.""" self._ga_t1.set(None) self._ga_t0.set(None) def addMouseEvent(self, ea): """Add the current mouse GUIEvent to internal stack.""" self._ga_t1.set(self._ga_t0()) self._ga_t0.set(ea) def setByMatrix(self, matrix): self._center = matrix.getTrans() matrix.get(self._rotation) self._distance = 1.0 def getMatrix(self): return osg.Matrix.rotate(self._rotation) * osg.Matrix.translate(self._center) def getInverseMatrix(self): return osg.Matrix.translate(-self._center) * osg.Matrix.rotate(self._rotation.inverse()) def computePosition(self, eye, lv, up): f = lv f.normalize() s = f ^ up s.normalize() u = s ^ f u.normalize rotation_matrix = osg.Matrix(( s[0], u[0], -f[0], 0.0, s[1], u[1], -f[1], 0.0, s[2], u[2], -f[2], 0.0, 0.0, 0.0, 0.0, 1.0)) self._center = eye+lv self._distance = lv.length() rotation_matrix.get(self._rotation) self._rotation = self._rotation.inverse() def calcMovement(self): # return if less then two events have been added. if self._ga_t0() == None or self._ga_t1() == None: return False dx = self._ga_t0().getXnormalized()-self._ga_t1().getXnormalized(); dy = self._ga_t0().getYnormalized()-self._ga_t1().getYnormalized(); # return if there is no movement. if dx==0 and dy==0: return False buttonMask = self._ga_t1().getButtonMask() if buttonMask==osgGA.GUIEventAdapter.LEFT_MOUSE_BUTTON: # rotate camera. new_rotate = osg.Quat() new_rotate.makeRotate(dx / 3.0, osg.Vec3(0.0, 0.0, 1.0)) self._rotation = self._rotation*new_rotate return True elif buttonMask==osgGA.GUIEventAdapter.MIDDLE_MOUSE_BUTTON: # pan model. dv = osg.Vec3(0.0, 0.0, -500.0) * dy self._center += dv return True elif buttonMask==osgGA.GUIEventAdapter.RIGHT_MOUSE_BUTTON: rotation_matrix = osg.Matrix(self._rotation) uv = osg.Vec3(0.0,1.0,0.0)*rotation_matrix sv = osg.Vec3(1.0,0.0,0.0)*rotation_matrix fv = uv ^ sv dv = fv*(dy*-500.0)-sv*(dx*500.0) self._center += dv return True; return False; if __name__ == "__main__": import sys from PyOSG import Producer from PyOSG import osgDB from PyOSG import osgUtil from PyOSG import osgProducer viewer = osgProducer.Viewer() viewer.setUpViewer(osgProducer.Viewer.STANDARD_SETTINGS) rootnode = osgDB.readNodeFile("cow.osg") if rootnode == None: sys.exit(1) viewer.setSceneData(rootnode) pos = viewer.addCameraManipulator(TestManipulator()) viewer.selectCameraManipulator(pos) viewer.realize() while not viewer.done(): viewer.sync() viewer.update() viewer.frame() viewer.sync() sys.exit(0)