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.Query; 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 cpVect QUERY_START = { 0, 0 }; 37 38 void update(cpSpace* space, double dt) 39 { 40 cpSpaceStep(space, dt); 41 42 if (ChipmunkDemoRightClick) 43 { 44 QUERY_START = ChipmunkDemoMouse; 45 } 46 47 cpVect start = QUERY_START; 48 cpVect end = ChipmunkDemoMouse; 49 ChipmunkDebugDrawSegment(start, end, RGBAColor(0, 1, 0, 1)); 50 51 ChipmunkDemoPrintString("Query: Dist(%f) Point%s, ", cpvdist(start, end), cpvstr(end)); 52 53 cpSegmentQueryInfo segInfo = {}; 54 55 if (cpSpaceSegmentQueryFirst(space, start, end, CP_ALL_LAYERS, CP_NO_GROUP, &segInfo)) 56 { 57 cpVect point = cpSegmentQueryHitPoint(start, end, segInfo); 58 59 // Draw blue over the occluded part of the query 60 ChipmunkDebugDrawSegment(point, end, RGBAColor(0, 0, 1, 1)); 61 62 // Draw a little red surface normal 63 ChipmunkDebugDrawSegment(point, cpvadd(point, cpvmult(segInfo.n, 16)), RGBAColor(1, 0, 0, 1)); 64 65 // Draw a little red dot on the hit point. 66 ChipmunkDebugDrawDot(3, point, RGBAColor(1, 0, 0, 1)); 67 68 ChipmunkDemoPrintString("Segment Query: Dist(%f) Normal%s", cpSegmentQueryHitDist(start, end, segInfo), cpvstr(segInfo.n)); 69 } 70 else 71 { 72 ChipmunkDemoPrintString("Segment Query (None)"); 73 } 74 75 cpNearestPointQueryInfo nearestInfo = {}; 76 cpSpaceNearestPointQueryNearest(space, ChipmunkDemoMouse, 100.0, CP_ALL_LAYERS, CP_NO_GROUP, &nearestInfo); 77 78 if (nearestInfo.shape) 79 { 80 // Draw a grey line to the closest shape. 81 ChipmunkDebugDrawDot(3, ChipmunkDemoMouse, RGBAColor(0.5, 0.5, 0.5, 1.0)); 82 ChipmunkDebugDrawSegment(ChipmunkDemoMouse, nearestInfo.p, RGBAColor(0.5, 0.5, 0.5, 1.0)); 83 84 // Draw a red bounding box around the shape under the mouse. 85 if (nearestInfo.d < 0) 86 ChipmunkDebugDrawBB(cpShapeGetBB(nearestInfo.shape), RGBAColor(1, 0, 0, 1)); 87 } 88 } 89 90 cpSpace* init() 91 { 92 QUERY_START = cpvzero; 93 94 cpSpace* space = cpSpaceNew(); 95 cpSpaceSetIterations(space, 5); 96 97 { 98 // add a fat segment 99 cpFloat mass = 1.0f; 100 cpFloat length = 100.0f; 101 cpVect a = cpv(-length / 2.0f, 0.0f), b = cpv(length / 2.0f, 0.0f); 102 103 cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b))); 104 cpBodySetPos(body_, cpv(0.0f, 100.0f)); 105 106 cpSpaceAddShape(space, cpSegmentShapeNew(body_, a, b, 20.0f)); 107 } 108 109 { 110 // add a static segment 111 cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(0, 300), cpv(300, 0), 0.0f)); 112 } 113 114 { 115 // add a pentagon 116 cpFloat mass = 1.0f; 117 const int NUM_VERTS = 5; 118 119 cpVect verts[NUM_VERTS]; 120 121 for (int i = 0; i < NUM_VERTS; i++) 122 { 123 cpFloat angle = -2 * M_PI * i / (cast(cpFloat)NUM_VERTS); 124 verts[i] = cpv(30 * cos(angle), 30 * sin(angle)); 125 } 126 127 cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, NUM_VERTS, verts.ptr, cpvzero))); 128 cpBodySetPos(body_, cpv(50.0f, 30.0f)); 129 130 cpSpaceAddShape(space, cpPolyShapeNew2(body_, NUM_VERTS, verts.ptr, cpvzero, 10.0f)); 131 } 132 133 { 134 // add a circle 135 cpFloat mass = 1.0f; 136 cpFloat r = 20.0f; 137 138 cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, r, cpvzero))); 139 cpBodySetPos(body_, cpv(100.0f, 100.0f)); 140 141 cpSpaceAddShape(space, cpCircleShapeNew(body_, r, cpvzero)); 142 } 143 144 return space; 145 } 146 147 void destroy(cpSpace* space) 148 { 149 ChipmunkDemoFreeSpaceChildren(space); 150 cpSpaceFree(space); 151 } 152 153 ChipmunkDemo Query = { 154 "Segment Query", 155 1.0 / 60.0, 156 &init, 157 &update, 158 &ChipmunkDemoDefaultDrawImpl, 159 &destroy, 160 };