2020-01-03 20:05:16 +01:00
// 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
2021-08-27 21:20:42 +02:00
# ifndef IRR_I_SCENE_COLLISION_MANAGER_H_INCLUDED
# define IRR_I_SCENE_COLLISION_MANAGER_H_INCLUDED
2020-01-03 20:05:16 +01:00
# include "IReferenceCounted.h"
# include "vector3d.h"
# include "triangle3d.h"
# include "position2d.h"
# include "line3d.h"
namespace irr
{
namespace scene
{
class ISceneNode ;
class ICameraSceneNode ;
class ITriangleSelector ;
class IMeshBuffer ;
struct SCollisionHit
{
//! Point of collision
core : : vector3df Intersection ;
//! Triangle with which we collided
core : : triangle3df Triangle ;
//! Triangle selector which contained the colliding triangle (useful when having MetaTriangleSelector)
ITriangleSelector * TriangleSelector ;
//! Node which contained the triangle (is 0 when selector doesn't have that information)
ISceneNode * Node ;
//! Meshbuffer which contained the triangle (is 0 when the selector doesn't have that information, only works when selectors are created per meshbuffer)
const IMeshBuffer * MeshBuffer ;
//! Index of selected material of the triangle in the SceneNode. Usually only valid when MeshBuffer is also set, otherwise always 0
irr : : u32 MaterialIndex ;
SCollisionHit ( ) : TriangleSelector ( 0 ) , Node ( 0 ) , MeshBuffer ( 0 ) , MaterialIndex ( 0 )
{ }
} ;
//! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes.
class ISceneCollisionManager : public virtual IReferenceCounted
{
public :
//! Finds the nearest collision point of a line and lots of triangles, if there is one.
/** \param hitResult: Contains collision result when there was a collision detected.
\ param ray : Line with which collisions are tested .
\ param selector : TriangleSelector to be used for the collision check .
\ return true if a collision was detected and false if not . */
virtual bool getCollisionPoint ( SCollisionHit & hitResult , const core : : line3d < f32 > & ray ,
ITriangleSelector * selector ) = 0 ;
//! Finds the nearest collision point of a line and lots of triangles, if there is one.
/** \param ray: Line with which collisions are tested.
\ param selector : TriangleSelector containing the triangles . It
can be created for example using
ISceneManager : : createTriangleSelector ( ) or
ISceneManager : : createTriangleOctreeSelector ( ) .
\ param outCollisionPoint : If a collision is detected , this will
contain the position of the nearest collision to the line - start .
\ param outTriangle : If a collision is detected , this will
contain the triangle with which the ray collided .
\ param outNode : If a collision is detected , this will contain
the scene node associated with the triangle that was hit .
\ return True if a collision was detected and false if not . */
virtual bool getCollisionPoint ( const core : : line3d < f32 > & ray ,
ITriangleSelector * selector , core : : vector3df & outCollisionPoint ,
core : : triangle3df & outTriangle , ISceneNode * & outNode )
{
SCollisionHit hitResult ;
if ( getCollisionPoint ( hitResult , ray , selector ) )
{
outCollisionPoint = hitResult . Intersection ;
outTriangle = hitResult . Triangle ;
outNode = hitResult . Node ;
return true ;
}
return false ;
}
//! Collides a moving ellipsoid with a 3d world with gravity and returns the resulting new position of the ellipsoid.
/** This can be used for moving a character in a 3d world: The
character will slide at walls and is able to walk up stairs .
The method used how to calculate the collision result position
is based on the paper " Improved Collision detection and
Response " by Kasper Fauerby.
\ param selector : TriangleSelector containing the triangles of
the world . It can be created for example using
ISceneManager : : createTriangleSelector ( ) or
ISceneManager : : createTriangleOctreeSelector ( ) .
\ param ellipsoidPosition : Position of the ellipsoid .
\ param ellipsoidRadius : Radius of the ellipsoid .
\ param ellipsoidDirectionAndSpeed : Direction and speed of the
movement of the ellipsoid .
\ param triout : Optional parameter where the last triangle
causing a collision is stored , if there is a collision .
\ param hitPosition : Return value for the position of the collision
\ param outFalling : Is set to true if the ellipsoid is falling
down , caused by gravity .
\ param outNode : the node with which the ellipsoid collided ( if any )
\ param slidingSpeed : DOCUMENTATION NEEDED .
\ param gravityDirectionAndSpeed : Direction and force of gravity .
\ return 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 = 0.0005f ,
const core : : vector3df & gravityDirectionAndSpeed
= core : : vector3df ( 0.0f , 0.0f , 0.0f ) ) = 0 ;
//! Returns a 3d ray which would go through the 2d screen coordinates.
/** \param pos: Screen coordinates in pixels.
\ param camera : Camera from which the ray starts . If null , the
active camera is used .
\ return Ray starting from the position of the camera and ending
at a length of the far value of the camera at a position which
would be behind the 2 d screen coordinates . */
virtual core : : line3d < f32 > getRayFromScreenCoordinates (
const core : : position2d < s32 > & pos , const ICameraSceneNode * camera = 0 ) = 0 ;
//! Calculates 2d screen position from a 3d position.
/** \param pos: 3D position in world space to be transformed
into 2 d .
\ param camera : Camera to be used . If null , the currently active
camera is used .
\ param useViewPort : Calculate screen coordinates relative to
the current view port . Please note that unless the driver does
not take care of the view port , it is usually best to get the
result in absolute screen coordinates ( flag = false ) .
\ return 2 d screen coordinates which a object in the 3 d world
would have if it would be rendered to the screen . If the 3 d
position is behind the camera , it is set to ( - 1000 , - 1000 ) . In
most cases you can ignore this fact , because if you use this
method for drawing a decorator over a 3 d object , it will be
clipped by the screen borders . */
virtual core : : position2d < s32 > getScreenCoordinatesFrom3DPosition (
const core : : vector3df & pos , const ICameraSceneNode * camera = 0 , bool useViewPort = false ) = 0 ;
//! Gets the scene node, which is currently visible under the given screen coordinates, viewed from the currently active camera.
/** The collision tests are done using a bounding box for each
scene node . You can limit the recursive search so just all children of the specified root are tested .
\ param pos : Position in pixel screen coordinates , under which
the returned scene node will be .
\ param idBitMask : Only scene nodes with an id with bits set
like in this mask will be tested . If the BitMask is 0 , this
feature is disabled .
Please note that the default node id of - 1 will match with
every bitmask ! = 0
\ param bNoDebugObjects : Doesn ' t take debug objects into account
when true . These are scene nodes with IsDebugObject ( ) = true .
\ param root If different from 0 , the search is limited to the children of this node .
\ return Visible scene node under screen coordinates with
matching bits in its id . If there is no scene node under this
position , 0 is returned . */
virtual ISceneNode * getSceneNodeFromScreenCoordinatesBB ( const core : : position2d < s32 > & pos ,
s32 idBitMask = 0 , bool bNoDebugObjects = false , ISceneNode * root = 0 ) = 0 ;
//! Returns the nearest scene node which collides with a 3d ray and whose id matches a bitmask.
/** The collision tests are done using a bounding box for each
scene node . The recursive search can be limited be specifying a scene node .
\ param ray Line with which collisions are tested .
\ param idBitMask Only scene nodes with an id which matches at
least one of the bits contained in this mask will be tested .
However , if this parameter is 0 , then all nodes are checked .
\ param bNoDebugObjects : Doesn ' t take debug objects into account when true . These
are scene nodes with IsDebugObject ( ) = true .
\ param root If different from 0 , the search is limited to the children of this node .
\ return Scene node nearest to ray . start , which collides with
the ray and matches the idBitMask , if the mask is not null . If
no scene node is found , 0 is returned . */
virtual ISceneNode * getSceneNodeFromRayBB ( const core : : line3d < f32 > & ray ,
s32 idBitMask = 0 , bool bNoDebugObjects = false , ISceneNode * root = 0 ) = 0 ;
//! Get the scene node, which the given camera is looking at and whose id matches the bitmask.
/** A ray is simply cast from the position of the camera to
the view target position , and all scene nodes are tested
against this ray . The collision tests are done using a bounding
box for each scene node .
\ param camera : Camera from which the ray is cast .
\ param idBitMask : Only scene nodes with an id which matches at least one of the
bits contained in this mask will be tested . However , if this parameter is 0 , then
all nodes are checked .
feature is disabled .
Please note that the default node id of - 1 will match with
every bitmask ! = 0
\ param bNoDebugObjects : Doesn ' t take debug objects into account
when true . These are scene nodes with IsDebugObject ( ) = true .
\ return Scene node nearest to the camera , which collides with
the ray and matches the idBitMask , if the mask is not null . If
no scene node is found , 0 is returned . */
virtual ISceneNode * getSceneNodeFromCameraBB ( const ICameraSceneNode * camera ,
s32 idBitMask = 0 , bool bNoDebugObjects = false ) = 0 ;
//! Perform a ray/box and ray/triangle collision check on a hierarchy of scene nodes.
/** This checks all scene nodes under the specified one, first by ray/bounding
box , and then by accurate ray / triangle collision , finding the nearest collision ,
and the scene node containing it . It returns the node hit , and ( via output
parameters ) the position of the collision , and the triangle that was hit .
All scene nodes in the hierarchy tree under the specified node are checked . Only
nodes that are visible , with an ID that matches at least one bit in the supplied
bitmask , and which have a triangle selector are considered as candidates for being hit .
You do not have to build a meta triangle selector ; the individual triangle selectors
of each candidate scene node are used automatically .
\ param ray : Line with which collisions are tested .
\ param outCollisionPoint : If a collision is detected , this will contain the
position of the nearest collision .
\ param outTriangle : If a collision is detected , this will contain the triangle
with which the ray collided .
\ param idBitMask : Only scene nodes with an id which matches at least one of the
bits contained in this mask will be tested . However , if this parameter is 0 , then
all nodes are checked .
\ param collisionRootNode : the scene node at which to begin checking . Only this
node and its children will be checked . If you want to check the entire scene ,
pass 0 , and the root scene node will be used ( this is the default ) .
\ param noDebugObjects : when true , debug objects are not considered viable targets .
Debug objects are scene nodes with IsDebugObject ( ) = true .
\ return Returns the scene node containing the hit triangle nearest to ray . start .
If no collision is detected , then 0 is returned . */
virtual ISceneNode * getSceneNodeAndCollisionPointFromRay (
SCollisionHit & hitResult ,
const core : : line3df & ray ,
s32 idBitMask = 0 ,
ISceneNode * collisionRootNode = 0 ,
bool noDebugObjects = false ) = 0 ;
//! Perform a ray/box and ray/triangle collision check on a hierarchy of scene nodes.
/** Works same as other getSceneNodeAndCollisionPointFromRay but returns less information.
( was written before the other getSceneNodeAndCollisionPointFromRay implementation ) .
\ param ray : Line with which collisions are tested .
\ param outCollisionPoint : If a collision is detected , this will contain the
position of the nearest collision .
\ param outTriangle : If a collision is detected , this will contain the triangle
with which the ray collided .
\ param idBitMask : Only scene nodes with an id which matches at least one of the
bits contained in this mask will be tested . However , if this parameter is 0 , then
all nodes are checked .
\ param collisionRootNode : the scene node at which to begin checking . Only this
node and its children will be checked . If you want to check the entire scene ,
pass 0 , and the root scene node will be used ( this is the default ) .
\ param noDebugObjects : when true , debug objects are not considered viable targets .
Debug objects are scene nodes with IsDebugObject ( ) = true .
\ return Returns the scene node containing the hit triangle nearest to ray . start .
If no collision is detected , then 0 is returned . */
virtual ISceneNode * getSceneNodeAndCollisionPointFromRay (
const core : : line3df & ray ,
core : : vector3df & outCollisionPoint ,
core : : triangle3df & outTriangle ,
s32 idBitMask = 0 ,
ISceneNode * collisionRootNode = 0 ,
bool noDebugObjects = false )
{
SCollisionHit hitResult ;
ISceneNode * node = getSceneNodeAndCollisionPointFromRay ( hitResult , ray , idBitMask , collisionRootNode , noDebugObjects ) ;
if ( node )
{
outCollisionPoint = hitResult . Intersection ;
outTriangle = hitResult . Triangle ;
}
return node ;
}
} ;
} // end namespace scene
} // end namespace irr
# endif