camera.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. from math import *
  2. # -----------------------------------------------------------------------------
  3. # Set of helper functions
  4. # -----------------------------------------------------------------------------
  5. def normalize(vect, tolerance=0.00001):
  6. mag2 = sum(n * n for n in vect)
  7. if abs(mag2 - 1.0) > tolerance:
  8. mag = sqrt(mag2)
  9. vect = tuple(n / mag for n in vect)
  10. return vect
  11. def q_mult(q1, q2):
  12. w1, x1, y1, z1 = q1
  13. w2, x2, y2, z2 = q2
  14. w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
  15. x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
  16. y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2
  17. z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2
  18. return w, x, y, z
  19. def q_conjugate(q):
  20. w, x, y, z = q
  21. return (w, -x, -y, -z)
  22. def qv_mult(q1, v1):
  23. q2 = (0.0,) + v1
  24. return q_mult(q_mult(q1, q2), q_conjugate(q1))[1:]
  25. def axisangle_to_q(v, theta):
  26. v = normalize(v)
  27. x, y, z = v
  28. theta /= 2
  29. w = cos(theta)
  30. x = x * sin(theta)
  31. y = y * sin(theta)
  32. z = z * sin(theta)
  33. return w, x, y, z
  34. def vectProduct(axisA, axisB):
  35. xa, ya, za = axisA
  36. xb, yb, zb = axisB
  37. normalVect = (ya * zb - za * yb, za * xb - xa * zb, xa * yb - ya * xb)
  38. normalVect = normalize(normalVect)
  39. return normalVect
  40. def dotProduct(vecA, vecB):
  41. return (vecA[0] * vecB[0]) + (vecA[1] * vecB[1]) + (vecA[2] * vecB[2])
  42. def rotate(axis, angle, center, point):
  43. angleInRad = 3.141592654 * angle / 180.0
  44. rotation = axisangle_to_q(axis, angleInRad)
  45. tPoint = tuple((point[i] - center[i]) for i in range(3))
  46. rtPoint = qv_mult(rotation, tPoint)
  47. rPoint = tuple((rtPoint[i] + center[i]) for i in range(3))
  48. return rPoint
  49. # -----------------------------------------------------------------------------
  50. # Spherical Camera
  51. # -----------------------------------------------------------------------------
  52. class SphericalCamera(object):
  53. def __init__(
  54. self, dataHandler, focalPoint, position, phiAxis, phiAngles, thetaAngles
  55. ):
  56. self.dataHandler = dataHandler
  57. self.cameraSettings = []
  58. self.thetaBind = {
  59. "mouse": {
  60. "drag": {"modifier": 0, "coordinate": 1, "step": 30, "orientation": 1}
  61. }
  62. }
  63. self.phiBind = {
  64. "mouse": {
  65. "drag": {"modifier": 0, "coordinate": 0, "step": 30, "orientation": 1}
  66. }
  67. }
  68. # Convert to serializable type
  69. fp = tuple(i for i in focalPoint)
  70. # Register arguments to the data handler
  71. if len(phiAngles) > 1 and phiAngles[-1] + phiAngles[1] == 360:
  72. self.dataHandler.registerArgument(
  73. priority=0,
  74. name="phi",
  75. values=phiAngles,
  76. ui="slider",
  77. loop="modulo",
  78. bind=self.phiBind,
  79. )
  80. else:
  81. self.dataHandler.registerArgument(
  82. priority=0, name="phi", values=phiAngles, ui="slider", bind=self.phiBind
  83. )
  84. if thetaAngles[0] < 0 and thetaAngles[0] >= -90:
  85. idx = 0
  86. for theta in thetaAngles:
  87. if theta < 0:
  88. idx += 1
  89. self.dataHandler.registerArgument(
  90. priority=0,
  91. name="theta",
  92. values=[(x + 90) for x in thetaAngles],
  93. ui="slider",
  94. default=idx,
  95. bind=self.thetaBind,
  96. )
  97. else:
  98. self.dataHandler.registerArgument(
  99. priority=0,
  100. name="theta",
  101. values=thetaAngles,
  102. ui="slider",
  103. bind=self.thetaBind,
  104. )
  105. # Compute all camera settings
  106. for theta in thetaAngles:
  107. for phi in phiAngles:
  108. phiPos = rotate(phiAxis, -phi, fp, position)
  109. thetaAxis = vectProduct(
  110. phiAxis, tuple(fp[i] - phiPos[i] for i in range(3))
  111. )
  112. thetaPhiPos = rotate(thetaAxis, theta, fp, phiPos)
  113. viewUp = rotate(thetaAxis, theta, (0, 0, 0), phiAxis)
  114. self.cameraSettings.append(
  115. {
  116. "theta": theta,
  117. "thetaIdx": thetaAngles.index(theta),
  118. "phi": phi,
  119. "phiIdx": phiAngles.index(phi),
  120. "focalPoint": fp,
  121. "position": thetaPhiPos,
  122. "viewUp": viewUp,
  123. }
  124. )
  125. self.dataHandler.updateBasePattern()
  126. def updatePriority(self, priorityList):
  127. keyList = ["theta", "phi"]
  128. for idx in range(min(len(priorityList), len(keyList))):
  129. self.dataHandler.updatePriority(keyList[idx], priorityList[idx])
  130. def __iter__(self):
  131. for cameraData in self.cameraSettings:
  132. self.dataHandler.setArguments(
  133. phi=cameraData["phiIdx"], theta=cameraData["thetaIdx"]
  134. )
  135. yield cameraData
  136. # -----------------------------------------------------------------------------
  137. # Cylindrical Camera
  138. # -----------------------------------------------------------------------------
  139. class CylindricalCamera(object):
  140. def __init__(
  141. self,
  142. dataHandler,
  143. focalPoint,
  144. position,
  145. rotationAxis,
  146. phiAngles,
  147. translationValues,
  148. ):
  149. self.dataHandler = dataHandler
  150. self.cameraSettings = []
  151. # Register arguments to the data handler
  152. self.dataHandler.registerArgument(
  153. priority=0, name="phi", values=phiAngles, ui="slider", loop="modulo"
  154. )
  155. self.dataHandler.registerArgument(
  156. priority=0, name="n_pos", values=translationValues, ui="slider"
  157. )
  158. # Compute all camera settings
  159. for translation in translationValues:
  160. for phi in phiAngles:
  161. phiPos = rotate(rotationAxis, phi, focalPoint, position)
  162. newfocalPoint = tuple(
  163. focalPoint[i] + (translation * rotationAxis[i]) for i in range(3)
  164. )
  165. transPhiPoint = tuple(
  166. phiPos[i] + (translation * rotationAxis[i]) for i in range(3)
  167. )
  168. self.cameraSettings.append(
  169. {
  170. "n_pos": translation,
  171. "n_posIdx": translationValues.index(translation),
  172. "phi": phi,
  173. "phiIdx": phiAngles.index(phi),
  174. "focalPoint": newfocalPoint,
  175. "position": transPhiPoint,
  176. "viewUp": rotationAxis,
  177. }
  178. )
  179. self.dataHandler.updateBasePattern()
  180. def updatePriority(self, priorityList):
  181. keyList = ["n_pos", "phi"]
  182. for idx in range(min(len(priorityList), len(keyList))):
  183. self.dataHandler.updatePriority(keyList[idx], priorityList[idx])
  184. def __iter__(self):
  185. for cameraData in self.cameraSettings:
  186. self.dataHandler.setArguments(
  187. phi=cameraData["phiIdx"], n_pos=cameraData["n_posIdx"]
  188. )
  189. yield cameraData
  190. # -----------------------------------------------------------------------------
  191. # MultiView Cube Camera
  192. # -----------------------------------------------------------------------------
  193. class CubeCamera(object):
  194. # positions = [ { position: [x,y,z], args: { i: 1, j: 0, k: 7 } }, ... ]
  195. def __init__(self, dataHandler, viewForward, viewUp, positions):
  196. self.dataHandler = dataHandler
  197. self.cameraSettings = []
  198. self.viewForward = viewForward
  199. self.viewUp = viewUp
  200. self.rightDirection = vectProduct(viewForward, viewUp)
  201. self.positions = positions
  202. # Register arguments to the data handler
  203. self.dataHandler.registerArgument(
  204. priority=0, name="orientation", values=["f", "b", "r", "l", "u", "d"]
  205. )
  206. # Register arguments to id position
  207. self.args = {}
  208. for pos in positions:
  209. for key in pos["args"]:
  210. if key not in self.args:
  211. self.args[key] = {}
  212. self.args[key][pos["args"][key]] = True
  213. for key in self.args:
  214. self.args[key] = sorted(self.args[key], key=lambda k: int(k))
  215. self.keyList = self.args.keys()
  216. for key in self.args:
  217. self.dataHandler.registerArgument(
  218. priority=1, name=key, values=self.args[key]
  219. )
  220. self.dataHandler.updateBasePattern()
  221. def updatePriority(self, priorityList):
  222. keyList = ["orientation"]
  223. for idx in range(min(len(priorityList), len(keyList))):
  224. self.dataHandler.updatePriority(keyList[idx], priorityList[idx])
  225. def __iter__(self):
  226. for pos in self.positions:
  227. cameraData = {
  228. "position": pos["position"],
  229. }
  230. print("=" * 80)
  231. for key in pos["args"]:
  232. idx = self.args[key].index(pos["args"][key])
  233. self.dataHandler.setArguments(**{key: idx})
  234. print(key, idx)
  235. print("position", cameraData["position"])
  236. # front
  237. cameraData["focalPoint"] = [
  238. (cameraData["position"][i] + self.viewForward[i]) for i in range(3)
  239. ]
  240. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  241. cameraData["orientation"] = "front"
  242. self.dataHandler.setArguments(orientation=0)
  243. yield cameraData
  244. # back
  245. cameraData["focalPoint"] = [
  246. (cameraData["position"][i] - self.viewForward[i]) for i in range(3)
  247. ]
  248. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  249. cameraData["orientation"] = "back"
  250. self.dataHandler.setArguments(orientation=1)
  251. yield cameraData
  252. # right
  253. self.dataHandler.setArguments(orientation=2)
  254. cameraData["focalPoint"] = [
  255. (cameraData["position"][i] + self.rightDirection[i]) for i in range(3)
  256. ]
  257. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  258. cameraData["orientation"] = "right"
  259. yield cameraData
  260. # left
  261. self.dataHandler.setArguments(orientation=3)
  262. cameraData["focalPoint"] = [
  263. (cameraData["position"][i] - self.rightDirection[i]) for i in range(3)
  264. ]
  265. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  266. cameraData["orientation"] = "left"
  267. yield cameraData
  268. # up
  269. self.dataHandler.setArguments(orientation=4)
  270. cameraData["focalPoint"] = [
  271. (cameraData["position"][i] + self.viewUp[i]) for i in range(3)
  272. ]
  273. cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)]
  274. cameraData["orientation"] = "up"
  275. yield cameraData
  276. # doww
  277. self.dataHandler.setArguments(orientation=5)
  278. cameraData["focalPoint"] = [
  279. (cameraData["position"][i] - self.viewUp[i]) for i in range(3)
  280. ]
  281. cameraData["viewUp"] = [self.viewForward[i] for i in range(3)]
  282. cameraData["orientation"] = "down"
  283. yield cameraData
  284. # -----------------------------------------------------------------------------
  285. # MultiView Cube Camera
  286. # -----------------------------------------------------------------------------
  287. class StereoCubeCamera(object):
  288. # positions = [ { position: [x,y,z], args: { i: 1, j: 0, k: 7 } }, ... ]
  289. def __init__(self, dataHandler, viewForward, viewUp, positions, eyeSpacing):
  290. self.dataHandler = dataHandler
  291. self.cameraSettings = []
  292. self.viewForward = viewForward
  293. self.viewUp = viewUp
  294. self.rightDirection = vectProduct(viewForward, viewUp)
  295. self.positions = positions
  296. self.eyeSpacing = eyeSpacing
  297. # Register arguments to the data handler
  298. self.dataHandler.registerArgument(
  299. priority=0, name="orientation", values=["f", "b", "r", "l", "u", "d"]
  300. )
  301. self.dataHandler.registerArgument(
  302. priority=0, name="eye", values=["left", "right"]
  303. )
  304. # Register arguments to id position
  305. self.args = {}
  306. for pos in positions:
  307. for key in pos["args"]:
  308. if key not in self.args:
  309. self.args[key] = {}
  310. self.args[key][pos["args"][key]] = True
  311. for key in self.args:
  312. self.args[key] = sorted(self.args[key], key=lambda k: int(k))
  313. self.keyList = self.args.keys()
  314. for key in self.args:
  315. self.dataHandler.registerArgument(
  316. priority=1, name=key, values=self.args[key]
  317. )
  318. self.dataHandler.updateBasePattern()
  319. def updatePriority(self, priorityList):
  320. keyList = ["orientation"]
  321. for idx in range(min(len(priorityList), len(keyList))):
  322. self.dataHandler.updatePriority(keyList[idx], priorityList[idx])
  323. def __iter__(self):
  324. for pos in self.positions:
  325. cameraData = {}
  326. for key in pos["args"]:
  327. idx = self.args[key].index(pos["args"][key])
  328. self.dataHandler.setArguments(**{key: idx})
  329. # front
  330. cameraData["orientation"] = "front"
  331. self.dataHandler.setArguments(orientation=0)
  332. deltaVect = [
  333. (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection
  334. ]
  335. ## Left-Eye
  336. self.dataHandler.setArguments(eye=0)
  337. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  338. cameraData["position"] = [
  339. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  340. ]
  341. cameraData["focalPoint"] = [
  342. (pos["position"][i] + self.viewForward[i] - deltaVect[i])
  343. for i in range(3)
  344. ]
  345. yield cameraData
  346. ## Right-Eye
  347. self.dataHandler.setArguments(eye=1)
  348. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  349. cameraData["position"] = [
  350. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  351. ]
  352. cameraData["focalPoint"] = [
  353. (pos["position"][i] + self.viewForward[i] + deltaVect[i])
  354. for i in range(3)
  355. ]
  356. yield cameraData
  357. # back
  358. cameraData["orientation"] = "back"
  359. self.dataHandler.setArguments(orientation=1)
  360. deltaVect = [
  361. -(v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection
  362. ]
  363. ## Left-Eye
  364. self.dataHandler.setArguments(eye=0)
  365. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  366. cameraData["position"] = [
  367. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  368. ]
  369. cameraData["focalPoint"] = [
  370. (pos["position"][i] - self.viewForward[i] - deltaVect[i])
  371. for i in range(3)
  372. ]
  373. yield cameraData
  374. ## Right-Eye
  375. self.dataHandler.setArguments(eye=1)
  376. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  377. cameraData["position"] = [
  378. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  379. ]
  380. cameraData["focalPoint"] = [
  381. (pos["position"][i] - self.viewForward[i] + deltaVect[i])
  382. for i in range(3)
  383. ]
  384. yield cameraData
  385. # right
  386. self.dataHandler.setArguments(orientation=2)
  387. cameraData["orientation"] = "right"
  388. deltaVect = [-(v * float(self.eyeSpacing) * 0.5) for v in self.viewForward]
  389. ## Left-Eye
  390. self.dataHandler.setArguments(eye=0)
  391. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  392. cameraData["position"] = [
  393. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  394. ]
  395. cameraData["focalPoint"] = [
  396. (pos["position"][i] + self.rightDirection[i] - deltaVect[i])
  397. for i in range(3)
  398. ]
  399. yield cameraData
  400. ## Right-Eye
  401. self.dataHandler.setArguments(eye=1)
  402. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  403. cameraData["position"] = [
  404. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  405. ]
  406. cameraData["focalPoint"] = [
  407. (pos["position"][i] + self.rightDirection[i] + deltaVect[i])
  408. for i in range(3)
  409. ]
  410. yield cameraData
  411. # left
  412. self.dataHandler.setArguments(orientation=3)
  413. cameraData["orientation"] = "left"
  414. deltaVect = [(v * float(self.eyeSpacing) * 0.5) for v in self.viewForward]
  415. ## Left-Eye
  416. self.dataHandler.setArguments(eye=0)
  417. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  418. cameraData["position"] = [
  419. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  420. ]
  421. cameraData["focalPoint"] = [
  422. (pos["position"][i] - self.rightDirection[i] - deltaVect[i])
  423. for i in range(3)
  424. ]
  425. yield cameraData
  426. ## Right-Eye
  427. self.dataHandler.setArguments(eye=1)
  428. cameraData["viewUp"] = [self.viewUp[i] for i in range(3)]
  429. cameraData["position"] = [
  430. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  431. ]
  432. cameraData["focalPoint"] = [
  433. (pos["position"][i] - self.rightDirection[i] + deltaVect[i])
  434. for i in range(3)
  435. ]
  436. yield cameraData
  437. # up
  438. self.dataHandler.setArguments(orientation=4)
  439. cameraData["orientation"] = "up"
  440. deltaVect = [
  441. (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection
  442. ]
  443. ## Left-Eye
  444. self.dataHandler.setArguments(eye=0)
  445. cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)]
  446. cameraData["position"] = [
  447. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  448. ]
  449. cameraData["focalPoint"] = [
  450. (pos["position"][i] + self.viewUp[i] - deltaVect[i]) for i in range(3)
  451. ]
  452. yield cameraData
  453. ## Right-Eye
  454. self.dataHandler.setArguments(eye=1)
  455. cameraData["viewUp"] = [(-self.viewForward[i]) for i in range(3)]
  456. cameraData["position"] = [
  457. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  458. ]
  459. cameraData["focalPoint"] = [
  460. (pos["position"][i] + self.viewUp[i] + deltaVect[i]) for i in range(3)
  461. ]
  462. yield cameraData
  463. # doww
  464. self.dataHandler.setArguments(orientation=5)
  465. cameraData["orientation"] = "down"
  466. deltaVect = [
  467. (v * float(self.eyeSpacing) * 0.5) for v in self.rightDirection
  468. ]
  469. ## Left-Eye
  470. self.dataHandler.setArguments(eye=0)
  471. cameraData["viewUp"] = [self.viewForward[i] for i in range(3)]
  472. cameraData["position"] = [
  473. (pos["position"][idx] - deltaVect[idx]) for idx in range(3)
  474. ]
  475. cameraData["focalPoint"] = [
  476. (pos["position"][i] - self.viewUp[i] - deltaVect[i]) for i in range(3)
  477. ]
  478. yield cameraData
  479. ## Right-Eye
  480. self.dataHandler.setArguments(eye=1)
  481. cameraData["viewUp"] = [self.viewForward[i] for i in range(3)]
  482. cameraData["position"] = [
  483. (pos["position"][idx] + deltaVect[idx]) for idx in range(3)
  484. ]
  485. cameraData["focalPoint"] = [
  486. (pos["position"][i] - self.viewUp[i] + deltaVect[i]) for i in range(3)
  487. ]
  488. yield cameraData
  489. # -----------------------------------------------------------------------------
  490. # MultiView Camera
  491. # -----------------------------------------------------------------------------
  492. class MultiViewCamera(object):
  493. def __init__(self, dataHandler):
  494. self.dataHandler = dataHandler
  495. self.cameraSettings = []
  496. self.positionNames = []
  497. def registerViewPoint(self, name, focalPoint, position, viewUp):
  498. self.cameraSettings.append(
  499. {
  500. "name": name,
  501. "nameIdx": len(self.positionNames),
  502. "focalPoint": focalPoint,
  503. "position": position,
  504. "viewUp": viewUp,
  505. }
  506. )
  507. self.positionNames.append(name)
  508. self.dataHandler.registerArgument(
  509. priority=0, name="multiView", values=self.positionNames
  510. )
  511. self.dataHandler.updateBasePattern()
  512. def updatePriority(self, priorityList):
  513. keyList = ["multiView"]
  514. for idx in range(min(len(priorityList), len(keyList))):
  515. self.dataHandler.updatePriority(keyList[idx], priorityList[idx])
  516. def __iter__(self):
  517. for cameraData in self.cameraSettings:
  518. self.dataHandler.setArguments(multiView=cameraData["nameIdx"])
  519. yield cameraData
  520. # -----------------------------------------------------------------------------
  521. # Helper methods
  522. # -----------------------------------------------------------------------------
  523. def update_camera(renderer, cameraData):
  524. camera = renderer.GetActiveCamera()
  525. camera.SetPosition(cameraData["position"])
  526. camera.SetFocalPoint(cameraData["focalPoint"])
  527. camera.SetViewUp(cameraData["viewUp"])
  528. def create_spherical_camera(renderer, dataHandler, phiValues, thetaValues):
  529. camera = renderer.GetActiveCamera()
  530. return SphericalCamera(
  531. dataHandler,
  532. camera.GetFocalPoint(),
  533. camera.GetPosition(),
  534. camera.GetViewUp(),
  535. phiValues,
  536. thetaValues,
  537. )
  538. def create_cylindrical_camera(renderer, dataHandler, phiValues, translationValues):
  539. camera = renderer.GetActiveCamera()
  540. return CylindricalCamera(
  541. dataHandler,
  542. camera.GetFocalPoint(),
  543. camera.GetPosition(),
  544. camera.GetViewUp(),
  545. phiValues,
  546. translationValues,
  547. )