1 /*
2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty.  In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
17 */
18 
19 #ifndef B2_SHAPE_H
20 #define B2_SHAPE_H
21 
22 #include "../../Common/b2Math.h"
23 #include "../b2Collision.h"
24 
25 class b2BlockAllocator;
26 class b2Body;
27 class b2BroadPhase;
28 
29 /// This holds the mass data computed for a shape.
30 struct b2MassData
31 {
32 	/// The mass of the shape, usually in kilograms.
33 	float32 mass;
34 
35 	/// The position of the shape's centroid relative to the shape's origin.
36 	b2Vec2 center;
37 
38 	/// The rotational inertia of the shape.
39 	float32 I;
40 };
41 
42 /// This holds contact filtering data.
43 struct b2FilterData
44 {
45 	/// The collision category bits. Normally you would just set one bit.
46 	uint16 categoryBits;
47 
48 	/// The collision mask bits. This states the categories that this
49 	/// shape would accept for collision.
50 	uint16 maskBits;
51 
52 	/// Collision groups allow a certain group of objects to never collide (negative)
53 	/// or always collide (positive). Zero means no collision group. Non-zero group
54 	/// filtering always wins against the mask bits.
55 	int16 groupIndex;
56 };
57 
58 /// The various collision shape types supported by Box2D.
59 enum b2ShapeType
60 {
61 	e_unknownShape = -1,
62 	e_circleShape,
63 	e_polygonShape,
64 	e_shapeTypeCount,
65 };
66 
67 /// A shape definition is used to construct a shape. This class defines an
68 /// abstract shape definition. You can reuse shape definitions safely.
69 struct b2ShapeDef
70 {
71 	/// The constructor sets the default shape definition values.
b2ShapeDefb2ShapeDef72 	b2ShapeDef()
73 	{
74 		type = e_unknownShape;
75 		userData = NULL;
76 		friction = 0.2f;
77 		restitution = 0.0f;
78 		density = 0.0f;
79 		filter.categoryBits = 0x0001;
80 		filter.maskBits = 0xFFFF;
81 		filter.groupIndex = 0;
82 		isSensor = false;
83 	}
84 
~b2ShapeDefb2ShapeDef85 	virtual ~b2ShapeDef() {}
86 
87 	/// Holds the shape type for down-casting.
88 	b2ShapeType type;
89 
90 	/// Use this to store application specify shape data.
91 	void* userData;
92 
93 	/// The shape's friction coefficient, usually in the range [0,1].
94 	float32 friction;
95 
96 	/// The shape's restitution (elasticity) usually in the range [0,1].
97 	float32 restitution;
98 
99 	/// The shape's density, usually in kg/m^2.
100 	float32 density;
101 
102 	/// A sensor shape collects contact information but never generates a collision
103 	/// response.
104 	bool isSensor;
105 
106 	/// Contact filtering data.
107 	b2FilterData filter;
108 };
109 
110 /// A shape is used for collision detection. Shapes are created in b2World.
111 /// You can use shape for collision detection before they are attached to the world.
112 /// @warning you cannot reuse shapes.
113 class b2Shape
114 {
115 public:
116 	/// Get the type of this shape. You can use this to down cast to the concrete shape.
117 	/// @return the shape type.
118 	b2ShapeType GetType() const;
119 
120 	/// Is this shape a sensor (non-solid)?
121 	/// @return the true if the shape is a sensor.
122 	bool IsSensor() const;
123 
124 	/// Set the contact filtering data. You must call b2World::Refilter to correct
125 	/// existing contacts/non-contacts.
126 	void SetFilterData(const b2FilterData& filter);
127 
128 	/// Get the contact filtering data.
129 	const b2FilterData& GetFilterData() const;
130 
131 	/// Get the parent body of this shape. This is NULL if the shape is not attached.
132 	/// @return the parent body.
133 	b2Body* GetBody();
134 
135 	/// Get the next shape in the parent body's shape list.
136 	/// @return the next shape.
137 	b2Shape* GetNext();
138 
139 	/// Get the user data that was assigned in the shape definition. Use this to
140 	/// store your application specific data.
141 	void* GetUserData();
142 
143 	/// Set the user data. Use this to store your application specific data.
144 	void SetUserData(void* data);
145 
146 	/// Test a point for containment in this shape. This only works for convex shapes.
147 	/// @param xf the shape world transform.
148 	/// @param p a point in world coordinates.
149 	virtual bool TestPoint(const b2XForm& xf, const b2Vec2& p) const = 0;
150 
151 	/// Perform a ray cast against this shape.
152 	/// @param xf the shape world transform.
153 	/// @param lambda returns the hit fraction. You can use this to compute the contact point
154 	/// p = (1 - lambda) * segment.p1 + lambda * segment.p2.
155 	/// @param normal returns the normal at the contact point. If there is no intersection, the normal
156 	/// is not set.
157 	/// @param segment defines the begin and end point of the ray cast.
158 	/// @param maxLambda a number typically in the range [0,1].
159 	/// @return true if there was an intersection.
160 	virtual bool TestSegment(	const b2XForm& xf,
161 								float32* lambda,
162 								b2Vec2* normal,
163 								const b2Segment& segment,
164 								float32 maxLambda) const = 0;
165 
166 	/// Given a transform, compute the associated axis aligned bounding box for this shape.
167 	/// @param aabb returns the axis aligned box.
168 	/// @param xf the world transform of the shape.
169 	virtual void ComputeAABB(b2AABB* aabb, const b2XForm& xf) const = 0;
170 
171 	/// Given two transforms, compute the associated swept axis aligned bounding box for this shape.
172 	/// @param aabb returns the axis aligned box.
173 	/// @param xf1 the starting shape world transform.
174 	/// @param xf2 the ending shape world transform.
175 	virtual void ComputeSweptAABB(	b2AABB* aabb,
176 									const b2XForm& xf1,
177 									const b2XForm& xf2) const = 0;
178 
179 	/// Compute the mass properties of this shape using its dimensions and density.
180 	/// The inertia tensor is computed about the local origin, not the centroid.
181 	/// @param massData returns the mass data for this shape.
182 	virtual void ComputeMass(b2MassData* massData) const = 0;
183 
184 	/// Get the maximum radius about the parent body's center of mass.
185 	float32 GetSweepRadius() const;
186 
187 	/// Get the coefficient of friction.
188 	float32 GetFriction() const;
189 
190 	/// Get the coefficient of restitution.
191 	float32 GetRestitution() const;
192 
193 	float32 m_density;
194 	float32 m_friction;
195 	float32 m_restitution;
196 	bool m_isSensor;
197 
198 protected:
199 
200 	friend class b2Body;
201 	friend class b2World;
202 
203 	static b2Shape* Create(const b2ShapeDef* def, b2BlockAllocator* allocator);
204 	static void Destroy(b2Shape* shape, b2BlockAllocator* allocator);
205 
206 	b2Shape(const b2ShapeDef* def);
207 	virtual ~b2Shape();
208 
209 	void CreateProxy(b2BroadPhase* broadPhase, const b2XForm& xf);
210 	void DestroyProxy(b2BroadPhase* broadPhase);
211 	bool Synchronize(b2BroadPhase* broadPhase, const b2XForm& xf1, const b2XForm& xf2);
212 	void RefilterProxy(b2BroadPhase* broadPhase, const b2XForm& xf);
213 
214 	virtual void UpdateSweepRadius(const b2Vec2& center) = 0;
215 
216 	b2ShapeType m_type;
217 	b2Shape* m_next;
218 	b2Body* m_body;
219 
220 	// Sweep radius relative to the parent body's center of mass.
221 	float32 m_sweepRadius;
222 
223 	uint16 m_proxyId;
224 	b2FilterData m_filter;
225 
226 
227 
228 	void* m_userData;
229 };
230 
GetType()231 inline b2ShapeType b2Shape::GetType() const
232 {
233 	return m_type;
234 }
235 
IsSensor()236 inline bool b2Shape::IsSensor() const
237 {
238 	return m_isSensor;
239 }
240 
SetFilterData(const b2FilterData & filter)241 inline void b2Shape::SetFilterData(const b2FilterData& filter)
242 {
243 	m_filter = filter;
244 }
245 
GetFilterData()246 inline const b2FilterData& b2Shape::GetFilterData() const
247 {
248 	return m_filter;
249 }
250 
GetUserData()251 inline void* b2Shape::GetUserData()
252 {
253 	return m_userData;
254 }
255 
SetUserData(void * data)256 inline void b2Shape::SetUserData(void* data)
257 {
258 	m_userData = data;
259 }
260 
GetBody()261 inline b2Body* b2Shape::GetBody()
262 {
263 	return m_body;
264 }
265 
GetNext()266 inline b2Shape* b2Shape::GetNext()
267 {
268 	return m_next;
269 }
270 
GetSweepRadius()271 inline float32 b2Shape::GetSweepRadius() const
272 {
273 	return m_sweepRadius;
274 }
275 
GetFriction()276 inline float32 b2Shape::GetFriction() const
277 {
278 	return m_friction;
279 }
280 
GetRestitution()281 inline float32 b2Shape::GetRestitution() const
282 {
283 	return m_restitution;
284 }
285 
286 #endif
287