CSceneNodeAnimatorCameraMaya.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "CSceneNodeAnimatorCameraMaya.h"
  5. #include "ICursorControl.h"
  6. #include "ICameraSceneNode.h"
  7. #include "SViewFrustum.h"
  8. #include "ISceneManager.h"
  9. namespace irr
  10. {
  11. namespace scene
  12. {
  13. //! constructor
  14. CSceneNodeAnimatorCameraMaya::CSceneNodeAnimatorCameraMaya(gui::ICursorControl* cursor,
  15. f32 rotateSpeed, f32 zoomSpeed, f32 translateSpeed, f32 distance)
  16. : CursorControl(cursor), OldCamera(0), MousePos(0.5f, 0.5f),
  17. ZoomSpeed(zoomSpeed), RotateSpeed(rotateSpeed), TranslateSpeed(translateSpeed),
  18. CurrentZoom(distance), RotX(0.0f), RotY(0.0f),
  19. Zooming(false), Rotating(false), Moving(false), Translating(false)
  20. {
  21. #ifdef _DEBUG
  22. setDebugName("CSceneNodeAnimatorCameraMaya");
  23. #endif
  24. if (CursorControl)
  25. {
  26. CursorControl->grab();
  27. MousePos = CursorControl->getRelativePosition();
  28. }
  29. allKeysUp();
  30. }
  31. //! destructor
  32. CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya()
  33. {
  34. if (CursorControl)
  35. CursorControl->drop();
  36. }
  37. //! It is possible to send mouse and key events to the camera. Most cameras
  38. //! may ignore this input, but camera scene nodes which are created for
  39. //! example with scene::ISceneManager::addMayaCameraSceneNode or
  40. //! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input
  41. //! for changing their position, look at target or whatever.
  42. bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event)
  43. {
  44. if (event.EventType != EET_MOUSE_INPUT_EVENT)
  45. return false;
  46. switch(event.MouseInput.Event)
  47. {
  48. case EMIE_LMOUSE_PRESSED_DOWN:
  49. MouseKeys[0] = true;
  50. break;
  51. case EMIE_RMOUSE_PRESSED_DOWN:
  52. MouseKeys[2] = true;
  53. break;
  54. case EMIE_MMOUSE_PRESSED_DOWN:
  55. MouseKeys[1] = true;
  56. break;
  57. case EMIE_LMOUSE_LEFT_UP:
  58. MouseKeys[0] = false;
  59. break;
  60. case EMIE_RMOUSE_LEFT_UP:
  61. MouseKeys[2] = false;
  62. break;
  63. case EMIE_MMOUSE_LEFT_UP:
  64. MouseKeys[1] = false;
  65. break;
  66. case EMIE_MOUSE_MOVED:
  67. MousePos = CursorControl->getRelativePosition();
  68. break;
  69. case EMIE_MOUSE_WHEEL:
  70. case EMIE_LMOUSE_DOUBLE_CLICK:
  71. case EMIE_RMOUSE_DOUBLE_CLICK:
  72. case EMIE_MMOUSE_DOUBLE_CLICK:
  73. case EMIE_LMOUSE_TRIPLE_CLICK:
  74. case EMIE_RMOUSE_TRIPLE_CLICK:
  75. case EMIE_MMOUSE_TRIPLE_CLICK:
  76. case EMIE_COUNT:
  77. return false;
  78. }
  79. return true;
  80. }
  81. //! OnAnimate() is called just before rendering the whole scene.
  82. void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs)
  83. {
  84. //Alt + LM = Rotate around camera pivot
  85. //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot)
  86. //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed)
  87. if (!node || node->getType() != ESNT_CAMERA)
  88. return;
  89. ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
  90. // If the camera isn't the active camera, and receiving input, then don't process it.
  91. if (!camera->isInputReceiverEnabled())
  92. return;
  93. scene::ISceneManager * smgr = camera->getSceneManager();
  94. if (smgr && smgr->getActiveCamera() != camera)
  95. return;
  96. if (OldCamera != camera)
  97. {
  98. LastCameraTarget = OldTarget = camera->getTarget();
  99. OldCamera = camera;
  100. }
  101. else
  102. {
  103. OldTarget += camera->getTarget() - LastCameraTarget;
  104. }
  105. f32 nRotX = RotX;
  106. f32 nRotY = RotY;
  107. f32 nZoom = CurrentZoom;
  108. if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) )
  109. {
  110. if (!Zooming)
  111. {
  112. ZoomStart = MousePos;
  113. Zooming = true;
  114. }
  115. else
  116. {
  117. const f32 targetMinDistance = 0.1f;
  118. nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed;
  119. if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close
  120. nZoom = targetMinDistance;
  121. }
  122. }
  123. else if (Zooming)
  124. {
  125. const f32 old = CurrentZoom;
  126. CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed;
  127. nZoom = CurrentZoom;
  128. if (nZoom < 0)
  129. nZoom = CurrentZoom = old;
  130. Zooming = false;
  131. }
  132. // Translation ---------------------------------
  133. core::vector3df translate(OldTarget);
  134. const core::vector3df upVector(camera->getUpVector());
  135. const core::vector3df target = camera->getTarget();
  136. core::vector3df pos = camera->getPosition();
  137. core::vector3df tvectX = pos - target;
  138. tvectX = tvectX.crossProduct(upVector);
  139. tvectX.normalize();
  140. const SViewFrustum* const va = camera->getViewFrustum();
  141. core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown());
  142. tvectY = tvectY.crossProduct(upVector.Y > 0 ? pos - target : target - pos);
  143. tvectY.normalize();
  144. if (isMouseKeyDown(2) && !Zooming)
  145. {
  146. if (!Translating)
  147. {
  148. TranslateStart = MousePos;
  149. Translating = true;
  150. }
  151. else
  152. {
  153. translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
  154. tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
  155. }
  156. }
  157. else if (Translating)
  158. {
  159. translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
  160. tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
  161. OldTarget = translate;
  162. Translating = false;
  163. }
  164. // Rotation ------------------------------------
  165. if (isMouseKeyDown(0) && !Zooming)
  166. {
  167. if (!Rotating)
  168. {
  169. RotateStart = MousePos;
  170. Rotating = true;
  171. nRotX = RotX;
  172. nRotY = RotY;
  173. }
  174. else
  175. {
  176. nRotX += (RotateStart.X - MousePos.X) * RotateSpeed;
  177. nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
  178. }
  179. }
  180. else if (Rotating)
  181. {
  182. RotX += (RotateStart.X - MousePos.X) * RotateSpeed;
  183. RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
  184. nRotX = RotX;
  185. nRotY = RotY;
  186. Rotating = false;
  187. }
  188. // Set pos ------------------------------------
  189. pos = translate;
  190. pos.X += nZoom;
  191. pos.rotateXYBy(nRotY, translate);
  192. pos.rotateXZBy(-nRotX, translate);
  193. camera->setPosition(pos);
  194. camera->setTarget(translate);
  195. // Rotation Error ----------------------------
  196. // jox: fixed bug: jitter when rotating to the top and bottom of y
  197. pos.set(0,1,0);
  198. pos.rotateXYBy(-nRotY);
  199. pos.rotateXZBy(-nRotX+180.f);
  200. camera->setUpVector(pos);
  201. LastCameraTarget = camera->getTarget();
  202. }
  203. bool CSceneNodeAnimatorCameraMaya::isMouseKeyDown(s32 key) const
  204. {
  205. return MouseKeys[key];
  206. }
  207. void CSceneNodeAnimatorCameraMaya::allKeysUp()
  208. {
  209. for (s32 i=0; i<3; ++i)
  210. MouseKeys[i] = false;
  211. }
  212. //! Sets the rotation speed
  213. void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed)
  214. {
  215. RotateSpeed = speed;
  216. }
  217. //! Sets the movement speed
  218. void CSceneNodeAnimatorCameraMaya::setMoveSpeed(f32 speed)
  219. {
  220. TranslateSpeed = speed;
  221. }
  222. //! Sets the zoom speed
  223. void CSceneNodeAnimatorCameraMaya::setZoomSpeed(f32 speed)
  224. {
  225. ZoomSpeed = speed;
  226. }
  227. //! Set the distance
  228. void CSceneNodeAnimatorCameraMaya::setDistance(f32 distance)
  229. {
  230. CurrentZoom=distance;
  231. }
  232. //! Gets the rotation speed
  233. f32 CSceneNodeAnimatorCameraMaya::getRotateSpeed() const
  234. {
  235. return RotateSpeed;
  236. }
  237. // Gets the movement speed
  238. f32 CSceneNodeAnimatorCameraMaya::getMoveSpeed() const
  239. {
  240. return TranslateSpeed;
  241. }
  242. //! Gets the zoom speed
  243. f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const
  244. {
  245. return ZoomSpeed;
  246. }
  247. //! Returns the current distance, i.e. orbit radius
  248. f32 CSceneNodeAnimatorCameraMaya::getDistance() const
  249. {
  250. return CurrentZoom;
  251. }
  252. ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager)
  253. {
  254. CSceneNodeAnimatorCameraMaya * newAnimator =
  255. new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed);
  256. return newAnimator;
  257. }
  258. } // end namespace
  259. } // end namespace