Mercurial > projects > chipmunkd
view trunk/chipmunkd/cpSpaceQuery.d @ 23:4ceef5833c8c
updated to chipmunk 5.3.3
author | Extrawurst |
---|---|
date | Fri, 10 Dec 2010 02:10:27 +0100 |
parents | df4ebc8add66 |
children | 80058cee1a77 |
line wrap: on
line source
// written in the D programming language module chipmunkd.cpSpaceQuery; import chipmunkd.chipmunk; import chipmunkd.chipmunk_types; struct pointQueryContext { cpLayers layers; cpGroup group; cpSpacePointQueryFunc func; void *data; } static void pointQueryHelper(cpVect *point, cpShape *shape, pointQueryContext *context) { if( !(shape.group && context.group == shape.group) && (context.layers&shape.layers) && cpShapePointQuery(shape, *point) ){ context.func(shape, context.data); } } void cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data) { pointQueryContext context = {layers, group, func, data}; cpBool locked = space.locked; space.locked = cpTrue; { cpSpaceHashPointQuery(space.activeShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context); cpSpaceHashPointQuery(space.staticShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context); } space.locked = locked; } static void rememberLastPointQuery(cpShape *shape, cpShape **outShape) { if(!shape.sensor) *outShape = shape; } cpShape * cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group) { cpShape *shape = null; cpSpacePointQuery(space, point, layers, group, cast(cpSpacePointQueryFunc)&rememberLastPointQuery, &shape); 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 { cpVect start, end; cpLayers layers; cpGroup group; cpSpaceSegmentQueryFunc func; } static cpFloat segQueryFunc(segQueryContext *context, cpShape *shape, void *data) { cpSegmentQueryInfo info; if( !(shape.group && context.group == shape.group) && (context.layers&shape.layers) && cpShapeSegmentQuery(shape, context.start, context.end, &info) ){ context.func(shape, info.t, info.n, data); } return 1.0f; } void cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data) { segQueryContext context = { start, end, layers, group, func, }; cpBool locked = space.locked; space.locked = cpTrue; { 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; } struct segQueryFirstContext { cpVect start, end; cpLayers layers; cpGroup group; } static cpFloat segQueryFirst(segQueryFirstContext *context, cpShape *shape, cpSegmentQueryInfo *_out) { cpSegmentQueryInfo info; if( !(shape.group && context.group == shape.group) && (context.layers&shape.layers) && !shape.sensor && cpShapeSegmentQuery(shape, context.start, context.end, &info) && info.t < _out.t ){ *_out = info; } return _out.t; } cpShape * cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *_out) { cpSegmentQueryInfo info = {null, 1.0f, cpvzero}; if(_out){ (*_out) = info; } else { _out = &info; } segQueryFirstContext context = { start, end, layers, group }; cpSpaceHashSegmentQuery(space.staticShapes, &context, start, end, 1.0f, cast(cpSpaceHashSegmentQueryFunc)&segQueryFirst, _out); cpSpaceHashSegmentQuery(space.activeShapes, &context, start, end, _out.t, cast(cpSpaceHashSegmentQueryFunc)&segQueryFirst, _out); return _out.shape; } //#pragma mark BB Query functions struct bbQueryContext { cpLayers layers; cpGroup group; cpSpaceBBQueryFunc func; void *data; } static void bbQueryHelper(cpBB *bb, cpShape *shape, bbQueryContext *context) { if( !(shape.group && context.group == shape.group) && (context.layers&shape.layers) && cpBBintersects(*bb, shape.bb) ){ context.func(shape, context.data); } } void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data) { bbQueryContext context = {layers, group, func, data}; cpBool locked = space.locked; space.locked = cpTrue; { cpSpaceHashQuery(space.activeShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context); cpSpaceHashQuery(space.staticShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context); } space.locked = locked; } //#pragma mark Shape Query Functions struct shapeQueryContext { cpSpaceShapeQueryFunc func; void *data; cpBool anyCollision; } // Callback from the spatial hash. static void shapeQueryHelper(cpShape *a, cpShape *b, shapeQueryContext *context) { // Reject any of the simple cases if( (a.group && a.group == b.group) || !(a.layers & b.layers) || a.sensor || b.sensor ) return; cpContact contacts[CP_MAX_CONTACTS_PER_ARBITER]; int numContacts = 0; // Shape 'a' should have the lower shape type. (required by cpCollideShapes() ) if(a.klass.type <= b.klass.type){ numContacts = cpCollideShapes(a, b, contacts.ptr); } else { numContacts = cpCollideShapes(b, a, contacts.ptr); for(int i=0; i<numContacts; i++) contacts[i].n = cpvneg(contacts[i].n); } if(numContacts){ context.anyCollision = cpTrue; if(context.func){ cpContactPointSet set; set.count = numContacts; for(int i=0; i<set.count; i++){ set.points[i].point = contacts[i].p; set.points[i].normal = contacts[i].p; set.points[i].dist = contacts[i].dist; } context.func(b, &set, context.data); } } } cpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data) { cpBB bb = cpShapeCacheBB(shape); shapeQueryContext context = {func, data, cpFalse}; cpBool locked = space.locked; space.locked = cpTrue; { cpSpaceHashQuery(space.activeShapes, shape, bb, cast(cpSpaceHashQueryFunc)&shapeQueryHelper, &context); cpSpaceHashQuery(space.staticShapes, shape, bb, cast(cpSpaceHashQueryFunc)&shapeQueryHelper, &context); } space.locked = locked; return context.anyCollision; }