aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CSceneCollisionManager.h
blob: c581a475afc5531fc146754a1e8698f47b60c635 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 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<s32>& pos,
				s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0);

		//! Returns the nearest scene node which collides with a 3d ray and
		//! whose id matches a bitmask.
		virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d<f32>& ray,
						s32 idBitMask=0, bool bNoDebugObjects=false,
						ISceneNode* root=0);

		//! Returns the scene node, at which the overgiven camera is looking at and
		//! which id matches the bitmask.
		virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera,
				s32 idBitMask=0, bool bNoDebugObjects = false);

		//! Finds the collision point of a line and lots of triangles, if there is one.
		virtual bool getCollisionPoint(const core::line3d<f32>& ray,
			ITriangleSelector* selector, core::vector3df& outCollisionPoint,
			core::triangle3df& outTriangle,
			ISceneNode* & outNode);

		//! 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);

		//! Returns a 3d ray which would go through the 2d screen coodinates.
		virtual core::line3d<f32> getRayFromScreenCoordinates(
			const core::position2d<s32> & pos, ICameraSceneNode* camera = 0);

		//! Calculates 2d screen position from a 3d position.
		virtual core::position2d<s32> getScreenCoordinatesFrom3DPosition(
			const core::vector3df & pos, ICameraSceneNode* camera=0, bool useViewPort=false);

		//! 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(
								core::line3df ray,
								core::vector3df & outCollisionPoint,
								core::triangle3df & outTriangle,
								s32 idBitMask = 0,
								ISceneNode * collisionRootNode = 0,
								bool noDebugObjects = false);


	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(ISceneNode * root,
						core::line3df & ray,
						s32 bits,
						bool noDebugObjects,
						f32 & outBestDistanceSquared,
						ISceneNode * & outBestNode,
						core::vector3df & outBestCollisionPoint,
						core::triangle3df & outBestTriangle);


		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;
			s32 triangleIndex;
			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,
			core::vector3df pos, core::vector3df vel);

		inline bool getLowestRoot(f32 a, f32 b, f32 c, f32 maxR, f32* root);

		ISceneManager* SceneManager;
		video::IVideoDriver* Driver;
		core::array<core::triangle3df> Triangles; // triangle buffer
	};


} // end namespace scene
} // end namespace irr

#endif