1 /* 2 * Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 module demo.Convex; 23 24 import core.stdc.stdlib; 25 26 import std.math; 27 28 alias M_PI_2 = PI_2; 29 30 import demo.dchip; 31 32 import demo.ChipmunkDebugDraw; 33 import demo.ChipmunkDemo; 34 import demo.types; 35 36 enum DENSITY = (1.0 / 10000.0); 37 38 static cpShape* shape; 39 40 static void update(cpSpace* space, double dt) 41 { 42 cpFloat tolerance = 2.0; 43 44 if (ChipmunkDemoRightClick && cpShapeNearestPointQuery(shape, ChipmunkDemoMouse, null) > tolerance) 45 { 46 cpBody* body_ = cpShapeGetBody(shape); 47 int count = cpPolyShapeGetNumVerts(shape); 48 49 // Allocate the space for the new vertexes on the stack. 50 cpVect* verts = cast(cpVect*)alloca((count + 1) * cpVect.sizeof); 51 52 for (int i = 0; i < count; i++) 53 { 54 verts[i] = cpPolyShapeGetVert(shape, i); 55 } 56 57 verts[count] = cpBodyWorld2Local(body_, ChipmunkDemoMouse); 58 59 // This function builds a convex hull for the vertexes. 60 // Because the result array is null, it will reduce the input array instead. 61 int hullCount = cpConvexHull(count + 1, verts, null, null, tolerance); 62 63 // Figure out how much to shift the body_ by. 64 cpVect centroid = cpCentroidForPoly(hullCount, verts); 65 66 // Recalculate the body_ properties to match the updated shape. 67 cpFloat mass = cpAreaForPoly(hullCount, verts) * DENSITY; 68 cpBodySetMass(body_, mass); 69 cpBodySetMoment(body_, cpMomentForPoly(mass, hullCount, verts, cpvneg(centroid))); 70 cpBodySetPos(body_, cpBodyLocal2World(body_, centroid)); 71 72 // Use the setter function from chipmunk_unsafe.h. 73 // You could also remove and recreate the shape if you wanted. 74 cpPolyShapeSetVerts(shape, hullCount, verts, cpvneg(centroid)); 75 } 76 77 cpSpaceStep(space, dt); 78 } 79 80 static cpSpace* init() 81 { 82 ChipmunkDemoMessageString = "Right click and drag to change the blocks's shape.".dup; 83 84 cpSpace* space = cpSpaceNew(); 85 cpSpaceSetIterations(space, 30); 86 cpSpaceSetGravity(space, cpv(0, -500)); 87 cpSpaceSetSleepTimeThreshold(space, 0.5f); 88 cpSpaceSetCollisionSlop(space, 0.5f); 89 90 cpBody* body_; 91 cpBody* staticBody = cpSpaceGetStaticBody(space); 92 93 // Create segments around the edge of the screen. 94 shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); 95 cpShapeSetElasticity(shape, 1.0f); 96 cpShapeSetFriction(shape, 1.0f); 97 cpShapeSetLayers(shape, NOT_GRABABLE_MASK); 98 99 cpFloat width = 50.0f; 100 cpFloat height = 70.0f; 101 cpFloat mass = width * height * DENSITY; 102 cpFloat moment = cpMomentForBox(mass, width, height); 103 104 body_ = cpSpaceAddBody(space, cpBodyNew(mass, moment)); 105 106 shape = cpSpaceAddShape(space, cpBoxShapeNew(body_, width, height)); 107 cpShapeSetFriction(shape, 0.6f); 108 109 return space; 110 } 111 112 static void destroy(cpSpace* space) 113 { 114 ChipmunkDemoFreeSpaceChildren(space); 115 cpSpaceFree(space); 116 } 117 118 ChipmunkDemo Convex = { 119 "Convex.", 120 1.0 / 60.0, 121 &init, 122 &update, 123 &ChipmunkDemoDefaultDrawImpl, 124 &destroy, 125 };