Mercurial > projects > chipmunkd
diff trunk/chipmunkd/cpSpaceQuery.d @ 4:7ebbd4d05553
initial commit
author | Extrawurst |
---|---|
date | Thu, 02 Dec 2010 02:11:26 +0100 |
parents | |
children | df4ebc8add66 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/chipmunkd/cpSpaceQuery.d Thu Dec 02 02:11:26 2010 +0100 @@ -0,0 +1,167 @@ + +// written in the D programming language + +module chipmunkd.cpSpaceQuery; + +import chipmunkd.chipmunk; +import chipmunkd.chipmunk_types_h; + +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}; + cpSpaceHashPointQuery(space.activeShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context); + cpSpaceHashPointQuery(space.staticShapes, point, cast(cpSpaceHashQueryFunc)&pointQueryHelper, &context); +} + +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, + }; + + cpSpaceHashSegmentQuery(space.staticShapes, &context, start, end, 1.0f, cast(cpSpaceHashSegmentQueryFunc)&segQueryFunc, data); + cpSpaceHashSegmentQuery(space.activeShapes, &context, start, end, 1.0f, cast(cpSpaceHashSegmentQueryFunc)&segQueryFunc, data); +} + +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}; + cpSpaceHashQuery(space.activeShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context); + cpSpaceHashQuery(space.staticShapes, &bb, bb, cast(cpSpaceHashQueryFunc)&bbQueryHelper, &context); +}