changeset 29:80058cee1a77

updated to chipmunk 5.3.4
author Extrawurst
date Thu, 16 Dec 2010 00:33:06 +0100
parents 4541ca17975b
children 34b36b5193af
files trunk/chipmunkd/cpSpace.d trunk/chipmunkd/cpSpaceComponent.d trunk/chipmunkd/cpSpaceQuery.d trunk/chipmunkd/cpSpaceStep.d
diffstat 4 files changed, 126 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/chipmunkd/cpSpace.d	Mon Dec 13 21:40:56 2010 +0100
+++ b/trunk/chipmunkd/cpSpace.d	Thu Dec 16 00:33:06 2010 +0100
@@ -1,4 +1,3 @@
-
 // written in the D programming language
 
 module chipmunkd.cpSpace;
@@ -58,7 +57,7 @@
 	// *** Internally Used Fields
 	
 	// When the space is locked, you should not add or remove objects;
-	cpBool locked;
+	int locked;
 	
 	// Time stamp. Is incremented on every call to cpSpaceStep().
 	cpTimestamp stamp;
@@ -73,6 +72,9 @@
 	// List of groups of sleeping bodies.
 	cpArray *sleepingComponents;
 	
+	// List of bodies that have been flagged to be awoken.
+	cpArray *rousedBodies;
+	
 	// List of active arbiters for the impulse solver.
 	cpArray* arbiters, pooledArbiters;
 	
@@ -278,6 +280,8 @@
 	
 	space.bodies = cpArrayNew(0);
 	space.sleepingComponents = cpArrayNew(0);
+	space.rousedBodies = cpArrayNew(0);
+
 	space.sleepTimeThreshold = INFINITY;
 	space.idleSpeedThreshold = 0.0f;
 	
@@ -315,6 +319,7 @@
 	
 	cpArrayFree(space.bodies);
 	cpArrayFree(space.sleepingComponents);
+	cpArrayFree(space.rousedBodies);
 	
 	cpArrayFree(space.constraints);
 	
@@ -448,7 +453,7 @@
 cpSpaceAddShape(cpSpace *space, cpShape *shape)
 {
 	cpBody *_body = shape._body;
-	if(!_body || _body == &space.staticBody) return cpSpaceAddStaticShape(space, shape);
+	if(!_body || cpBodyIsStatic(_body)) return cpSpaceAddStaticShape(space, shape);
 	
 	assert(!cpHashSetFind(space.activeShapes.handleSet, shape.hashid, shape),
 		"Cannot add the same shape more than once.");
@@ -623,3 +628,51 @@
 	cpSpaceHashRehashObject(space.staticShapes, shape, shape.hashid);
 }
 
+void
+cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data)
+{
+	cpArray *bodies = space.bodies;
+	
+	for(int i=0; i<bodies.num; i++){
+		func(cast(cpBody *)bodies.arr[i], data);
+	}
+	
+	cpArray *components = space.sleepingComponents;
+	for(int i=0; i<components.num; i++){
+		cpBody *root = cast(cpBody *)components.arr[i];
+		cpBody *_body = root, next;
+		do {
+			next = _body.node.next;
+			func(_body , data);
+		} while((_body = next) != root);
+	}
+}
+
+// chipmunk_private.h
+
+//void *cpSpaceGetPostStepData(cpSpace *space, void *obj);
+
+//void cpSpaceActivateBody(cpSpace *space, cpBody *body);
+
+static void
+cpSpaceLock(cpSpace *space)
+{
+	space.locked++;
+}
+
+static void
+cpSpaceUnlock(cpSpace *space)
+{
+	space.locked--;
+	assert(space.locked >= 0, "Internal error:Space lock underflow.");
+	
+	if(!space.locked){
+		cpArray *waking = space.rousedBodies;
+		for(int i=0, count=waking.num; i<count; i++){
+			cpSpaceActivateBody(space, cast(cpBody *)waking.arr[i]);
+		}
+		
+		waking.num = 0;
+	}
+}
+
--- a/trunk/chipmunkd/cpSpaceComponent.d	Mon Dec 13 21:40:56 2010 +0100
+++ b/trunk/chipmunkd/cpSpaceComponent.d	Thu Dec 16 00:33:06 2010 +0100
@@ -35,6 +35,21 @@
 	}
 }
 
+void
+cpSpaceActivateBody(cpSpace *space, cpBody *_body)
+{
+	if(space.locked){
+		// cpSpaceActivateBody() is called again once the space is unlocked
+		cpArrayPush(space.rousedBodies, _body);
+	} else {
+		cpArrayPush(space.bodies, _body);
+		for(cpShape *shape=_body.shapesList; shape; shape=shape.next){
+			cpSpaceHashRemove(space.staticShapes, shape, shape.hashid);
+			cpSpaceHashInsert(space.activeShapes, shape, shape.hashid, shape.bb);
+		}
+	}
+}
+
 static void
 componentActivate(cpBody *root)
 {
@@ -42,22 +57,16 @@
 	
 	cpSpace *space = root.space;
 	assert(space, "Trying to activate a body that was never added to a space.");
-	assert(!space.locked, "Bodies can not be awakened during a query or a call to cpSpaceSte(). Put these calls into a post-step callback.");
-	
-	cpBody *_body = root;
-	cpBody *next;
-	do {
-		next = _body.node.next;
-		
-		cpFloat idleTime = (cpBodyIsStatic(_body) ? cast(cpFloat)INFINITY : 0.0f);
-		cpComponentNode node = {null, null, 0, idleTime};
-		_body.node = node;
-		if(!cpBodyIsRogue(_body)) cpArrayPush(space.bodies, _body);
-		
-		for(cpShape *shape=_body.shapesList; shape; shape=shape.next){
-			cpSpaceHashRemove(space.staticShapes, shape, shape.hashid);
-			cpSpaceHashInsert(space.activeShapes, shape, shape.hashid, shape.bb);
-		}
+
+	cpBody *_body = root, next;
+	do {
+		next = _body.node.next;
+		
+		cpComponentNode node = {null, null, 0, 0.0f};
+		_body.node = node;
+		
+		cpSpaceActivateBody(space, _body);
+
 	} while((_body = next) != root);
 	
 	cpArrayDeleteObj(space.sleepingComponents, root);
@@ -66,16 +75,15 @@
 void
 cpBodyActivate(cpBody *_body)
 {
-	// Reset the idle time even if it's not in a currently sleeping component
-	// Like a body resting on or jointed to a rogue body.
-	if(!cpBodyIsStatic(_body)) _body.node.idleTime = 0.0f;
-	componentActivate(componentNodeRoot(_body));
+	//NOTE: dmd compiler bug when useing -inline
+	auto foo = componentNodeRoot(_body);
+	componentActivate(foo);
 }
 
 static void
 mergeBodies(cpSpace *space, cpArray *components, cpArray *rogueBodies, cpBody *a, cpBody *b)
 {
-	// Don't merge with the static body
+	// Ignore connections to static bodies
 	if(cpBodyIsStatic(a) || cpBodyIsStatic(b)) return;
 	
 	cpBody *a_root = componentNodeRoot(a);
@@ -91,9 +99,9 @@
 		componentActivate(b_root);
 	} 
 	
-	// Add any rogue bodies (bodies not added to the space)
-	if(cpBodyIsRogue(a)) cpArrayPush(rogueBodies, a);
-	if(cpBodyIsRogue(b)) cpArrayPush(rogueBodies, b);
+	// Add any rogue bodies found to the list and reset the idle time of anything they touch.
+	if(cpBodyIsRogue(a)){ cpArrayPush(rogueBodies, a); b.node.idleTime = 0.0f; }
+	if(cpBodyIsRogue(b)){ cpArrayPush(rogueBodies, b); a.node.idleTime = 0.0f; }
 	
 	componentNodeMerge(a_root, b_root);
 }
@@ -142,10 +150,11 @@
 	cpArray *rogueBodies = cpArrayNew(16);
 	cpArray *arbiters = space.arbiters;
 	cpArray *constraints = space.constraints;
-	cpArray *components = cpArrayNew(bodies.num/8);
+	cpArray *components = cpArrayNew(space.sleepingComponents.num);
 	
 	cpFloat dv = space.idleSpeedThreshold;
 	cpFloat dvsq = (dv ? dv*dv : cpvdot(space.gravity, space.gravity)*dt*dt);
+	
 	// update idling
 	for(int i=0; i<bodies.num; i++){
 		cpBody *_body = cast(cpBody*)bodies.arr[i];
@@ -165,10 +174,8 @@
 	}
 	
 	// iterate bodies and add them to their components
-	for(int i=0; i<bodies.num; i++)
-		addToComponent(cast(cpBody*)bodies.arr[i], components);
-	for(int i=0; i<rogueBodies.num; i++)
-		addToComponent(cast(cpBody*)rogueBodies.arr[i], components);
+	for(int i=0; i<bodies.num; i++) addToComponent(cast(cpBody*)bodies.arr[i], components);
+	for(int i=0; i<rogueBodies.num; i++) addToComponent(cast(cpBody*)rogueBodies.arr[i], components);
 	
 	// iterate components, copy or deactivate
 	for(int i=0; i<components.num; i++){
@@ -180,9 +187,8 @@
 				next = _body.node.next;
 				
 				if(!cpBodyIsRogue(_body)) cpArrayPush(newBodies, _body);
-				_body.node.next = null;
-				_body.node.parent = null;
-				_body.node.rank = 0;
+				cpComponentNode node = {null, null, 0, _body.node.idleTime};
+				_body.node = node;
 			} while((_body = next) != root);
 		} else {
 			cpBody *_body = root;
@@ -224,9 +230,8 @@
 	if(cpBodyIsSleeping(_body)) return;
 	
 	for(cpShape *shape = _body.shapesList; shape; shape = shape.next){
+		cpShapeCacheBB(shape);
 		cpSpaceHashRemove(space.activeShapes, shape, shape.hashid);
-		
-		cpShapeCacheBB(shape);
 		cpSpaceHashInsert(space.staticShapes, shape, shape.hashid, shape.bb);
 	}
 	
@@ -248,19 +253,11 @@
 
 static void
 activateTouchingHelper(cpShape *shape, cpContactPointSet *points, cpArray **bodies){
-	if(*bodies == null) (*bodies) = cpArrayNew(0);
-	cpArrayPush(*bodies, shape._body);
+	cpBodyActivate(shape._body);
 }
 
 void
 cpSpaceActivateShapesTouchingShape(cpSpace *space, cpShape *shape){
 	cpArray *bodies = null;
 	cpSpaceShapeQuery(space, shape, cast(cpSpaceShapeQueryFunc)&activateTouchingHelper, &bodies);
-	
-	if(bodies){
-		for(int i=0; i<bodies.num; i++){
-			cpBody *_body = cast(cpBody *)bodies.arr[i];
-			cpBodyActivate(_body);
-		}
-	}
 }
--- a/trunk/chipmunkd/cpSpaceQuery.d	Mon Dec 13 21:40:56 2010 +0100
+++ b/trunk/chipmunkd/cpSpaceQuery.d	Thu Dec 16 00:33:06 2010 +0100
@@ -29,10 +29,10 @@
 {
 	pointQueryContext context = {layers, group, func, data};
 	
-	cpBool locked = space.locked; space.locked = cpTrue; {
+	cpSpaceLock(space);{
 		cpSpaceHashPointQuery(space.activeShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context);
 		cpSpaceHashPointQuery(space.staticShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context);
-	} space.locked = locked;
+	} cpSpaceUnlock(space);
 }
 
 static void
@@ -50,15 +50,6 @@
 	return shape;
 }
 
-void
-cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data)
-{
-	cpArray *bodies = space.bodies;
-	
-	for(int i=0; i<bodies.num; i++)
-		func(cast(cpBody *)bodies.arr[i], data);
-}
-
 //#pragma mark Segment Query Functions
 
 struct segQueryContext {
@@ -92,10 +83,10 @@
 		func,
 	};
 	
-	cpBool locked = space.locked; space.locked = cpTrue; {
+	cpSpaceLock(space);{
 		cpSpaceHashSegmentQuery(space.staticShapes, &context, start, end, 1.0f, cast(cpSpaceHashSegmentQueryFunc)&segQueryFunc, data);
 		cpSpaceHashSegmentQuery(space.activeShapes, &context, start, end, 1.0f, cast(cpSpaceHashSegmentQueryFunc)&segQueryFunc, data);
-	} space.locked = locked;
+	} cpSpaceUnlock(space);
 }
 
 struct segQueryFirstContext {
@@ -168,10 +159,10 @@
 {
 	bbQueryContext context = {layers, group, func, data};
 	
-	cpBool locked = space.locked; space.locked = cpTrue; {
+	cpSpaceLock(space);{
 	cpSpaceHashQuery(space.activeShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context);
 	cpSpaceHashQuery(space.staticShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context);
-	} space.locked = locked;
+	} cpSpaceUnlock(space);
 }
 
 //#pragma mark Shape Query Functions
@@ -226,10 +217,10 @@
 	cpBB bb = cpShapeCacheBB(shape);
 	shapeQueryContext context = {func, data, cpFalse};
 	
-	cpBool locked = space.locked; space.locked = cpTrue; {
+	cpSpaceLock(space);{
 		cpSpaceHashQuery(space.activeShapes, shape, bb, cast(cpSpaceHashQueryFunc)&shapeQueryHelper, &context);
 		cpSpaceHashQuery(space.staticShapes, shape, bb, cast(cpSpaceHashQueryFunc)&shapeQueryHelper, &context);
-	} space.locked = locked;
+	} cpSpaceUnlock(space);
 	
 	return context.anyCollision;
 }
--- a/trunk/chipmunkd/cpSpaceStep.d	Mon Dec 13 21:40:56 2010 +0100
+++ b/trunk/chipmunkd/cpSpaceStep.d	Thu Dec 16 00:33:06 2010 +0100
@@ -19,21 +19,21 @@
 //
 //#pragma mark Post Step Callback Functions
 
-struct postStepCallback {
+struct PostStepCallback {
 	cpPostStepFunc func;
 	void *obj;
 	void *data;
 }
 
 static cpBool
-postStepFuncSetEql(postStepCallback *a, postStepCallback *b){
+postStepFuncSetEql(PostStepCallback *a, PostStepCallback *b){
 	return a.obj == b.obj;
 }
 
 static void *
-postStepFuncSetTrans(postStepCallback *callback, void *ignored)
+postStepFuncSetTrans(PostStepCallback *callback, void *ignored)
 {
-	postStepCallback *value = cast(postStepCallback *)cpmalloc(postStepCallback.sizeof);
+	PostStepCallback *value = cast(PostStepCallback *)cpmalloc(PostStepCallback.sizeof);
 	(*value) = (*callback);
 	
 	return value;
@@ -46,10 +46,22 @@
 		space.postStepCallbacks = cpHashSetNew(0, cast(cpHashSetEqlFunc)&postStepFuncSetEql, cast(cpHashSetTransFunc)&postStepFuncSetTrans);
 	}
 	
-	postStepCallback callback = {func, obj, data};
+	PostStepCallback callback = {func, obj, data};
 	cpHashSetInsert(space.postStepCallbacks, cast(cpHashValue)cast(size_t)obj, &callback, null);
 }
 
+void *
+cpSpaceGetPostStepData(cpSpace *space, void *obj)
+{
+	if(space.postStepCallbacks){
+		PostStepCallback query = {null, obj, null};
+		PostStepCallback *callback = cast(PostStepCallback *)cpHashSetFind(space.postStepCallbacks, cast(cpHashValue)cast(size_t)obj, &query);
+		return (callback ? callback.data : null);
+	} else {
+		return null;
+	}
+}
+
 //#pragma mark Contact Buffer Functions
 
 enum CP_CONTACTS_BUFFER_SIZE = ((CP_BUFFER_BYTES - cpContactBufferHeader.sizeof)/cpContact.sizeof);
@@ -253,7 +265,7 @@
 
 // Hashset filter func to call and throw away post step callbacks.
 static void
-postStepCallbackSetIter(postStepCallback *callback, cpSpace *space)
+postStepCallbackSetIter(PostStepCallback *callback, cpSpace *space)
 {
 	callback.func(space, callback.obj, callback.data);
 	cpfree(callback);
@@ -269,7 +281,6 @@
 cpSpaceStep(cpSpace *space, cpFloat dt)
 {
 	if(!dt) return; // don't step if the timestep is 0!
-	
 	cpFloat dt_inv = 1.0f/dt;
 
 	cpArray *bodies = space.bodies;
@@ -287,7 +298,7 @@
 	// Pre-cache BBoxes and shape data.
 	cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&updateBBCache, null);
 	
-	space.locked = cpTrue;
+	cpSpaceLock(space);
 	
 	// Collide!
 	cpSpacePushFreshContactBuffer(space);
@@ -295,7 +306,7 @@
 		cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&active2staticIter, space);
 	cpSpaceHashQueryRehash(space.activeShapes, cast(cpSpaceHashQueryFunc)&queryFunc, space);
 	
-	space.locked = cpFalse;
+	cpSpaceUnlock(space);
 	
 	// If body sleeping is enabled, do that now.
 	if(space.sleepTimeThreshold != INFINITY){
@@ -351,7 +362,7 @@
 		}
 	}
 	
-	space.locked = cpTrue;
+	cpSpaceLock(space);
 	
 	// run the post solve callbacks
 	for(int i=0; i<arbiters.num; i++){
@@ -363,7 +374,7 @@
 		arb.state = cpArbiterState.cpArbiterStateNormal;
 	}
 	
-	space.locked = cpFalse;
+	cpSpaceUnlock(space);
 	
 	// Run the post step callbacks
 	// Loop because post step callbacks may create more post step callbacks