// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ #define __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ #include "ISceneCollisionManager.h" #include "ISceneManager.h" #include "IVideoDriver.h" namespace irr { namespace scene { //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. class CSceneCollisionManager : public ISceneCollisionManager { public: //! constructor CSceneCollisionManager(ISceneManager* smanager, video::IVideoDriver* driver); //! destructor virtual ~CSceneCollisionManager(); //! Returns the scene node, which is currently visible at the given //! screen coordinates, viewed from the currently active camera. virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) _IRR_OVERRIDE_; //! Returns the nearest scene node which collides with a 3d ray and //! whose id matches a bitmask. virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) _IRR_OVERRIDE_; //! Returns the scene node, at which the given camera is looking at and //! which id matches the bitmask. virtual ISceneNode* getSceneNodeFromCameraBB(const ICameraSceneNode* camera, s32 idBitMask=0, bool bNoDebugObjects = false) _IRR_OVERRIDE_; //! Finds the nearest collision point of a line and lots of triangles, if there is one. virtual bool getCollisionPoint(SCollisionHit& hitResult, const core::line3d& ray, ITriangleSelector* selector) _IRR_OVERRIDE_; //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. virtual core::vector3df getCollisionResultPosition( ITriangleSelector* selector, const core::vector3df &ellipsoidPosition, const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode, f32 slidingSpeed, const core::vector3df& gravityDirectionAndSpeed) _IRR_OVERRIDE_; //! Returns a 3d ray which would go through the 2d screen coordinates. virtual core::line3d getRayFromScreenCoordinates( const core::position2d & pos, const ICameraSceneNode* camera = 0) _IRR_OVERRIDE_; //! Calculates 2d screen position from a 3d position. virtual core::position2d getScreenCoordinatesFrom3DPosition( const core::vector3df & pos, const ICameraSceneNode* camera=0, bool useViewPort=false) _IRR_OVERRIDE_; //! Gets the scene node and nearest collision point for a ray based on //! the nodes' id bitmasks, bounding boxes and triangle selectors. virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( SCollisionHit& hitResult, const core::line3df& ray, s32 idBitMask = 0, ISceneNode * collisionRootNode = 0, bool noDebugObjects = false) _IRR_OVERRIDE_; private: //! recursive method for going through all scene nodes void getPickedNodeBB(ISceneNode* root, core::line3df& ray, s32 bits, bool bNoDebugObjects, f32& outbestdistance, ISceneNode*& outbestnode); //! recursive method for going through all scene nodes void getPickedNodeFromBBAndSelector( SCollisionHit& hitResult, ISceneNode * root, core::line3df & ray, s32 bits, bool noDebugObjects, f32 & outBestDistanceSquared); struct SCollisionData { core::vector3df eRadius; core::vector3df R3Velocity; core::vector3df R3Position; core::vector3df velocity; core::vector3df normalizedVelocity; core::vector3df basePoint; bool foundCollision; f32 nearestDistance; core::vector3df intersectionPoint; core::triangle3df intersectionTriangle; irr::scene::ISceneNode* node; s32 triangleHits; f32 slidingSpeed; ITriangleSelector* selector; }; //! Tests the current collision data against an individual triangle. /** \param colData: the collision data. \param triangle: the triangle to test against. \return true if the triangle is hit (and is the closest hit), false otherwise */ bool testTriangleIntersection(SCollisionData* colData, const core::triangle3df& triangle); //! recursive method for doing collision response core::vector3df collideEllipsoidWithWorld(ITriangleSelector* selector, const core::vector3df &position, const core::vector3df& radius, const core::vector3df& velocity, f32 slidingSpeed, const core::vector3df& gravity, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode); core::vector3df collideWithWorld(s32 recursionDepth, SCollisionData &colData, const core::vector3df& pos, const core::vector3df& vel); inline bool getLowestRoot(f32 a, f32 b, f32 c, f32 maxR, f32* root) const; ISceneManager* SceneManager; video::IVideoDriver* Driver; core::array Triangles; // triangle buffer }; } // end namespace scene } // end namespace irr #endif