CSceneNodeAnimatorCollisionResponse.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 "CSceneNodeAnimatorCollisionResponse.h"
  5. #include "ISceneCollisionManager.h"
  6. #include "ISceneManager.h"
  7. #include "ICameraSceneNode.h"
  8. #include "os.h"
  9. namespace irr
  10. {
  11. namespace scene
  12. {
  13. //! constructor
  14. CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse(
  15. ISceneManager* scenemanager,
  16. ITriangleSelector* world, ISceneNode* object,
  17. const core::vector3df& ellipsoidRadius,
  18. const core::vector3df& gravityPerSecond,
  19. const core::vector3df& ellipsoidTranslation,
  20. f32 slidingSpeed)
  21. : Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation),
  22. World(world), Object(object), SceneManager(scenemanager), LastTime(0),
  23. SlidingSpeed(slidingSpeed), CollisionNode(0), CollisionCallback(0),
  24. Falling(false), IsCamera(false), AnimateCameraTarget(true), CollisionOccurred(false),
  25. FirstUpdate(true)
  26. {
  27. #ifdef _DEBUG
  28. setDebugName("CSceneNodeAnimatorCollisionResponse");
  29. #endif
  30. if (World)
  31. World->grab();
  32. setNode(Object);
  33. }
  34. //! destructor
  35. CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse()
  36. {
  37. if (World)
  38. World->drop();
  39. if (CollisionCallback)
  40. CollisionCallback->drop();
  41. }
  42. //! Returns if the attached scene node is falling, which means that
  43. //! there is no blocking wall from the scene node in the direction of
  44. //! the gravity.
  45. bool CSceneNodeAnimatorCollisionResponse::isFalling() const
  46. {
  47. _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
  48. return Falling;
  49. }
  50. //! Sets the radius of the ellipsoid with which collision detection and
  51. //! response is done.
  52. void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius(
  53. const core::vector3df& radius)
  54. {
  55. Radius = radius;
  56. FirstUpdate = true;
  57. }
  58. //! Returns the radius of the ellipsoid with wich the collision detection and
  59. //! response is done.
  60. core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const
  61. {
  62. return Radius;
  63. }
  64. //! Sets the gravity of the environment.
  65. void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity)
  66. {
  67. Gravity = gravity;
  68. FirstUpdate = true;
  69. }
  70. //! Returns current vector of gravity.
  71. core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const
  72. {
  73. return Gravity;
  74. }
  75. //! 'Jump' the animator, by adding a jump speed opposite to its gravity
  76. void CSceneNodeAnimatorCollisionResponse::jump(f32 jumpSpeed)
  77. {
  78. FallingVelocity -= (core::vector3df(Gravity).normalize()) * jumpSpeed;
  79. Falling = true;
  80. }
  81. //! Sets the translation of the ellipsoid for collision detection.
  82. void CSceneNodeAnimatorCollisionResponse::setEllipsoidTranslation(const core::vector3df &translation)
  83. {
  84. Translation = translation;
  85. }
  86. //! Returns the translation of the ellipsoid for collision detection.
  87. core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() const
  88. {
  89. return Translation;
  90. }
  91. //! Sets a triangle selector holding all triangles of the world with which
  92. //! the scene node may collide.
  93. void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld)
  94. {
  95. if (newWorld)
  96. newWorld->grab();
  97. if (World)
  98. World->drop();
  99. World = newWorld;
  100. FirstUpdate = true;
  101. }
  102. //! Returns the current triangle selector containing all triangles for
  103. //! collision detection.
  104. ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const
  105. {
  106. return World;
  107. }
  108. void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs)
  109. {
  110. CollisionOccurred = false;
  111. if (node != Object)
  112. setNode(node);
  113. if(!Object || !World)
  114. return;
  115. // trigger reset
  116. if ( timeMs == 0 )
  117. {
  118. FirstUpdate = true;
  119. timeMs = LastTime;
  120. }
  121. if ( FirstUpdate )
  122. {
  123. LastPosition = Object->getPosition();
  124. Falling = false;
  125. LastTime = timeMs;
  126. FallingVelocity.set ( 0, 0, 0 );
  127. FirstUpdate = false;
  128. }
  129. const u32 diff = timeMs - LastTime;
  130. LastTime = timeMs;
  131. CollisionResultPosition = Object->getPosition();
  132. core::vector3df vel = CollisionResultPosition - LastPosition;
  133. FallingVelocity += Gravity * (f32)diff * 0.001f;
  134. CollisionTriangle = RefTriangle;
  135. CollisionPoint = core::vector3df();
  136. CollisionResultPosition = core::vector3df();
  137. CollisionNode = 0;
  138. // core::vector3df force = vel + FallingVelocity;
  139. if ( AnimateCameraTarget )
  140. {
  141. // TODO: divide SlidingSpeed by frame time
  142. bool f = false;
  143. CollisionResultPosition
  144. = SceneManager->getSceneCollisionManager()->getCollisionResultPosition(
  145. World, LastPosition-Translation,
  146. Radius, vel, CollisionTriangle, CollisionPoint, f,
  147. CollisionNode, SlidingSpeed, FallingVelocity);
  148. CollisionOccurred = (CollisionTriangle != RefTriangle);
  149. CollisionResultPosition += Translation;
  150. if (f)//CollisionTriangle == RefTriangle)
  151. {
  152. Falling = true;
  153. }
  154. else
  155. {
  156. Falling = false;
  157. FallingVelocity.set(0, 0, 0);
  158. }
  159. bool collisionConsumed = false;
  160. if (CollisionOccurred && CollisionCallback)
  161. collisionConsumed = CollisionCallback->onCollision(*this);
  162. if(!collisionConsumed)
  163. Object->setPosition(CollisionResultPosition);
  164. }
  165. // move camera target
  166. if (AnimateCameraTarget && IsCamera)
  167. {
  168. const core::vector3df pdiff = Object->getPosition() - LastPosition - vel;
  169. ICameraSceneNode* cam = (ICameraSceneNode*)Object;
  170. cam->setTarget(cam->getTarget() + pdiff);
  171. }
  172. LastPosition = Object->getPosition();
  173. }
  174. void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node)
  175. {
  176. Object = node;
  177. if (Object)
  178. {
  179. LastPosition = Object->getPosition();
  180. IsCamera = (Object->getType() == ESNT_CAMERA);
  181. }
  182. LastTime = os::Timer::getTime();
  183. }
  184. //! Writes attributes of the scene node animator.
  185. void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
  186. {
  187. out->addVector3d("Radius", Radius);
  188. out->addVector3d("Gravity", Gravity);
  189. out->addVector3d("Translation", Translation);
  190. out->addBool("AnimateCameraTarget", AnimateCameraTarget);
  191. }
  192. //! Reads attributes of the scene node animator.
  193. void CSceneNodeAnimatorCollisionResponse::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
  194. {
  195. Radius = in->getAttributeAsVector3d("Radius");
  196. Gravity = in->getAttributeAsVector3d("Gravity");
  197. Translation = in->getAttributeAsVector3d("Translation");
  198. AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget");
  199. }
  200. ISceneNodeAnimator* CSceneNodeAnimatorCollisionResponse::createClone(ISceneNode* node, ISceneManager* newManager)
  201. {
  202. if (!newManager) newManager = SceneManager;
  203. CSceneNodeAnimatorCollisionResponse * newAnimator =
  204. new CSceneNodeAnimatorCollisionResponse(newManager, World, Object, Radius,
  205. (Gravity * 1000.0f), Translation, SlidingSpeed);
  206. return newAnimator;
  207. }
  208. void CSceneNodeAnimatorCollisionResponse::setCollisionCallback(ICollisionCallback* callback)
  209. {
  210. if ( CollisionCallback == callback )
  211. return;
  212. if (CollisionCallback)
  213. CollisionCallback->drop();
  214. CollisionCallback = callback;
  215. if (CollisionCallback)
  216. CollisionCallback->grab();
  217. }
  218. //! Should the Target react on collision ( default = true )
  219. void CSceneNodeAnimatorCollisionResponse::setAnimateTarget ( bool enable )
  220. {
  221. AnimateCameraTarget = enable;
  222. FirstUpdate = true;
  223. }
  224. //! Should the Target react on collision ( default = true )
  225. bool CSceneNodeAnimatorCollisionResponse::getAnimateTarget () const
  226. {
  227. return AnimateCameraTarget;
  228. }
  229. } // end namespace scene
  230. } // end namespace irr