1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #ifndef B2_FIXTURE_H
24 #define B2_FIXTURE_H
25 
26 #include "b2_api.h"
27 #include "b2_body.h"
28 #include "b2_collision.h"
29 #include "b2_shape.h"
30 
31 class b2BlockAllocator;
32 class b2Body;
33 class b2BroadPhase;
34 class b2Fixture;
35 
36 /// This holds contact filtering data.
37 struct B2_API b2Filter
38 {
b2Filterb2Filter39 	b2Filter()
40 	{
41 		categoryBits = 0x0001;
42 		maskBits = 0xFFFF;
43 		groupIndex = 0;
44 	}
45 
46 	/// The collision category bits. Normally you would just set one bit.
47 	uint16 categoryBits;
48 
49 	/// The collision mask bits. This states the categories that this
50 	/// shape would accept for collision.
51 	uint16 maskBits;
52 
53 	/// Collision groups allow a certain group of objects to never collide (negative)
54 	/// or always collide (positive). Zero means no collision group. Non-zero group
55 	/// filtering always wins against the mask bits.
56 	int16 groupIndex;
57 };
58 
59 /// A fixture definition is used to create a fixture. This class defines an
60 /// abstract fixture definition. You can reuse fixture definitions safely.
61 struct B2_API b2FixtureDef
62 {
63 	/// The constructor sets the default fixture definition values.
b2FixtureDefb2FixtureDef64 	b2FixtureDef()
65 	{
66 		shape = nullptr;
67 		friction = 0.2f;
68 		restitution = 0.0f;
69 		restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter;
70 		density = 0.0f;
71 		isSensor = false;
72 	}
73 
74 	/// The shape, this must be set. The shape will be cloned, so you
75 	/// can create the shape on the stack.
76 	const b2Shape* shape;
77 
78 	/// Use this to store application specific fixture data.
79 	b2FixtureUserData userData;
80 
81 	/// The friction coefficient, usually in the range [0,1].
82 	float friction;
83 
84 	/// The restitution (elasticity) usually in the range [0,1].
85 	float restitution;
86 
87 	/// Restitution velocity threshold, usually in m/s. Collisions above this
88 	/// speed have restitution applied (will bounce).
89 	float restitutionThreshold;
90 
91 	/// The density, usually in kg/m^2.
92 	float density;
93 
94 	/// A sensor shape collects contact information but never generates a collision
95 	/// response.
96 	bool isSensor;
97 
98 	/// Contact filtering data.
99 	b2Filter filter;
100 };
101 
102 /// This proxy is used internally to connect fixtures to the broad-phase.
103 struct B2_API b2FixtureProxy
104 {
105 	b2AABB aabb;
106 	b2Fixture* fixture;
107 	int32 childIndex;
108 	int32 proxyId;
109 };
110 
111 /// A fixture is used to attach a shape to a body for collision detection. A fixture
112 /// inherits its transform from its parent. Fixtures hold additional non-geometric data
113 /// such as friction, collision filters, etc.
114 /// Fixtures are created via b2Body::CreateFixture.
115 /// @warning you cannot reuse fixtures.
116 class B2_API b2Fixture
117 {
118 public:
119 	/// Get the type of the child shape. You can use this to down cast to the concrete shape.
120 	/// @return the shape type.
121 	b2Shape::Type GetType() const;
122 
123 	/// Get the child shape. You can modify the child shape, however you should not change the
124 	/// number of vertices because this will crash some collision caching mechanisms.
125 	/// Manipulating the shape may lead to non-physical behavior.
126 	b2Shape* GetShape();
127 	const b2Shape* GetShape() const;
128 
129 	/// Set if this fixture is a sensor.
130 	void SetSensor(bool sensor);
131 
132 	/// Is this fixture a sensor (non-solid)?
133 	/// @return the true if the shape is a sensor.
134 	bool IsSensor() const;
135 
136 	/// Set the contact filtering data. This will not update contacts until the next time
137 	/// step when either parent body is active and awake.
138 	/// This automatically calls Refilter.
139 	void SetFilterData(const b2Filter& filter);
140 
141 	/// Get the contact filtering data.
142 	const b2Filter& GetFilterData() const;
143 
144 	/// Call this if you want to establish collision that was previously disabled by b2ContactFilter::ShouldCollide.
145 	void Refilter();
146 
147 	/// Get the parent body of this fixture. This is nullptr if the fixture is not attached.
148 	/// @return the parent body.
149 	b2Body* GetBody();
150 	const b2Body* GetBody() const;
151 
152 	/// Get the next fixture in the parent body's fixture list.
153 	/// @return the next shape.
154 	b2Fixture* GetNext();
155 	const b2Fixture* GetNext() const;
156 
157 	/// Get the user data that was assigned in the fixture definition. Use this to
158 	/// store your application specific data.
159 	b2FixtureUserData& GetUserData();
160 
161 	/// Test a point for containment in this fixture.
162 	/// @param p a point in world coordinates.
163 	bool TestPoint(const b2Vec2& p) const;
164 
165 	/// Cast a ray against this shape.
166 	/// @param output the ray-cast results.
167 	/// @param input the ray-cast input parameters.
168 	/// @param childIndex the child shape index (e.g. edge index)
169 	bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const;
170 
171 	/// Get the mass data for this fixture. The mass data is based on the density and
172 	/// the shape. The rotational inertia is about the shape's origin. This operation
173 	/// may be expensive.
174 	void GetMassData(b2MassData* massData) const;
175 
176 	/// Set the density of this fixture. This will _not_ automatically adjust the mass
177 	/// of the body. You must call b2Body::ResetMassData to update the body's mass.
178 	void SetDensity(float density);
179 
180 	/// Get the density of this fixture.
181 	float GetDensity() const;
182 
183 	/// Get the coefficient of friction.
184 	float GetFriction() const;
185 
186 	/// Set the coefficient of friction. This will _not_ change the friction of
187 	/// existing contacts.
188 	void SetFriction(float friction);
189 
190 	/// Get the coefficient of restitution.
191 	float GetRestitution() const;
192 
193 	/// Set the coefficient of restitution. This will _not_ change the restitution of
194 	/// existing contacts.
195 	void SetRestitution(float restitution);
196 
197 	/// Get the restitution velocity threshold.
198 	float GetRestitutionThreshold() const;
199 
200 	/// Set the restitution threshold. This will _not_ change the restitution threshold of
201 	/// existing contacts.
202 	void SetRestitutionThreshold(float threshold);
203 
204 	/// Get the fixture's AABB. This AABB may be enlarge and/or stale.
205 	/// If you need a more accurate AABB, compute it using the shape and
206 	/// the body transform.
207 	const b2AABB& GetAABB(int32 childIndex) const;
208 
209 	/// Dump this fixture to the log file.
210 	void Dump(int32 bodyIndex);
211 
212 protected:
213 
214 	friend class b2Body;
215 	friend class b2World;
216 	friend class b2Contact;
217 	friend class b2ContactManager;
218 
219 	b2Fixture();
220 
221 	// We need separation create/destroy functions from the constructor/destructor because
222 	// the destructor cannot access the allocator (no destructor arguments allowed by C++).
223 	void Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def);
224 	void Destroy(b2BlockAllocator* allocator);
225 
226 	// These support body activation/deactivation.
227 	void CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf);
228 	void DestroyProxies(b2BroadPhase* broadPhase);
229 
230 	void Synchronize(b2BroadPhase* broadPhase, const b2Transform& xf1, const b2Transform& xf2);
231 
232 	float m_density;
233 
234 	b2Fixture* m_next;
235 	b2Body* m_body;
236 
237 	b2Shape* m_shape;
238 
239 	float m_friction;
240 	float m_restitution;
241 	float m_restitutionThreshold;
242 
243 	b2FixtureProxy* m_proxies;
244 	int32 m_proxyCount;
245 
246 	b2Filter m_filter;
247 
248 	bool m_isSensor;
249 
250 	b2FixtureUserData m_userData;
251 };
252 
GetType()253 inline b2Shape::Type b2Fixture::GetType() const
254 {
255 	return m_shape->GetType();
256 }
257 
GetShape()258 inline b2Shape* b2Fixture::GetShape()
259 {
260 	return m_shape;
261 }
262 
GetShape()263 inline const b2Shape* b2Fixture::GetShape() const
264 {
265 	return m_shape;
266 }
267 
IsSensor()268 inline bool b2Fixture::IsSensor() const
269 {
270 	return m_isSensor;
271 }
272 
GetFilterData()273 inline const b2Filter& b2Fixture::GetFilterData() const
274 {
275 	return m_filter;
276 }
277 
GetUserData()278 inline b2FixtureUserData& b2Fixture::GetUserData()
279 {
280 	return m_userData;
281 }
282 
GetBody()283 inline b2Body* b2Fixture::GetBody()
284 {
285 	return m_body;
286 }
287 
GetBody()288 inline const b2Body* b2Fixture::GetBody() const
289 {
290 	return m_body;
291 }
292 
GetNext()293 inline b2Fixture* b2Fixture::GetNext()
294 {
295 	return m_next;
296 }
297 
GetNext()298 inline const b2Fixture* b2Fixture::GetNext() const
299 {
300 	return m_next;
301 }
302 
SetDensity(float density)303 inline void b2Fixture::SetDensity(float density)
304 {
305 	b2Assert(b2IsValid(density) && density >= 0.0f);
306 	m_density = density;
307 }
308 
GetDensity()309 inline float b2Fixture::GetDensity() const
310 {
311 	return m_density;
312 }
313 
GetFriction()314 inline float b2Fixture::GetFriction() const
315 {
316 	return m_friction;
317 }
318 
SetFriction(float friction)319 inline void b2Fixture::SetFriction(float friction)
320 {
321 	m_friction = friction;
322 }
323 
GetRestitution()324 inline float b2Fixture::GetRestitution() const
325 {
326 	return m_restitution;
327 }
328 
SetRestitution(float restitution)329 inline void b2Fixture::SetRestitution(float restitution)
330 {
331 	m_restitution = restitution;
332 }
333 
GetRestitutionThreshold()334 inline float b2Fixture::GetRestitutionThreshold() const
335 {
336 	return m_restitutionThreshold;
337 }
338 
SetRestitutionThreshold(float threshold)339 inline void b2Fixture::SetRestitutionThreshold(float threshold)
340 {
341 	m_restitutionThreshold = threshold;
342 }
343 
TestPoint(const b2Vec2 & p)344 inline bool b2Fixture::TestPoint(const b2Vec2& p) const
345 {
346 	return m_shape->TestPoint(m_body->GetTransform(), p);
347 }
348 
RayCast(b2RayCastOutput * output,const b2RayCastInput & input,int32 childIndex)349 inline bool b2Fixture::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const
350 {
351 	return m_shape->RayCast(output, input, m_body->GetTransform(), childIndex);
352 }
353 
GetMassData(b2MassData * massData)354 inline void b2Fixture::GetMassData(b2MassData* massData) const
355 {
356 	m_shape->ComputeMass(massData, m_density);
357 }
358 
GetAABB(int32 childIndex)359 inline const b2AABB& b2Fixture::GetAABB(int32 childIndex) const
360 {
361 	b2Assert(0 <= childIndex && childIndex < m_proxyCount);
362 	return m_proxies[childIndex].aabb;
363 }
364 
365 #endif
366