home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / camcontrol.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  9.2 KB  |  311 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2004
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # $Id: camcontrol.py,v 1.4 2005/08/31 14:49:13 mbaas Exp $
  36.  
  37. ## \file camcontrol.py
  38. ## Contains the CameraControl class.
  39.  
  40. import component
  41. import eventmanager
  42. from scene import getScene
  43. from events import *
  44. from keydefs import *
  45. from cgtypes import *
  46.  
  47. # CameraControl
  48. class CameraControl(component.Component):
  49.     """Camera control component.
  50.  
  51.     This component lets you control a camera interactively with the mouse.
  52.  
  53.     Todo: - About what point rotates the FreeCam?
  54.           - Make movement distances customizable (auto configurable?)
  55.     """
  56.     
  57.     def __init__(self,
  58.                  cam,
  59.                  name = "CameraControl",
  60.                  mode = 0,
  61.                  auto_insert = True):
  62.         """Constructor.
  63.  
  64.         \param cam (\c ...Cam?...) Camera to control
  65.         \param name (\c str) Name of the component
  66.         \param mode (\c int) 0=Emulate MAX behavior, 1=Emulate Maya behavior
  67.         \param auto_insert (\c bool) Insert into scene or not
  68.         """
  69.         
  70.         component.Component.__init__(self, name=name, auto_insert=auto_insert)
  71.         
  72.         # mode: 0=Emulate MAX / 1=Emulate Maya / 2=Emulate Softimage (Navigation tool)
  73.         self.mode = mode  
  74.         self.cam = cam
  75.         self.left_down = False
  76.         self.middle_down = False
  77.         self.right_down = False
  78.         self.alt_down = False
  79.         self.ctrl_down = False
  80.         em = eventmanager.eventManager()
  81.         em.connect(KEY_PRESS, self)
  82.         em.connect(KEY_RELEASE, self)
  83.         em.connect(LEFT_DOWN, self)
  84.         em.connect(LEFT_UP, self)
  85.         em.connect(MIDDLE_DOWN, self)
  86.         em.connect(MIDDLE_UP, self)
  87.         em.connect(RIGHT_DOWN, self)
  88.         em.connect(RIGHT_UP, self)
  89.         em.connect(MOUSE_MOVE, self)
  90.         em.connect(MOUSE_WHEEL, self)
  91.         em.connect(SPACE_MOTION, self)
  92.  
  93.     def panCondition(self):
  94.         """Return True if the panning mode is active.
  95.         """
  96.         if self.mode==0:
  97.             # MAX
  98.             return self.middle_down and not self.alt_down and not self.ctrl_down
  99.         elif self.mode==1:
  100.             # Maya
  101.             return self.middle_down and self.alt_down
  102.         else:
  103.             # Softimage
  104.             return self.left_down
  105.  
  106.     def rotCondition(self):
  107.         """Return True if rotation mode is active.
  108.         """
  109.         if self.mode==0:
  110.             # MAX
  111.             return self.middle_down and self.alt_down and not self.ctrl_down
  112.         elif self.mode==1:
  113.             # Maya
  114.             return self.left_down and self.alt_down
  115.         else:
  116.             # Softimage
  117.             return self.right_down
  118.  
  119.     def fbCondition(self):
  120.         """Return True if 'forward/backward' movement mode is active.
  121.         """        
  122.         if self.mode==0:
  123.             # MAX
  124.             return self.middle_down and self.alt_down and self.ctrl_down
  125.         elif self.mode==1:
  126.             # Maya
  127.             return self.right_down and self.alt_down
  128.         else:
  129.             # Softimage
  130.             return self.middle_down
  131.  
  132.     def translateXYAmount(self, evt):
  133.         """Return the amount of sideways movement."""
  134.         if self.mode==0:
  135.             # MAX
  136.             return 0.003*evt.dx, 0.003*evt.dy
  137.         elif self.mode==1:
  138.             # Maya
  139.             return 0.003*evt.dx, 0.003*evt.dy
  140.         else:
  141.             # Softimage
  142.             return 0.002*evt.dx, 0.002*evt.dy
  143.  
  144.     def translateZAmount(self, evt):
  145.         """Return the amount of 'forward/backward' movement."""
  146.         if self.mode==0:
  147.             # MAX
  148.             return -0.01*evt.dy
  149.         elif self.mode==1:
  150.             # Maya
  151.             return 0.004*(evt.dy+evt.dx)
  152.         else:
  153.             # Softimage
  154.             return 0.008*(evt.dy-evt.dx)
  155.  
  156.     def rotationAmount(self, evt):
  157.         """Return the amount of rotation."""
  158.         if self.mode==0:
  159.             # MAX
  160.             return 0.01*evt.dx, 0.01*evt.dy
  161.         elif self.mode==1:
  162.             # Maya
  163.             return 0.01*evt.dx, 0.01*evt.dy
  164.         else:
  165.             # Softimage
  166.             return 0.015*evt.dx, 0.015*evt.dy
  167.  
  168.     # onKeyPress
  169.     def onKeyPress(self, e):
  170.         """Set key flags."""
  171.         if e.altKey():
  172.             self.alt_down = True
  173.         elif e.controlKey():
  174.             self.ctrl_down = True
  175.  
  176.     # onKeyRelease
  177.     def onKeyRelease(self, e):
  178.         """Unset key flags."""
  179.         if e.altKey():
  180.             self.alt_down = False
  181.         elif e.controlKey():
  182.             self.ctrl_down = False
  183.  
  184.     # onMouseMove
  185.     def onMouseMove(self, e):
  186.  
  187.         if self.panCondition():
  188.             dx, dy = self.translateXYAmount(e)
  189.             self.translateXY(dx, dy)
  190.  
  191.         elif self.rotCondition():
  192.             dx, dy = self.rotationAmount(e)
  193.             self.rotate(dx, dy)
  194.             
  195.         elif self.fbCondition():
  196.             f = self.translateZAmount(e)
  197.             self.translateZ(f)
  198.  
  199.     def onMouseWheel(self, e):
  200.         self.translateZ(0.002*e.delta)
  201.                             
  202.     def onLeftDown(self, e):
  203.         self.left_down = True
  204.  
  205.     def onLeftUp(self, e):
  206.         self.left_down = False
  207.  
  208.     def onMiddleDown(self, e):
  209.         self.middle_down = True
  210.  
  211.     def onMiddleUp(self, e):
  212.         self.middle_down = False
  213.  
  214.     def onRightDown(self, e):
  215.         self.right_down = True
  216.  
  217.     def onRightUp(self, e):
  218.         self.right_down = False
  219.  
  220.     # translateXY
  221.     def translateXY(self, dx, dy):
  222.         """Translate the camera in local XY.
  223.         """
  224.  
  225.         T = self.cam.transform
  226.         bx = vec3(tuple(T.getColumn(0))[:3])
  227.         by = vec3(tuple(T.getColumn(1))[:3])
  228.         if hasattr(self.cam, "target"):
  229.             f = (self.cam.target-self.cam.pos).length()
  230.             dx *= f
  231.             dy *= f
  232.         delta = dx*bx + dy*by
  233.         self.cam.pos += delta
  234.         if hasattr(self.cam, "target"):
  235.             self.cam.target += delta
  236.  
  237.     # rotate
  238.     def rotate(self, dx, dy):
  239.         """Rotate around target."""
  240.        
  241.         T = self.cam.transform
  242.         if hasattr(self.cam, "target"):
  243.             pivot = self.cam.target
  244.         else:
  245.             pivot = vec3(0)
  246.         up = getScene().up
  247.         R = mat4(1).rotation(-dx, up)
  248.         dp = self.cam.pos-pivot
  249.         self.cam.pos = pivot + R*dp
  250.             
  251.         T = self.cam.transform
  252.         bx = vec3(tuple(T.getColumn(0))[:3])
  253.         R = mat4(1).rotation(dy, bx)
  254.         dp = self.cam.pos-pivot
  255.         self.cam.pos = pivot + R*dp
  256.  
  257.     # translateZ
  258.     def translateZ(self, dz):
  259.         """Move in viewing direction.
  260.         """
  261.  
  262.         T = self.cam.transform
  263.         bz = vec3(tuple(T.getColumn(2))[:3])
  264.         if hasattr(self.cam, "target"):
  265.             f = (self.cam.target-self.cam.pos).length()
  266.         else:
  267.             f = 1
  268.         delta = f*dz*bz
  269.         self.cam.pos += delta
  270. #        self.cam.target += delta            
  271.         
  272.  
  273.     # onSpaceMotion
  274.     def onSpaceMotion(self, e):
  275.         """
  276.         this is still somewhat experimental
  277.         (should distinguish between the camera types as it's meant to be
  278.         used with a FreeCamera)
  279.         """
  280.  
  281.         scene = getScene()
  282.  
  283.         tr = 0.001*e.translation
  284.         rot = e.rotation
  285.  
  286.         if scene.handedness=='r':
  287.             tr.x = -tr.x
  288.             rot.y = -rot.y
  289.             rot.z = -rot.z
  290.  
  291.         M = mat4().translation(tr)
  292.  
  293.         if rot!=vec3(0):
  294.             a = 0.0002*rot.length()
  295.             M = M*mat4().rotation(a, rot)
  296.  
  297.         T = self.cam.transform*M
  298.         # Align camera to up direction
  299.         R = T.getMat3()
  300.         bz = vec3(tuple(T.getColumn(2))[:3])
  301.         by = scene.up
  302.         bx = by.cross(bz)
  303.         by = bz.cross(bx)
  304.         try:
  305.             R = mat3(bx.normalize(), by.normalize(), bz.normalize())
  306.         except:
  307.             R = mat3(1)
  308.         T.setMat3(R)
  309.  
  310.         self.cam.transform = T
  311.