4
|
1
|
|
2 // written in the D programming language
|
|
3
|
|
4 module chipmunkd.chipmunk;
|
13
|
5
|
|
6 import std.stdio;
|
|
7 import std.string:format;
|
|
8 import std.conv:to;
|
23
|
9 import std.math:PI;
|
13
|
10
|
|
11 void
|
|
12 cpMessage(string message, string condition, string file, int line, bool isError)
|
|
13 {
|
|
14 stderr.writeln(.format("%s:%s", isError ? "Aborting due to Chipmunk error" : "Chipmunk warning", message));
|
|
15 stderr.writeln(.format("\tFailed condition: %s", condition));
|
|
16 stderr.writeln(.format("\tSource: %s(%s)", file, line));
|
|
17
|
|
18 if(isError) {debug{assert(false);}else{asm{int 3;}}}
|
|
19 }
|
4
|
20
|
|
21 debug
|
|
22 {
|
13
|
23 template cpAssertWarn(string _condition, string message,string _f = __FILE__,int _l=__LINE__)
|
|
24 {
|
|
25 enum cpAssertWarn = "if(!("~_condition~"))"~
|
|
26 "cpMessage(\""~message~"\",\""~_condition~"\",r\""~_f~"\","~to!string(_l)~",false);";
|
|
27 }
|
4
|
28 }
|
|
29 else
|
|
30 {
|
13
|
31 template cpAssertWarn(string _condition, string message,string _f = __FILE__,int _l=__LINE__)
|
|
32 {
|
|
33 enum cpAssertWarn = "";
|
|
34 }
|
4
|
35 }
|
|
36
|
13
|
37 //TODO
|
4
|
38 //#ifdef NDEBUG
|
|
39 // #define cpAssert(condition, message)
|
|
40 //#else
|
|
41 // #define cpAssert(condition, message) if(!(condition)) cpMessage(message, #condition, __FILE__, __LINE__, 1)
|
|
42 //#endif
|
|
43 //
|
13
|
44
|
15
|
45 import chipmunkd.chipmunk_types;
|
4
|
46 import core.stdc.stdlib;
|
|
47
|
|
48 enum INFINITY = cpFloat.infinity;
|
|
49
|
|
50 // Maximum allocated size for various Chipmunk buffer sizes
|
|
51 enum CP_BUFFER_BYTES = (32*1024);
|
|
52
|
|
53 alias core.stdc.stdlib.malloc cpmalloc;
|
|
54 alias core.stdc.stdlib.calloc cpcalloc;
|
|
55 alias core.stdc.stdlib.realloc cprealloc;
|
|
56 alias core.stdc.stdlib.free cpfree;
|
|
57
|
15
|
58 public import chipmunkd.cpVect;
|
4
|
59 public import chipmunkd.cpBB;
|
|
60 public import chipmunkd.cpArray;
|
|
61 public import chipmunkd.cpHashSet;
|
|
62 public import chipmunkd.cpSpaceHash;
|
|
63 //
|
|
64 public import chipmunkd.cpBody;
|
|
65 public import chipmunkd.cpShape;
|
|
66 public import chipmunkd.cpPolyShape;
|
|
67 //
|
|
68 public import chipmunkd.cpArbiter;
|
|
69 public import chipmunkd.cpCollision;
|
|
70 //
|
|
71 public import chipmunkd.constraints.cpConstraint;
|
|
72 //
|
|
73 public import chipmunkd.cpSpace;
|
|
74 public import chipmunkd.cpSpaceComponent;
|
|
75 public import chipmunkd.cpSpaceQuery;
|
|
76 public import chipmunkd.cpSpaceStep;
|
|
77
|
15
|
78 public import chipmunkd.chipmunk_types;
|
4
|
79
|
|
80 enum cpHashValue CP_HASH_COEF = cast(cpHashValue)(3344921057uL); // ulong to uint ??
|
|
81 static cpHashValue CP_HASH_PAIR(T)(T A, T B) {return (cast(cpHashValue)(A)*CP_HASH_COEF ^ cast(cpHashValue)(B)*CP_HASH_COEF);}
|
|
82
|
|
83 extern const char *cpVersionString;
|
|
84 void cpInitChipmunk()
|
|
85 {
|
|
86 cpInitCollisionFuncs();
|
|
87 }
|
|
88
|
|
89 /**
|
|
90 Calculate the moment of inertia for a circle.
|
|
91 r1 and r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
|
|
92 */
|
|
93 cpFloat
|
|
94 cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
|
|
95 {
|
23
|
96 return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset));
|
4
|
97 }
|
23
|
98
|
|
99 /**
|
|
100 Calculate area of a hollow circle.
|
|
101 */
|
|
102 cpFloat cpAreaForCircle(cpFloat r1, cpFloat r2)
|
|
103 {
|
|
104 return 2.0f*cast(cpFloat)PI*cpfabs(r1*r1 - r2*r2);
|
|
105 }
|
|
106
|
4
|
107 /**
|
|
108 Calculate the moment of inertia for a line segment.
|
|
109 Beveling radius is not supported.
|
|
110 */
|
|
111 cpFloat
|
|
112 cpMomentForSegment(cpFloat m, cpVect a, cpVect b)
|
|
113 {
|
|
114 cpFloat length = cpvlength(cpvsub(b, a));
|
|
115 cpVect offset = cpvmult(cpvadd(a, b), 1.0f/2.0f);
|
|
116
|
23
|
117 return m*(length*length/12.0f + cpvlengthsq(offset));
|
|
118 }
|
|
119
|
|
120 /**
|
|
121 Calculate the area of a fattened (capsule shaped) line segment.
|
|
122 */
|
|
123 cpFloat
|
|
124 cpAreaForSegment(cpVect a, cpVect b, cpFloat r)
|
|
125 {
|
|
126 return 2.0f*r*(cast(cpFloat)PI*r + cpvdist(a, b));
|
4
|
127 }
|
|
128
|
|
129 /**
|
|
130 Calculate the moment of inertia for a solid polygon shape.
|
|
131 */
|
|
132 cpFloat
|
|
133 cpMomentForPoly(cpFloat m, const int numVerts, cpVect *verts, cpVect offset)
|
|
134 {
|
|
135 cpVect *tVerts = cast(cpVect *)cpcalloc(numVerts, cpVect.sizeof);
|
|
136 for(int i=0; i<numVerts; i++)
|
|
137 tVerts[i] = cpvadd(verts[i], offset);
|
|
138
|
|
139 cpFloat sum1 = 0.0f;
|
|
140 cpFloat sum2 = 0.0f;
|
|
141 for(int i=0; i<numVerts; i++){
|
|
142 cpVect v1 = tVerts[i];
|
|
143 cpVect v2 = tVerts[(i+1)%numVerts];
|
|
144
|
|
145 cpFloat a = cpvcross(v2, v1);
|
|
146 cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);
|
|
147
|
|
148 sum1 += a*b;
|
|
149 sum2 += a;
|
|
150 }
|
|
151
|
|
152 cpfree(tVerts);
|
|
153 return (m*sum1)/(6.0f*sum2);
|
|
154 }
|
|
155
|
|
156 /**
|
23
|
157 Calculate the signed area of a polygon.
|
|
158 */
|
|
159 cpFloat cpAreaForPoly(const int numVerts, const cpVect *verts)
|
|
160 {
|
|
161 cpFloat area = 0.0f;
|
|
162 for(int i=0; i<numVerts; i++){
|
|
163 area += cpvcross(verts[i], verts[(i+1)%numVerts]);
|
|
164 }
|
|
165
|
|
166 return area/2.0f;
|
|
167 }
|
|
168
|
|
169 /**
|
|
170 Calculate the natural centroid of a polygon.
|
|
171 */
|
|
172 cpVect cpCentroidForPoly(const int numVerts, const cpVect *verts)
|
|
173 {
|
|
174 cpFloat sum = 0.0f;
|
|
175 cpVect vsum = cpvzero;
|
|
176
|
|
177 for(int i=0; i<numVerts; i++){
|
|
178 cpVect v1 = verts[i];
|
|
179 cpVect v2 = verts[(i+1)%numVerts];
|
|
180 cpFloat cross = cpvcross(v1, v2);
|
|
181
|
|
182 sum += cross;
|
|
183 vsum = cpvadd(vsum, cpvmult(cpvadd(v1, v2), cross));
|
|
184 }
|
|
185
|
|
186 return cpvmult(vsum, 1.0f/(3.0f*sum));
|
|
187 }
|
|
188
|
|
189 /**
|
|
190 Center the polygon on the origin. (Subtracts the centroid of the polygon from each vertex)
|
|
191 */
|
|
192 void cpRecenterPoly(const int numVerts, cpVect *verts)
|
|
193 {
|
|
194 cpVect centroid = cpCentroidForPoly(numVerts, verts);
|
|
195
|
|
196 for(int i=0; i<numVerts; i++){
|
|
197 verts[i] = cpvsub(verts[i], centroid);
|
|
198 }
|
|
199 }
|
|
200
|
|
201 /**
|
4
|
202 Calculate the moment of inertia for a solid box.
|
|
203 */
|
|
204 cpFloat
|
|
205 cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
|
|
206 {
|
|
207 return m*(width*width + height*height)/12.0f;
|
|
208 }
|