def GetCorrectCameraXandYFactors(self, position, poi): cameraZ = geo2.Vec3Normalize(geo2.Subtract(position, poi)) cameraX = geo2.Vec3Cross(cameraZ, (0.0, 1.0, 0.0)) cameraY = geo2.Vec3Cross(cameraZ, cameraX) cameraMatrix = ((cameraX[0], cameraY[0], cameraZ[0], 0.0), (cameraX[1], cameraY[1], cameraZ[1], 0.0), (cameraX[2], cameraY[2], cameraZ[2], 0.0), (0.0, 0.0, 0.0, 1.0)) offset = geo2.Subtract(self.focus, poi) res = geo2.Vec3Transform(offset, cameraMatrix) return (res[0], res[1])
def _EnforceMinMaxZoom(self, eyePos): vEye = geo2.Subtract(eyePos, self.atPosition) vMaxZoom = geo2.Scale(self.GetZAxis(), self.maxZoom) vEyeToMaxZoom = geo2.Subtract(vEye, vMaxZoom) if geo2.Vec3Dot(vEyeToMaxZoom, vMaxZoom) < 0: eyePos = geo2.Add(self.atPosition, vMaxZoom) self.zoomTarget = None vMinZoom = geo2.Scale(self.GetZAxis(), self.minZoom) vEyeToMinZoom = geo2.Subtract(vEye, vMinZoom) if geo2.Vec3Dot(vEyeToMinZoom, vMinZoom) > 0: eyePos = geo2.Add(self.atPosition, vMinZoom) self.zoomTarget = None return eyePos
def Zoom(self, val): dev = trinity.device pos = self.GetPosition() target = self.GetPointOfInterest() view = geo2.Vec3Normalize(geo2.Subtract(pos, target)) length = geo2.Vec3Length(geo2.Subtract(pos, target)) nextPos = geo2.Vec3Add(pos, geo2.Vec3Scale(view, length * val)) nextLength = geo2.Vec3Length(geo2.Vec3Subtract(nextPos, target)) if nextLength < self.minZoomDistance: nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.minZoomDistance)) elif nextLength > self.maxZoomDistance: nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.maxZoomDistance)) self.SetPosition(nextPos)
def PickObject(self, x, y): if self.sceneManager.GetActiveScene() != self.renderScene: return rescale = 1.0 / 10000.0 projection = trinity.TriProjection() projection.PerspectiveFov(trinity.GetFieldOfView(), trinity.GetAspectRatio(), trinity.GetFrontClip(), trinity.GetBackClip()) view = trinity.TriView() view.transform = trinity.GetViewTransform() scaling, rotation, translation = geo2.MatrixDecompose( self.transform.worldTransform) pZ = geo2.Vec3Transform((0, 0, 1), self.transform.worldTransform) surfaceNormal = geo2.Subtract(pZ, translation) cameraZ = geo2.Vector(view.transform[0][2], view.transform[1][2], view.transform[2][2]) if geo2.Vec3Dot(surfaceNormal, cameraZ) < 0: return self.renderObject.translation = geo2.Vec3Scale(translation, rescale) self.renderObject.rotation = rotation self.renderObject.scaling = geo2.Vec3Scale(scaling, rescale) scaling, rotation, translation = geo2.MatrixDecompose(view.transform) translation = geo2.Vec3Scale(translation, rescale) view.transform = geo2.MatrixTransformation(None, None, scaling, None, rotation, translation) return self.renderObject.PickObject(x, y, projection, view, trinity.device.viewport)
def OverridePick(self, x, y): overrideObject = None entityID = self._PickObject(x, y) if entityID: entity = sm.GetService('entityClient').FindEntityByID(entityID) if entity: camera = self.cameraClient.GetActiveCamera() startPoint, endPoint = camera.GetRay(x, y) direction = geo2.Subtract(endPoint, startPoint) uvSvc = sm.GetService('uvPickingClient') if entity.HasComponent('UIDesktopComponent' ) and entity.HasComponent('uvPicking'): uv = uvSvc.PickEntity(entity, startPoint, direction) if not uv: return desktopComponent = entity.GetComponent( 'UIDesktopComponent') desktop = desktopComponent.uiDesktop u = int(uv[1][0] * desktop.width) v = int(uv[1][1] * desktop.height) triobj = desktopComponent.uiDesktop.renderObject.PickObject( u, v, None, None, None) if triobj: overrideObject = uicore.uilib.GetPyObjectFromRenderObject( triobj) return overrideObject
def Orbit(self, yaw, pitch): dev = trinity.device self.Focus(self.pointOfInterest) up = geo2.Vector(0.0, 1.0, 0.0) t = geo2.Vector(self.localViewMatrix[1][0], self.localViewMatrix[1][1], self.localViewMatrix[1][2]) if geo2.Vec3Dot(t, up) <= 0.0: pitch = -pitch yaw = -yaw pos = self.GetPosition() target = self.pointOfInterest view = geo2.Subtract(pos, target) view = geo2.Vec3Normalize(view) right = geo2.Vec3Cross(view, up) mat = self.localViewMatrix ipmat = geo2.MatrixTranslation(-target[0], -target[1], -target[2]) pmat = geo2.MatrixTranslation(target[0], target[1], target[2]) mat = geo2.MatrixInverse(mat) yrotMat = geo2.MatrixRotationAxis(up, yaw) rrotMat = geo2.MatrixRotationAxis(right, pitch) yrotMat = geo2.MatrixMultiply(yrotMat, rrotMat) mat = geo2.MatrixMultiply(mat, ipmat) mat = geo2.MatrixMultiply(mat, yrotMat) mat = geo2.MatrixMultiply(mat, pmat) self._position = geo2.MatrixDecompose(mat)[2] mat = geo2.MatrixInverse(mat) self.localViewMatrix = mat
def OverridePick(self, x, y): """ Called by the uilib when it is updating mouseover. Here we get a chance to see if we should route events into any of the ingame UI desktops. """ overrideObject = None entityID = self._PickObject(x, y) if entityID: entity = sm.GetService('entityClient').FindEntityByID(entityID) if entity: camera = self.cameraClient.GetActiveCamera() startPoint, endPoint = camera.GetRay(x, y) direction = geo2.Subtract(endPoint, startPoint) uvSvc = sm.GetService('uvPickingClient') if entity.HasComponent('UIDesktopComponent' ) and entity.HasComponent('uvPicking'): uv = uvSvc.PickEntity(entity, startPoint, direction) if not uv: return desktopComponent = entity.GetComponent( 'UIDesktopComponent') desktop = desktopComponent.uiDesktop u = int(uv[1][0] * desktop.width) v = int(uv[1][1] * desktop.height) triobj = desktopComponent.uiDesktop.renderObject.PickObject( u, v, None, None, None) if triobj: overrideObject = uicore.uilib.GetPyObjectFromRenderObject( triobj) return overrideObject
def OrbitUpdateThread(self): try: while True: if self.orbitTarget is None: break vLookAt = self.GetLookAtDirection() currPitch = self.GetAngleLookAtToUpDirection() self.eyePosition = geo2.Subtract(self.eyePosition, self.atPosition) yawLeft = self.orbitTarget[0] if yawLeft: yaw = self.kOrbitSpeed * yawLeft / blue.os.fps if math.fabs(yawLeft) < self.kOrbitStopAngle: yaw = yawLeft rotYaw = geo2.MatrixRotationAxis(self.upDirection, yaw) self.eyePosition = geo2.Vec3Transform(self.eyePosition, rotYaw) self.orbitTarget[0] -= yaw targetPitch = self.orbitTarget[1] pitchLeft = currPitch - targetPitch if pitchLeft: pitch = self.kOrbitSpeed * pitchLeft / blue.os.fps if math.fabs(pitchLeft) < self.kOrbitStopAngle: pitch = pitchLeft axis = geo2.Vec3Cross(vLookAt, self.upDirection) rotPitch = geo2.MatrixRotationAxis(axis, pitch) self.eyePosition = geo2.Vec3Transform(self.eyePosition, rotPitch) self.eyePosition = geo2.Add(self.eyePosition, self.atPosition) if not pitchLeft and not yawLeft: break blue.synchro.Yield() finally: self.orbitUpdateThread = None self.orbitTarget = None
def ProjectPointTowardsFrontPlane(point, dist=7.0): ppos = point viewMat = trinity.GetViewTransform() cpos = geo2.Vector(*trinity.GetViewPosition()) dir = geo2.Vec3Normalize(geo2.Subtract(cpos, ppos)) lookat = geo2.Vector(viewMat[0][2], viewMat[1][2], viewMat[2][2]) point = cpos + lookat * dist return RayToPlaneIntersection(ppos, dir, point, lookat)
def Zoom(self, val): """ Move the camera towards the point of interest val - the percentage of the distance between the camera and the target point """ dev = trinity.device pos = self.GetPosition() target = self.GetPointOfInterest() view = geo2.Vec3Normalize(geo2.Subtract(pos, target)) length = geo2.Vec3Length(geo2.Subtract(pos, target)) nextPos = geo2.Vec3Add(pos, geo2.Vec3Scale(view, length * val)) nextLength = geo2.Vec3Length(geo2.Vec3Subtract(nextPos, target)) if nextLength < self.minZoomDistance: nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.minZoomDistance)) elif nextLength > self.maxZoomDistance: nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.maxZoomDistance)) self.SetPosition(nextPos)
def Rotate(self, x = 0, y = 0): xAxis = self.GetXAxis() yAxis = self.GetYAxis() self.atPosition = geo2.Subtract(self.atPosition, self.eyePosition) rotY = geo2.MatrixRotationAxis(xAxis, y) self.atPosition = geo2.Vec3Transform(self.atPosition, rotY) rotX = geo2.MatrixRotationAxis(yAxis, x) self.atPosition = geo2.Vec3Transform(self.atPosition, rotX) self.atPosition = geo2.Add(self.atPosition, self.eyePosition)
def SetViewVector(self, viewVector): self.StopUpdateThreads() atPosition = self.GetAtPosition() eyePosition = self.GetEyePosition() eyePositionLocal = geo2.Subtract(atPosition, eyePosition) eyeDistance = geo2.Vec3Length(eyePositionLocal) newEyePosition = geo2.Vec3Scale(viewVector, eyeDistance) self.eyePosition = geo2.Vec3Add(newEyePosition, atPosition) if not self.isActive: self.Update()
def Orbit(self, dx = 0, dy = 0): diff = geo2.Subtract(self.eyePosition, self.atPosition) if not self.orbitTarget: self.orbitTarget = (0, self.GetAngleLookAtToUpDirection()) yaw = self.orbitTarget[0] - dx pitch = self.orbitTarget[1] - dy / 2.0 pitch = max(self.kMinPitch, min(pitch, self.kMaxPitch)) self.orbitTarget = [yaw, pitch] if not self.orbitUpdateThread: self.orbitUpdateThread = uthread.new(self.OrbitUpdateThread)
def PlacePortraitCamera(self, pos, poi): direction = geo2.Subtract(pos, poi) self.distance = geo2.Vec3Length(direction) direction = geo2.Vec3Normalize(direction) self.yaw = math.acos(direction[0]) self.pitch = math.asin(direction[1]) + math.pi / 2.0 right = self.GetBonePosition('fj_eyeballRight') left = self.GetBonePosition('fj_eyeballLeft') self.focus = geo2.Add(right, left) self.focus = geo2.Vector(*self.focus) * 0.5 xFactor, yFactor = self.GetCorrectCameraXandYFactors(pos, poi) self.xFactor = xFactor self.yFactor = yFactor
def LookAt(self, position, duration = None, followWithEye = True, eyePos = None): if duration: uicore.animations.MorphVector3(self, 'atPosition', self.atPosition, position, duration=duration) else: self.atPosition = position if followWithEye: if not eyePos: eyePos = geo2.Subtract(self.eyePosition, self.atPosition) eyePos = geo2.Add(eyePos, position) if duration: uicore.animations.MorphVector3(self, 'eyePosition', self.eyePosition, eyePos, duration=duration) else: self.eyePosition = eyePos
def PlacePortraitCamera(self, pos, poi): """ This method takes in pos and poi and places the camera with correct yaw and pitch, distance, xFactor, yFactor and focus.""" direction = geo2.Subtract(pos, poi) self.distance = geo2.Vec3Length(direction) direction = geo2.Vec3Normalize(direction) self.yaw = math.acos(direction[0]) self.pitch = math.asin(direction[1]) + math.pi / 2.0 right = self.GetBonePosition('fj_eyeballRight') left = self.GetBonePosition('fj_eyeballLeft') self.focus = geo2.Add(right, left) self.focus = geo2.Vector(*self.focus) * 0.5 xFactor, yFactor = self.GetCorrectCameraXandYFactors(pos, poi) self.xFactor = xFactor self.yFactor = yFactor
def OrbitUpdateThread(self): try: while True: if self.orbitTarget is None: break vLookAt = self.GetLookAtDirectionWithOffset() currPitch = self.GetAngleLookAtToUpDirection() offset = self.GetOrbitPoint() self.eyePosition = geo2.Subtract(self._eyePosition, offset) yawRemaining = self._UpdateYaw() pitchRemaining = self._UpdatePitch(currPitch, vLookAt) self.SetEyePosition(geo2.Add(self._eyePosition, offset)) if not pitchRemaining and not yawRemaining: break blue.synchro.Yield() finally: self.orbitUpdateThread = None self.orbitTarget = None