View difference between Paste ID: WTihivb1 and RqNmfEVq
SHOW: | | - or go back to the newest paste.
1
/*
2-
* Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
2+
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
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-
#include <Box2D/Dynamics/b2World.h>
19+
#ifndef B2_BROAD_PHASE_H
20-
#include <Box2D/Dynamics/b2Body.h>
20+
#define B2_BROAD_PHASE_H
21-
#include <Box2D/Dynamics/b2Fixture.h>
21+
22-
#include <Box2D/Dynamics/b2Island.h>
22+
#include <Box2D/Common/b2Settings.h>
23-
#include <Box2D/Dynamics/Joints/b2PulleyJoint.h>
23+
24-
#include <Box2D/Dynamics/Contacts/b2Contact.h>
24+
#include <Box2D/Collision/b2DynamicTree.h>
25-
#include <Box2D/Dynamics/Contacts/b2ContactSolver.h>
25+
//#include <algorithm>
26
#include <stdlib.h>
27-
#include <Box2D/Collision/b2BroadPhase.h>
27+
28-
#include <Box2D/Collision/Shapes/b2CircleShape.h>
28+
29-
#include <Box2D/Collision/Shapes/b2EdgeShape.h>
29+
30-
#include <Box2D/Collision/Shapes/b2ChainShape.h>
30+
31-
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
31+
struct b2Pair
32-
#include <Box2D/Collision/b2TimeOfImpact.h>
32+
33-
#include <Box2D/Common/b2Draw.h>
33+
	int32 proxyIdA;
34-
#include <Box2D/Common/b2Timer.h>
34+
	int32 proxyIdB;
35-
#include <new>
35+
36
37
/// The broad-phase is used for computing pairs and performing volume queries and ray casts.
38
/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs.
39
/// It is up to the client to consume the new pairs and to track subsequent overlap.
40-
b2World::b2World(const b2Vec2& gravity)
40+
class b2BroadPhase
41
{
42-
	m_destructionListener = NULL;
42+
public:
43-
	g_debugDraw = NULL;
43+
44
	enum
45-
	m_bodyList = NULL;
45+
46-
	m_jointList = NULL;
46+
		e_nullProxy = -1
47
	};
48-
	m_bodyCount = 0;
48+
49-
	m_jointCount = 0;
49+
	b2BroadPhase();
50
	~b2BroadPhase();
51-
	m_warmStarting = true;
51+
52-
	m_continuousPhysics = true;
52+
	/// Create a proxy with an initial AABB. Pairs are not reported until
53-
	m_subStepping = false;
53+
	/// UpdatePairs is called.
54
	int32 CreateProxy(const b2AABB& aabb, void* userData);
55-
	m_stepComplete = true;
55+
56
	/// Destroy a proxy. It is up to the client to remove any pairs.
57-
	m_allowSleep = true;
57+
	void DestroyProxy(int32 proxyId);
58-
	m_gravity = gravity;
58+
59
	/// Call MoveProxy as many times as you like, then when you are done
60-
	m_flags = e_clearForces;
60+
	/// call UpdatePairs to finalized the proxy pairs (for your time step).
61
	void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement);
62-
	m_inv_dt0 = 0.0f;
62+
63
	/// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs.
64-
	m_contactManager.m_allocator = &m_blockAllocator;
64+
	void TouchProxy(int32 proxyId);
65
66-
	memset(&m_profile, 0, sizeof(b2Profile));
66+
	/// Get the fat AABB for a proxy.
67
	const b2AABB& GetFatAABB(int32 proxyId) const;
68
69-
b2World::~b2World()
69+
	/// Get user data from a proxy. Returns NULL if the id is invalid.
70
	void* GetUserData(int32 proxyId) const;
71-
	// Some shapes allocate using b2Alloc.
71+
72-
	b2Body* b = m_bodyList;
72+
	/// Test overlap of fat AABBs.
73-
	while (b)
73+
	bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const;
74
75-
		b2Body* bNext = b->m_next;
75+
	/// Get the number of proxies.
76
	int32 GetProxyCount() const;
77-
		b2Fixture* f = b->m_fixtureList;
77+
78-
		while (f)
78+
	/// Update the pairs. This results in pair callbacks. This can only add pairs.
79
	template <typename T>
80-
			b2Fixture* fNext = f->m_next;
80+
	void UpdatePairs(T* callback);
81-
			f->m_proxyCount = 0;
81+
82-
			f->Destroy(&m_blockAllocator);
82+
	/// Query an AABB for overlapping proxies. The callback class
83-
			f = fNext;
83+
	/// is called for each proxy that overlaps the supplied AABB.
84
	template <typename T>
85
	void Query(T* callback, const b2AABB& aabb) const;
86-
		b = bNext;
86+
87
	/// Ray-cast against the proxies in the tree. This relies on the callback
88
	/// to perform a exact ray-cast in the case were the proxy contains a shape.
89
	/// The callback also performs the any collision filtering. This has performance
90-
void b2World::SetDestructionListener(b2DestructionListener* listener)
90+
	/// roughly equal to k * log(n), where k is the number of collisions and n is the
91
	/// number of proxies in the tree.
92-
	m_destructionListener = listener;
92+
	/// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
93
	/// @param callback a callback class that is called for each proxy that is hit by the ray.
94
	template <typename T>
95-
void b2World::SetContactFilter(b2ContactFilter* filter)
95+
	void RayCast(T* callback, const b2RayCastInput& input) const;
96
97-
	m_contactManager.m_contactFilter = filter;
97+
	/// Get the height of the embedded tree.
98
	int32 GetTreeHeight() const;
99
100-
void b2World::SetContactListener(b2ContactListener* listener)
100+
	/// Get the balance of the embedded tree.
101
	int32 GetTreeBalance() const;
102-
	m_contactManager.m_contactListener = listener;
102+
103
	/// Get the quality metric of the embedded tree.
104
	float32 GetTreeQuality() const;
105-
void b2World::SetDebugDraw(b2Draw* debugDraw)
105+
106
	/// Shift the world origin. Useful for large worlds.
107-
	g_debugDraw = debugDraw;
107+
	/// The shift formula is: position -= newOrigin
108
	/// @param newOrigin the new origin with respect to the old origin
109
	void ShiftOrigin(const b2Vec2& newOrigin);
110-
b2Body* b2World::CreateBody(const b2BodyDef* def)
110+
111
private:
112-
	b2Assert(IsLocked() == false);
112+
113-
	if (IsLocked())
113+
	friend class b2DynamicTree;
114
115-
		return NULL;
115+
	void BufferMove(int32 proxyId);
116
	void UnBufferMove(int32 proxyId);
117
118-
	void* mem = m_blockAllocator.Allocate(sizeof(b2Body));
118+
	bool QueryCallback(int32 proxyId);
119-
	b2Body* b = new (mem) b2Body(def, this);
119+
120
	b2DynamicTree m_tree;
121-
	// Add to world doubly linked list.
121+
122-
	b->m_prev = NULL;
122+
	int32 m_proxyCount;
123-
	b->m_next = m_bodyList;
123+
124-
	if (m_bodyList)
124+
	int32* m_moveBuffer;
125
	int32 m_moveCapacity;
126-
		m_bodyList->m_prev = b;
126+
	int32 m_moveCount;
127
128-
	m_bodyList = b;
128+
	b2Pair* m_pairBuffer;
129-
	++m_bodyCount;
129+
	int32 m_pairCapacity;
130
	int32 m_pairCount;
131-
	return b;
131+
132
	int32 m_queryProxyId;
133
};
134-
void b2World::DestroyBody(b2Body* b)
134+
135
//The return value of this function should represent whether elem1 is considered less than,
136-
	b2Assert(m_bodyCount > 0);
136+
//equal to, or greater than elem2 by returning, respectively, a negative value, zero or a positive value.
137-
	b2Assert(IsLocked() == false);
137+
inline int b2PairCompareQSort(const void * elem1, const void * elem2)
138-
	if (IsLocked())
138+
139
   b2Pair* pair1 = (b2Pair*) elem1;
140-
		return;
140+
   b2Pair* pair2 = (b2Pair*) elem2;
141
142
   if (pair1->proxyIdA < pair2->proxyIdA)
143-
	// Delete the attached joints.
143+
   {
144-
	b2JointEdge* je = b->m_jointList;
144+
      return -1;
145-
	while (je)
145+
   }
146
147-
		b2JointEdge* je0 = je;
147+
   if (pair1->proxyIdA == pair2->proxyIdA)
148-
		je = je->next;
148+
   {
149
      if( pair1->proxyIdB < pair2->proxyIdB ) {
150-
		if (m_destructionListener)
150+
         return -1;
151
      }
152-
			m_destructionListener->SayGoodbye(je0->joint);
152+
      else if(pair1->proxyIdB > pair2->proxyIdB) {
153
         return 1;
154
      }
155-
		DestroyJoint(je0->joint);
155+
      else {
156
         return 0;
157-
		b->m_jointList = je;
157+
      }
158
   }
159-
	b->m_jointList = NULL;
159+
   else {
160
      return 1;
161-
	// Delete the attached contacts.
161+
   }
162-
	b2ContactEdge* ce = b->m_contactList;
162+
163-
	while (ce)
163+
164
165-
		b2ContactEdge* ce0 = ce;
165+
/// This is used to sort pairs.
166-
		ce = ce->next;
166+
inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2)
167-
		m_contactManager.Destroy(ce0->contact);
167+
168
	if (pair1.proxyIdA < pair2.proxyIdA)
169-
	b->m_contactList = NULL;
169+
170
		return true;
171-
	// Delete the attached fixtures. This destroys broad-phase proxies.
171+
172-
	b2Fixture* f = b->m_fixtureList;
172+
173-
	while (f)
173+
	if (pair1.proxyIdA == pair2.proxyIdA)
174
	{
175-
		b2Fixture* f0 = f;
175+
		return pair1.proxyIdB < pair2.proxyIdB;
176-
		f = f->m_next;
176+
177
178-
		if (m_destructionListener)
178+
	return false;
179
}
180-
			m_destructionListener->SayGoodbye(f0);
180+
181
inline void* b2BroadPhase::GetUserData(int32 proxyId) const
182
{
183-
		f0->DestroyProxies(&m_contactManager.m_broadPhase);
183+
	return m_tree.GetUserData(proxyId);
184-
		f0->Destroy(&m_blockAllocator);
184+
185-
		f0->~b2Fixture();
185+
186-
		m_blockAllocator.Free(f0, sizeof(b2Fixture));
186+
inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const
187
{
188-
		b->m_fixtureList = f;
188+
	const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);
189-
		b->m_fixtureCount -= 1;
189+
	const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);
190
	return b2TestOverlap(aabbA, aabbB);
191-
	b->m_fixtureList = NULL;
191+
192-
	b->m_fixtureCount = 0;
192+
193
inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const
194-
	// Remove world body list.
194+
195-
	if (b->m_prev)
195+
	return m_tree.GetFatAABB(proxyId);
196
}
197-
		b->m_prev->m_next = b->m_next;
197+
198
inline int32 b2BroadPhase::GetProxyCount() const
199
{
200-
	if (b->m_next)
200+
	return m_proxyCount;
201
}
202-
		b->m_next->m_prev = b->m_prev;
202+
203
inline int32 b2BroadPhase::GetTreeHeight() const
204
{
205-
	if (b == m_bodyList)
205+
	return m_tree.GetHeight();
206
}
207-
		m_bodyList = b->m_next;
207+
208
inline int32 b2BroadPhase::GetTreeBalance() const
209
{
210-
	--m_bodyCount;
210+
	return m_tree.GetMaxBalance();
211-
	b->~b2Body();
211+
212-
	m_blockAllocator.Free(b, sizeof(b2Body));
212+
213
inline float32 b2BroadPhase::GetTreeQuality() const
214
{
215-
b2Joint* b2World::CreateJoint(const b2JointDef* def)
215+
	return m_tree.GetAreaRatio();
216
}
217-
	b2Assert(IsLocked() == false);
217+
218-
	if (IsLocked())
218+
template <typename T>
219
void b2BroadPhase::UpdatePairs(T* callback)
220-
		return NULL;
220+
221
222
	printf("\n");
223-
	b2Joint* j = b2Joint::Create(def, &m_blockAllocator);
223+
	printf("{");
224
	printf("%d",m_moveCount);
225-
	// Connect to the world list.
225+
226-
	j->m_prev = NULL;
226+
227-
	j->m_next = m_jointList;
227+
228-
	if (m_jointList)
228+
	// Reset pair buffer
229
	m_pairCount = 0;
230-
		m_jointList->m_prev = j;
230+
231
	// Perform tree queries for all moving proxies.
232-
	m_jointList = j;
232+
	for (int32 i = 0; i < m_moveCount; ++i)
233-
	++m_jointCount;
233+
234
		m_queryProxyId = m_moveBuffer[i];
235-
	// Connect to the bodies' doubly linked lists.
235+
		if (m_queryProxyId == e_nullProxy)
236-
	j->m_edgeA.joint = j;
236+
237-
	j->m_edgeA.other = j->m_bodyB;
237+
238-
	j->m_edgeA.prev = NULL;
238+
239-
	j->m_edgeA.next = j->m_bodyA->m_jointList;
239+
240-
	if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA;
240+
		// We have to query the tree with the fat AABB so that
241-
	j->m_bodyA->m_jointList = &j->m_edgeA;
241+
		// we don't fail to create a pair that may touch later.
242
		const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);
243-
	j->m_edgeB.joint = j;
243+
244-
	j->m_edgeB.other = j->m_bodyA;
244+
		// Query tree, create pairs and add them pair buffer.
245-
	j->m_edgeB.prev = NULL;
245+
		m_tree.Query(this, fatAABB);
246-
	j->m_edgeB.next = j->m_bodyB->m_jointList;
246+
247-
	if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB;
247+
248-
	j->m_bodyB->m_jointList = &j->m_edgeB;
248+
	// Reset move buffer
249
	m_moveCount = 0;
250-
	b2Body* bodyA = def->bodyA;
250+
251-
	b2Body* bodyB = def->bodyB;
251+
	// Sort the pair buffer to expose duplicates.
252
	//std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan);
253-
	// If the joint prevents collisions, then flag any contacts for filtering.
253+
254-
	if (def->collideConnected == false)
254+
	// FIX from http://www.box2d.org/forum/viewtopic.php?f=7&t=4756&start=0 to get rid of stl dependency
255
	qsort(m_pairBuffer, sizeof(m_pairBuffer) / sizeof(struct b2Pair) , sizeof(struct b2Pair), b2PairCompareQSort);
256-
		b2ContactEdge* edge = bodyB->GetContactList();
256+
	// Send the pairs back to the client.
257-
		while (edge)
257+
258
	int32 i = 0;
259-
			if (edge->other == bodyA)
259+
260
	printf("|");
261-
				// Flag the contact for filtering at the next time step (where either
261+
	printf("%d",m_pairCount);
262-
				// body is awake).
262+
263-
				edge->contact->FlagForFiltering();
263+
264
265
	while (i < m_pairCount)
266-
			edge = edge->next;
266+
267
		b2Pair* primaryPair = m_pairBuffer + i;
268
		void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);
269
		void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);
270-
	// Note: creating a joint doesn't wake the bodies.
270+
271
		callback->AddPair(userDataA, userDataB);
272-
	return j;
272+
273
274
		// Skip any duplicate pairs.
275-
void b2World::DestroyJoint(b2Joint* j)
275+
		while (i < m_pairCount)
276
		{
277-
	b2Assert(IsLocked() == false);
277+
			b2Pair* pair = m_pairBuffer + i;
278-
	if (IsLocked())
278+
			if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB)
279
			{
280-
		return;
280+
				break;
281
			}
282
			++i;
283-
	bool collideConnected = j->m_collideConnected;
283+
284
	}
285-
	// Remove from the doubly linked list.
285+
286-
	if (j->m_prev)
286+
	printf("{*}");
287
	fflush(stdout);
288-
		j->m_prev->m_next = j->m_next;
288+
289
	// Try to keep the tree balanced.
290
	//m_tree.Rebalance(4);
291-
	if (j->m_next)
291+
292
293-
		j->m_next->m_prev = j->m_prev;
293+
template <typename T>
294
inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const
295
{
296-
	if (j == m_jointList)
296+
	m_tree.Query(callback, aabb);
297
}
298-
		m_jointList = j->m_next;
298+
299
template <typename T>
300
inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const
301-
	// Disconnect from island graph.
301+
302-
	b2Body* bodyA = j->m_bodyA;
302+
	m_tree.RayCast(callback, input);
303-
	b2Body* bodyB = j->m_bodyB;
303+
304
305-
	// Wake up connected bodies.
305+
inline void b2BroadPhase::ShiftOrigin(const b2Vec2& newOrigin)
306-
	bodyA->SetAwake(true);
306+
307-
	bodyB->SetAwake(true);
307+
	m_tree.ShiftOrigin(newOrigin);
308
}
309-
	// Remove from body 1.
309+
310-
	if (j->m_edgeA.prev)
310+
#endif