from math import * # ----------------------------------------------------------------------------- # Set of helper functions # ----------------------------------------------------------------------------- def normalize(vect, tolerance=0.00001): mag2 = sum(n * n for n in vect) if abs(mag2 - 1.0) > tolerance: mag = sqrt(mag2) vect = tuple(n / mag for n in vect) return vect def q_mult(q1, q2): w1, x1, y1, z1 = q1 w2, x2, y2, z2 = q2 w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2 x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2 y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2 z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2 return w, x, y, z def q_conjugate(q): w, x, y, z = q return (w, -x, -y, -z) def qv_mult(q1, v1): q2 = (0.0,) + v1 return q_mult(q_mult(q1, q2), q_conjugate(q1))[1:] def axisangle_to_q(v, theta): v = normalize(v) x, y, z = v theta /= 2 w = cos(theta) x = x * sin(theta) y = y * sin(theta) z = z * sin(theta) return w, x, y, z def vectProduct(axisA, axisB): xa, ya, za = axisA xb, yb, zb = axisB normalVect = (ya * zb - za * yb, za * xb - xa * zb, xa * yb - ya * xb) normalVect = normalize(normalVect) return normalVect def dotProduct(vecA, vecB): return (vecA[0] * vecB[0]) + (vecA[1] * vecB[1]) + (vecA[2] * vecB[2]) def rotate(axis, angle, center, point): angleInRad = 3.141592654 * angle / 180.0 rotation = axisangle_to_q(axis, angleInRad) tPoint = tuple((point[i] - center[i]) for i in range(3)) rtPoint = qv_mult(rotation, tPoint) rPoint = tuple((rtPoint[i] + center[i]) for i in range(3)) return rPoint # ----------------------------------------------------------------------------- # Spherical Camera # ----------------------------------------------------------------------------- class SphericalCamera(object): def __init__( self, dataHandler, focalPoint, position, phiAxis, phiAngles, thetaAngles ): self.dataHandler = dataHandler self.cameraSettings = [] self.thetaBind = { "mouse": { "drag": {"modifier": 0, "coordinate": 1, "step": 30, "orientation": 1} } } self.phiBind = { "mouse": { "drag": {"modifier": 0, "coordinate": 0, "step": 30, "orientation": 1} } } # Convert to serializable type fp = tuple(i for i in focalPoint) # Register arguments to the data handler if len(phiAngles) > 1 and phiAngles[-1] + phiAngles[1] == 360: self.dataHandler.registerArgument( priority=0, name="phi", values=phiAngles, ui="slider", loop="modulo", bind=self.phiBind, ) else: self.dataHandler.registerArgument( priority=0, name="phi", values=phiAngles, ui="slider", bind=self.phiBind ) if thetaAngles[0] < 0 and thetaAngles[0] >= -90: idx = 0 for theta in thetaAngles: if theta < 0: idx += 1 self.dataHandler.registerArgument( priority=0, name="theta", values=[(x + 90) for x in thetaAngles], ui="slider", default=idx, bind=self.thetaBind, ) else: self.dataHandler.registerArgument( priority=0, name="theta", values=thetaAngles, ui="slider", bind=self.thetaBind, ) # Compute all camera settings for theta in thetaAngles: for phi in phiAngles: phiPos = rotate(phiAxis, -phi, fp, position) thetaAxis = vectProduct( phiAxis, tuple(fp[i] - phiPos[i] for i in range(3)) ) thetaPhiPos = rotate(thetaAxis, theta, fp, phiPos) viewUp = rotate(thetaAxis, theta, (0, 0, 0), phiAxis) self.cameraSettings.append( { "theta": theta, "thetaIdx": thetaAngles.index(theta), "phi": phi, "phiIdx": phiAngles.index(phi), "focalPoint": fp, "position": thetaPhiPos, "viewUp": viewUp, } ) self.dataHandler.updateBasePattern() def updatePriority(self, priorityList): keyList = ["theta", "phi"] for idx in range(min(len(priorityList), len(keyList))): self.dataHandler.updatePriority(keyList[idx], priorityList[idx]) def __iter__(self): for cameraData in self.cameraSettings: self.dataHandler.setArguments( phi=cameraData["phiIdx"], theta=cameraData["thetaIdx"] ) yield cameraData # ----------------------------------------------------------------------------- # Cylindrical Camera # ----------------------------------------------------------------------------- class CylindricalCamera(object): def __init__( self, dataHandler, focalPoint, position, rotationAxis, phiAngles, translationValues, ): self.dataHandler = dataHandler self.cameraSettings = [] # Register arguments to the data handler self.dataHandler.registerArgument( priority=0, name="phi", values=phiAngles, ui="slider", loop="modulo" ) self.dataHandler.registerArgument( priority=0, name="n_pos", values=translationValues, ui="slider" ) # Compute all camera settings for translation in translationValues: for phi in phiAngles: phiPos = rotate(rotationAxis, phi, focalPoint, position) newfocalPoint = tuple( focalPoint[i] + (translation * rotationAxis[i]) for i in range(3) ) transPhiPoint = tuple( phiPos[i] + (translation * rotationAxis[i]) for i in range(3) ) self.cameraSettings.append( { "n_pos": translation, "n_posIdx": translationValues.index(translation), "phi": phi, "phiIdx": phiAngles.index(phi), "focalPoint": newfocalPoint, "position": transPhiPoint, "viewUp": rotationAxis, } ) self.dataHandler.updateBasePattern() def updatePriority(self, priorityList): keyList = ["n_pos", "phi"] for idx in range(min(len(priorityList), len(keyList))): self.dataHandler.updatePriority(keyList[idx], priorityList[idx]) def __iter__(self): for cameraData in self.cameraSettings: self.dataHandler.setArguments( phi=cameraData["phiIdx"], n_pos=cameraData["n_posIdx"] ) yield cameraData # ----------------------------------------------------------------------------- # MultiView Cube Camera # ----------------------------------------------------------------------------- class CubeCamera(object): # positions = [ { position: [x,y,z], args: { i: 1, j: 0, k: 7 } }, ... ] def __init__(self, dataHandler, viewForward, viewUp, positions): self.dataHandler = dataHandler self.cameraSettings = [] self.viewForward = viewForward self.viewUp = viewUp self.rightDirection = vectProduct(viewForward, viewUp) self.positions = positions # Register arguments to the data handler self.dataHandler.registerArgument( priority=0, name="orientation", values=["f", "b", "r", "l", "u", "d"] ) # Register arguments to id position self.args = {} for pos in positions: for key in pos["args"]: if key not in self.args: self.args[key] = {} self.args[key][pos["args"][key]] = True for key in self.args: self.args[key] = sorted(self.args[key], key=lambda k: int(k)) self.keyList = self.args.keys() for key in self.args: self.dataHandler.registerArgument( priority=1, name=key, values=self.args[key] ) self.dataHandler.updateBasePattern() def updatePriority(self, priorityList): keyList = ["orientation"] for idx in range(min(len(priorityList), len(keyList))): self.dataHandler.updatePriority(keyList[idx], priorityList[idx]) def __iter__(self): for pos in self.positions: cameraData = { "position": pos["position"], } print("=" * 80) for key in pos["args"]: idx = self.args[key].index(pos["args"][key]) self.dataHandler.setArguments(**{key: idx}) print(key, idx) print("position", cameraData["position"]) # front cameraData["focalPoint"] = [ (cameraData["position"][i] + self.viewForward[i]) for i in range(3) ] cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["orientation"] = "front" self.dataHandler.setArguments(orientation=0) yield cameraData # back cameraData["focalPoint"] = [ (cameraData["position"][i] - self.viewForward[i]) for i in range(3) ] cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["orientation"] = "back" self.dataHandler.setArguments(orientation=1) yield cameraData # right self.dataHandler.setArguments(orientation=2) cameraData["focalPoint"] = [ (cameraData["position"][i] + self.rightDirection[i]) for i in range(3) ] cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["orientation"] = "right" yield cameraData # left self.dataHandler.setArguments(orientation=3) cameraData["focalPoint"] = [ (cameraData["position"][i] - self.rightDirection[i]) for i in range(3) ] cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["orientation"] = "left" yield cameraData # up self.dataHandler.setArguments(orientation=4) cameraData["focalPoint"] = [ (cameraData["position"][i] + self.viewUp[i]) for i in range(3) ] cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)] cameraData["orientation"] = "up" yield cameraData # doww self.dataHandler.setArguments(orientation=5) cameraData["focalPoint"] = [ (cameraData["position"][i] - self.viewUp[i]) for i in range(3) ] cameraData["viewUp"] = [self.viewForward[i] for i in range(3)] cameraData["orientation"] = "down" yield cameraData # ----------------------------------------------------------------------------- # MultiView Cube Camera # ----------------------------------------------------------------------------- class StereoCubeCamera(object): # positions = [ { position: [x,y,z], args: { i: 1, j: 0, k: 7 } }, ... ] def __init__(self, dataHandler, viewForward, viewUp, positions, eyeSpacing): self.dataHandler = dataHandler self.cameraSettings = [] self.viewForward = viewForward self.viewUp = viewUp self.rightDirection = vectProduct(viewForward, viewUp) self.positions = positions self.eyeSpacing = eyeSpacing # Register arguments to the data handler self.dataHandler.registerArgument( priority=0, name="orientation", values=["f", "b", "r", "l", "u", "d"] ) self.dataHandler.registerArgument( priority=0, name="eye", values=["left", "right"] ) # Register arguments to id position self.args = {} for pos in positions: for key in pos["args"]: if key not in self.args: self.args[key] = {} self.args[key][pos["args"][key]] = True for key in self.args: self.args[key] = sorted(self.args[key], key=lambda k: int(k)) self.keyList = self.args.keys() for key in self.args: self.dataHandler.registerArgument( priority=1, name=key, values=self.args[key] ) self.dataHandler.updateBasePattern() def updatePriority(self, priorityList): keyList = ["orientation"] for idx in range(min(len(priorityList), len(keyList))): self.dataHandler.updatePriority(keyList[idx], priorityList[idx]) def __iter__(self): for pos in self.positions: cameraData = {} for key in pos["args"]: idx = self.args[key].index(pos["args"][key]) self.dataHandler.setArguments(**{key: idx}) # front cameraData["orientation"] = "front" self.dataHandler.setArguments(orientation=0) deltaVect = [ (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection ] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.viewForward[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.viewForward[i] + deltaVect[i]) for i in range(3) ] yield cameraData # back cameraData["orientation"] = "back" self.dataHandler.setArguments(orientation=1) deltaVect = [ -(v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection ] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.viewForward[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.viewForward[i] + deltaVect[i]) for i in range(3) ] yield cameraData # right self.dataHandler.setArguments(orientation=2) cameraData["orientation"] = "right" deltaVect = [-(v * float(self.eyeSpacing) * 0.5) for v in self.viewForward] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.rightDirection[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.rightDirection[i] + deltaVect[i]) for i in range(3) ] yield cameraData # left self.dataHandler.setArguments(orientation=3) cameraData["orientation"] = "left" deltaVect = [(v * float(self.eyeSpacing) * 0.5) for v in self.viewForward] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.rightDirection[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [self.viewUp[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.rightDirection[i] + deltaVect[i]) for i in range(3) ] yield cameraData # up self.dataHandler.setArguments(orientation=4) cameraData["orientation"] = "up" deltaVect = [ (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection ] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.viewUp[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] + self.viewUp[i] + deltaVect[i]) for i in range(3) ] yield cameraData # doww self.dataHandler.setArguments(orientation=5) cameraData["orientation"] = "down" deltaVect = [ (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection ] ## Left-Eye self.dataHandler.setArguments(eye=0) cameraData["viewUp"] = [self.viewForward[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] - deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.viewUp[i] - deltaVect[i]) for i in range(3) ] yield cameraData ## Right-Eye self.dataHandler.setArguments(eye=1) cameraData["viewUp"] = [self.viewForward[i] for i in range(3)] cameraData["position"] = [ (pos["position"][idx] + deltaVect[idx]) for idx in range(3) ] cameraData["focalPoint"] = [ (pos["position"][i] - self.viewUp[i] + deltaVect[i]) for i in range(3) ] yield cameraData # ----------------------------------------------------------------------------- # MultiView Camera # ----------------------------------------------------------------------------- class MultiViewCamera(object): def __init__(self, dataHandler): self.dataHandler = dataHandler self.cameraSettings = [] self.positionNames = [] def registerViewPoint(self, name, focalPoint, position, viewUp): self.cameraSettings.append( { "name": name, "nameIdx": len(self.positionNames), "focalPoint": focalPoint, "position": position, "viewUp": viewUp, } ) self.positionNames.append(name) self.dataHandler.registerArgument( priority=0, name="multiView", values=self.positionNames ) self.dataHandler.updateBasePattern() def updatePriority(self, priorityList): keyList = ["multiView"] for idx in range(min(len(priorityList), len(keyList))): self.dataHandler.updatePriority(keyList[idx], priorityList[idx]) def __iter__(self): for cameraData in self.cameraSettings: self.dataHandler.setArguments(multiView=cameraData["nameIdx"]) yield cameraData # ----------------------------------------------------------------------------- # Helper methods # ----------------------------------------------------------------------------- def update_camera(renderer, cameraData): camera = renderer.GetActiveCamera() camera.SetPosition(cameraData["position"]) camera.SetFocalPoint(cameraData["focalPoint"]) camera.SetViewUp(cameraData["viewUp"]) def create_spherical_camera(renderer, dataHandler, phiValues, thetaValues): camera = renderer.GetActiveCamera() return SphericalCamera( dataHandler, camera.GetFocalPoint(), camera.GetPosition(), camera.GetViewUp(), phiValues, thetaValues, ) def create_cylindrical_camera(renderer, dataHandler, phiValues, translationValues): camera = renderer.GetActiveCamera() return CylindricalCamera( dataHandler, camera.GetFocalPoint(), camera.GetPosition(), camera.GetViewUp(), phiValues, translationValues, )