├── .gitignore ├── LICENSE ├── README.md ├── chipmunkd.lib ├── demo ├── .gitignore ├── Bench.d ├── Buoyancy.d ├── Chains.d ├── ChipmunkDebugDraw.d ├── ChipmunkDemo.d ├── ChipmunkDemoShaderSupport.d ├── ChipmunkDemoTextSupport.d ├── ContactGraph.d ├── ContactPoints.d_ ├── Convex.d ├── Crane.d ├── GJK.d_ ├── GL │ ├── glew.d │ ├── glfw.d │ └── glu.d ├── Joints.d ├── LogoSmash.d ├── OneWay.d ├── Planet.d ├── Player.d ├── Plink.d ├── Pump.d ├── PyramidStack.d ├── PyramidTopple.d ├── Query.d ├── Shatter.d ├── Slice.d ├── Smooth.d_ ├── Springies.d ├── Sticky.d ├── Tank.d ├── TheoJansen.d ├── Tumble.d ├── Unicycle.d ├── VeraMoBI_ttf_sdf.d ├── VeraMoBd_ttf_sdf.d ├── dub.sdl └── dub.selections.json ├── dub.sdl ├── dub.selections.json └── src └── chipmunk ├── chipmunk.d ├── chipmunk_private.d ├── chipmunk_structs.d ├── chipmunk_types.d ├── chipmunk_unsafe.d ├── cpArbiter.d ├── cpBB.d ├── cpBody.d ├── cpConstraint.d ├── cpDampedRotarySpring.d ├── cpDampedSpring.d ├── cpGearJoint.d ├── cpGrooveJoint.d ├── cpHastySpace.d ├── cpMarch.d ├── cpPinJoint.d ├── cpPivotJoint.d ├── cpPolyShape.d ├── cpPolyline.d ├── cpRatchetJoint.d ├── cpRobust.d ├── cpRotaryLimitJoint.d ├── cpShape.d ├── cpSimpleMotor.d ├── cpSlideJoint.d ├── cpSpace.d ├── cpSpatialIndex.d ├── cpTransform.d ├── cpVect.d └── package.d /.gitignore: -------------------------------------------------------------------------------- 1 | .dub 2 | docs.json 3 | __dummy.html 4 | *.o 5 | *.obj 6 | *.a 7 | *.lib 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 rcorre 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | chipmunkd 2 | === 3 | 4 | D bindings (-betterC) to the 7.X versions of [Chipmunk2D](http://chipmunk-physics.net/), a 5 | physics library. 6 | 7 | # Use 8 | 9 | You will need to have the chipmunk library installed to use chipmunkd. 10 | You could use something like the following in your `dub.sdl`: 11 | 12 | dependency "chipmunkd" version="<~1.0.0+7.0.1" 13 | libs "chipmunk" 14 | 15 | Note that the version spec `1.0.0+7.0.1` denotes that this is version `1.0.0` of 16 | the chipmunkd bindings, which target the `7.0.1` version of the C library. 17 | 18 | The [documentation](http://chipmunk-physics.net/documentation.php) for chipmunk 19 | should mostly apply to the D bindings as well. 20 | 21 | # Demos 22 | 23 | The `demo` folder contains demo programs ported from the demos included in the C 24 | library. These depend on `glew` and `glfw2`. This is an older version of `glfw`, 25 | so there are some quickly hacked-together bindings in the demo folder to get it 26 | working. 27 | 28 | You can build and run the demos using `dub`. 29 | 30 | # Comparison to DChip 31 | 32 | You might also be interested in [dchip](https://github.com/d-gamedev-team/dchip). 33 | While chipmunkd provides D bindings to the original C library, dchip fully 34 | implements the source in D. With dchip, you don't need to take a dependency on 35 | the original C library, but it may be harder to keep up to date with the 36 | upstream version. 37 | 38 | # License 39 | 40 | Both chipmunkd and Chipmunk2D are licensed under the 41 | [MIT License](https://opensource.org/licenses/MIT). 42 | 43 | # Credits 44 | 45 | These bindings were created with the help of 46 | [dstep](https://github.com/jacob-carlborg/dstep). 47 | -------------------------------------------------------------------------------- /chipmunkd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcorre/chipmunkd/0920298f50f31cc2884ebd55b808fef7e9e6df89/chipmunkd.lib -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | demo 2 | -------------------------------------------------------------------------------- /demo/Buoyancy.d: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | import chipmunk; 23 | 24 | import ChipmunkDemo; 25 | import ChipmunkDebugDraw; 26 | 27 | static void 28 | update(cpSpace *space, double dt) 29 | { 30 | cpSpaceStep(space, dt); 31 | } 32 | 33 | enum FLUID_DENSITY = 0.00014; 34 | enum FLUID_DRAG = 2.0; 35 | 36 | char messageBuffer[1024] = []; 37 | 38 | // Modified from chipmunk_private.h 39 | static cpFloat 40 | k_scalar_body(cpBody *body_, cpVect point, cpVect n) 41 | { 42 | cpFloat rcn = cpvcross(cpvsub(point, cpBodyGetPosition(body_)), n); 43 | return 1.0f/cpBodyGetMass(body_) + rcn*rcn/cpBodyGetMoment(body_); 44 | } 45 | 46 | extern(C) static cpBool 47 | waterPreSolve(cpArbiter *arb, cpSpace *space, void *ptr) 48 | { 49 | cpShape* water, poly; 50 | cpArbiterGetShapes(arb, &water, &poly); 51 | cpBody *body_ = cpShapeGetBody(poly); 52 | 53 | // Get the top of the water sensor bounding box to use as the water level. 54 | cpFloat level = cpShapeGetBB(water).t; 55 | 56 | // Clip the polygon against the water level 57 | int count = cpPolyShapeGetCount(poly); 58 | int clippedCount = 0; 59 | version (_MSC_VER) 60 | // MSVC is pretty much the only compiler in existence that doesn't support variable sized arrays. 61 | cpVect clipped[10]; 62 | else 63 | cpVect[] clipped = new cpVect[count + 1]; 64 | 65 | for(int i=0, j=count-1; i 0.9*maxForce){ 46 | cpSpaceAddPostStepCallback(space, cast(cpPostStepFunc)&BreakablejointPostStepRemove, joint, null); 47 | } 48 | } 49 | 50 | static void 51 | update(cpSpace *space, double dt) 52 | { 53 | cpSpaceStep(space, dt); 54 | } 55 | 56 | static cpSpace * 57 | init() 58 | { 59 | cpSpace *space = cpSpaceNew(); 60 | cpSpaceSetIterations(space, 30); 61 | cpSpaceSetGravity(space, cpv(0, -100)); 62 | cpSpaceSetSleepTimeThreshold(space, 0.5f); 63 | 64 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 65 | cpShape *shape; 66 | 67 | // Create segments around the edge of the screen. 68 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); 69 | cpShapeSetElasticity(shape, 1.0f); 70 | cpShapeSetFriction(shape, 1.0f); 71 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 72 | 73 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); 74 | cpShapeSetElasticity(shape, 1.0f); 75 | cpShapeSetFriction(shape, 1.0f); 76 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 77 | 78 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); 79 | cpShapeSetElasticity(shape, 1.0f); 80 | cpShapeSetFriction(shape, 1.0f); 81 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 82 | 83 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f)); 84 | cpShapeSetElasticity(shape, 1.0f); 85 | cpShapeSetFriction(shape, 1.0f); 86 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 87 | 88 | cpFloat mass = 1; 89 | cpFloat width = 20; 90 | cpFloat height = 30; 91 | 92 | cpFloat spacing = width*0.3; 93 | 94 | // Add lots of boxes. 95 | for(int i=0; i triangle_capacity){ 159 | triangle_capacity += MAX(triangle_capacity, count); 160 | triangle_buffer = cast(Triangle *)realloc(triangle_buffer, triangle_capacity*Triangle.sizeof); 161 | } 162 | 163 | Triangle *buffer = triangle_buffer + triangle_count; 164 | triangle_count += count; 165 | return buffer; 166 | } 167 | 168 | static GLfloat 169 | PushChar(int character, GLfloat x, GLfloat y, cpSpaceDebugColor color) 170 | { 171 | int i = glyph_indexes[character]; 172 | GLfloat w = cast(GLfloat)sdf_tex_width; 173 | GLfloat h = cast(GLfloat)sdf_tex_height; 174 | 175 | GLfloat gw = cast(GLfloat)sdf_spacing[i*8 + 3]; 176 | GLfloat gh = cast(GLfloat)sdf_spacing[i*8 + 4]; 177 | 178 | GLfloat txmin = sdf_spacing[i*8 + 1]/w; 179 | GLfloat tymin = sdf_spacing[i*8 + 2]/h; 180 | GLfloat txmax = txmin + gw/w; 181 | GLfloat tymax = tymin + gh/h; 182 | 183 | GLfloat s = Scale/scale_factor; 184 | GLfloat xmin = x + sdf_spacing[i*8 + 5]/scale_factor*Scale; 185 | GLfloat ymin = y + (sdf_spacing[i*8 + 6]/scale_factor - gh)*Scale; 186 | GLfloat xmax = xmin + gw*Scale; 187 | GLfloat ymax = ymin + gh*Scale; 188 | 189 | Vertex a = {{xmin, ymin}, {txmin, tymax}, color}; 190 | Vertex b = {{xmin, ymax}, {txmin, tymin}, color}; 191 | Vertex c = {{xmax, ymax}, {txmax, tymin}, color}; 192 | Vertex d = {{xmax, ymin}, {txmax, tymax}, color}; 193 | 194 | Triangle *triangles = PushTriangles(2); 195 | Triangle t0 = {a, b, c}; triangles[0] = t0; 196 | Triangle t1 = {a, c, d}; triangles[1] = t1; 197 | 198 | return sdf_spacing[i*8 + 7]*s; 199 | } 200 | 201 | void 202 | ChipmunkDemoTextDrawString(cpVect pos, const char *str) 203 | { 204 | cpSpaceDebugColor c = LAColor(1.0f, 1.0f); 205 | GLfloat x = cast(GLfloat)pos.x, y = cast(GLfloat)pos.y; 206 | 207 | for(size_t i=0, len=strlen(str); i 10.0f){ 97 | ChipmunkDemoPrintString("The ball is being crushed. (f: %.2f)", crushForce); 98 | } else { 99 | ChipmunkDemoPrintString("The ball is not being crushed. (f: %.2f)", crushForce); 100 | } 101 | } 102 | 103 | enum WIDTH = 4.0f; 104 | enum HEIGHT = 30.0f; 105 | 106 | static cpSpace * 107 | init() 108 | { 109 | cpSpace *space = cpSpaceNew(); 110 | cpSpaceSetIterations(space, 30); 111 | cpSpaceSetGravity(space, cpv(0, -300)); 112 | cpSpaceSetCollisionSlop(space, 0.5); 113 | cpSpaceSetSleepTimeThreshold(space, 1.0f); 114 | 115 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 116 | cpShape *shape; 117 | 118 | // Create segments around the edge of the screen. 119 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); 120 | cpShapeSetElasticity(shape, 1.0f); 121 | cpShapeSetFriction(shape, 1.0f); 122 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 123 | 124 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); 125 | cpShapeSetElasticity(shape, 1.0f); 126 | cpShapeSetFriction(shape, 1.0f); 127 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 128 | 129 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); 130 | cpShapeSetElasticity(shape, 1.0f); 131 | cpShapeSetFriction(shape, 1.0f); 132 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 133 | 134 | scaleStaticBody = cpSpaceAddBody(space, cpBodyNewStatic()); 135 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(scaleStaticBody, cpv(-240,-180), cpv(-140,-180), 4.0f)); 136 | cpShapeSetElasticity(shape, 1.0f); 137 | cpShapeSetFriction(shape, 1.0f); 138 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 139 | 140 | // add some boxes to stack on the scale 141 | for(int i=0; i<5; i++){ 142 | body_ = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForBox(1.0f, 30.0f, 30.0f))); 143 | cpBodySetPosition(body_, cpv(0, i*32 - 220)); 144 | 145 | shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, 30.0f, 30.0f, 0.0)); 146 | cpShapeSetElasticity(shape, 0.0f); 147 | cpShapeSetFriction(shape, 0.8f); 148 | } 149 | 150 | // Add a ball that we'll track which objects are beneath it. 151 | cpFloat radius = 15.0f; 152 | ballBody = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); 153 | cpBodySetPosition(ballBody, cpv(120, -240 + radius+5)); 154 | 155 | shape = cpSpaceAddShape(space, cpCircleShapeNew(ballBody, radius, cpvzero)); 156 | cpShapeSetElasticity(shape, 0.0f); 157 | cpShapeSetFriction(shape, 0.9f); 158 | 159 | return space; 160 | } 161 | 162 | static void 163 | destroy(cpSpace *space) 164 | { 165 | ChipmunkDemoFreeSpaceChildren(space); 166 | cpSpaceFree(space); 167 | } 168 | 169 | ChipmunkDemo ContactGraph = { 170 | "Contact Graph", 171 | 1.0/60.0, 172 | &init, 173 | &update, 174 | &ChipmunkDemoDefaultDrawImpl, 175 | &destroy, 176 | }; 177 | -------------------------------------------------------------------------------- /demo/ContactPoints.d_: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | import core.stdc.stdlib; 23 | import core.stdc.stdio; 24 | import core.stdc.math; 25 | import core.stdc.string; 26 | 27 | import chipmunk.chipmunk_private; 28 | import ChipmunkDemo; 29 | 30 | static cpBool NeverCollide(cpArbiter *arb, cpSpace *space, void *data){return cpFalse;} 31 | 32 | static void 33 | update(cpSpace *space, cpFloat dt) 34 | { 35 | int steps = 1; 36 | dt = 1.0f/60.0f/cast(cpFloat)steps; 37 | 38 | for(int i=0; i tolerance){ 40 | cpBody *body_ = cpShapeGetBody(shape); 41 | int count = cpPolyShapeGetCount(shape); 42 | 43 | // Allocate the space for the new vertexes on the stack. 44 | cpVect *verts = cast(cpVect *)alloca((count + 1)*cpVect.sizeof); 45 | 46 | for(int i=0; i>3) + y*image_row_length]>>(~x&0x7)) & 1; 69 | } 70 | 71 | static int bodyCount = 0; 72 | 73 | static void 74 | update(cpSpace *space, double dt) 75 | { 76 | cpSpaceStep(space, dt); 77 | } 78 | 79 | extern(C) static void 80 | DrawDot(cpBody *body_, void *unused) 81 | { 82 | ChipmunkDebugDrawDot(3.0, cpBodyGetPosition(body_), RGBAColor(200.0f/255.0f, 210.0f/255.0f, 230.0f/255.0f, 1.0f)); 83 | } 84 | 85 | static void 86 | draw(cpSpace *space) 87 | { 88 | cpSpaceEachBody(space, &DrawDot, null); 89 | 90 | // ChipmunkDebugDrawCollisionPoints(space); 91 | } 92 | 93 | static cpShape * 94 | make_ball(cpFloat x, cpFloat y) 95 | { 96 | cpBody *body_ = cpBodyNew(1.0, INFINITY); 97 | cpBodySetPosition(body_, cpv(x, y)); 98 | 99 | cpShape *shape = cpCircleShapeNew(body_, 0.95, cpvzero); 100 | cpShapeSetElasticity(shape, 0.0); 101 | cpShapeSetFriction(shape, 0.0); 102 | 103 | return shape; 104 | } 105 | 106 | static cpSpace * 107 | init() 108 | { 109 | cpSpace *space = cpSpaceNew(); 110 | cpSpaceSetIterations(space, 1); 111 | 112 | // The space will contain a very large number of similary sized objects. 113 | // This is the perfect candidate for using the spatial hash. 114 | // Generally you will never need to do this. 115 | cpSpaceUseSpatialHash(space, 2.0, 10000); 116 | 117 | bodyCount = 0; 118 | 119 | cpBody *body_; 120 | cpShape *shape; 121 | 122 | for(int y=0; y groundNormal.y){ 50 | (*groundNormal) = n; 51 | } 52 | } 53 | 54 | extern(C) static void 55 | playerUpdateVelocity(cpBody *body_, cpVect gravity, cpFloat damping, cpFloat dt) 56 | { 57 | int jumpState = (ChipmunkDemoKeyboard.y > 0.0f); 58 | 59 | // Grab the grounding normal from last frame 60 | cpVect groundNormal = cpvzero; 61 | cpBodyEachArbiter(playerBody, cast(cpBodyArbiterIteratorFunc)&SelectPlayerGroundNormal, &groundNormal); 62 | 63 | grounded = (groundNormal.y > 0.0); 64 | if(groundNormal.y < 0.0f) remainingBoost = 0.0f; 65 | 66 | // Do a normal-ish update 67 | cpBool boost = (jumpState && remainingBoost > 0.0f); 68 | cpVect g = (boost ? cpvzero : gravity); 69 | cpBodyUpdateVelocity(body_, g, damping, dt); 70 | 71 | // Target horizontal speed for air/ground control 72 | cpFloat target_vx = PLAYER_VELOCITY*ChipmunkDemoKeyboard.x; 73 | 74 | // Update the surface velocity and friction 75 | // Note that the "feet" move in the opposite direction of the player. 76 | cpVect surface_v = cpv(-target_vx, 0.0); 77 | playerShape.surfaceV = surface_v; 78 | playerShape.u = (grounded ? PLAYER_GROUND_ACCEL/GRAVITY : 0.0); 79 | 80 | // Apply air control if not grounded 81 | if(!grounded){ 82 | // Smoothly accelerate the velocity 83 | playerBody.v.x = cpflerpconst(playerBody.v.x, target_vx, PLAYER_AIR_ACCEL*dt); 84 | } 85 | 86 | body_.v.y = cpfclamp(body_.v.y, -FALL_VELOCITY, INFINITY); 87 | } 88 | 89 | static void 90 | update(cpSpace *space, double dt) 91 | { 92 | int jumpState = (ChipmunkDemoKeyboard.y > 0.0f); 93 | 94 | // If the jump key was just pressed this frame, jump! 95 | if(jumpState && !lastJumpState && grounded){ 96 | cpFloat jump_v = cpfsqrt(2.0*JUMP_HEIGHT*GRAVITY); 97 | playerBody.v = cpvadd(playerBody.v, cpv(0.0, jump_v)); 98 | 99 | remainingBoost = JUMP_BOOST_HEIGHT/jump_v; 100 | } 101 | 102 | // Step the space 103 | cpSpaceStep(space, dt); 104 | 105 | remainingBoost -= dt; 106 | lastJumpState = cast(ubyte) jumpState; 107 | } 108 | 109 | static cpSpace * 110 | init() 111 | { 112 | cpSpace *space = cpSpaceNew(); 113 | space.iterations = 10; 114 | space.gravity = cpv(0, -GRAVITY); 115 | // space.sleepTimeThreshold = 1000; 116 | 117 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 118 | cpShape *shape; 119 | 120 | // Create segments around the edge of the screen. 121 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); 122 | shape.e = 1.0f; shape.u = 1.0f; 123 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 124 | 125 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); 126 | shape.e = 1.0f; shape.u = 1.0f; 127 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 128 | 129 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); 130 | shape.e = 1.0f; shape.u = 1.0f; 131 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 132 | 133 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f)); 134 | shape.e = 1.0f; shape.u = 1.0f; 135 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 136 | 137 | // Set up the player 138 | body_ = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY)); 139 | body_.p = cpv(0, -200); 140 | body_.velocity_func = &playerUpdateVelocity; 141 | playerBody = body_; 142 | 143 | shape = cpSpaceAddShape(space, cpBoxShapeNew2(body_, cpBBNew(-15.0, -27.5, 15.0, 27.5), 10.0)); 144 | // shape = cpSpaceAddShape(space, cpSegmentShapeNew(playerBody, cpvzero, cpv(0, radius), radius)); 145 | shape.e = 0.0f; shape.u = 0.0f; 146 | shape.type = 1; 147 | playerShape = shape; 148 | 149 | // Add some boxes to jump on 150 | for(int i=0; i<6; i++){ 151 | for(int j=0; j<3; j++){ 152 | body_ = cpSpaceAddBody(space, cpBodyNew(4.0f, INFINITY)); 153 | body_.p = cpv(100 + j*60, -200 + i*60); 154 | 155 | shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, 50, 50, 0.0)); 156 | shape.e = 0.0f; shape.u = 0.7f; 157 | } 158 | } 159 | 160 | return space; 161 | } 162 | 163 | static void 164 | destroy(cpSpace *space) 165 | { 166 | ChipmunkDemoFreeSpaceChildren(space); 167 | cpSpaceFree(space); 168 | } 169 | 170 | ChipmunkDemo Player = { 171 | "Platformer Player Controls", 172 | 1.0/180.0, 173 | &init, 174 | &update, 175 | &ChipmunkDemoDefaultDrawImpl, 176 | &destroy, 177 | }; 178 | -------------------------------------------------------------------------------- /demo/Plink.d: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | import chipmunk; 23 | import ChipmunkDemo; 24 | 25 | import std.math; 26 | import std.random; 27 | 28 | static cpFloat pentagon_mass = 0.0f; 29 | static cpFloat pentagon_moment = 0.0f; 30 | 31 | // Iterate over all of the bodies and reset the ones that have fallen offscreen. 32 | extern(C) static void 33 | eachBody(cpBody *body_, void *unused) 34 | { 35 | cpVect pos = cpBodyGetPosition(body_); 36 | if(pos.y < -260 || cpfabs(pos.x) > 340){ 37 | cpFloat x = uniform01()*640 - 320; 38 | cpBodySetPosition(body_, cpv(x, 260)); 39 | } 40 | } 41 | 42 | static void 43 | update(cpSpace *space, double dt) 44 | { 45 | if(ChipmunkDemoRightDown){ 46 | cpShape *nearest = cpSpacePointQueryNearest(space, ChipmunkDemoMouse, 0.0, GRAB_FILTER, null); 47 | if(nearest){ 48 | cpBody *body_ = cpShapeGetBody(nearest); 49 | if(cpBodyGetType(body_) == cpBodyType.CP_BODY_TYPE_STATIC){ 50 | cpBodySetType(body_, cpBodyType.CP_BODY_TYPE_DYNAMIC); 51 | cpBodySetMass(body_, pentagon_mass); 52 | cpBodySetMoment(body_, pentagon_moment); 53 | } else if(cpBodyGetType(body_) == cpBodyType.CP_BODY_TYPE_DYNAMIC) { 54 | cpBodySetType(body_, cpBodyType.CP_BODY_TYPE_STATIC); 55 | } 56 | } 57 | } 58 | 59 | cpSpaceEachBody(space, &eachBody, null); 60 | cpSpaceStep(space, dt); 61 | } 62 | 63 | enum NUM_VERTS = 5; 64 | 65 | static cpSpace * 66 | init() 67 | { 68 | ChipmunkDemoMessageString = "Right click to make pentagons static/dynamic."; 69 | 70 | cpSpace *space = cpSpaceNew(); 71 | cpSpaceSetIterations(space, 5); 72 | cpSpaceSetGravity(space, cpv(0, -100)); 73 | 74 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 75 | cpShape *shape; 76 | 77 | // Vertexes for a triangle shape. 78 | cpVect tris[] = [ 79 | cpv(-15,-15), 80 | cpv( 0, 10), 81 | cpv( 15,-15), 82 | ]; 83 | 84 | // Create the static triangles. 85 | for(int i=0; i<9; i++){ 86 | for(int j=0; j<6; j++){ 87 | cpFloat stagger = (j%2)*40; 88 | cpVect offset = cpv(i*80 - 320 + stagger, j*70 - 240); 89 | shape = cpSpaceAddShape(space, cpPolyShapeNew(staticBody, 3, tris.ptr, cpTransformTranslate(offset), 0.0)); 90 | cpShapeSetElasticity(shape, 1.0f); 91 | cpShapeSetFriction(shape, 1.0f); 92 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 93 | } 94 | } 95 | 96 | // Create vertexes for a pentagon shape. 97 | cpVect verts[NUM_VERTS]; 98 | for(int i=0; i 320.0f){ 47 | cpBodySetVelocity(ball, cpvzero); 48 | cpBodySetPosition(ball, cpv(-224.0f, 200.0f)); 49 | } 50 | } 51 | } 52 | 53 | static cpBody * 54 | add_ball(cpSpace *space, cpVect pos) 55 | { 56 | cpBody *body_ = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 30, 0, cpvzero))); 57 | cpBodySetPosition(body_, pos); 58 | 59 | cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, 30, cpvzero)); 60 | cpShapeSetElasticity(shape, 0.0f); 61 | cpShapeSetFriction(shape, 0.5f); 62 | 63 | return body_; 64 | } 65 | 66 | static cpSpace * 67 | init() 68 | { 69 | ChipmunkDemoMessageString = "Use the arrow keys to control the machine."; 70 | 71 | cpSpace *space = cpSpaceNew(); 72 | cpSpaceSetGravity(space, cpv(0, -600)); 73 | 74 | cpBody *staticBody = cpSpaceGetStaticBody(space); 75 | cpShape *shape; 76 | 77 | // beveling all of the line segments slightly helps prevent things from getting stuck on cracks 78 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-256,300), 2.0f)); 79 | cpShapeSetElasticity(shape, 0.0f); 80 | cpShapeSetFriction(shape, 0.5f); 81 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 82 | 83 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-192,0), 2.0f)); 84 | cpShapeSetElasticity(shape, 0.0f); 85 | cpShapeSetFriction(shape, 0.5f); 86 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 87 | 88 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,0), cpv(-192, -64), 2.0f)); 89 | cpShapeSetElasticity(shape, 0.0f); 90 | cpShapeSetFriction(shape, 0.5f); 91 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 92 | 93 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,-64), cpv(-128,144), 2.0f)); 94 | cpShapeSetElasticity(shape, 0.0f); 95 | cpShapeSetFriction(shape, 0.5f); 96 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 97 | 98 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,80), cpv(-192,176), 2.0f)); 99 | cpShapeSetElasticity(shape, 0.0f); 100 | cpShapeSetFriction(shape, 0.5f); 101 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 102 | 103 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,176), cpv(-128,240), 2.0f)); 104 | cpShapeSetElasticity(shape, 0.0f); 105 | cpShapeSetFriction(shape, 0.5f); 106 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 107 | 108 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,144), cpv(192,64), 2.0f)); 109 | cpShapeSetElasticity(shape, 0.0f); 110 | cpShapeSetFriction(shape, 0.5f); 111 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 112 | 113 | cpVect verts[] = [ 114 | cpv(-30,-80), 115 | cpv(-30, 80), 116 | cpv( 30, 64), 117 | cpv( 30,-80), 118 | ]; 119 | 120 | cpBody *plunger = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY)); 121 | cpBodySetPosition(plunger, cpv(-160,-80)); 122 | 123 | shape = cpSpaceAddShape(space, cpPolyShapeNew(plunger, 4, verts.ptr, cpTransformIdentity, 0.0)); 124 | cpShapeSetElasticity(shape, 1.0f); 125 | cpShapeSetFriction(shape, 0.5f); 126 | cpShapeSetFilter(shape, cpShapeFilterNew(CP_NO_GROUP, 1, 1)); 127 | 128 | // add balls to hopper 129 | for(int i=0; i>16) & 0xFFFF)/cast(cpFloat)0xFFFF) 51 | ); 52 | } 53 | 54 | static cpVect 55 | WorleyPoint(int i, int j, WorleyContex *context) 56 | { 57 | cpFloat size = context.cellSize; 58 | int width = context.width; 59 | int height = context.height; 60 | cpBB bb = context.bb; 61 | 62 | // cpVect fv = cpv(0.5, 0.5); 63 | cpVect fv = HashVect(i, j, context.seed); 64 | 65 | return cpv( 66 | cpflerp(bb.l, bb.r, 0.5f) + size*(i + fv.x - width*0.5f), 67 | cpflerp(bb.b, bb.t, 0.5f) + size*(j + fv.y - height*0.5f) 68 | ); 69 | } 70 | 71 | static int 72 | ClipCell(cpShape *shape, cpVect center, int i, int j, WorleyContex *context, cpVect *verts, cpVect *clipped, int count) 73 | { 74 | cpVect other = WorleyPoint(i, j, context); 75 | // printf(" other %dx%d: (% 5.2f, % 5.2f) ", i, j, other.x, other.y); 76 | if(cpShapePointQuery(shape, other, null) > 0.0f){ 77 | // printf("excluded\n"); 78 | memcpy(clipped, verts, count*cpVect.sizeof); 79 | return count; 80 | } else { 81 | // printf("clipped\n"); 82 | } 83 | 84 | cpVect n = cpvsub(other, center); 85 | cpFloat dist = cpvdot(n, cpvlerp(center, other, 0.5f)); 86 | 87 | int clipped_count = 0; 88 | for(int j_=0, i_=count-1; j_ MAX_VERTEXES_PER_VORONOI ? MAX_VERTEXES_PER_VORONOI : count); 123 | 124 | for(int i=0; i 5.0f){ 191 | ShatterShape(space, cast(cpShape *)info.shape, cell_size, ChipmunkDemoMouse); 192 | } else { 193 | // printf("Too small to splinter %f\n", cell_size); 194 | } 195 | } 196 | } 197 | } 198 | 199 | static cpSpace * 200 | init() 201 | { 202 | ChipmunkDemoMessageString = "Right click something to shatter it."; 203 | 204 | cpSpace *space = cpSpaceNew(); 205 | cpSpaceSetIterations(space, 30); 206 | cpSpaceSetGravity(space, cpv(0, -500)); 207 | cpSpaceSetSleepTimeThreshold(space, 0.5f); 208 | cpSpaceSetCollisionSlop(space, 0.5f); 209 | 210 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 211 | cpShape *shape; 212 | 213 | // Create segments around the edge of the screen. 214 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-1000, -240), cpv( 1000, -240), 0.0f)); 215 | cpShapeSetElasticity(shape, 1.0f); 216 | cpShapeSetFriction(shape, 1.0f); 217 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 218 | 219 | cpFloat width = 200.0f; 220 | cpFloat height = 200.0f; 221 | cpFloat mass = width*height*DENSITY; 222 | cpFloat moment = cpMomentForBox(mass, width, height); 223 | 224 | body_ = cpSpaceAddBody(space, cpBodyNew(mass, moment)); 225 | 226 | shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, width, height, 0.0)); 227 | cpShapeSetFriction(shape, 0.6f); 228 | 229 | return space; 230 | } 231 | 232 | static void 233 | destroy(cpSpace *space) 234 | { 235 | ChipmunkDemoFreeSpaceChildren(space); 236 | cpSpaceFree(space); 237 | } 238 | 239 | ChipmunkDemo Shatter = { 240 | "Shatter.", 241 | 1.0f/60.0f, 242 | &init, 243 | &update, 244 | &ChipmunkDemoDefaultDrawImpl, 245 | &destroy, 246 | }; 247 | -------------------------------------------------------------------------------- /demo/Slice.d: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | import chipmunk; 23 | 24 | import ChipmunkDemo; 25 | import core.stdc.stdlib; 26 | 27 | enum DENSITY = (1.0/10000.0); 28 | 29 | static void 30 | ClipPoly(cpSpace *space, cpShape *shape, cpVect n, cpFloat dist) 31 | { 32 | cpBody *body_ = cpShapeGetBody(shape); 33 | 34 | int count = cpPolyShapeGetCount(shape); 35 | int clippedCount = 0; 36 | 37 | cpVect *clipped = cast(cpVect *)alloca((count + 1)*cpVect.sizeof); 38 | 39 | for(int i=0, j=count-1; i 0.0f && cpShapePointQuery(shape, b, null) > 0.0f){ 108 | // Can't modify the space during a query. 109 | // Must make a post-step callback to do the actual slicing. 110 | cpSpaceAddPostStepCallback(context.space, cast(cpPostStepFunc)&SliceShapePostStep, shape, context); 111 | } 112 | } 113 | 114 | static void 115 | update(cpSpace *space, double dt) 116 | { 117 | cpSpaceStep(space, dt); 118 | 119 | static cpBool lastClickState = cpFalse; 120 | static cpVect sliceStart = {0.0, 0.0}; 121 | 122 | // Annoying state tracking code that you wouldn't need 123 | // in a real event driven system. 124 | if(ChipmunkDemoRightClick != lastClickState){ 125 | if(ChipmunkDemoRightClick){ 126 | // MouseDown 127 | sliceStart = ChipmunkDemoMouse; 128 | } else { 129 | // MouseUp 130 | SliceContext context = {sliceStart, ChipmunkDemoMouse, space}; 131 | cpSpaceSegmentQuery(space, sliceStart, ChipmunkDemoMouse, 0.0, GRAB_FILTER, cast(cpSpaceSegmentQueryFunc)&SliceQuery, &context); 132 | } 133 | 134 | lastClickState = ChipmunkDemoRightClick; 135 | } 136 | 137 | if(ChipmunkDemoRightClick){ 138 | ChipmunkDebugDrawSegment(sliceStart, ChipmunkDemoMouse, RGBAColor(1, 0, 0, 1)); 139 | } 140 | } 141 | 142 | static cpSpace * 143 | init() 144 | { 145 | ChipmunkDemoMessageString = "Right click and drag to slice up the block."; 146 | 147 | cpSpace *space = cpSpaceNew(); 148 | cpSpaceSetIterations(space, 30); 149 | cpSpaceSetGravity(space, cpv(0, -500)); 150 | cpSpaceSetSleepTimeThreshold(space, 0.5f); 151 | cpSpaceSetCollisionSlop(space, 0.5f); 152 | 153 | cpBody *body_, staticBody = cpSpaceGetStaticBody(space); 154 | cpShape *shape; 155 | 156 | // Create segments around the edge of the screen. 157 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-1000,-240), cpv(1000,-240), 0.0f)); 158 | cpShapeSetElasticity(shape, 1.0f); 159 | cpShapeSetFriction(shape, 1.0f); 160 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 161 | 162 | cpFloat width = 200.0f; 163 | cpFloat height = 300.0f; 164 | cpFloat mass = width*height*DENSITY; 165 | cpFloat moment = cpMomentForBox(mass, width, height); 166 | 167 | body_ = cpSpaceAddBody(space, cpBodyNew(mass, moment)); 168 | 169 | shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, width, height, 0.0)); 170 | cpShapeSetFriction(shape, 0.6f); 171 | 172 | return space; 173 | } 174 | 175 | static void 176 | destroy(cpSpace *space) 177 | { 178 | ChipmunkDemoFreeSpaceChildren(space); 179 | cpSpaceFree(space); 180 | } 181 | 182 | ChipmunkDemo Slice = { 183 | "Slice.", 184 | 1.0/60.0, 185 | &init, 186 | &update, 187 | &ChipmunkDemoDefaultDrawImpl, 188 | &destroy, 189 | }; 190 | -------------------------------------------------------------------------------- /demo/Smooth.d_: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | import core.stdc.stdlib; 23 | import core.stdc.stdio; 24 | import core.stdc.math; 25 | import core.stdc.string; 26 | 27 | import chipmunk.chipmunk_private; 28 | import ChipmunkDemo; 29 | 30 | static cpBool DrawContacts(cpArbiter *arb, cpSpace *space, void *data){ 31 | cpContactPointSet set = cpArbiterGetContactPointSet(arb); 32 | 33 | for(int i=0; i 0.0 ? 1.0 : -1.0); 40 | cpBodySetVelocity(tankControlBody, cpvrotate(cpBodyGetRotation(tankBody), cpv(30.0f*direction, 0.0f))); 41 | } 42 | 43 | cpSpaceStep(space, dt); 44 | } 45 | 46 | static cpBody * 47 | add_box(cpSpace *space, cpFloat size, cpFloat mass) 48 | { 49 | cpFloat radius = cpvlength(cpv(size, size)); 50 | 51 | cpBody *body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size))); 52 | cpBodySetPosition(body_, cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius))); 53 | 54 | cpShape *shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, size, size, 0.0)); 55 | cpShapeSetElasticity(shape, 0.0f); 56 | cpShapeSetFriction(shape, 0.7f); 57 | 58 | return body_; 59 | } 60 | 61 | static cpSpace * 62 | init() 63 | { 64 | ChipmunkDemoMessageString = "Use the mouse to drive the tank, it will follow the cursor."; 65 | 66 | cpSpace *space = cpSpaceNew(); 67 | cpSpaceSetIterations(space, 10); 68 | cpSpaceSetSleepTimeThreshold(space, 0.5f); 69 | 70 | cpBody *staticBody = cpSpaceGetStaticBody(space); 71 | cpShape *shape; 72 | 73 | // Create segments around the edge of the screen. 74 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); 75 | cpShapeSetElasticity(shape, 1.0f); 76 | cpShapeSetFriction(shape, 1.0f); 77 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 78 | 79 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); 80 | cpShapeSetElasticity(shape, 1.0f); 81 | cpShapeSetFriction(shape, 1.0f); 82 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 83 | 84 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); 85 | cpShapeSetElasticity(shape, 1.0f); 86 | cpShapeSetFriction(shape, 1.0f); 87 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 88 | 89 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f)); 90 | cpShapeSetElasticity(shape, 1.0f); 91 | cpShapeSetFriction(shape, 1.0f); 92 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 93 | 94 | for(int i=0; i<50; i++){ 95 | cpBody *body_ = add_box(space, 20, 1); 96 | 97 | cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, body_, cpvzero, cpvzero)); 98 | cpConstraintSetMaxBias(pivot, 0); // disable joint correction 99 | cpConstraintSetMaxForce(pivot, 1000.0f); // emulate linear friction 100 | 101 | cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(staticBody, body_, 0.0f, 1.0f)); 102 | cpConstraintSetMaxBias(gear, 0); // disable joint correction 103 | cpConstraintSetMaxForce(gear, 5000.0f); // emulate angular friction 104 | } 105 | 106 | // We joint the tank to the control body_ and control the tank indirectly by modifying the control body_. 107 | tankControlBody = cpSpaceAddBody(space, cpBodyNewKinematic()); 108 | tankBody = add_box(space, 30, 10); 109 | 110 | cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero)); 111 | cpConstraintSetMaxBias(pivot, 0); // disable joint correction 112 | cpConstraintSetMaxForce(pivot, 10000.0f); // emulate linear friction 113 | 114 | cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(tankControlBody, tankBody, 0.0f, 1.0f)); 115 | cpConstraintSetErrorBias(gear, 0); // attempt to fully correct the joint each step 116 | cpConstraintSetMaxBias(gear, 1.2f); // but limit it's angular correction rate 117 | cpConstraintSetMaxForce(gear, 50000.0f); // emulate angular friction 118 | 119 | return space; 120 | } 121 | 122 | static void 123 | destroy(cpSpace *space) 124 | { 125 | ChipmunkDemoFreeSpaceChildren(space); 126 | cpSpaceFree(space); 127 | } 128 | 129 | ChipmunkDemo Tank = { 130 | "Tank", 131 | 1.0/60.0, 132 | &init, 133 | &update, 134 | &ChipmunkDemoDefaultDrawImpl, 135 | &destroy, 136 | }; 137 | -------------------------------------------------------------------------------- /demo/TheoJansen.d: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007 Scott Lembcke 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | 22 | /* 23 | * The previous WalkBot demo I designed was fairly disappointing, so I implemented 24 | * the mechanism that Theo Jansen uses in his kinetic sculptures. Brilliant. 25 | * Read more here: http://en.wikipedia.org/wiki/Theo_Jansen 26 | */ 27 | 28 | import chipmunk; 29 | import ChipmunkDemo; 30 | 31 | static cpConstraint *motor; 32 | 33 | static void 34 | update(cpSpace *space, double dt) 35 | { 36 | cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y)/3.0f; 37 | cpFloat rate = ChipmunkDemoKeyboard.x*10.0f*coef; 38 | cpSimpleMotorSetRate(motor, rate); 39 | cpConstraintSetMaxForce(motor, (rate) ? 100000.0f : 0.0f); 40 | 41 | cpSpaceStep(space, dt); 42 | } 43 | 44 | static cpFloat seg_radius = 3.0f; 45 | 46 | static void 47 | make_leg(cpSpace *space, cpFloat side, cpFloat offset, cpBody *chassis, cpBody *crank, cpVect anchor) 48 | { 49 | cpVect a, b; 50 | cpShape *shape; 51 | 52 | cpFloat leg_mass = 1.0f; 53 | 54 | // make leg 55 | a = cpvzero, b = cpv(0.0f, side); 56 | cpBody *upper_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f))); 57 | cpBodySetPosition(upper_leg, cpv(offset, 0.0f)); 58 | 59 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(upper_leg, a, b, seg_radius)); 60 | cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); 61 | 62 | cpSpaceAddConstraint(space, cpPivotJointNew2(chassis, upper_leg, cpv(offset, 0.0f), cpvzero)); 63 | 64 | // lower leg 65 | a = cpvzero, b = cpv(0.0f, -1.0f*side); 66 | cpBody *lower_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f))); 67 | cpBodySetPosition(lower_leg, cpv(offset, -side)); 68 | 69 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(lower_leg, a, b, seg_radius)); 70 | cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); 71 | 72 | shape = cpSpaceAddShape(space, cpCircleShapeNew(lower_leg, seg_radius*2.0f, b)); 73 | cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); 74 | cpShapeSetElasticity(shape, 0.0f); 75 | cpShapeSetFriction(shape, 1.0f); 76 | 77 | cpSpaceAddConstraint(space, cpPinJointNew(chassis, lower_leg, cpv(offset, 0.0f), cpvzero)); 78 | 79 | cpSpaceAddConstraint(space, cpGearJointNew(upper_leg, lower_leg, 0.0f, 1.0f)); 80 | 81 | cpConstraint *constraint; 82 | cpFloat diag = cpfsqrt(side*side + offset*offset); 83 | 84 | constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, upper_leg, anchor, cpv(0.0f, side))); 85 | cpPinJointSetDist(constraint, diag); 86 | 87 | constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, lower_leg, anchor, cpvzero)); 88 | cpPinJointSetDist(constraint, diag); 89 | } 90 | 91 | static cpSpace * 92 | init() 93 | { 94 | ChipmunkDemoMessageString = "Use the arrow keys to control the machine."; 95 | 96 | cpSpace *space = cpSpaceNew(); 97 | cpSpaceSetIterations(space, 20); 98 | cpSpaceSetGravity(space, cpv(0,-500)); 99 | 100 | cpBody *staticBody = cpSpaceGetStaticBody(space); 101 | cpShape *shape; 102 | cpVect a, b; 103 | 104 | // Create segments around the edge of the screen. 105 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); 106 | cpShapeSetElasticity(shape, 1.0f); 107 | cpShapeSetFriction(shape, 1.0f); 108 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 109 | 110 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); 111 | cpShapeSetElasticity(shape, 1.0f); 112 | cpShapeSetFriction(shape, 1.0f); 113 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 114 | 115 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); 116 | cpShapeSetElasticity(shape, 1.0f); 117 | cpShapeSetFriction(shape, 1.0f); 118 | cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); 119 | 120 | cpFloat offset = 30.0f; 121 | 122 | // make chassis 123 | cpFloat chassis_mass = 2.0f; 124 | a = cpv(-offset, 0.0f), b = cpv(offset, 0.0f); 125 | cpBody *chassis = cpSpaceAddBody(space, cpBodyNew(chassis_mass, cpMomentForSegment(chassis_mass, a, b, 0.0f))); 126 | 127 | shape = cpSpaceAddShape(space, cpSegmentShapeNew(chassis, a, b, seg_radius)); 128 | cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); 129 | 130 | // make crank 131 | cpFloat crank_mass = 1.0f; 132 | cpFloat crank_radius = 13.0f; 133 | cpBody *crank = cpSpaceAddBody(space, cpBodyNew(crank_mass, cpMomentForCircle(crank_mass, crank_radius, 0.0f, cpvzero))); 134 | 135 | shape = cpSpaceAddShape(space, cpCircleShapeNew(crank, crank_radius, cpvzero)); 136 | cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); 137 | 138 | cpSpaceAddConstraint(space, cpPivotJointNew2(chassis, crank, cpvzero, cpvzero)); 139 | 140 | cpFloat side = 30.0f; 141 | 142 | int num_legs = 2; 143 | for(int i=0; i b) ? a : b; 100 | } 101 | 102 | /// Return the min of two cpFloats. 103 | static cpFloat cpfmin(cpFloat a, cpFloat b) 104 | { 105 | return (a < b) ? a : b; 106 | } 107 | 108 | /// Return the absolute value of a cpFloat. 109 | static cpFloat cpfabs(cpFloat f) 110 | { 111 | return (f < 0) ? -f : f; 112 | } 113 | 114 | /// Clamp @c f to be between @c min and @c max. 115 | static cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max) 116 | { 117 | return cpfmin(cpfmax(f, min), max); 118 | } 119 | 120 | /// Clamp @c f to be between 0 and 1. 121 | static cpFloat cpfclamp01(cpFloat f) 122 | { 123 | return cpfmax(0.0f, cpfmin(f, 1.0f)); 124 | } 125 | 126 | /// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent. 127 | static cpFloat cpflerp(cpFloat f1, cpFloat f2, cpFloat t) 128 | { 129 | return f1*(1.0f - t) + f2*t; 130 | } 131 | 132 | /// Linearly interpolate from @c f1 to @c f2 by no more than @c d. 133 | static cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d) 134 | { 135 | return f1 + cpfclamp(f2 - f1, -d, d); 136 | } 137 | -------------------------------------------------------------------------------- /src/chipmunk/chipmunk_unsafe.d: -------------------------------------------------------------------------------- 1 | module chipmunk.chipmunk_unsafe; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | void cpCircleShapeSetRadius (cpShape* shape, cpFloat radius); 10 | void cpCircleShapeSetOffset (cpShape* shape, cpVect offset); 11 | void cpSegmentShapeSetEndpoints (cpShape* shape, cpVect a, cpVect b); 12 | void cpSegmentShapeSetRadius (cpShape* shape, cpFloat radius); 13 | void cpPolyShapeSetVerts (cpShape* shape, int count, cpVect* verts, cpTransform transform); 14 | void cpPolyShapeSetVertsRaw (cpShape* shape, int count, cpVect* verts); 15 | void cpPolyShapeSetRadius (cpShape* shape, cpFloat radius); 16 | -------------------------------------------------------------------------------- /src/chipmunk/cpArbiter.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpArbiter; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | enum CP_MAX_CONTACTS_PER_ARBITER = 2; 10 | 11 | struct cpContactPointSet 12 | { 13 | int count; 14 | cpVect normal; 15 | contactPoint[CP_MAX_CONTACTS_PER_ARBITER] points; 16 | 17 | private struct contactPoint { 18 | cpVect pointA, pointB; 19 | cpFloat distance; 20 | } 21 | } 22 | 23 | cpFloat cpArbiterGetRestitution (const(cpArbiter)* arb); 24 | void cpArbiterSetRestitution (cpArbiter* arb, cpFloat restitution); 25 | cpFloat cpArbiterGetFriction (const(cpArbiter)* arb); 26 | void cpArbiterSetFriction (cpArbiter* arb, cpFloat friction); 27 | cpVect cpArbiterGetSurfaceVelocity (cpArbiter* arb); 28 | void cpArbiterSetSurfaceVelocity (cpArbiter* arb, cpVect vr); 29 | cpDataPointer cpArbiterGetUserData (const(cpArbiter)* arb); 30 | void cpArbiterSetUserData (cpArbiter* arb, cpDataPointer userData); 31 | cpVect cpArbiterTotalImpulse (const(cpArbiter)* arb); 32 | cpFloat cpArbiterTotalKE (const(cpArbiter)* arb); 33 | cpBool cpArbiterIgnore (cpArbiter* arb); 34 | void cpArbiterGetShapes (const(cpArbiter)* arb, cpShape** a, cpShape** b); 35 | void cpArbiterGetBodies (const(cpArbiter)* arb, cpBody** a, cpBody** b); 36 | cpContactPointSet cpArbiterGetContactPointSet (const(cpArbiter)* arb); 37 | void cpArbiterSetContactPointSet (cpArbiter* arb, cpContactPointSet* set); 38 | cpBool cpArbiterIsFirstContact (const(cpArbiter)* arb); 39 | cpBool cpArbiterIsRemoval (const(cpArbiter)* arb); 40 | int cpArbiterGetCount (const(cpArbiter)* arb); 41 | cpVect cpArbiterGetNormal (const(cpArbiter)* arb); 42 | cpVect cpArbiterGetPointA (const(cpArbiter)* arb, int i); 43 | cpVect cpArbiterGetPointB (const(cpArbiter)* arb, int i); 44 | cpFloat cpArbiterGetDepth (const(cpArbiter)* arb, int i); 45 | cpBool cpArbiterCallWildcardBeginA (cpArbiter* arb, cpSpace* space); 46 | cpBool cpArbiterCallWildcardBeginB (cpArbiter* arb, cpSpace* space); 47 | cpBool cpArbiterCallWildcardPreSolveA (cpArbiter* arb, cpSpace* space); 48 | cpBool cpArbiterCallWildcardPreSolveB (cpArbiter* arb, cpSpace* space); 49 | void cpArbiterCallWildcardPostSolveA (cpArbiter* arb, cpSpace* space); 50 | void cpArbiterCallWildcardPostSolveB (cpArbiter* arb, cpSpace* space); 51 | void cpArbiterCallWildcardSeparateA (cpArbiter* arb, cpSpace* space); 52 | void cpArbiterCallWildcardSeparateB (cpArbiter* arb, cpSpace* space); 53 | -------------------------------------------------------------------------------- /src/chipmunk/cpBB.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpBB; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.cpVect; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | struct cpBB 10 | { 11 | cpFloat l; 12 | cpFloat b; 13 | cpFloat r; 14 | cpFloat t; 15 | } 16 | 17 | // these functions are inlined in the chipmunk headers: 18 | 19 | static cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) 20 | { 21 | cpBB bb = {l, b, r, t}; 22 | return bb; 23 | } 24 | 25 | /// Constructs a cpBB centered on a point with the given extents (half sizes). 26 | static cpBB 27 | cpBBNewForExtents(const cpVect c, const cpFloat hw, const cpFloat hh) 28 | { 29 | return cpBBNew(c.x - hw, c.y - hh, c.x + hw, c.y + hh); 30 | } 31 | 32 | /// Constructs a cpBB for a circle with the given position and radius. 33 | static cpBB cpBBNewForCircle(const cpVect p, const cpFloat r) 34 | { 35 | return cpBBNewForExtents(p, r, r); 36 | } 37 | 38 | /// Returns true if @c a and @c b intersect. 39 | static cpBool cpBBIntersects(const cpBB a, const cpBB b) 40 | { 41 | return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t); 42 | } 43 | 44 | /// Returns true if @c other lies completely within @c bb. 45 | static cpBool cpBBContainsBB(const cpBB bb, const cpBB other) 46 | { 47 | return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t); 48 | } 49 | 50 | /// Returns true if @c bb contains @c v. 51 | static cpBool cpBBContainsVect(const cpBB bb, const cpVect v) 52 | { 53 | return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y); 54 | } 55 | 56 | /// Returns a bounding box that holds both bounding boxes. 57 | static cpBB cpBBMerge(const cpBB a, const cpBB b){ 58 | return cpBBNew( 59 | cpfmin(a.l, b.l), 60 | cpfmin(a.b, b.b), 61 | cpfmax(a.r, b.r), 62 | cpfmax(a.t, b.t) 63 | ); 64 | } 65 | 66 | /// Returns a bounding box that holds both @c bb and @c v. 67 | static cpBB cpBBExpand(const cpBB bb, const cpVect v){ 68 | return cpBBNew( 69 | cpfmin(bb.l, v.x), 70 | cpfmin(bb.b, v.y), 71 | cpfmax(bb.r, v.x), 72 | cpfmax(bb.t, v.y) 73 | ); 74 | } 75 | 76 | /// Returns the center of a bounding box. 77 | static cpVect 78 | cpBBCenter(cpBB bb) 79 | { 80 | return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f); 81 | } 82 | 83 | /// Returns the area of the bounding box. 84 | static cpFloat cpBBArea(cpBB bb) 85 | { 86 | return (bb.r - bb.l)*(bb.t - bb.b); 87 | } 88 | 89 | /// Merges @c a and @c b and returns the area of the merged bounding box. 90 | static cpFloat cpBBMergedArea(cpBB a, cpBB b) 91 | { 92 | return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b)); 93 | } 94 | 95 | /// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit. 96 | static cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b) 97 | { 98 | cpVect delta = cpvsub(b, a); 99 | cpFloat tmin = -INFINITY, tmax = INFINITY; 100 | 101 | if(delta.x != 0.0f){ 102 | cpFloat t1 = (bb.l - a.x)/delta.x; 103 | cpFloat t2 = (bb.r - a.x)/delta.x; 104 | tmin = cpfmax(tmin, cpfmin(t1, t2)); 105 | tmax = cpfmin(tmax, cpfmax(t1, t2)); 106 | } 107 | 108 | if(delta.y != 0.0f){ 109 | cpFloat t1 = (bb.b - a.y)/delta.y; 110 | cpFloat t2 = (bb.t - a.y)/delta.y; 111 | tmin = cpfmax(tmin, cpfmin(t1, t2)); 112 | tmax = cpfmin(tmax, cpfmax(t1, t2)); 113 | } 114 | 115 | if(tmin <= tmax && 0.0f <= tmax && tmin <= 1.0f){ 116 | return cpfmax(tmin, 0.0f); 117 | } 118 | 119 | return INFINITY; 120 | } 121 | 122 | /// Return true if the bounding box intersects the line segment with ends @c a and @c b. 123 | static cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b) 124 | { 125 | return (cpBBSegmentQuery(bb, a, b) != INFINITY); 126 | } 127 | 128 | /// Clamp a vector to a bounding box. 129 | static cpVect 130 | cpBBClampVect(const cpBB bb, const cpVect v) 131 | { 132 | return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t)); 133 | } 134 | 135 | /// Wrap a vector to a bounding box. 136 | static cpVect 137 | cpBBWrapVect(const cpBB bb, const cpVect v) 138 | { 139 | cpFloat dx = cpfabs(bb.r - bb.l); 140 | cpFloat modx = cpfmod(v.x - bb.l, dx); 141 | cpFloat x = (modx > 0.0f) ? modx : modx + dx; 142 | 143 | cpFloat dy = cpfabs(bb.t - bb.b); 144 | cpFloat mody = cpfmod(v.y - bb.b, dy); 145 | cpFloat y = (mody > 0.0f) ? mody : mody + dy; 146 | 147 | return cpv(x + bb.l, y + bb.b); 148 | } 149 | 150 | /// Returns a bounding box offseted by @c v. 151 | static cpBB 152 | cpBBOffset(const cpBB bb, const cpVect v) 153 | { 154 | return cpBBNew( 155 | bb.l + v.x, 156 | bb.b + v.y, 157 | bb.r + v.x, 158 | bb.t + v.y 159 | ); 160 | } 161 | 162 | -------------------------------------------------------------------------------- /src/chipmunk/cpBody.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpBody; 2 | import chipmunk.chipmunk_types; 3 | import chipmunk.chipmunk_structs; 4 | 5 | extern (C): 6 | @nogc nothrow: 7 | 8 | alias void function (cpBody*, cpVect, double, double) cpBodyVelocityFunc; 9 | alias void function (cpBody*, double) cpBodyPositionFunc; 10 | alias void function (cpBody*, cpShape*, void*) cpBodyShapeIteratorFunc; 11 | alias void function (cpBody*, cpConstraint*, void*) cpBodyConstraintIteratorFunc; 12 | alias void function (cpBody*, cpArbiter*, void*) cpBodyArbiterIteratorFunc; 13 | 14 | enum cpBodyType 15 | { 16 | CP_BODY_TYPE_DYNAMIC = 0, 17 | CP_BODY_TYPE_KINEMATIC = 1, 18 | CP_BODY_TYPE_STATIC = 2 19 | } 20 | 21 | cpBody* cpBodyAlloc (); 22 | cpBody* cpBodyInit (cpBody* body_, cpFloat mass, cpFloat moment); 23 | cpBody* cpBodyNew (cpFloat mass, cpFloat moment); 24 | cpBody* cpBodyNewKinematic (); 25 | cpBody* cpBodyNewStatic (); 26 | void cpBodyDestroy (cpBody* body_); 27 | void cpBodyFree (cpBody* body_); 28 | void cpBodyActivate (cpBody* body_); 29 | void cpBodyActivateStatic (cpBody* body_, cpShape* filter); 30 | void cpBodySleep (cpBody* body_); 31 | void cpBodySleepWithGroup (cpBody* body_, cpBody* group); 32 | cpBool cpBodyIsSleeping (const(cpBody)* body_); 33 | cpBodyType cpBodyGetType (cpBody* body_); 34 | void cpBodySetType (cpBody* body_, cpBodyType type); 35 | cpSpace* cpBodyGetSpace (const(cpBody)* body_); 36 | cpFloat cpBodyGetMass (const(cpBody)* body_); 37 | void cpBodySetMass (cpBody* body_, cpFloat m); 38 | cpFloat cpBodyGetMoment (const(cpBody)* body_); 39 | void cpBodySetMoment (cpBody* body_, cpFloat i); 40 | cpVect cpBodyGetPosition (const(cpBody)* body_); 41 | void cpBodySetPosition (cpBody* body_, cpVect pos); 42 | cpVect cpBodyGetCenterOfGravity (const(cpBody)* body_); 43 | void cpBodySetCenterOfGravity (cpBody* body_, cpVect cog); 44 | cpVect cpBodyGetVelocity (const(cpBody)* body_); 45 | void cpBodySetVelocity (cpBody* body_, cpVect velocity); 46 | cpVect cpBodyGetForce (const(cpBody)* body_); 47 | void cpBodySetForce (cpBody* body_, cpVect force); 48 | cpFloat cpBodyGetAngle (const(cpBody)* body_); 49 | void cpBodySetAngle (cpBody* body_, cpFloat a); 50 | cpFloat cpBodyGetAngularVelocity (const(cpBody)* body_); 51 | void cpBodySetAngularVelocity (cpBody* body_, cpFloat angularVelocity); 52 | cpFloat cpBodyGetTorque (const(cpBody)* body_); 53 | void cpBodySetTorque (cpBody* body_, cpFloat torque); 54 | cpVect cpBodyGetRotation (const(cpBody)* body_); 55 | cpDataPointer cpBodyGetUserData (const(cpBody)* body_); 56 | void cpBodySetUserData (cpBody* body_, cpDataPointer userData); 57 | void cpBodySetVelocityUpdateFunc (cpBody* body_, cpBodyVelocityFunc velocityFunc); 58 | void cpBodySetPositionUpdateFunc (cpBody* body_, cpBodyPositionFunc positionFunc); 59 | void cpBodyUpdateVelocity (cpBody* body_, cpVect gravity, cpFloat damping, cpFloat dt); 60 | void cpBodyUpdatePosition (cpBody* body_, cpFloat dt); 61 | cpVect cpBodyLocalToWorld (const(cpBody)* body_, const cpVect point); 62 | cpVect cpBodyWorldToLocal (const(cpBody)* body_, const cpVect point); 63 | void cpBodyApplyForceAtWorldPoint (cpBody* body_, cpVect force, cpVect point); 64 | void cpBodyApplyForceAtLocalPoint (cpBody* body_, cpVect force, cpVect point); 65 | void cpBodyApplyImpulseAtWorldPoint (cpBody* body_, cpVect impulse, cpVect point); 66 | void cpBodyApplyImpulseAtLocalPoint (cpBody* body_, cpVect impulse, cpVect point); 67 | cpVect cpBodyGetVelocityAtWorldPoint (const(cpBody)* body_, cpVect point); 68 | cpVect cpBodyGetVelocityAtLocalPoint (const(cpBody)* body_, cpVect point); 69 | cpFloat cpBodyKineticEnergy (const(cpBody)* body_); 70 | void cpBodyEachShape (cpBody* body_, cpBodyShapeIteratorFunc func, void* data); 71 | void cpBodyEachConstraint (cpBody* body_, cpBodyConstraintIteratorFunc func, void* data); 72 | void cpBodyEachArbiter (cpBody* body_, cpBodyArbiterIteratorFunc func, void* data); 73 | -------------------------------------------------------------------------------- /src/chipmunk/cpConstraint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpConstraint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | alias void function (cpConstraint*, cpSpace*) cpConstraintPreSolveFunc; 10 | alias void function (cpConstraint*, cpSpace*) cpConstraintPostSolveFunc; 11 | 12 | void cpConstraintDestroy (cpConstraint* constraint); 13 | void cpConstraintFree (cpConstraint* constraint); 14 | cpSpace* cpConstraintGetSpace (const(cpConstraint)* constraint); 15 | cpBody* cpConstraintGetBodyA (const(cpConstraint)* constraint); 16 | cpBody* cpConstraintGetBodyB (const(cpConstraint)* constraint); 17 | cpFloat cpConstraintGetMaxForce (const(cpConstraint)* constraint); 18 | void cpConstraintSetMaxForce (cpConstraint* constraint, cpFloat maxForce); 19 | cpFloat cpConstraintGetErrorBias (const(cpConstraint)* constraint); 20 | void cpConstraintSetErrorBias (cpConstraint* constraint, cpFloat errorBias); 21 | cpFloat cpConstraintGetMaxBias (const(cpConstraint)* constraint); 22 | void cpConstraintSetMaxBias (cpConstraint* constraint, cpFloat maxBias); 23 | cpBool cpConstraintGetCollideBodies (const(cpConstraint)* constraint); 24 | void cpConstraintSetCollideBodies (cpConstraint* constraint, cpBool collideBodies); 25 | cpConstraintPreSolveFunc cpConstraintGetPreSolveFunc (const(cpConstraint)* constraint); 26 | void cpConstraintSetPreSolveFunc (cpConstraint* constraint, cpConstraintPreSolveFunc preSolveFunc); 27 | cpConstraintPostSolveFunc cpConstraintGetPostSolveFunc (const(cpConstraint)* constraint); 28 | void cpConstraintSetPostSolveFunc (cpConstraint* constraint, cpConstraintPostSolveFunc postSolveFunc); 29 | cpDataPointer cpConstraintGetUserData (const(cpConstraint)* constraint); 30 | void cpConstraintSetUserData (cpConstraint* constraint, cpDataPointer userData); 31 | cpFloat cpConstraintGetImpulse (cpConstraint* constraint); 32 | -------------------------------------------------------------------------------- /src/chipmunk/cpDampedRotarySpring.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpDampedRotarySpring; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | alias double function (cpConstraint*, double) cpDampedRotarySpringTorqueFunc; 10 | 11 | cpBool cpConstraintIsDampedRotarySpring (const(cpConstraint)* constraint); 12 | cpDampedRotarySpring* cpDampedRotarySpringAlloc (); 13 | cpDampedRotarySpring* cpDampedRotarySpringInit (cpDampedRotarySpring* joint, cpBody* a, cpBody* b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 14 | cpConstraint* cpDampedRotarySpringNew (cpBody* a, cpBody* b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 15 | cpFloat cpDampedRotarySpringGetRestAngle (const(cpConstraint)* constraint); 16 | void cpDampedRotarySpringSetRestAngle (cpConstraint* constraint, cpFloat restAngle); 17 | cpFloat cpDampedRotarySpringGetStiffness (const(cpConstraint)* constraint); 18 | void cpDampedRotarySpringSetStiffness (cpConstraint* constraint, cpFloat stiffness); 19 | cpFloat cpDampedRotarySpringGetDamping (const(cpConstraint)* constraint); 20 | void cpDampedRotarySpringSetDamping (cpConstraint* constraint, cpFloat damping); 21 | cpDampedRotarySpringTorqueFunc cpDampedRotarySpringGetSpringTorqueFunc (const(cpConstraint)* constraint); 22 | void cpDampedRotarySpringSetSpringTorqueFunc (cpConstraint* constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc); 23 | -------------------------------------------------------------------------------- /src/chipmunk/cpDampedSpring.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpDampedSpring; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | import chipmunk.cpConstraint; 6 | import chipmunk.cpBB; 7 | 8 | extern (C): 9 | @nogc nothrow: 10 | 11 | alias double function (cpConstraint*, double) cpDampedSpringForceFunc; 12 | 13 | cpBool cpConstraintIsDampedSpring (const(cpConstraint)* constraint); 14 | cpDampedSpring* cpDampedSpringAlloc (); 15 | cpDampedSpring* cpDampedSpringInit (cpDampedSpring* joint, cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping); 16 | cpConstraint* cpDampedSpringNew (cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping); 17 | cpVect cpDampedSpringGetAnchorA (const(cpConstraint)* constraint); 18 | void cpDampedSpringSetAnchorA (cpConstraint* constraint, cpVect anchorA); 19 | cpVect cpDampedSpringGetAnchorB (const(cpConstraint)* constraint); 20 | void cpDampedSpringSetAnchorB (cpConstraint* constraint, cpVect anchorB); 21 | cpFloat cpDampedSpringGetRestLength (const(cpConstraint)* constraint); 22 | void cpDampedSpringSetRestLength (cpConstraint* constraint, cpFloat restLength); 23 | cpFloat cpDampedSpringGetStiffness (const(cpConstraint)* constraint); 24 | void cpDampedSpringSetStiffness (cpConstraint* constraint, cpFloat stiffness); 25 | cpFloat cpDampedSpringGetDamping (const(cpConstraint)* constraint); 26 | void cpDampedSpringSetDamping (cpConstraint* constraint, cpFloat damping); 27 | cpDampedSpringForceFunc cpDampedSpringGetSpringForceFunc (const(cpConstraint)* constraint); 28 | void cpDampedSpringSetSpringForceFunc (cpConstraint* constraint, cpDampedSpringForceFunc springForceFunc); 29 | -------------------------------------------------------------------------------- /src/chipmunk/cpGearJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpGearJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsGearJoint (const(cpConstraint)* constraint); 10 | cpGearJoint* cpGearJointAlloc (); 11 | cpGearJoint* cpGearJointInit (cpGearJoint* joint, cpBody* a, cpBody* b, cpFloat phase, cpFloat ratio); 12 | cpConstraint* cpGearJointNew (cpBody* a, cpBody* b, cpFloat phase, cpFloat ratio); 13 | cpFloat cpGearJointGetPhase (const(cpConstraint)* constraint); 14 | void cpGearJointSetPhase (cpConstraint* constraint, cpFloat phase); 15 | cpFloat cpGearJointGetRatio (const(cpConstraint)* constraint); 16 | void cpGearJointSetRatio (cpConstraint* constraint, cpFloat ratio); 17 | -------------------------------------------------------------------------------- /src/chipmunk/cpGrooveJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpGrooveJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsGrooveJoint (const(cpConstraint)* constraint); 10 | cpGrooveJoint* cpGrooveJointAlloc (); 11 | cpGrooveJoint* cpGrooveJointInit (cpGrooveJoint* joint, cpBody* a, cpBody* b, cpVect groove_a, cpVect groove_b, cpVect anchorB); 12 | cpConstraint* cpGrooveJointNew (cpBody* a, cpBody* b, cpVect groove_a, cpVect groove_b, cpVect anchorB); 13 | cpVect cpGrooveJointGetGrooveA (const(cpConstraint)* constraint); 14 | void cpGrooveJointSetGrooveA (cpConstraint* constraint, cpVect grooveA); 15 | cpVect cpGrooveJointGetGrooveB (const(cpConstraint)* constraint); 16 | void cpGrooveJointSetGrooveB (cpConstraint* constraint, cpVect grooveB); 17 | cpVect cpGrooveJointGetAnchorB (const(cpConstraint)* constraint); 18 | void cpGrooveJointSetAnchorB (cpConstraint* constraint, cpVect anchorB); 19 | cpBool cpConstraintIsGrooveJoint (const(cpConstraint)* constraint); 20 | -------------------------------------------------------------------------------- /src/chipmunk/cpHastySpace.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpHastySpace; 2 | import core.stdc.config; 3 | 4 | import chipmunk.chipmunk_types; 5 | import chipmunk.chipmunk_structs; 6 | 7 | extern (C): 8 | @nogc nothrow: 9 | 10 | struct cpHastySpace; 11 | 12 | cpSpace* cpHastySpaceNew (); 13 | void cpHastySpaceFree (cpSpace* space); 14 | void cpHastySpaceSetThreads (cpSpace* space, c_ulong threads); 15 | c_ulong cpHastySpaceGetThreads (cpSpace* space); 16 | void cpHastySpaceStep (cpSpace* space, cpFloat dt); 17 | -------------------------------------------------------------------------------- /src/chipmunk/cpMarch.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpMarch; 2 | import core.stdc.config; 3 | 4 | import chipmunk.chipmunk_types; 5 | import chipmunk.chipmunk_structs; 6 | import chipmunk.cpBB; 7 | 8 | extern (C): 9 | @nogc nothrow: 10 | 11 | alias double function (cpVect, void*) cpMarchSampleFunc; 12 | alias void function (cpVect, cpVect, void*) cpMarchSegmentFunc; 13 | 14 | void cpMarchSoft (cpBB bb, c_ulong x_samples, c_ulong y_samples, cpFloat threshold, cpMarchSegmentFunc segment, void* segment_data, cpMarchSampleFunc sample, void* sample_data); 15 | void cpMarchHard (cpBB bb, c_ulong x_samples, c_ulong y_samples, cpFloat threshold, cpMarchSegmentFunc segment, void* segment_data, cpMarchSampleFunc sample, void* sample_data); 16 | -------------------------------------------------------------------------------- /src/chipmunk/cpPinJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpPinJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsPinJoint (const(cpConstraint)* constraint); 10 | cpPinJoint* cpPinJointAlloc (); 11 | cpPinJoint* cpPinJointInit (cpPinJoint* joint, cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB); 12 | cpConstraint* cpPinJointNew (cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB); 13 | cpVect cpPinJointGetAnchorA (const(cpConstraint)* constraint); 14 | void cpPinJointSetAnchorA (cpConstraint* constraint, cpVect anchorA); 15 | cpVect cpPinJointGetAnchorB (const(cpConstraint)* constraint); 16 | void cpPinJointSetAnchorB (cpConstraint* constraint, cpVect anchorB); 17 | cpFloat cpPinJointGetDist (const(cpConstraint)* constraint); 18 | void cpPinJointSetDist (cpConstraint* constraint, cpFloat dist); 19 | -------------------------------------------------------------------------------- /src/chipmunk/cpPivotJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpPivotJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsPivotJoint (const(cpConstraint)* constraint); 10 | cpPivotJoint* cpPivotJointAlloc (); 11 | cpPivotJoint* cpPivotJointInit (cpPivotJoint* joint, cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB); 12 | cpConstraint* cpPivotJointNew (cpBody* a, cpBody* b, cpVect pivot); 13 | cpConstraint* cpPivotJointNew2 (cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB); 14 | cpVect cpPivotJointGetAnchorA (const(cpConstraint)* constraint); 15 | void cpPivotJointSetAnchorA (cpConstraint* constraint, cpVect anchorA); 16 | cpVect cpPivotJointGetAnchorB (const(cpConstraint)* constraint); 17 | void cpPivotJointSetAnchorB (cpConstraint* constraint, cpVect anchorB); 18 | -------------------------------------------------------------------------------- /src/chipmunk/cpPolyShape.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpPolyShape; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | import chipmunk.cpBB; 6 | 7 | extern (C): 8 | @nogc nothrow: 9 | 10 | cpPolyShape* cpPolyShapeAlloc (); 11 | cpPolyShape* cpPolyShapeInit (cpPolyShape* poly, cpBody* body_, int count, const(cpVect)* verts, cpTransform transform, cpFloat radius); 12 | cpPolyShape* cpPolyShapeInitRaw (cpPolyShape* poly, cpBody* body_, int count, const(cpVect)* verts, cpFloat radius); 13 | cpShape* cpPolyShapeNew (cpBody* body_, int count, const(cpVect)* verts, cpTransform transform, cpFloat radius); 14 | cpShape* cpPolyShapeNewRaw (cpBody* body_, int count, const(cpVect)* verts, cpFloat radius); 15 | cpPolyShape* cpBoxShapeInit (cpPolyShape* poly, cpBody* body_, cpFloat width, cpFloat height, cpFloat radius); 16 | cpPolyShape* cpBoxShapeInit2 (cpPolyShape* poly, cpBody* body_, cpBB box, cpFloat radius); 17 | cpShape* cpBoxShapeNew (cpBody* body_, cpFloat width, cpFloat height, cpFloat radius); 18 | cpShape* cpBoxShapeNew2 (cpBody* body_, cpBB box, cpFloat radius); 19 | int cpPolyShapeGetCount (const(cpShape)* shape); 20 | cpVect cpPolyShapeGetVert (const(cpShape)* shape, int index); 21 | cpFloat cpPolyShapeGetRadius (const(cpShape)* shape); 22 | -------------------------------------------------------------------------------- /src/chipmunk/cpPolyline.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpPolyline; 2 | 3 | import chipmunk.cpVect; 4 | import chipmunk.chipmunk_types; 5 | 6 | extern (C): 7 | 8 | struct cpPolyline 9 | { 10 | int count; 11 | int capacity; 12 | cpVect[] verts; 13 | } 14 | 15 | struct cpPolylineSet 16 | { 17 | int count; 18 | int capacity; 19 | cpPolyline** lines; 20 | } 21 | @nogc nothrow: 22 | 23 | void cpPolylineFree (cpPolyline* line); 24 | cpBool cpPolylineIsClosed (cpPolyline* line); 25 | cpPolyline* cpPolylineSimplifyCurves (cpPolyline* line, cpFloat tol); 26 | cpPolyline* cpPolylineSimplifyVertexes (cpPolyline* line, cpFloat tol); 27 | cpPolyline* cpPolylineToConvexHull (cpPolyline* line, cpFloat tol); 28 | cpPolylineSet* cpPolylineSetAlloc (); 29 | cpPolylineSet* cpPolylineSetInit (cpPolylineSet* set); 30 | cpPolylineSet* cpPolylineSetNew (); 31 | void cpPolylineSetDestroy (cpPolylineSet* set, cpBool freePolylines); 32 | void cpPolylineSetFree (cpPolylineSet* set, cpBool freePolylines); 33 | void cpPolylineSetCollectSegment (cpVect v0, cpVect v1, cpPolylineSet* lines); 34 | cpPolylineSet* cpPolylineConvexDecomposition (cpPolyline* line, cpFloat tol); 35 | -------------------------------------------------------------------------------- /src/chipmunk/cpRatchetJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpRatchetJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsRatchetJoint (const(cpConstraint)* constraint); 10 | cpRatchetJoint* cpRatchetJointAlloc (); 11 | cpRatchetJoint* cpRatchetJointInit (cpRatchetJoint* joint, cpBody* a, cpBody* b, cpFloat phase, cpFloat ratchet); 12 | cpConstraint* cpRatchetJointNew (cpBody* a, cpBody* b, cpFloat phase, cpFloat ratchet); 13 | cpFloat cpRatchetJointGetAngle (const(cpConstraint)* constraint); 14 | void cpRatchetJointSetAngle (cpConstraint* constraint, cpFloat angle); 15 | cpFloat cpRatchetJointGetPhase (const(cpConstraint)* constraint); 16 | void cpRatchetJointSetPhase (cpConstraint* constraint, cpFloat phase); 17 | cpFloat cpRatchetJointGetRatchet (const(cpConstraint)* constraint); 18 | void cpRatchetJointSetRatchet (cpConstraint* constraint, cpFloat ratchet); 19 | -------------------------------------------------------------------------------- /src/chipmunk/cpRobust.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpRobust; 2 | 3 | import chipmunk.chipmunk_types; 4 | 5 | extern (C): 6 | @nogc nothrow: 7 | 8 | cpBool cpCheckPointGreater (const cpVect a, const cpVect b, const cpVect c); 9 | cpBool cpCheckAxis (cpVect v0, cpVect v1, cpVect p, cpVect n); 10 | -------------------------------------------------------------------------------- /src/chipmunk/cpRotaryLimitJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpRotaryLimitJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsRotaryLimitJoint (const(cpConstraint)* constraint); 10 | cpRotaryLimitJoint* cpRotaryLimitJointAlloc (); 11 | cpRotaryLimitJoint* cpRotaryLimitJointInit (cpRotaryLimitJoint* joint, cpBody* a, cpBody* b, cpFloat min, cpFloat max); 12 | cpConstraint* cpRotaryLimitJointNew (cpBody* a, cpBody* b, cpFloat min, cpFloat max); 13 | cpFloat cpRotaryLimitJointGetMin (const(cpConstraint)* constraint); 14 | void cpRotaryLimitJointSetMin (cpConstraint* constraint, cpFloat min); 15 | cpFloat cpRotaryLimitJointGetMax (const(cpConstraint)* constraint); 16 | void cpRotaryLimitJointSetMax (cpConstraint* constraint, cpFloat max); 17 | -------------------------------------------------------------------------------- /src/chipmunk/cpShape.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpShape; 2 | 3 | import chipmunk.chipmunk; 4 | import chipmunk.chipmunk_types; 5 | import chipmunk.chipmunk_structs; 6 | import chipmunk.cpBB; 7 | import chipmunk.cpArbiter; 8 | 9 | extern (C): 10 | @nogc nothrow: 11 | 12 | static const cpShapeFilter CP_SHAPE_FILTER_ALL = {CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES}; 13 | 14 | /// Collision filter value for a shape that does not collide with anything. 15 | static const cpShapeFilter CP_SHAPE_FILTER_NONE = {CP_NO_GROUP, ~CP_ALL_CATEGORIES, ~CP_ALL_CATEGORIES}; 16 | 17 | struct cpPointQueryInfo 18 | { 19 | const(cpShape)* shape; 20 | cpVect point; 21 | cpFloat distance; 22 | cpVect gradient; 23 | } 24 | 25 | struct cpSegmentQueryInfo 26 | { 27 | const(cpShape)* shape; 28 | cpVect point; 29 | cpVect normal; 30 | cpFloat alpha; 31 | } 32 | 33 | struct cpShapeFilter 34 | { 35 | cpGroup group; 36 | cpBitmask categories; 37 | cpBitmask mask; 38 | } 39 | 40 | // inlined in chipmunk header 41 | static cpShapeFilter 42 | cpShapeFilterNew(cpGroup group, cpBitmask categories, cpBitmask mask) 43 | { 44 | cpShapeFilter filter = {group, categories, mask}; 45 | return filter; 46 | } 47 | 48 | void cpShapeDestroy (cpShape* shape); 49 | void cpShapeFree (cpShape* shape); 50 | cpBB cpShapeCacheBB (cpShape* shape); 51 | cpBB cpShapeUpdate (cpShape* shape, cpTransform transform); 52 | cpFloat cpShapePointQuery (const(cpShape)* shape, cpVect p, cpPointQueryInfo* out_); 53 | cpBool cpShapeSegmentQuery (const(cpShape)* shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo* info); 54 | cpContactPointSet cpShapesCollide (const(cpShape)* a, const(cpShape)* b); 55 | cpSpace* cpShapeGetSpace (const(cpShape)* shape); 56 | cpBody* cpShapeGetBody (const(cpShape)* shape); 57 | void cpShapeSetBody (cpShape* shape, cpBody* body_); 58 | cpFloat cpShapeGetMass (cpShape* shape); 59 | void cpShapeSetMass (cpShape* shape, cpFloat mass); 60 | cpFloat cpShapeGetDensity (cpShape* shape); 61 | void cpShapeSetDensity (cpShape* shape, cpFloat density); 62 | cpFloat cpShapeGetMoment (cpShape* shape); 63 | cpFloat cpShapeGetArea (cpShape* shape); 64 | cpVect cpShapeGetCenterOfGravity (cpShape* shape); 65 | cpBB cpShapeGetBB (const(cpShape)* shape); 66 | cpBool cpShapeGetSensor (const(cpShape)* shape); 67 | void cpShapeSetSensor (cpShape* shape, cpBool sensor); 68 | cpFloat cpShapeGetElasticity (const(cpShape)* shape); 69 | void cpShapeSetElasticity (cpShape* shape, cpFloat elasticity); 70 | cpFloat cpShapeGetFriction (const(cpShape)* shape); 71 | void cpShapeSetFriction (cpShape* shape, cpFloat friction); 72 | cpVect cpShapeGetSurfaceVelocity (const(cpShape)* shape); 73 | void cpShapeSetSurfaceVelocity (cpShape* shape, cpVect surfaceVelocity); 74 | cpDataPointer cpShapeGetUserData (const(cpShape)* shape); 75 | void cpShapeSetUserData (cpShape* shape, cpDataPointer userData); 76 | cpCollisionType cpShapeGetCollisionType (const(cpShape)* shape); 77 | void cpShapeSetCollisionType (cpShape* shape, cpCollisionType collisionType); 78 | cpShapeFilter cpShapeGetFilter (const(cpShape)* shape); 79 | void cpShapeSetFilter (cpShape* shape, cpShapeFilter filter); 80 | cpCircleShape* cpCircleShapeAlloc (); 81 | cpCircleShape* cpCircleShapeInit (cpCircleShape* circle, cpBody* body_, cpFloat radius, cpVect offset); 82 | cpShape* cpCircleShapeNew (cpBody* body_, cpFloat radius, cpVect offset); 83 | cpVect cpCircleShapeGetOffset (const(cpShape)* shape); 84 | cpFloat cpCircleShapeGetRadius (const(cpShape)* shape); 85 | cpSegmentShape* cpSegmentShapeAlloc (); 86 | cpSegmentShape* cpSegmentShapeInit (cpSegmentShape* seg, cpBody* body_, cpVect a, cpVect b, cpFloat radius); 87 | cpShape* cpSegmentShapeNew (cpBody* body_, cpVect a, cpVect b, cpFloat radius); 88 | void cpSegmentShapeSetNeighbors (cpShape* shape, cpVect prev, cpVect next); 89 | cpVect cpSegmentShapeGetA (const(cpShape)* shape); 90 | cpVect cpSegmentShapeGetB (const(cpShape)* shape); 91 | cpVect cpSegmentShapeGetNormal (const(cpShape)* shape); 92 | cpFloat cpSegmentShapeGetRadius (const(cpShape)* shape); 93 | -------------------------------------------------------------------------------- /src/chipmunk/cpSimpleMotor.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpSimpleMotor; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsSimpleMotor (const(cpConstraint)* constraint); 10 | cpSimpleMotor* cpSimpleMotorAlloc (); 11 | cpSimpleMotor* cpSimpleMotorInit (cpSimpleMotor* joint, cpBody* a, cpBody* b, cpFloat rate); 12 | cpConstraint* cpSimpleMotorNew (cpBody* a, cpBody* b, cpFloat rate); 13 | cpFloat cpSimpleMotorGetRate (const(cpConstraint)* constraint); 14 | void cpSimpleMotorSetRate (cpConstraint* constraint, cpFloat rate); 15 | -------------------------------------------------------------------------------- /src/chipmunk/cpSlideJoint.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpSlideJoint; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | 6 | extern (C): 7 | @nogc nothrow: 8 | 9 | cpBool cpConstraintIsSlideJoint (const(cpConstraint)* constraint); 10 | cpSlideJoint* cpSlideJointAlloc (); 11 | cpSlideJoint* cpSlideJointInit (cpSlideJoint* joint, cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max); 12 | cpConstraint* cpSlideJointNew (cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max); 13 | cpVect cpSlideJointGetAnchorA (const(cpConstraint)* constraint); 14 | void cpSlideJointSetAnchorA (cpConstraint* constraint, cpVect anchorA); 15 | cpVect cpSlideJointGetAnchorB (const(cpConstraint)* constraint); 16 | void cpSlideJointSetAnchorB (cpConstraint* constraint, cpVect anchorB); 17 | cpFloat cpSlideJointGetMin (const(cpConstraint)* constraint); 18 | void cpSlideJointSetMin (cpConstraint* constraint, cpFloat min); 19 | cpFloat cpSlideJointGetMax (const(cpConstraint)* constraint); 20 | void cpSlideJointSetMax (cpConstraint* constraint, cpFloat max); 21 | -------------------------------------------------------------------------------- /src/chipmunk/cpSpace.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpSpace; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.chipmunk_structs; 5 | import chipmunk.cpArbiter; 6 | import chipmunk.cpShape; 7 | import chipmunk.cpBB; 8 | 9 | extern (C): 10 | @nogc nothrow: 11 | 12 | alias ubyte function (cpArbiter*, cpSpace*, void*) cpCollisionBeginFunc; 13 | alias ubyte function (cpArbiter*, cpSpace*, void*) cpCollisionPreSolveFunc; 14 | alias void function (cpArbiter*, cpSpace*, void*) cpCollisionPostSolveFunc; 15 | alias void function (cpArbiter*, cpSpace*, void*) cpCollisionSeparateFunc; 16 | alias void function (cpSpace*, void*, void*) cpPostStepFunc; 17 | alias void function (cpShape*, cpVect, double, cpVect, void*) cpSpacePointQueryFunc; 18 | alias void function (cpShape*, cpVect, cpVect, double, void*) cpSpaceSegmentQueryFunc; 19 | alias void function (cpShape*, void*) cpSpaceBBQueryFunc; 20 | alias void function (cpShape*, cpContactPointSet*, void*) cpSpaceShapeQueryFunc; 21 | alias void function (cpBody*, void*) cpSpaceBodyIteratorFunc; 22 | alias void function (cpShape*, void*) cpSpaceShapeIteratorFunc; 23 | alias void function (cpConstraint*, void*) cpSpaceConstraintIteratorFunc; 24 | alias void function (cpVect, double, double, cpSpaceDebugColor, cpSpaceDebugColor, void*) cpSpaceDebugDrawCircleImpl; 25 | alias void function (cpVect, cpVect, cpSpaceDebugColor, void*) cpSpaceDebugDrawSegmentImpl; 26 | alias void function (cpVect, cpVect, double, cpSpaceDebugColor, cpSpaceDebugColor, void*) cpSpaceDebugDrawFatSegmentImpl; 27 | alias void function (int, const(cpVect)*, double, cpSpaceDebugColor, cpSpaceDebugColor, void*) cpSpaceDebugDrawPolygonImpl; 28 | alias void function (double, cpVect, cpSpaceDebugColor, void*) cpSpaceDebugDrawDotImpl; 29 | alias cpSpaceDebugColor function (cpShape*, void*) cpSpaceDebugDrawColorForShapeImpl; 30 | 31 | enum cpSpaceDebugDrawFlags 32 | { 33 | CP_SPACE_DEBUG_DRAW_SHAPES = 1, 34 | CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 2, 35 | CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 4 36 | } 37 | 38 | struct cpCollisionHandler 39 | { 40 | const cpCollisionType typeA; 41 | const cpCollisionType typeB; 42 | cpCollisionBeginFunc beginFunc; 43 | cpCollisionPreSolveFunc preSolveFunc; 44 | cpCollisionPostSolveFunc postSolveFunc; 45 | cpCollisionSeparateFunc separateFunc; 46 | cpDataPointer userData; 47 | } 48 | 49 | struct cpSpaceDebugColor 50 | { 51 | float r; 52 | float g; 53 | float b; 54 | float a; 55 | } 56 | 57 | struct cpSpaceDebugDrawOptions 58 | { 59 | cpSpaceDebugDrawCircleImpl drawCircle; 60 | cpSpaceDebugDrawSegmentImpl drawSegment; 61 | cpSpaceDebugDrawFatSegmentImpl drawFatSegment; 62 | cpSpaceDebugDrawPolygonImpl drawPolygon; 63 | cpSpaceDebugDrawDotImpl drawDot; 64 | cpSpaceDebugDrawFlags flags; 65 | cpSpaceDebugColor shapeOutlineColor; 66 | cpSpaceDebugDrawColorForShapeImpl colorForShape; 67 | cpSpaceDebugColor constraintColor; 68 | cpSpaceDebugColor collisionPointColor; 69 | cpDataPointer data; 70 | } 71 | 72 | cpSpace* cpSpaceAlloc (); 73 | cpSpace* cpSpaceInit (cpSpace* space); 74 | cpSpace* cpSpaceNew (); 75 | void cpSpaceDestroy (cpSpace* space); 76 | void cpSpaceFree (cpSpace* space); 77 | int cpSpaceGetIterations (const(cpSpace)* space); 78 | void cpSpaceSetIterations (cpSpace* space, int iterations); 79 | cpVect cpSpaceGetGravity (const(cpSpace)* space); 80 | void cpSpaceSetGravity (cpSpace* space, cpVect gravity); 81 | cpFloat cpSpaceGetDamping (const(cpSpace)* space); 82 | void cpSpaceSetDamping (cpSpace* space, cpFloat damping); 83 | cpFloat cpSpaceGetIdleSpeedThreshold (const(cpSpace)* space); 84 | void cpSpaceSetIdleSpeedThreshold (cpSpace* space, cpFloat idleSpeedThreshold); 85 | cpFloat cpSpaceGetSleepTimeThreshold (const(cpSpace)* space); 86 | void cpSpaceSetSleepTimeThreshold (cpSpace* space, cpFloat sleepTimeThreshold); 87 | cpFloat cpSpaceGetCollisionSlop (const(cpSpace)* space); 88 | void cpSpaceSetCollisionSlop (cpSpace* space, cpFloat collisionSlop); 89 | cpFloat cpSpaceGetCollisionBias (const(cpSpace)* space); 90 | void cpSpaceSetCollisionBias (cpSpace* space, cpFloat collisionBias); 91 | cpTimestamp cpSpaceGetCollisionPersistence (const(cpSpace)* space); 92 | void cpSpaceSetCollisionPersistence (cpSpace* space, cpTimestamp collisionPersistence); 93 | cpDataPointer cpSpaceGetUserData (const(cpSpace)* space); 94 | void cpSpaceSetUserData (cpSpace* space, cpDataPointer userData); 95 | cpBody* cpSpaceGetStaticBody (const(cpSpace)* space); 96 | cpFloat cpSpaceGetCurrentTimeStep (const(cpSpace)* space); 97 | cpBool cpSpaceIsLocked (cpSpace* space); 98 | cpCollisionHandler* cpSpaceAddDefaultCollisionHandler (cpSpace* space); 99 | cpCollisionHandler* cpSpaceAddCollisionHandler (cpSpace* space, cpCollisionType a, cpCollisionType b); 100 | cpCollisionHandler* cpSpaceAddWildcardHandler (cpSpace* space, cpCollisionType type); 101 | cpShape* cpSpaceAddShape (cpSpace* space, cpShape* shape); 102 | cpBody* cpSpaceAddBody (cpSpace* space, cpBody* body_); 103 | cpConstraint* cpSpaceAddConstraint (cpSpace* space, cpConstraint* constraint); 104 | void cpSpaceRemoveShape (cpSpace* space, cpShape* shape); 105 | void cpSpaceRemoveBody (cpSpace* space, cpBody* body_); 106 | void cpSpaceRemoveConstraint (cpSpace* space, cpConstraint* constraint); 107 | cpBool cpSpaceContainsShape (cpSpace* space, cpShape* shape); 108 | cpBool cpSpaceContainsBody (cpSpace* space, cpBody* body_); 109 | cpBool cpSpaceContainsConstraint (cpSpace* space, cpConstraint* constraint); 110 | cpBool cpSpaceAddPostStepCallback (cpSpace* space, cpPostStepFunc func, void* key, void* data); 111 | void cpSpacePointQuery (cpSpace* space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void* data); 112 | cpShape* cpSpacePointQueryNearest (cpSpace* space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo* out_); 113 | void cpSpaceSegmentQuery (cpSpace* space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void* data); 114 | cpShape* cpSpaceSegmentQueryFirst (cpSpace* space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo* out_); 115 | void cpSpaceBBQuery (cpSpace* space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void* data); 116 | cpBool cpSpaceShapeQuery (cpSpace* space, cpShape* shape, cpSpaceShapeQueryFunc func, void* data); 117 | void cpSpaceEachBody (cpSpace* space, cpSpaceBodyIteratorFunc func, void* data); 118 | void cpSpaceEachShape (cpSpace* space, cpSpaceShapeIteratorFunc func, void* data); 119 | void cpSpaceEachConstraint (cpSpace* space, cpSpaceConstraintIteratorFunc func, void* data); 120 | void cpSpaceReindexStatic (cpSpace* space); 121 | void cpSpaceReindexShape (cpSpace* space, cpShape* shape); 122 | void cpSpaceReindexShapesForBody (cpSpace* space, cpBody* body_); 123 | void cpSpaceUseSpatialHash (cpSpace* space, cpFloat dim, int count); 124 | void cpSpaceStep (cpSpace* space, cpFloat dt); 125 | void cpSpaceDebugDraw (cpSpace* space, cpSpaceDebugDrawOptions* options); 126 | -------------------------------------------------------------------------------- /src/chipmunk/cpSpatialIndex.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpSpatialIndex; 2 | import core.stdc.config; 3 | 4 | import chipmunk.chipmunk_types; 5 | import chipmunk.chipmunk_structs; 6 | import chipmunk.cpBB; 7 | 8 | extern (C): 9 | @nogc nothrow: 10 | 11 | alias cpBB function (void*) cpSpatialIndexBBFunc; 12 | alias void function (void*, void*) cpSpatialIndexIteratorFunc; 13 | alias uint function (void*, void*, uint, void*) cpSpatialIndexQueryFunc; 14 | alias double function (void*, void*, void*) cpSpatialIndexSegmentQueryFunc; 15 | alias cpVect function (void*) cpBBTreeVelocityFunc; 16 | alias void function (cpSpatialIndex*) cpSpatialIndexDestroyImpl; 17 | alias int function (cpSpatialIndex*) cpSpatialIndexCountImpl; 18 | alias void function (cpSpatialIndex*, void function (void*, void*), void*) cpSpatialIndexEachImpl; 19 | alias ubyte function (cpSpatialIndex*, void*, c_ulong) cpSpatialIndexContainsImpl; 20 | alias void function (cpSpatialIndex*, void*, c_ulong) cpSpatialIndexInsertImpl; 21 | alias void function (cpSpatialIndex*, void*, c_ulong) cpSpatialIndexRemoveImpl; 22 | alias void function (cpSpatialIndex*) cpSpatialIndexReindexImpl; 23 | alias void function (cpSpatialIndex*, void*, c_ulong) cpSpatialIndexReindexObjectImpl; 24 | alias void function (cpSpatialIndex*, uint function (void*, void*, uint, void*), void*) cpSpatialIndexReindexQueryImpl; 25 | alias void function (cpSpatialIndex*, void*, cpBB, uint function (void*, void*, uint, void*), void*) cpSpatialIndexQueryImpl; 26 | alias void function (cpSpatialIndex*, void*, cpVect, cpVect, double, double function (void*, void*, void*), void*) cpSpatialIndexSegmentQueryImpl; 27 | 28 | struct cpSpatialIndex 29 | { 30 | cpSpatialIndexClass* klass; 31 | cpSpatialIndexBBFunc bbfunc; 32 | cpSpatialIndex* staticIndex; 33 | cpSpatialIndex* dynamicIndex; 34 | } 35 | 36 | struct cpSpatialIndexClass 37 | { 38 | cpSpatialIndexDestroyImpl destroy; 39 | cpSpatialIndexCountImpl count; 40 | cpSpatialIndexEachImpl each; 41 | cpSpatialIndexContainsImpl contains; 42 | cpSpatialIndexInsertImpl insert; 43 | cpSpatialIndexRemoveImpl remove; 44 | cpSpatialIndexReindexImpl reindex; 45 | cpSpatialIndexReindexObjectImpl reindexObject; 46 | cpSpatialIndexReindexQueryImpl reindexQuery; 47 | cpSpatialIndexQueryImpl query; 48 | cpSpatialIndexSegmentQueryImpl segmentQuery; 49 | } 50 | 51 | struct cpBBTree; 52 | 53 | 54 | struct cpSweep1D; 55 | 56 | 57 | struct cpSpaceHash; 58 | 59 | 60 | cpSpaceHash* cpSpaceHashAlloc (); 61 | cpSpatialIndex* cpSpaceHashInit (cpSpaceHash* hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 62 | cpSpatialIndex* cpSpaceHashNew (cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 63 | void cpSpaceHashResize (cpSpaceHash* hash, cpFloat celldim, int numcells); 64 | cpBBTree* cpBBTreeAlloc (); 65 | cpSpatialIndex* cpBBTreeInit (cpBBTree* tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 66 | cpSpatialIndex* cpBBTreeNew (cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 67 | void cpBBTreeOptimize (cpSpatialIndex* index); 68 | void cpBBTreeSetVelocityFunc (cpSpatialIndex* index, cpBBTreeVelocityFunc func); 69 | cpSweep1D* cpSweep1DAlloc (); 70 | cpSpatialIndex* cpSweep1DInit (cpSweep1D* sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 71 | cpSpatialIndex* cpSweep1DNew (cpSpatialIndexBBFunc bbfunc, cpSpatialIndex* staticIndex); 72 | void cpSpatialIndexFree (cpSpatialIndex* index); 73 | void cpSpatialIndexCollideStatic (cpSpatialIndex* dynamicIndex, cpSpatialIndex* staticIndex, cpSpatialIndexQueryFunc func, void* data); 74 | 75 | // inlined in chipmunk headers: 76 | 77 | static void cpSpatialIndexDestroy(cpSpatialIndex *index) 78 | { 79 | if(index.klass) index.klass.destroy(index); 80 | } 81 | 82 | /// Get the number of objects in the spatial index. 83 | static int cpSpatialIndexCount(cpSpatialIndex *index) 84 | { 85 | return index.klass.count(index); 86 | } 87 | 88 | /// Iterate the objects in the spatial index. @c func will be called once for each object. 89 | static void cpSpatialIndexEach(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data) 90 | { 91 | index.klass.each(index, func, data); 92 | } 93 | 94 | /// Returns true if the spatial index contains the given object. 95 | /// Most spatial indexes use hashed storage, so you must provide a hash value too. 96 | static cpBool cpSpatialIndexContains(cpSpatialIndex *index, void *obj, cpHashValue hashid) 97 | { 98 | return index.klass.contains(index, obj, hashid); 99 | } 100 | 101 | /// Add an object to a spatial index. 102 | /// Most spatial indexes use hashed storage, so you must provide a hash value too. 103 | static void cpSpatialIndexInsert(cpSpatialIndex *index, void *obj, cpHashValue hashid) 104 | { 105 | index.klass.insert(index, obj, hashid); 106 | } 107 | 108 | /// Remove an object from a spatial index. 109 | /// Most spatial indexes use hashed storage, so you must provide a hash value too. 110 | static void cpSpatialIndexRemove(cpSpatialIndex *index, void *obj, cpHashValue hashid) 111 | { 112 | index.klass.remove(index, obj, hashid); 113 | } 114 | 115 | /// Perform a full reindex of a spatial index. 116 | static void cpSpatialIndexReindex(cpSpatialIndex *index) 117 | { 118 | index.klass.reindex(index); 119 | } 120 | 121 | /// Reindex a single object in the spatial index. 122 | static void cpSpatialIndexReindexObject(cpSpatialIndex *index, void *obj, cpHashValue hashid) 123 | { 124 | index.klass.reindexObject(index, obj, hashid); 125 | } 126 | 127 | /// Perform a rectangle query against the spatial index, calling @c func for each potential match. 128 | static void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) 129 | { 130 | index.klass.query(index, obj, bb, func, data); 131 | } 132 | 133 | /// Perform a segment query against the spatial index, calling @c func for each potential match. 134 | static void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data) 135 | { 136 | index.klass.segmentQuery(index, obj, a, b, t_exit, func, data); 137 | } 138 | 139 | /// Simultaneously reindex and find all colliding objects. 140 | /// @c func will be called once for each potentially overlapping pair of objects found. 141 | /// If the spatial index was initialized with a static index, it will collide it's objects against that as well. 142 | static void cpSpatialIndexReindexQuery(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data) 143 | { 144 | index.klass.reindexQuery(index, func, data); 145 | } 146 | -------------------------------------------------------------------------------- /src/chipmunk/cpTransform.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpTransform; 2 | 3 | import chipmunk.chipmunk_types; 4 | import chipmunk.cpBB; 5 | import chipmunk.cpVect; 6 | 7 | extern (C): 8 | @nogc nothrow: 9 | 10 | /// Identity transform matrix. 11 | static const cpTransform cpTransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; 12 | 13 | /// Construct a new transform matrix. 14 | /// (a, b) is the x basis vector. 15 | /// (c, d) is the y basis vector. 16 | /// (tx, ty) is the translation. 17 | static cpTransform 18 | cpTransformNew(cpFloat a, cpFloat b, cpFloat c, cpFloat d, cpFloat tx, cpFloat ty) 19 | { 20 | cpTransform t = {a, b, c, d, tx, ty}; 21 | return t; 22 | } 23 | 24 | /// Construct a new transform matrix in transposed order. 25 | static cpTransform 26 | cpTransformNewTranspose(cpFloat a, cpFloat c, cpFloat tx, cpFloat b, cpFloat d, cpFloat ty) 27 | { 28 | cpTransform t = {a, b, c, d, tx, ty}; 29 | return t; 30 | } 31 | 32 | /// Get the inverse of a transform matrix. 33 | static cpTransform 34 | cpTransformInverse(cpTransform t) 35 | { 36 | cpFloat inv_det = 1.0/(t.a*t.d - t.c*t.b); 37 | return cpTransformNewTranspose( 38 | t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det, 39 | -t.b*inv_det, t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det 40 | ); 41 | } 42 | 43 | /// Multiply two transformation matrices. 44 | static cpTransform 45 | cpTransformMult(cpTransform t1, cpTransform t2) 46 | { 47 | return cpTransformNewTranspose( 48 | t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx, 49 | t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty 50 | ); 51 | } 52 | 53 | /// Transform an absolute point. (i.e. a vertex) 54 | static cpVect 55 | cpTransformPoint(cpTransform t, cpVect p) 56 | { 57 | return cpv(t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty); 58 | } 59 | 60 | /// Transform a vector (i.e. a normal) 61 | static cpVect 62 | cpTransformVect(cpTransform t, cpVect v) 63 | { 64 | return cpv(t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y); 65 | } 66 | 67 | /// Transform a cpBB. 68 | static cpBB 69 | cpTransformbBB(cpTransform t, cpBB bb) 70 | { 71 | cpVect center = cpBBCenter(bb); 72 | cpFloat hw = (bb.r - bb.l)*0.5; 73 | cpFloat hh = (bb.t - bb.b)*0.5; 74 | 75 | cpFloat a = t.a*hw, b = t.c*hh, d = t.b*hw, e = t.d*hh; 76 | cpFloat hw_max = cpfmax(cpfabs(a + b), cpfabs(a - b)); 77 | cpFloat hh_max = cpfmax(cpfabs(d + e), cpfabs(d - e)); 78 | return cpBBNewForExtents(cpTransformPoint(t, center), hw_max, hh_max); 79 | } 80 | 81 | /// Create a transation matrix. 82 | static cpTransform 83 | cpTransformTranslate(cpVect translate) 84 | { 85 | return cpTransformNewTranspose( 86 | 1.0, 0.0, translate.x, 87 | 0.0, 1.0, translate.y 88 | ); 89 | } 90 | 91 | /// Create a scale matrix. 92 | static cpTransform 93 | cpTransformScale(cpFloat scaleX, cpFloat scaleY) 94 | { 95 | return cpTransformNewTranspose( 96 | scaleX, 0.0, 0.0, 97 | 0.0, scaleY, 0.0 98 | ); 99 | } 100 | 101 | /// Create a rotation matrix. 102 | static cpTransform 103 | cpTransformRotate(cpFloat radians) 104 | { 105 | cpVect rot = cpvforangle(radians); 106 | return cpTransformNewTranspose( 107 | rot.x, -rot.y, 0.0, 108 | rot.y, rot.x, 0.0 109 | ); 110 | } 111 | 112 | /// Create a rigid transformation matrix. (transation + rotation) 113 | static cpTransform 114 | cpTransformRigid(cpVect translate, cpFloat radians) 115 | { 116 | cpVect rot = cpvforangle(radians); 117 | return cpTransformNewTranspose( 118 | rot.x, -rot.y, translate.x, 119 | rot.y, rot.x, translate.y 120 | ); 121 | } 122 | 123 | /// Fast inverse of a rigid transformation matrix. 124 | static cpTransform 125 | cpTransformRigidInverse(cpTransform t) 126 | { 127 | return cpTransformNewTranspose( 128 | t.d, -t.c, (t.c*t.ty - t.tx*t.d), 129 | -t.b, t.a, (t.tx*t.b - t.a*t.ty) 130 | ); 131 | } 132 | 133 | //MARK: Miscellaneous (but useful) transformation matrices. 134 | // See source for documentation... 135 | 136 | static cpTransform 137 | cpTransformWrap(cpTransform outer, cpTransform inner) 138 | { 139 | return cpTransformMult(cpTransformInverse(outer), cpTransformMult(inner, outer)); 140 | } 141 | 142 | static cpTransform 143 | cpTransformWrapInverse(cpTransform outer, cpTransform inner) 144 | { 145 | return cpTransformMult(outer, cpTransformMult(inner, cpTransformInverse(outer))); 146 | } 147 | 148 | static cpTransform 149 | cpTransformOrtho(cpBB bb) 150 | { 151 | return cpTransformNewTranspose( 152 | 2.0/(bb.r - bb.l), 0.0, -(bb.r + bb.l)/(bb.r - bb.l), 153 | 0.0, 2.0/(bb.t - bb.b), -(bb.t + bb.b)/(bb.t - bb.b) 154 | ); 155 | } 156 | 157 | static cpTransform 158 | cpTransformBoneScale(cpVect v0, cpVect v1) 159 | { 160 | cpVect d = cpvsub(v1, v0); 161 | return cpTransformNewTranspose( 162 | d.x, -d.y, v0.x, 163 | d.y, d.x, v0.y 164 | ); 165 | } 166 | 167 | static cpTransform 168 | cpTransformAxialScale(cpVect axis, cpVect pivot, cpFloat scale) 169 | { 170 | cpFloat A = axis.x*axis.y*(scale - 1.0); 171 | cpFloat B = cpvdot(axis, pivot)*(1.0 - scale); 172 | 173 | return cpTransformNewTranspose( 174 | scale*axis.x*axis.x + axis.y*axis.y, A, axis.x*B, 175 | A, axis.x*axis.x + scale*axis.y*axis.y, axis.y*B 176 | ); 177 | } 178 | -------------------------------------------------------------------------------- /src/chipmunk/cpVect.d: -------------------------------------------------------------------------------- 1 | module chipmunk.cpVect; 2 | 3 | import chipmunk.chipmunk_types; 4 | 5 | extern (C): 6 | @nogc nothrow: 7 | 8 | const cpVect cpvzero = {0.0f,0.0f}; 9 | 10 | // In the C library these are static inlined functions in the header. 11 | // We reimplement them here rather than binding to them. 12 | 13 | /// Convenience constructor for cpVect structs. 14 | static cpVect cpv(const cpFloat x, const cpFloat y) 15 | { 16 | cpVect v = {x, y}; 17 | return v; 18 | } 19 | 20 | /// Check if two vectors are equal. (Be careful when comparing floating point numbers!) 21 | static cpBool cpveql(const cpVect v1, const cpVect v2) 22 | { 23 | return (v1.x == v2.x && v1.y == v2.y); 24 | } 25 | 26 | /// Add two vectors 27 | static cpVect cpvadd(const cpVect v1, const cpVect v2) 28 | { 29 | return cpv(v1.x + v2.x, v1.y + v2.y); 30 | } 31 | 32 | /// Subtract two vectors. 33 | static cpVect cpvsub(const cpVect v1, const cpVect v2) 34 | { 35 | return cpv(v1.x - v2.x, v1.y - v2.y); 36 | } 37 | 38 | /// Negate a vector. 39 | static cpVect cpvneg(const cpVect v) 40 | { 41 | return cpv(-v.x, -v.y); 42 | } 43 | 44 | /// Scalar multiplication. 45 | static cpVect cpvmult(const cpVect v, const cpFloat s) 46 | { 47 | return cpv(v.x*s, v.y*s); 48 | } 49 | 50 | /// Vector dot product. 51 | static cpFloat cpvdot(const cpVect v1, const cpVect v2) 52 | { 53 | return v1.x*v2.x + v1.y*v2.y; 54 | } 55 | 56 | /// 2D vector cross product analog. 57 | /// The cross product of 2D vectors results in a 3D vector with only a z component. 58 | /// This function returns the magnitude of the z value. 59 | static cpFloat cpvcross(const cpVect v1, const cpVect v2) 60 | { 61 | return v1.x*v2.y - v1.y*v2.x; 62 | } 63 | 64 | /// Returns a perpendicular vector. (90 degree rotation) 65 | static cpVect cpvperp(const cpVect v) 66 | { 67 | return cpv(-v.y, v.x); 68 | } 69 | 70 | /// Returns a perpendicular vector. (-90 degree rotation) 71 | static cpVect cpvrperp(const cpVect v) 72 | { 73 | return cpv(v.y, -v.x); 74 | } 75 | 76 | /// Returns the vector projection of v1 onto v2. 77 | static cpVect cpvproject(const cpVect v1, const cpVect v2) 78 | { 79 | return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2)); 80 | } 81 | 82 | /// Returns the unit length vector for the given angle (in radians). 83 | static cpVect cpvforangle(const cpFloat a) 84 | { 85 | return cpv(cpfcos(a), cpfsin(a)); 86 | } 87 | 88 | /// Returns the angular direction v is pointing in (in radians). 89 | static cpFloat cpvtoangle(const cpVect v) 90 | { 91 | return cpfatan2(v.y, v.x); 92 | } 93 | 94 | /// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector. 95 | static cpVect cpvrotate(const cpVect v1, const cpVect v2) 96 | { 97 | return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x); 98 | } 99 | 100 | /// Inverse of cpvrotate(). 101 | static cpVect cpvunrotate(const cpVect v1, const cpVect v2) 102 | { 103 | return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y); 104 | } 105 | 106 | /// Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths. 107 | static cpFloat cpvlengthsq(const cpVect v) 108 | { 109 | return cpvdot(v, v); 110 | } 111 | 112 | /// Returns the length of v. 113 | static cpFloat cpvlength(const cpVect v) 114 | { 115 | return cpfsqrt(cpvdot(v, v)); 116 | } 117 | 118 | /// Linearly interpolate between v1 and v2. 119 | static cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t) 120 | { 121 | return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t)); 122 | } 123 | 124 | /// Returns a normalized copy of v. 125 | static cpVect cpvnormalize(const cpVect v) 126 | { 127 | // Neat trick I saw somewhere to avoid div/0. 128 | return cpvmult(v, 1.0f/(cpvlength(v) + CPFLOAT_MIN)); 129 | } 130 | 131 | /// Spherical linearly interpolate between v1 and v2. 132 | static cpVect 133 | cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t) 134 | { 135 | cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); 136 | cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); 137 | 138 | if(omega < 1e-3){ 139 | // If the angle between two vectors is very small, lerp instead to avoid precision issues. 140 | return cpvlerp(v1, v2, t); 141 | } else { 142 | cpFloat denom = 1.0f/cpfsin(omega); 143 | return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom)); 144 | } 145 | } 146 | 147 | /// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians 148 | static cpVect 149 | cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a) 150 | { 151 | cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); 152 | cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); 153 | 154 | return cpvslerp(v1, v2, cpfmin(a, omega)/omega); 155 | } 156 | 157 | /// Clamp v to length len. 158 | static cpVect cpvclamp(const cpVect v, const cpFloat len) 159 | { 160 | return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v; 161 | } 162 | 163 | /// Linearly interpolate between v1 towards v2 by distance d. 164 | static cpVect cpvlerpconst(cpVect v1, cpVect v2, cpFloat d) 165 | { 166 | return cpvadd(v1, cpvclamp(cpvsub(v2, v1), d)); 167 | } 168 | 169 | /// Returns the distance between v1 and v2. 170 | static cpFloat cpvdist(const cpVect v1, const cpVect v2) 171 | { 172 | return cpvlength(cpvsub(v1, v2)); 173 | } 174 | 175 | /// Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances. 176 | static cpFloat cpvdistsq(const cpVect v1, const cpVect v2) 177 | { 178 | return cpvlengthsq(cpvsub(v1, v2)); 179 | } 180 | 181 | /// Returns true if the distance between v1 and v2 is less than dist. 182 | static cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist) 183 | { 184 | return cpvdistsq(v1, v2) < dist*dist; 185 | } 186 | 187 | /// @} 188 | 189 | /// @defgroup cpMat2x2 cpMat2x2 190 | /// 2x2 matrix type used for tensors and such. 191 | /// @{ 192 | 193 | // NUKE 194 | static cpMat2x2 195 | cpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d) 196 | { 197 | cpMat2x2 m = {a, b, c, d}; 198 | return m; 199 | } 200 | 201 | static cpVect 202 | cpMat2x2Transform(cpMat2x2 m, cpVect v) 203 | { 204 | return cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d); 205 | } 206 | -------------------------------------------------------------------------------- /src/chipmunk/package.d: -------------------------------------------------------------------------------- 1 | module chipmunk; 2 | 3 | // import everything except chipmunk_private 4 | public import chipmunk.chipmunk; 5 | public import chipmunk.chipmunk_structs; 6 | public import chipmunk.chipmunk_types; 7 | public import chipmunk.cpArbiter; 8 | public import chipmunk.cpBB; 9 | public import chipmunk.cpBody; 10 | public import chipmunk.cpConstraint; 11 | public import chipmunk.cpDampedRotarySpring; 12 | public import chipmunk.cpDampedSpring; 13 | public import chipmunk.cpGearJoint; 14 | public import chipmunk.cpGrooveJoint; 15 | public import chipmunk.cpHastySpace; 16 | public import chipmunk.cpMarch; 17 | public import chipmunk.cpPinJoint; 18 | public import chipmunk.cpPivotJoint; 19 | public import chipmunk.cpPolyline; 20 | public import chipmunk.cpPolyShape; 21 | public import chipmunk.cpRatchetJoint; 22 | public import chipmunk.cpRobust; 23 | public import chipmunk.cpRotaryLimitJoint; 24 | public import chipmunk.cpShape; 25 | public import chipmunk.cpSimpleMotor; 26 | public import chipmunk.cpSlideJoint; 27 | public import chipmunk.cpSpace; 28 | public import chipmunk.cpSpatialIndex; 29 | public import chipmunk.cpTransform; 30 | public import chipmunk.cpVect; 31 | --------------------------------------------------------------------------------