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 22const Lib = "libchipmunk.so.6.1.1" 23 24when defined(MoreNim): 25 {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".} 26from math import sqrt, sin, cos, arctan2 27when defined(CpUseFloat): 28 {.hint: "CpUseFloat defined; using float32 as float".} 29 type CpFloat* = cfloat 30else: 31 type CpFloat* = cdouble 32const 33 CP_BUFFER_BYTES* = (32 * 1024) 34 CP_MAX_CONTACTS_PER_ARBITER* = 4 35 CpInfinity*: CpFloat = 1.0/0 36{.pragma: pf, pure, final.} 37type 38 Bool32* = cint #replace one day with cint-compatible bool 39 CpDataPointer* = pointer 40 TVector* {.final, pure.} = object 41 x*, y*: CpFloat 42 TTimestamp* = cuint 43 TBodyVelocityFunc* = proc(body: PBody, gravity: TVector, 44 damping: CpFloat; dt: CpFloat){.cdecl.} 45 TBodyPositionFunc* = proc(body: PBody; dt: CpFloat){.cdecl.} 46 TComponentNode*{.pf.} = object 47 root*: PBody 48 next*: PBody 49 idleTime*: CpFloat 50 51 THashValue = cuint # uintptr_t 52 TCollisionType* = cuint #uintptr_t 53 TGroup * = cuint #uintptr_t 54 TLayers* = cuint 55 PArray = ptr TArray 56 TArray{.pure,final.} = object 57 PHashSet = ptr THashSet 58 THashSet{.pf.} = object 59 PContact* = ptr TContact 60 TContact*{.pure,final.} = object 61 PArbiter* = ptr TArbiter 62 TArbiter*{.pf.} = object 63 e*: CpFloat 64 u*: CpFloat 65 surface_vr*: TVector 66 a*: PShape 67 b*: PShape 68 body_a*: PBody 69 body_b*: PBody 70 thread_a*: TArbiterThread 71 thread_b*: TArbiterThread 72 numContacts*: cint 73 contacts*: PContact 74 stamp*: TTimestamp 75 handler*: PCollisionHandler 76 swappedColl*: Bool32 77 state*: TArbiterState 78 PCollisionHandler* = ptr TCollisionHandler 79 TCollisionHandler*{.pf.} = object 80 a*: TCollisionType 81 b*: TCollisionType 82 begin*: TCollisionBeginFunc 83 preSolve*: TCollisionPreSolveFunc 84 postSolve*: TCollisionPostSolveFunc 85 separate*: TCollisionSeparateFunc 86 data*: pointer 87 TArbiterState*{.size: sizeof(cint).} = enum 88 ArbiterStateFirstColl, # Arbiter is active and its not the first collision. 89 ArbiterStateNormal, # Collision has been explicitly ignored. 90 # Either by returning false from a begin collision handler or calling cpArbiterIgnore(). 91 ArbiterStateIgnore, # Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps. 92 ArbiterStateCached 93 TArbiterThread*{.pf.} = object 94 next*: PArbiter # Links to next and previous arbiters in the contact graph. 95 prev*: PArbiter 96 97 TContactPoint*{.pf.} = object 98 point*: TVector #/ The position of the contact point. 99 normal*: TVector #/ The normal of the contact point. 100 dist*: CpFloat #/ The depth of the contact point. 101 #/ A struct that wraps up the important collision data for an arbiter. 102 PContactPointSet* = ptr TContactPointSet 103 TContactPointSet*{.pf.} = object 104 count*: cint #/ The number of contact points in the set. 105 points*: array[0..CP_MAX_CONTACTS_PER_ARBITER - 1, TContactPoint] #/ The array of contact points. 106 107 #/ Collision begin event function callback type. 108 #/ Returning false from a begin callback causes the collision to be ignored until 109 #/ the separate callback is called when the objects stop colliding. 110 TCollisionBeginFunc* = proc (arb: PArbiter; space: PSpace; data: pointer): bool{. 111 cdecl.} 112 #/ Collision pre-solve event function callback type. 113 #/ Returning false from a pre-step callback causes the collision to be ignored until the next step. 114 TCollisionPreSolveFunc* = proc (arb: PArbiter; space: PSpace; 115 data: pointer): bool {.cdecl.} 116 #/ Collision post-solve event function callback type. 117 TCollisionPostSolveFunc* = proc (arb: PArbiter; space: PSpace; 118 data: pointer){.cdecl.} 119 #/ Collision separate event function callback type. 120 TCollisionSeparateFunc* = proc (arb: PArbiter; space: PSpace; 121 data: pointer){.cdecl.} 122 123 #/ Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top) 124 PBB* = ptr TBB 125 TBB* {.pf.} = object 126 l*, b*, r*, t*: CpFloat 127 128 #/ Spatial index bounding box callback function type. 129 #/ The spatial index calls this function and passes you a pointer to an object you added 130 #/ when it needs to get the bounding box associated with that object. 131 TSpatialIndexBBFunc* = proc (obj: pointer): TBB{.cdecl.} 132 #/ Spatial index/object iterator callback function type. 133 TSpatialIndexIteratorFunc* = proc (obj: pointer; data: pointer){.cdecl.} 134 #/ Spatial query callback function type. 135 TSpatialIndexQueryFunc* = proc (obj1: pointer; obj2: pointer; data: pointer){. 136 cdecl.} 137 #/ Spatial segment query callback function type. 138 TSpatialIndexSegmentQueryFunc* = proc (obj1: pointer; obj2: pointer; 139 data: pointer): CpFloat {.cdecl.} 140 #/ private 141 PSpatialIndex = ptr TSpatialIndex 142 TSpatialIndex{.pf.} = object 143 klass: PSpatialIndexClass 144 bbfun: TSpatialIndexBBFunc 145 staticIndex: PSpatialIndex 146 dynamicIndex: PSpatialIndex 147 148 TSpatialIndexDestroyImpl* = proc (index: PSpatialIndex){.cdecl.} 149 TSpatialIndexCountImpl* = proc (index: PSpatialIndex): cint{.cdecl.} 150 TSpatialIndexEachImpl* = proc (index: PSpatialIndex; 151 fun: TSpatialIndexIteratorFunc; data: pointer){. 152 cdecl.} 153 TSpatialIndexContainsImpl* = proc (index: PSpatialIndex; obj: pointer; 154 hashid: THashValue): Bool32 {.cdecl.} 155 TSpatialIndexInsertImpl* = proc (index: PSpatialIndex; obj: pointer; 156 hashid: THashValue){.cdecl.} 157 TSpatialIndexRemoveImpl* = proc (index: PSpatialIndex; obj: pointer; 158 hashid: THashValue){.cdecl.} 159 TSpatialIndexReindexImpl* = proc (index: PSpatialIndex){.cdecl.} 160 TSpatialIndexReindexObjectImpl* = proc (index: PSpatialIndex; 161 obj: pointer; hashid: THashValue){.cdecl.} 162 TSpatialIndexReindexQueryImpl* = proc (index: PSpatialIndex; 163 fun: TSpatialIndexQueryFunc; data: pointer){.cdecl.} 164 TSpatialIndexPointQueryImpl* = proc (index: PSpatialIndex; point: TVector; 165 fun: TSpatialIndexQueryFunc; 166 data: pointer){.cdecl.} 167 TSpatialIndexSegmentQueryImpl* = proc (index: PSpatialIndex; obj: pointer; 168 a: TVector; b: TVector; t_exit: CpFloat; fun: TSpatialIndexSegmentQueryFunc; 169 data: pointer){.cdecl.} 170 TSpatialIndexQueryImpl* = proc (index: PSpatialIndex; obj: pointer; 171 bb: TBB; fun: TSpatialIndexQueryFunc; 172 data: pointer){.cdecl.} 173 PSpatialIndexClass* = ptr TSpatialIndexClass 174 TSpatialIndexClass*{.pf.} = object 175 destroy*: TSpatialIndexDestroyImpl 176 count*: TSpatialIndexCountImpl 177 each*: TSpatialIndexEachImpl 178 contains*: TSpatialIndexContainsImpl 179 insert*: TSpatialIndexInsertImpl 180 remove*: TSpatialIndexRemoveImpl 181 reindex*: TSpatialIndexReindexImpl 182 reindexObject*: TSpatialIndexReindexObjectImpl 183 reindexQuery*: TSpatialIndexReindexQueryImpl 184 pointQuery*: TSpatialIndexPointQueryImpl 185 segmentQuery*: TSpatialIndexSegmentQueryImpl 186 query*: TSpatialIndexQueryImpl 187 188 PSpaceHash* = ptr TSpaceHash 189 TSpaceHash* {.pf.} = object 190 PBBTree* = ptr TBBTree 191 TBBTree* {.pf.} = object 192 PSweep1D* = ptr TSweep1D 193 TSweep1D* {.pf.} = object 194 195 #/ Bounding box tree velocity callback function. 196 #/ This function should return an estimate for the object's velocity. 197 TBBTreeVelocityFunc* = proc (obj: pointer): TVector {.cdecl.} 198 199 PContactBufferHeader* = ptr TContentBufferHeader 200 TContentBufferHeader* {.pf.} = object 201 TSpaceArbiterApplyImpulseFunc* = proc (arb: PArbiter){.cdecl.} 202 203 PSpace* = ptr TSpace 204 TSpace* {.pf.} = object 205 iterations*: cint 206 gravity*: TVector 207 damping*: CpFloat 208 idleSpeedThreshold*: CpFloat 209 sleepTimeThreshold*: CpFloat 210 collisionSlop*: CpFloat 211 collisionBias*: CpFloat 212 collisionPersistence*: TTimestamp 213 enableContactGraph*: cint ##BOOL 214 data*: pointer 215 staticBody*: PBody 216 stamp: TTimestamp 217 currDT: CpFloat 218 bodies: PArray 219 rousedBodies: PArray 220 sleepingComponents: PArray 221 staticShapes: PSpatialIndex 222 activeShapes: PSpatialIndex 223 arbiters: PArray 224 contactBuffersHead: PContactBufferHeader 225 cachedArbiters: PHashSet 226 pooledArbiters: PArray 227 constraints: PArray 228 allocatedBuffers: PArray 229 locked: cint 230 collisionHandlers: PHashSet 231 defaultHandler: TCollisionHandler 232 postStepCallbacks: PHashSet 233 arbiterApplyImpulse: TSpaceArbiterApplyImpulseFunc 234 staticBody2: TBody #_staticBody 235 PBody* = ptr TBody 236 TBody*{.pf.} = object 237 velocityFunc*: TBodyVelocityFunc 238 positionFunc*: TBodyPositionFunc 239 m*: CpFloat 240 mInv*: CpFloat 241 i*: CpFloat 242 iInv*: CpFloat 243 p*: TVector 244 v*: TVector 245 f*: TVector 246 a*: CpFloat 247 w*: CpFloat 248 t*: CpFloat 249 rot*: TVector 250 data*: pointer 251 vLimit*: CpFloat 252 wLimit*: CpFloat 253 vBias*: TVector 254 wBias*: CpFloat 255 space*: PSpace 256 shapeList*: PShape 257 arbiterList*: PArbiter 258 constraintList*: PConstraint 259 node*: TComponentNode 260 #/ Body/shape iterator callback function type. 261 TBodyShapeIteratorFunc* = proc (body: PBody; shape: PShape; 262 data: pointer) {.cdecl.} 263 #/ Body/constraint iterator callback function type. 264 TBodyConstraintIteratorFunc* = proc (body: PBody; 265 constraint: PConstraint; 266 data: pointer) {.cdecl.} 267 #/ Body/arbiter iterator callback function type. 268 TBodyArbiterIteratorFunc* = proc (body: PBody; arbiter: PArbiter; 269 data: pointer) {.cdecl.} 270 271 PNearestPointQueryInfo* = ptr TNearestPointQueryInfo 272 #/ Nearest point query info struct. 273 TNearestPointQueryInfo*{.pf.} = object 274 shape: PShape #/ The nearest shape, NULL if no shape was within range. 275 p: TVector #/ The closest point on the shape's surface. (in world space coordinates) 276 d: CpFloat #/ The distance to the point. The distance is negative if the point is inside the shape. 277 278 PSegmentQueryInfo* = ptr TSegmentQueryInfo 279 #/ Segment query info struct. 280 TSegmentQueryInfo*{.pf.} = object 281 shape*: PShape #/ The shape that was hit, NULL if no collision occurred. 282 t*: CpFloat #/ The normalized distance along the query segment in the range [0, 1]. 283 n*: TVector #/ The normal of the surface hit. 284 TShapeType*{.size: sizeof(cint).} = enum 285 CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES 286 TShapeCacheDataImpl* = proc (shape: PShape; p: TVector; rot: TVector): TBB{.cdecl.} 287 TShapeDestroyImpl* = proc (shape: PShape){.cdecl.} 288 TShapePointQueryImpl* = proc (shape: PShape; p: TVector): Bool32 {.cdecl.} 289 TShapeSegmentQueryImpl* = proc (shape: PShape; a: TVector; b: TVector; 290 info: PSegmentQueryInfo){.cdecl.} 291 PShapeClass* = ptr TShapeClass 292 TShapeClass*{.pf.} = object 293 kind*: TShapeType 294 cacheData*: TShapeCacheDataImpl 295 destroy*: TShapeDestroyImpl 296 pointQuery*: TShapePointQueryImpl 297 segmentQuery*: TShapeSegmentQueryImpl 298 PShape* = ptr TShape 299 TShape*{.pf.} = object 300 klass: PShapeClass #/ PRIVATE 301 body*: PBody #/ The rigid body this collision shape is attached to. 302 bb*: TBB #/ The current bounding box of the shape. 303 sensor*: Bool32 #/ Sensor flag. 304 #/ Sensor shapes call collision callbacks but don't produce collisions. 305 e*: CpFloat #/ Coefficient of restitution. (elasticity) 306 u*: CpFloat #/ Coefficient of friction. 307 surface_v*: TVector #/ Surface velocity used when solving for friction. 308 data*: pointer #/ User definable data pointer. Generally this points to your the game object class so you can access it when given a cpShape reference in a callback. 309 collision_type*: TCollisionType #/ Collision type of this shape used when picking collision handlers. 310 group*: TGroup #/ Group of this shape. Shapes in the same group don't collide. 311 layers*: TLayers #/ Layer bitmask for this shape. Shapes only collide if the bitwise and of their layers is non-zero. 312 space: PSpace #PRIVATE 313 next: PShape #PRIVATE 314 prev: PShape #PRIVATE 315 hashid: THashValue #PRIVATE 316 PCircleShape* = ptr TCircleShape 317 TCircleShape*{.pf.} = object 318 shape: PShape 319 c, tc: TVector 320 r: CpFloat 321 PPolyShape* = ptr TPolyShape 322 TPolyShape*{.pf.} = object 323 shape: PShape 324 numVerts: cint 325 verts, tVerts: TVector 326 planes, tPlanes: PSplittingPlane 327 PSegmentShape* = ptr TSegmentShape 328 TSegmentShape*{.pf.} = object 329 shape: PShape 330 a, b, n: TVector 331 ta, tb, tn: TVector 332 r: CpFloat 333 aTangent, bTangent: TVector 334 PSplittingPlane* = ptr TSplittingPlane 335 TSplittingPlane*{.pf.} = object 336 n: TVector 337 d: CpFloat 338 339 #/ Post Step callback function type. 340 TPostStepFunc* = proc (space: PSpace; obj: pointer; data: pointer){.cdecl.} 341 #/ Point query callback function type. 342 TSpacePointQueryFunc* = proc (shape: PShape; data: pointer){.cdecl.} 343 #/ Segment query callback function type. 344 TSpaceSegmentQueryFunc* = proc (shape: PShape; t: CpFloat; n: TVector; 345 data: pointer){.cdecl.} 346 #/ Rectangle Query callback function type. 347 TSpaceBBQueryFunc* = proc (shape: PShape; data: pointer){.cdecl.} 348 #/ Shape query callback function type. 349 TSpaceShapeQueryFunc* = proc (shape: PShape; points: PContactPointSet; 350 data: pointer){.cdecl.} 351 #/ Space/body iterator callback function type. 352 TSpaceBodyIteratorFunc* = proc (body: PBody; data: pointer){.cdecl.} 353 #/ Space/body iterator callback function type. 354 TSpaceShapeIteratorFunc* = proc (shape: PShape; data: pointer){.cdecl.} 355 #/ Space/constraint iterator callback function type. 356 TSpaceConstraintIteratorFunc* = proc (constraint: PConstraint; 357 data: pointer){.cdecl.} 358 #/ Opaque cpConstraint struct. 359 PConstraint* = ptr TConstraint 360 TConstraint*{.pf.} = object 361 klass: PConstraintClass #/PRIVATE 362 a*: PBody #/ The first body connected to this constraint. 363 b*: PBody #/ The second body connected to this constraint. 364 space: PSpace #/PRIVATE 365 next_a: PConstraint #/PRIVATE 366 next_b: PConstraint #/PRIVATE 367 maxForce*: CpFloat #/ The maximum force that this constraint is allowed to use. Defaults to infinity. 368 errorBias*: CpFloat #/ The rate at which joint error is corrected. Defaults to pow(1.0 - 0.1, 60.0) meaning that it will correct 10% of the error every 1/60th of a second. 369 maxBias*: CpFloat #/ The maximum rate at which joint error is corrected. Defaults to infinity. 370 preSolve*: TConstraintPreSolveFunc #/ Function called before the solver runs. Animate your joint anchors, update your motor torque, etc. 371 postSolve*: TConstraintPostSolveFunc #/ Function called after the solver runs. Use the applied impulse to perform effects like breakable joints. 372 data*: CpDataPointer # User definable data pointer. Generally this points to your the game object class so you can access it when given a cpConstraint reference in a callback. 373 TConstraintPreStepImpl = proc (constraint: PConstraint; dt: CpFloat){.cdecl.} 374 TConstraintApplyCachedImpulseImpl = proc (constraint: PConstraint; dt_coef: CpFloat){.cdecl.} 375 TConstraintApplyImpulseImpl = proc (constraint: PConstraint){.cdecl.} 376 TConstraintGetImpulseImpl = proc (constraint: PConstraint): CpFloat{.cdecl.} 377 PConstraintClass = ptr TConstraintClass 378 TConstraintClass{.pf.} = object 379 preStep*: TConstraintPreStepImpl 380 applyCachedImpulse*: TConstraintApplyCachedImpulseImpl 381 applyImpulse*: TConstraintApplyImpulseImpl 382 getImpulse*: TConstraintGetImpulseImpl 383 #/ Callback function type that gets called before solving a joint. 384 TConstraintPreSolveFunc* = proc (constraint: PConstraint; space: PSpace){. 385 cdecl.} 386 #/ Callback function type that gets called after solving a joint. 387 TConstraintPostSolveFunc* = proc (constraint: PConstraint; space: PSpace){. 388 cdecl.} 389 390##cp property emulators 391template defGetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = 392 proc `get procName`*(obj: otype): memberType {.cdecl.} = 393 return obj.memberName 394template defSetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = 395 proc `set procName`*(obj: otype, value: memberType) {.cdecl.} = 396 obj.memberName = value 397template defProp(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = 398 defGetter(otype, memberType, memberName, procName) 399 defSetter(otype, memberType, memberName, procName) 400 401 402##cpspace.h 403proc allocSpace*(): PSpace {. 404 importc: "cpSpaceAlloc", dynlib: Lib.} 405proc Init*(space: PSpace): PSpace {. 406 importc: "cpSpaceInit", dynlib: Lib.} 407proc newSpace*(): PSpace {. 408 importc: "cpSpaceNew", dynlib: Lib.} 409proc destroy*(space: PSpace) {. 410 importc: "cpSpaceDestroy", dynlib: Lib.} 411proc free*(space: PSpace) {. 412 importc: "cpSpaceFree", dynlib: Lib.} 413 414defProp(PSpace, cint, iterations, Iterations) 415defProp(PSpace, TVector, gravity, Gravity) 416defProp(PSpace, CpFloat, damping, Damping) 417defProp(PSpace, CpFloat, idleSpeedThreshold, IdleSpeedThreshold) 418defProp(PSpace, CpFloat, sleepTimeThreshold, SleepTimeThreshold) 419defProp(PSpace, CpFloat, collisionSlop, CollisionSlop) 420defProp(PSpace, CpFloat, collisionBias, CollisionBias) 421defProp(PSpace, TTimestamp, collisionPersistence, CollisionPersistence) 422defProp(PSpace, Bool32, enableContactGraph, EnableContactGraph) 423defProp(PSpace, pointer, data, UserData) 424defGetter(PSpace, PBody, staticBody, StaticBody) 425defGetter(PSpace, CpFloat, currDt, CurrentTimeStep) 426 427 428#/ returns true from inside a callback and objects cannot be added/removed. 429proc isLocked*(space: PSpace): bool{.inline.} = 430 result = space.locked.bool 431 432#/ Set a default collision handler for this space. 433#/ The default collision handler is invoked for each colliding pair of shapes 434#/ that isn't explicitly handled by a specific collision handler. 435#/ You can pass NULL for any function you don't want to implement. 436proc setDefaultCollisionHandler*(space: PSpace; begin: TCollisionBeginFunc; 437 preSolve: TCollisionPreSolveFunc; 438 postSolve: TCollisionPostSolveFunc; 439 separate: TCollisionSeparateFunc; 440 data: pointer){. 441 cdecl, importc: "cpSpaceSetDefaultCollisionHandler", dynlib: Lib.} 442#/ Set a collision handler to be used whenever the two shapes with the given collision types collide. 443#/ You can pass NULL for any function you don't want to implement. 444proc addCollisionHandler*(space: PSpace; a, b: TCollisionType; 445 begin: TCollisionBeginFunc; 446 preSolve: TCollisionPreSolveFunc; 447 postSolve: TCollisionPostSolveFunc; 448 separate: TCollisionSeparateFunc; data: pointer){. 449 cdecl, importc: "cpSpaceAddCollisionHandler", dynlib: Lib.} 450#/ Unset a collision handler. 451proc removeCollisionHandler*(space: PSpace; a: TCollisionType; 452 b: TCollisionType){. 453 cdecl, importc: "cpSpaceRemoveCollisionHandler", dynlib: Lib.} 454#/ Add a collision shape to the simulation. 455#/ If the shape is attached to a static body, it will be added as a static shape. 456proc addShape*(space: PSpace; shape: PShape): PShape{. 457 cdecl, importc: "cpSpaceAddShape", dynlib: Lib.} 458#/ Explicitly add a shape as a static shape to the simulation. 459proc addStaticShape*(space: PSpace; shape: PShape): PShape{. 460 cdecl, importc: "cpSpaceAddStaticShape", dynlib: Lib.} 461#/ Add a rigid body to the simulation. 462proc addBody*(space: PSpace; body: PBody): PBody{. 463 cdecl, importc: "cpSpaceAddBody", dynlib: Lib.} 464#/ Add a constraint to the simulation. 465proc addConstraint*(space: PSpace; constraint: PConstraint): PConstraint{. 466 cdecl, importc: "cpSpaceAddConstraint", dynlib: Lib.} 467#/ Remove a collision shape from the simulation. 468proc removeShape*(space: PSpace; shape: PShape){. 469 cdecl, importc: "cpSpaceRemoveShape", dynlib: Lib.} 470#/ Remove a collision shape added using cpSpaceAddStaticShape() from the simulation. 471proc removeStaticShape*(space: PSpace; shape: PShape){. 472 cdecl, importc: "cpSpaceRemoveStaticShape", dynlib: Lib.} 473#/ Remove a rigid body from the simulation. 474proc removeBody*(space: PSpace; body: PBody){. 475 cdecl, importc: "cpSpaceRemoveBody", dynlib: Lib.} 476#/ Remove a constraint from the simulation. 477proc RemoveConstraint*(space: PSpace; constraint: PConstraint){. 478 cdecl, importc: "cpSpaceRemoveConstraint", dynlib: Lib.} 479#/ Test if a collision shape has been added to the space. 480proc containsShape*(space: PSpace; shape: PShape): bool{. 481 cdecl, importc: "cpSpaceContainsShape", dynlib: Lib.} 482#/ Test if a rigid body has been added to the space. 483proc containsBody*(space: PSpace; body: PBody): bool{. 484 cdecl, importc: "cpSpaceContainsBody", dynlib: Lib.} 485#/ Test if a constraint has been added to the space. 486 487proc containsConstraint*(space: PSpace; constraint: PConstraint): bool{. 488 cdecl, importc: "cpSpaceContainsConstraint", dynlib: Lib.} 489#/ Schedule a post-step callback to be called when cpSpaceStep() finishes. 490#/ @c obj is used a key, you can only register one callback per unique value for @c obj 491proc addPostStepCallback*(space: PSpace; fun: TPostStepFunc; 492 obj: pointer; data: pointer){. 493 cdecl, importc: "cpSpaceAddPostStepCallback", dynlib: Lib.} 494 495#/ Query the space at a point and call @c func for each shape found. 496proc pointQuery*(space: PSpace; point: TVector; layers: TLayers; 497 group: TGroup; fun: TSpacePointQueryFunc; data: pointer){. 498 cdecl, importc: "cpSpacePointQuery", dynlib: Lib.} 499 500#/ Query the space at a point and return the first shape found. Returns NULL if no shapes were found. 501proc pointQueryFirst*(space: PSpace; point: TVector; layers: TLayers; 502 group: TGroup): PShape{. 503 cdecl, importc: "cpSpacePointQueryFirst", dynlib: Lib.} 504 505#/ Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected. 506proc segmentQuery*(space: PSpace; start: TVector; to: TVector; 507 layers: TLayers; group: TGroup; 508 fun: TSpaceSegmentQueryFunc; data: pointer){. 509 cdecl, importc: "cpSpaceSegmentQuery", dynlib: Lib.} 510#/ Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit. 511proc segmentQueryFirst*(space: PSpace; start: TVector; to: TVector; 512 layers: TLayers; group: TGroup; 513 res: PSegmentQueryInfo): PShape{. 514 cdecl, importc: "cpSpaceSegmentQueryFirst", dynlib: Lib.} 515 516#/ Perform a fast rectangle query on the space calling @c func for each shape found. 517#/ Only the shape's bounding boxes are checked for overlap, not their full shape. 518proc BBQuery*(space: PSpace; bb: TBB; layers: TLayers; group: TGroup; 519 fun: TSpaceBBQueryFunc; data: pointer){. 520 cdecl, importc: "cpSpaceBBQuery", dynlib: Lib.} 521 522#/ Query a space for any shapes overlapping the given shape and call @c func for each shape found. 523proc shapeQuery*(space: PSpace; shape: PShape; fun: TSpaceShapeQueryFunc; data: pointer): bool {. 524 cdecl, importc: "cpSpaceShapeQuery", dynlib: Lib.} 525#/ Call cpBodyActivate() for any shape that is overlaps the given shape. 526proc activateShapesTouchingShape*(space: PSpace; shape: PShape){. 527 cdecl, importc: "cpSpaceActivateShapesTouchingShape", dynlib: Lib.} 528 529#/ Call @c func for each body in the space. 530proc eachBody*(space: PSpace; fun: TSpaceBodyIteratorFunc; data: pointer){. 531 cdecl, importc: "cpSpaceEachBody", dynlib: Lib.} 532 533#/ Call @c func for each shape in the space. 534proc eachShape*(space: PSpace; fun: TSpaceShapeIteratorFunc; 535 data: pointer){. 536 cdecl, importc: "cpSpaceEachShape", dynlib: Lib.} 537#/ Call @c func for each shape in the space. 538proc eachConstraint*(space: PSpace; fun: TSpaceConstraintIteratorFunc; 539 data: pointer){. 540 cdecl, importc: "cpSpaceEachConstraint", dynlib: Lib.} 541#/ Update the collision detection info for the static shapes in the space. 542proc reindexStatic*(space: PSpace){. 543 cdecl, importc: "cpSpaceReindexStatic", dynlib: Lib.} 544#/ Update the collision detection data for a specific shape in the space. 545proc reindexShape*(space: PSpace; shape: PShape){. 546 cdecl, importc: "cpSpaceReindexShape", dynlib: Lib.} 547#/ Update the collision detection data for all shapes attached to a body. 548proc reindexShapesForBody*(space: PSpace; body: PBody){. 549 cdecl, importc: "cpSpaceReindexShapesForBody", dynlib: Lib.} 550#/ Switch the space to use a spatial has as it's spatial index. 551proc SpaceUseSpatialHash*(space: PSpace; dim: CpFloat; count: cint){. 552 cdecl, importc: "cpSpaceUseSpatialHash", dynlib: Lib.} 553#/ Step the space forward in time by @c dt. 554proc step*(space: PSpace; dt: CpFloat) {. 555 cdecl, importc: "cpSpaceStep", dynlib: Lib.} 556 557 558#/ Convenience constructor for cpVect structs. 559proc vector*(x, y: CpFloat): TVector {.inline.} = 560 result.x = x 561 result.y = y 562proc newVector*(x, y: CpFloat): TVector {.inline.} = 563 return vector(x, y) 564#let VectorZero* = newVector(0.0, 0.0) 565var VectorZero* = newVector(0.0, 0.0) 566 567#/ Vector dot product. 568proc dot*(v1, v2: TVector): CpFloat {.inline.} = 569 result = v1.x * v2.x + v1.y * v2.y 570 571#/ Returns the length of v. 572#proc len*(v: TVector): CpFloat {. 573# cdecl, importc: "cpvlength", dynlib: Lib.} 574proc len*(v: TVector): CpFloat {.inline.} = 575 result = v.dot(v).sqrt 576#/ Spherical linearly interpolate between v1 and v2. 577proc slerp*(v1, v2: TVector; t: CpFloat): TVector {. 578 cdecl, importc: "cpvslerp", dynlib: Lib.} 579#/ Spherical linearly interpolate between v1 towards v2 by no more than angle a radians 580proc slerpconst*(v1, v2: TVector; a: CpFloat): TVector {. 581 cdecl, importc: "cpvslerpconst", dynlib: Lib.} 582#/ Returns the unit length vector for the given angle (in radians). 583#proc vectorForAngle*(a: CpFloat): TVector {. 584# cdecl, importc: "cpvforangle", dynlib: Lib.} 585proc vectorForAngle*(a: CpFloat): TVector {.inline.} = 586 result = newVector(math.cos(a), math.sin(a)) 587#/ Returns the angular direction v is pointing in (in radians). 588proc toAngle*(v: TVector): CpFloat {.inline.} = 589 result = math.arctan2(v.y, v.x) 590#/ Returns a string representation of v. Intended mostly for debugging purposes and not production use. 591#/ @attention The string points to a static local and is reset every time the function is called. 592#/ If you want to print more than one vector you will have to split up your printing onto separate lines. 593proc `$`*(v: TVector): cstring {.cdecl, importc: "cpvstr", dynlib: Lib.} 594 595 596#/ Check if two vectors are equal. (Be careful when comparing floating point numbers!) 597proc `==`*(v1, v2: TVector): bool {.inline.} = 598 result = v1.x == v2.x and v1.y == v2.y 599 600#/ Add two vectors 601proc `+`*(v1, v2: TVector): TVector {.inline.} = 602 result = newVector(v1.x + v2.x, v1.y + v2.y) 603proc `+=`*(v1: var TVector; v2: TVector) = 604 v1.x = v1.x + v2.x 605 v1.y = v1.y + v2.y 606 607#/ Subtract two vectors. 608proc `-`*(v1, v2: TVector): TVector {.inline.} = 609 result = newVector(v1.x - v2.x, v1.y - v2.y) 610proc `-=`*(v1: var TVector; v2: TVector) = 611 v1.x = v1.x - v2.x 612 v1.y = v1.y - v2.y 613 614#/ Negate a vector. 615proc `-`*(v: TVector): TVector {.inline.} = 616 result = newVector(- v.x, - v.y) 617 618#/ Scalar multiplication. 619proc `*`*(v: TVector, s: CpFloat): TVector {.inline.} = 620 result.x = v.x * s 621 result.y = v.y * s 622proc `*=`*(v: var TVector; s: CpFloat) = 623 v.x = v.x * s 624 v.y = v.y * s 625 626#/ 2D vector cross product analog. 627#/ The cross product of 2D vectors results in a 3D vector with only a z component. 628#/ This function returns the magnitude of the z value. 629proc cross*(v1, v2: TVector): CpFloat {.inline.} = 630 result = v1.x * v2.y - v1.y * v2.x 631 632#/ Returns a perpendicular vector. (90 degree rotation) 633proc perp*(v: TVector): TVector {.inline.} = 634 result = newVector(- v.y, v.x) 635 636#/ Returns a perpendicular vector. (-90 degree rotation) 637proc rperp*(v: TVector): TVector {.inline.} = 638 result = newVector(v.y, - v.x) 639 640#/ Returns the vector projection of v1 onto v2. 641proc project*(v1,v2: TVector): TVector {.inline.} = 642 result = v2 * (v1.dot(v2) / v2.dot(v2)) 643 644#/ Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector. 645 646proc rotate*(v1, v2: TVector): TVector {.inline.} = 647 result = newVector(v1.x * v2.x - v1.y * v2.y, v1.x * v2.y + v1.y * v2.x) 648#/ Inverse of cpvrotate(). 649proc unrotate*(v1, v2: TVector): TVector {.inline.} = 650 result = newVector(v1.x * v2.x + v1.y * v2.y, v1.y * v2.x - v1.x * v2.y) 651#/ Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths. 652proc lenSq*(v: TVector): CpFloat {.inline.} = 653 result = v.dot(v) 654#/ Linearly interpolate between v1 and v2. 655proc lerp*(v1, v2: TVector; t: CpFloat): TVector {.inline.} = 656 result = (v1 * (1.0 - t)) + (v2 * t) 657#/ Returns a normalized copy of v. 658proc normalize*(v: TVector): TVector {.inline.} = 659 result = v * (1.0 / v.len) 660#/ Returns a normalized copy of v or cpvzero if v was already cpvzero. Protects against divide by zero errors. 661proc normalizeSafe*(v: TVector): TVector {.inline.} = 662 result = if v.x == 0.0 and v.y == 0.0: VectorZero else: v.normalize 663#/ Clamp v to length len. 664proc clamp*(v: TVector; len: CpFloat): TVector {.inline.} = 665 result = if v.dot(v) > len * len: v.normalize * len else: v 666#/ Linearly interpolate between v1 towards v2 by distance d. 667proc lerpconst*(v1, v2: TVector; d: CpFloat): TVector {.inline.} = 668 result = v1 + clamp(v2 - v1, d) #vadd(v1 + vclamp(vsub(v2, v1), d)) 669#/ Returns the distance between v1 and v2. 670proc dist*(v1, v2: TVector): CpFloat {.inline.} = 671 result = (v1 - v2).len #vlength(vsub(v1, v2)) 672#/ Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances. 673proc distsq*(v1, v2: TVector): CpFloat {.inline.} = 674 result = (v1 - v2).lenSq #vlengthsq(vsub(v1, v2)) 675#/ Returns true if the distance between v1 and v2 is less than dist. 676proc near*(v1, v2: TVector; dist: CpFloat): bool{.inline.} = 677 result = v1.distSq(v2) < dist * dist 678 679 680 681##cpBody.h 682proc allocBody*(): PBody {.importc: "cpBodyAlloc", dynlib: Lib.} 683proc init*(body: PBody; m: CpFloat; i: CpFloat): PBody {. 684 importc: "cpBodyInit", dynlib: Lib.} 685proc newBody*(m: CpFloat; i: CpFloat): PBody {. 686 importc: "cpBodyNew", dynlib: Lib.} 687 688proc initStaticBody*(body: PBody): PBody{. 689 importc: "cpBodyInitStatic", dynlib: Lib.} 690#/ Allocate and initialize a static cpBody. 691proc newStatic*(): PBody{.importc: "cpBodyNewStatic", dynlib: Lib.} 692#/ Destroy a cpBody. 693proc destroy*(body: PBody){.importc: "cpBodyDestroy", dynlib: Lib.} 694#/ Destroy and free a cpBody. 695proc free*(body: PBody){.importc: "cpBodyFree", dynlib: Lib.} 696 697#/ Wake up a sleeping or idle body. 698proc activate*(body: PBody){.importc: "cpBodyActivate", dynlib: Lib.} 699#/ Wake up any sleeping or idle bodies touching a static body. 700proc activateStatic*(body: PBody; filter: PShape){. 701 importc: "cpBodyActivateStatic", dynlib: Lib.} 702#/ Force a body to fall asleep immediately. 703proc Sleep*(body: PBody){.importc: "cpBodySleep", dynlib: Lib.} 704#/ Force a body to fall asleep immediately along with other bodies in a group. 705proc SleepWithGroup*(body: PBody; group: PBody){. 706 importc: "cpBodySleepWithGroup", dynlib: Lib.} 707#/ Returns true if the body is sleeping. 708proc isSleeping*(body: PBody): bool {.inline.} = 709 return body.node.root != nil 710#/ Returns true if the body is static. 711proc isStatic*(body: PBody): bool {.inline.} = 712 return body.node.idleTime == CpInfinity 713#/ Returns true if the body has not been added to a space. 714proc isRogue*(body: PBody): bool {.inline.} = 715 return body.space == nil 716 717# #define CP_DefineBodyStructGetter(type, member, name) \ 718# static inline type cpBodyGet##name(const cpBody *body){return body->member;} 719# #define CP_DefineBodyStructSetter(type, member, name) \ 720# static inline void cpBodySet##name(cpBody *body, const type value){ \ 721# cpBodyActivate(body); \ 722# cpBodyAssertSane(body); \ 723# body->member = value; \ 724# } 725# #define CP_DefineBodyStructProperty(type, member, name) \ 726# CP_DefineBodyStructGetter(type, member, name) \ 727# CP_DefineBodyStructSetter(type, member, name) 728 729defGetter(PBody, CpFloat, m, Mass) 730#/ Set the mass of a body. 731when defined(MoreNim): 732 defSetter(PBody, CpFloat, m, Mass) 733else: 734 proc setMass*(body: PBody; m: CpFloat){. 735 cdecl, importc: "cpBodySetMass", dynlib: Lib.} 736 737#/ Get the moment of a body. 738defGetter(PBody, CpFloat, i, Moment) 739#/ Set the moment of a body. 740when defined(MoreNim): 741 defSetter(PBody, CpFloat, i, Moment) 742else: 743 proc SetMoment*(body: PBody; i: CpFloat) {. 744 cdecl, importc: "cpBodySetMoment", dynlib: Lib.} 745 746#/ Get the position of a body. 747defGetter(PBody, TVector, p, Pos) 748#/ Set the position of a body. 749when defined(MoreNim): 750 defSetter(PBody, TVector, p, Pos) 751else: 752 proc setPos*(body: PBody; pos: TVector) {. 753 cdecl, importc: "cpBodySetPos", dynlib: Lib.} 754 755defProp(PBody, TVector, v, Vel) 756defProp(PBody, TVector, f, Force) 757 758#/ Get the angle of a body. 759defGetter(PBody, CpFloat, a, Angle) 760#/ Set the angle of a body. 761proc setAngle*(body: PBody; a: CpFloat){. 762 cdecl, importc: "cpBodySetAngle", dynlib: Lib.} 763 764defProp(PBody, CpFloat, w, AngVel) 765defProp(PBody, CpFloat, t, Torque) 766defGetter(PBody, TVector, rot, Rot) 767defProp(PBody, CpFloat, v_limit, VelLimit) 768defProp(PBody, CpFloat, w_limit, AngVelLimit) 769defProp(PBody, pointer, data, UserData) 770 771#/ Default Integration functions. 772proc UpdateVelocity*(body: PBody; gravity: TVector; damping: CpFloat; dt: CpFloat){. 773 cdecl, importc: "cpBodyUpdateVelocity", dynlib: Lib.} 774proc UpdatePosition*(body: PBody; dt: CpFloat){. 775 cdecl, importc: "cpBodyUpdatePosition", dynlib: Lib.} 776#/ Convert body relative/local coordinates to absolute/world coordinates. 777proc Local2World*(body: PBody; v: TVector): TVector{.inline.} = 778 result = body.p + v.rotate(body.rot) ##return cpvadd(body.p, cpvrotate(v, body.rot)) 779#/ Convert body absolute/world coordinates to relative/local coordinates. 780proc world2Local*(body: PBody; v: TVector): TVector{.inline.} = 781 result = (v - body.p).unrotate(body.rot) 782#/ Set the forces and torque or a body to zero. 783proc resetForces*(body: PBody){. 784 cdecl, importc: "cpBodyResetForces", dynlib: Lib.} 785#/ Apply an force (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates). 786proc applyForce*(body: PBody; f, r: TVector){. 787 cdecl, importc: "cpBodyApplyForce", dynlib: Lib.} 788#/ Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates). 789proc applyImpulse*(body: PBody; j, r: TVector){. 790 cdecl, importc: "cpBodyApplyImpulse", dynlib: Lib.} 791#/ Get the velocity on a body (in world units) at a point on the body in world coordinates. 792 793proc getVelAtWorldPoint*(body: PBody; point: TVector): TVector{. 794 cdecl, importc: "cpBodyGetVelAtWorldPoint", dynlib: Lib.} 795#/ Get the velocity on a body (in world units) at a point on the body in local coordinates. 796proc getVelAtLocalPoint*(body: PBody; point: TVector): TVector{. 797 cdecl, importc: "cpBodyGetVelAtLocalPoint", dynlib: Lib.} 798#/ Get the kinetic energy of a body. 799# static inline CpFloat cpBodyKineticEnergy(const cpBody *body) 800# { 801# // Need to do some fudging to avoid NaNs 802# cpFloat vsq = cpvdot(body->v, body->v); 803# cpFloat wsq = body->w*body->w; 804# return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f); 805# } 806proc kineticEnergy*(body: PBOdy): CpFloat = 807 result = (body.v.dot(body.v) * body.m) + (body.w * body.w * body.i) 808 809#/ Call @c func once for each shape attached to @c body and added to the space. 810proc eachShape*(body: PBody; fun: TBodyShapeIteratorFunc; 811 data: pointer){. 812 cdecl, importc: "cpBodyEachShape", dynlib: Lib.} 813#/ Call @c func once for each constraint attached to @c body and added to the space. 814proc eachConstraint*(body: PBody; fun: TBodyConstraintIteratorFunc; 815 data: pointer) {. 816 cdecl, importc: "cpBodyEachConstraint", dynlib: Lib.} 817#/ Call @c func once for each arbiter that is currently active on the body. 818proc eachArbiter*(body: PBody; fun: TBodyArbiterIteratorFunc; 819 data: pointer){. 820 cdecl, importc: "cpBodyEachArbiter", dynlib: Lib.} 821#/ Allocate a spatial hash. 822proc SpaceHashAlloc*(): PSpaceHash{. 823 cdecl, importc: "cpSpaceHashAlloc", dynlib: Lib.} 824#/ Initialize a spatial hash. 825proc SpaceHashInit*(hash: PSpaceHash; celldim: CpFloat; numcells: cint; 826 bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. 827 cdecl, importc: "cpSpaceHashInit", dynlib: Lib.} 828#/ Allocate and initialize a spatial hash. 829proc SpaceHashNew*(celldim: CpFloat; cells: cint; bbfun: TSpatialIndexBBFunc; 830 staticIndex: PSpatialIndex): PSpatialIndex{. 831 cdecl, importc: "cpSpaceHashNew", dynlib: Lib.} 832#/ Change the cell dimensions and table size of the spatial hash to tune it. 833#/ The cell dimensions should roughly match the average size of your objects 834#/ and the table size should be ~10 larger than the number of objects inserted. 835#/ Some trial and error is required to find the optimum numbers for efficiency. 836proc SpaceHashResize*(hash: PSpaceHash; celldim: CpFloat; numcells: cint){. 837 cdecl, importc: "cpSpaceHashResize", dynlib: Lib.} 838#MARK: AABB Tree 839 840 841#/ Allocate a bounding box tree. 842proc BBTreeAlloc*(): PBBTree{.cdecl, importc: "cpBBTreeAlloc", dynlib: Lib.} 843#/ Initialize a bounding box tree. 844proc BBTreeInit*(tree: PBBTree; bbfun: TSpatialIndexBBFunc; 845 staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl, 846 importc: "cpBBTreeInit", dynlib: Lib.} 847#/ Allocate and initialize a bounding box tree. 848proc BBTreeNew*(bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. 849 cdecl, importc: "cpBBTreeNew", dynlib: Lib.} 850#/ Perform a static top down optimization of the tree. 851proc BBTreeOptimize*(index: PSpatialIndex){. 852 cdecl, importc: "cpBBTreeOptimize", dynlib: Lib.} 853#/ Set the velocity function for the bounding box tree to enable temporal coherence. 854 855proc BBTreeSetVelocityFunc*(index: PSpatialIndex; fun: TBBTreeVelocityFunc){. 856 cdecl, importc: "cpBBTreeSetVelocityFunc", dynlib: Lib.} 857#MARK: Single Axis Sweep 858 859 860#/ Allocate a 1D sort and sweep broadphase. 861 862proc Sweep1DAlloc*(): ptr TSweep1D{.cdecl, importc: "cpSweep1DAlloc", 863 dynlib: Lib.} 864#/ Initialize a 1D sort and sweep broadphase. 865 866proc Sweep1DInit*(sweep: ptr TSweep1D; bbfun: TSpatialIndexBBFunc; 867 staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl, 868 importc: "cpSweep1DInit", dynlib: Lib.} 869#/ Allocate and initialize a 1D sort and sweep broadphase. 870 871proc Sweep1DNew*(bbfun: TSpatialIndexBBFunc; staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{. 872 cdecl, importc: "cpSweep1DNew", dynlib: Lib.} 873 874 875 876defProp(PArbiter, CpFloat, e, Elasticity) 877defProp(PArbiter, CpFloat, u, Friction) 878defProp(PArbiter, TVector, surface_vr, SurfaceVelocity) 879 880#/ Calculate the total impulse that was applied by this 881#/ This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. 882proc totalImpulse*(obj: PArbiter): TVector {.cdecl, importc: "cpArbiterTotalImpulse", dynlib: Lib.} 883 884#/ Calculate the total impulse including the friction that was applied by this arbiter. 885#/ This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. 886proc totalImpulseWithFriction*(obj: PArbiter): TVector {.cdecl, importc: "cpArbiterTotalImpulseWithFriction", dynlib: Lib.} 887 888#/ Calculate the amount of energy lost in a collision including static, but not dynamic friction. 889#/ This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. 890proc totalKE*(obj: PArbiter): CpFloat {.cdecl, importc: "cpArbiterTotalKE", dynlib: Lib.} 891 892 893#/ Causes a collision pair to be ignored as if you returned false from a begin callback. 894#/ If called from a pre-step callback, you will still need to return false 895#/ if you want it to be ignored in the current step. 896proc ignore*(arb: PArbiter) {.cdecl, importc: "cpArbiterIgnore", dynlib: Lib.} 897 898#/ Return the colliding shapes involved for this arbiter. 899#/ The order of their cpSpace.collision_type values will match 900#/ the order set when the collision handler was registered. 901proc getShapes*(arb: PArbiter, a, b: var PShape) {.inline.} = 902 if arb.swappedColl.bool: 903 a = arb.b 904 b = arb.a 905 else: 906 a = arb.a 907 b = arb.b 908 909#/ A macro shortcut for defining and retrieving the shapes from an arbiter. 910#define CP_ARBITER_GET_SHAPES(arb, a, b) cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b); 911template getShapes*(arb: PArbiter, name1, name2: untyped) = 912 var name1, name2: PShape 913 getShapes(arb, name1, name2) 914 915 916#/ Return the colliding bodies involved for this arbiter. 917#/ The order of the cpSpace.collision_type the bodies are associated with values will match 918#/ the order set when the collision handler was registered. 919#proc getBodies*(arb: PArbiter, a, b: var PBody) {.inline.} = 920# getShapes(arb, shape1, shape2) 921# a = shape1.body 922# b = shape2.body 923 924#/ A macro shortcut for defining and retrieving the bodies from an arbiter. 925#define CP_ARBITER_GET_BODIES(arb, a, b) cpBody *a, *b; cpArbiterGetBodies(arb, &a, &b); 926template getBodies*(arb: PArbiter, name1, name2: untyped) = 927 var name1, name2: PBOdy 928 getBodies(arb, name1, name2) 929 930proc isFirstContact*(arb: PArbiter): bool {.inline.} = 931 result = arb.state == ArbiterStateFirstColl 932 933proc getCount*(arb: PArbiter): cint {.inline.} = 934 result = arb.numContacts 935 936#/ Return a contact set from an arbiter. 937proc getContactPointSet*(arb: PArbiter): TContactPointSet {. 938 cdecl, importc: "cpArbiterGetContactPointSet", dynlib: Lib.} 939#/ Get the normal of the @c ith contact point. 940proc getNormal*(arb: PArbiter; i: cint): TVector {. 941 cdecl, importc: "cpArbiterGetNormal", dynlib: Lib.} 942#/ Get the position of the @c ith contact point. 943proc getPoint*(arb: PArbiter; i: cint): TVector {. 944 cdecl, importc: "cpArbiterGetPoint", dynlib: Lib.} 945#/ Get the depth of the @c ith contact point. 946proc getDepth*(arb: PArbiter; i: cint): CpFloat {. 947 cdecl, importc: "cpArbiterGetDepth", dynlib: Lib.} 948 949##Shapes 950template defShapeSetter(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) = 951 proc `set procName`*(obj: PShape, value: memberType) {.cdecl.} = 952 if activates and obj.body != nil: obj.body.activate() 953 obj.memberName = value 954template defShapeProp(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) = 955 defGetter(PShape, memberType, memberName, procName) 956 defShapeSetter(memberType, memberName, procName, activates) 957 958#/ Destroy a shape. 959proc destroy*(shape: PShape) {. 960 cdecl, importc: "cpShapeDestroy", dynlib: Lib.} 961#/ Destroy and Free a shape. 962proc free*(shape: PShape){. 963 cdecl, importc: "cpShapeFree", dynlib: Lib.} 964#/ Update, cache and return the bounding box of a shape based on the body it's attached to. 965proc cacheBB*(shape: PShape): TBB{. 966 cdecl, importc: "cpShapeCacheBB", dynlib: Lib.} 967#/ Update, cache and return the bounding box of a shape with an explicit transformation. 968proc update*(shape: PShape; pos: TVector; rot: TVector): TBB {. 969 cdecl, importc: "cpShapeUpdate", dynlib: Lib.} 970#/ Test if a point lies within a shape. 971proc pointQuery*(shape: PShape; p: TVector): Bool32 {. 972 cdecl, importc: "cpShapePointQuery", dynlib: Lib.} 973 974#/ Perform a nearest point query. It finds the closest point on the surface of shape to a specific point. 975#/ The value returned is the distance between the points. A negative distance means the point is inside the shape. 976proc nearestPointQuery*(shape: PShape; p: TVector; res: PNearestPointQueryInfo): CpFloat {. 977 cdecl, importc: "cpShapeNearestPointQuery", dynlib: Lib.} 978#/ Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure. 979proc segmentQuery*(shape: PShape, a, b: TVector, info: PSegmentQueryInfo): bool {. 980 cdecl, importc: "cpShapeSegmentQuery", dynlib: Lib.} 981 982#/ Get the hit point for a segment query. 983## Possibly change; info to PSegmentQueryInfo 984proc queryHitPoint*(start, to: TVector, info: TSegmentQueryInfo): TVector {.inline.} = 985 result = start.lerp(to, info.t) 986 987#/ Get the hit distance for a segment query. 988proc queryHitDist*(start, to: TVector, info: TSegmentQueryInfo): CpFloat {.inline.} = 989 result = start.dist(to) * info.t 990 991defGetter(PShape, PSpace, space, Space) 992 993defGetter(PShape, PBody, body, Body) 994proc setBody*(shape: PShape, value: PBody) {. 995 cdecl, importc: "cpShapeSetBody", dynlib: Lib.} 996 997 998defGetter(PShape, TBB, bb, BB) 999defShapeProp(Bool32, sensor, Sensor, true) 1000defShapeProp(CpFloat, e, Elasticity, false) 1001defShapeProp(CpFloat, u, Friction, true) 1002defShapeProp(TVector, surface_v, SurfaceVelocity, true) 1003defShapeProp(pointer, data, UserData, false) 1004defShapeProp(TCollisionType, collision_type, CollisionType, true) 1005defShapeProp(TGroup, group, Group, true) 1006defShapeProp(TLayers, layers, Layers, true) 1007 1008#/ When initializing a shape, it's hash value comes from a counter. 1009#/ Because the hash value may affect iteration order, you can reset the shape ID counter 1010#/ when recreating a space. This will make the simulation be deterministic. 1011proc resetShapeIdCounter*(): void {.cdecl, importc: "cpResetShapeIdCounter", dynlib: Lib.} 1012#/ Allocate a circle shape. 1013proc CircleShapeAlloc*(): PCircleShape {.cdecl, importc: "cpCircleShapeAlloc", dynlib: Lib.} 1014#/ Initialize a circle shape. 1015proc init*(circle: PCircleShape, body: PBody, radius: CpFloat, offset: TVector): PCircleShape {. 1016 cdecl, importc: "cpCircleShapeInit", dynlib: Lib.} 1017#/ Allocate and initialize a circle shape. 1018proc newCircleShape*(body: PBody, radius: CpFloat, offset: TVector): PShape {. 1019 cdecl, importc: "cpCircleShapeNew", dynlib: Lib.} 1020 1021proc getCircleOffset*(shape: PShape): TVector {. 1022 cdecl, importc: "cpCircleShapeGetOffset", dynlib: Lib.} 1023proc getCircleRadius*(shape: PShape): CpFloat {. 1024 cdecl, importc: "cpCircleShapeGetRadius", dynlib: Lib.} 1025 1026 1027#/ Allocate a polygon shape. 1028proc allocPolyShape*(): PPolyShape {. 1029 cdecl, importc: "cpPolyShapeAlloc", dynlib: Lib.} 1030#/ Initialize a polygon shape. 1031#/ A convex hull will be created from the vertices. 1032proc init*(poly: PPolyShape; body: PBody, numVerts: cint; 1033 verts: ptr TVector; offset: TVector): PPolyShape {. 1034 cdecl, importc: "cpPolyShapeInit", dynlib: Lib.} 1035#/ Allocate and initialize a polygon shape. 1036#/ A convex hull will be created from the vertices. 1037proc newPolyShape*(body: PBody; numVerts: cint; verts: ptr TVector; 1038 offset: TVector): PShape {. 1039 cdecl, importc: "cpPolyShapeNew", dynlib: Lib.} 1040#/ Initialize a box shaped polygon shape. 1041proc init*(poly: PPolyShape; body: PBody; width, height: CpFloat): PPolyShape {. 1042 cdecl, importc: "cpBoxShapeInit", dynlib: Lib.} 1043#/ Initialize an offset box shaped polygon shape. 1044proc init*(poly: PPolyShape; body: PBody; box: TBB): PPolyShape {. 1045 cdecl, importc: "cpBoxShapeInit2", dynlib: Lib.} 1046#/ Allocate and initialize a box shaped polygon shape. 1047proc newBoxShape*(body: PBody; width, height: CpFloat): PShape {. 1048 cdecl, importc: "cpBoxShapeNew", dynlib: Lib.} 1049#/ Allocate and initialize an offset box shaped polygon shape. 1050proc newBoxShape*(body: PBody; box: TBB): PShape {. 1051 cdecl, importc: "cpBoxShapeNew2", dynlib: Lib.} 1052 1053#/ Check that a set of vertices is convex and has a clockwise winding. 1054#/ NOTE: Due to floating point precision issues, hulls created with cpQuickHull() are not guaranteed to validate! 1055proc validatePoly*(verts: ptr TVector; numVerts: cint): bool {. 1056 cdecl, importc: "cpPolyValidate", dynlib: Lib.} 1057#/ Get the number of verts in a polygon shape. 1058proc getNumVerts*(shape: PShape): cint {. 1059 cdecl, importc: "cpPolyShapeGetNumVerts", dynlib: Lib.} 1060#/ Get the @c ith vertex of a polygon shape. 1061proc getVert*(shape: PShape; index: cint): TVector {. 1062 cdecl, importc: "cpPolyShapeGetVert", dynlib: Lib.} 1063 1064#/ Allocate a segment shape. 1065proc allocSegmentShape*(): PSegmentShape {. 1066 cdecl, importc: "cpSegmentShapeAlloc", dynlib: Lib.} 1067#/ Initialize a segment shape. 1068proc init*(seg: PSegmentShape, body: PBody, a, b: TVector, radius: CpFloat): PSegmentShape {. 1069 cdecl, importc: "cpSegmentShapeInit", dynlib: Lib.} 1070#/ Allocate and initialize a segment shape. 1071proc newSegmentShape*(body: PBody, a, b: TVector, radius: CpFloat): PShape {. 1072 cdecl, importc: "cpSegmentShapeNew", dynlib: Lib.} 1073 1074proc setSegmentNeighbors*(shape: PShape, prev, next: TVector) {. 1075 cdecl, importc: "cpSegmentShapeSetNeighbors", dynlib: Lib.} 1076proc getSegmentA*(shape: PShape): TVector {. 1077 cdecl, importc: "cpSegmentShapeGetA", dynlib: Lib.} 1078proc getSegmentB*(shape: PShape): TVector {. 1079 cdecl, importc: "cpSegmentShapeGetB", dynlib: Lib.} 1080proc getSegmentNormal*(shape: PShape): TVector {. 1081 cdecl, importc: "cpSegmentShapeGetNormal", dynlib: Lib.} 1082proc getSegmentRadius*(shape: PShape): CpFloat {. 1083 cdecl, importc: "cpSegmentShapeGetRadius", dynlib: Lib.} 1084 1085 1086#/ Version string. 1087#var VersionString*{.importc: "cpVersionString", dynlib: Lib.}: cstring 1088#/ Calculate the moment of inertia for a circle. 1089#/ @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0. 1090when defined(MoreNim): 1091 proc momentForCircle*(m, r1, r2: CpFloat; offset: TVector): CpFloat {.cdecl.} = 1092 result = m * (0.5 * (r1 * r1 + r2 * r2) + lenSq(offset)) 1093else: 1094 proc momentForCircle*(m, r1, r2: CpFloat; offset: TVector): CpFloat {. 1095 cdecl, importc: "cpMomentForCircle", dynlib: Lib.} 1096 1097#/ Calculate area of a hollow circle. 1098#/ @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0. 1099proc AreaForCircle*(r1: CpFloat; r2: CpFloat): CpFloat {. 1100 cdecl, importc: "cpAreaForCircle", dynlib: Lib.} 1101#/ Calculate the moment of inertia for a line segment. 1102#/ Beveling radius is not supported. 1103proc MomentForSegment*(m: CpFloat; a, b: TVector): CpFloat {. 1104 cdecl, importc: "cpMomentForSegment", dynlib: Lib.} 1105#/ Calculate the area of a fattened (capsule shaped) line segment. 1106proc AreaForSegment*(a, b: TVector; r: CpFloat): CpFloat {. 1107 cdecl, importc: "cpAreaForSegment", dynlib: Lib.} 1108#/ Calculate the moment of inertia for a solid polygon shape assuming it's center of gravity is at it's centroid. The offset is added to each vertex. 1109proc MomentForPoly*(m: CpFloat; numVerts: cint; verts: ptr TVector; offset: TVector): CpFloat {. 1110 cdecl, importc: "cpMomentForPoly", dynlib: Lib.} 1111#/ Calculate the signed area of a polygon. A Clockwise winding gives positive area. 1112#/ This is probably backwards from what you expect, but matches Chipmunk's the winding for poly shapes. 1113proc AreaForPoly*(numVerts: cint; verts: ptr TVector): CpFloat {. 1114 cdecl, importc: "cpAreaForPoly", dynlib: Lib.} 1115#/ Calculate the natural centroid of a polygon. 1116proc CentroidForPoly*(numVerts: cint; verts: ptr TVector): TVector {. 1117 cdecl, importc: "cpCentroidForPoly", dynlib: Lib.} 1118#/ Center the polygon on the origin. (Subtracts the centroid of the polygon from each vertex) 1119proc RecenterPoly*(numVerts: cint; verts: ptr TVector) {. 1120 cdecl, importc: "cpRecenterPoly", dynlib: Lib.} 1121#/ Calculate the moment of inertia for a solid box. 1122proc MomentForBox*(m, width, height: CpFloat): CpFloat {. 1123 cdecl, importc: "cpMomentForBox", dynlib: Lib.} 1124#/ Calculate the moment of inertia for a solid box. 1125proc MomentForBox2*(m: CpFloat; box: TBB): CpFloat {. 1126 cdecl, importc: "cpMomentForBox2", dynlib: Lib.} 1127 1128 1129 1130##constraints 1131type 1132 #TODO: all these are private 1133 #TODO: defConstraintProp() 1134 PPinJoint = ptr TPinJoint 1135 TPinJoint{.pf.} = object 1136 constraint: PConstraint 1137 anchr1: TVector 1138 anchr2: TVector 1139 dist: CpFloat 1140 r1: TVector 1141 r2: TVector 1142 n: TVector 1143 nMass: CpFloat 1144 jnAcc: CpFloat 1145 jnMax: CpFloat 1146 bias: CpFloat 1147 PSlideJoint = ptr TSlideJoint 1148 TSlideJoint{.pf.} = object 1149 constraint: PConstraint 1150 anchr1: TVector 1151 anchr2: TVector 1152 min: CpFloat 1153 max: CpFloat 1154 r1: TVector 1155 r2: TVector 1156 n: TVector 1157 nMass: CpFloat 1158 jnAcc: CpFloat 1159 jnMax: CpFloat 1160 bias: CpFloat 1161 PPivotJoint = ptr TPivotJoint 1162 TPivotJoint{.pf.} = object 1163 constraint: PConstraint 1164 anchr1: TVector 1165 anchr2: TVector 1166 r1: TVector 1167 r2: TVector 1168 k1: TVector 1169 k2: TVector 1170 jAcc: TVector 1171 jMaxLen: CpFloat 1172 bias: TVector 1173 PGrooveJoint = ptr TGrooveJoint 1174 TGrooveJoint{.pf.} = object 1175 constraint: PConstraint 1176 grv_n: TVector 1177 grv_a: TVector 1178 grv_b: TVector 1179 anchr2: TVector 1180 grv_tn: TVector 1181 clamp: CpFloat 1182 r1: TVector 1183 r2: TVector 1184 k1: TVector 1185 k2: TVector 1186 jAcc: TVector 1187 jMaxLen: CpFloat 1188 bias: TVector 1189 PDampedSpring = ptr TDampedSpring 1190 TDampedSpring{.pf.} = object 1191 constraint: PConstraint 1192 anchr1: TVector 1193 anchr2: TVector 1194 restLength: CpFloat 1195 stiffness: CpFloat 1196 damping: CpFloat 1197 springForceFunc: TDampedSpringForceFunc 1198 target_vrn: CpFloat 1199 v_coef: CpFloat 1200 r1: TVector 1201 r2: TVector 1202 nMass: CpFloat 1203 n: TVector 1204 PDampedRotarySpring = ptr TDampedRotarySpring 1205 TDampedRotarySpring{.pf.} = object 1206 constraint: PConstraint 1207 restAngle: CpFloat 1208 stiffness: CpFloat 1209 damping: CpFloat 1210 springTorqueFunc: TDampedRotarySpringTorqueFunc 1211 target_wrn: CpFloat 1212 w_coef: CpFloat 1213 iSum: CpFloat 1214 PRotaryLimitJoint = ptr TRotaryLimitJoint 1215 TRotaryLimitJoint{.pf.} = object 1216 constraint: PConstraint 1217 min: CpFloat 1218 max: CpFloat 1219 iSum: CpFloat 1220 bias: CpFloat 1221 jAcc: CpFloat 1222 jMax: CpFloat 1223 PRatchetJoint = ptr TRatchetJoint 1224 TRatchetJoint{.pf.} = object 1225 constraint: PConstraint 1226 angle: CpFloat 1227 phase: CpFloat 1228 ratchet: CpFloat 1229 iSum: CpFloat 1230 bias: CpFloat 1231 jAcc: CpFloat 1232 jMax: CpFloat 1233 PGearJoint = ptr TGearJoint 1234 TGearJoint{.pf.} = object 1235 constraint: PConstraint 1236 phase: CpFloat 1237 ratio: CpFloat 1238 ratio_inv: CpFloat 1239 iSum: CpFloat 1240 bias: CpFloat 1241 jAcc: CpFloat 1242 jMax: CpFloat 1243 PSimpleMotor = ptr TSimpleMotor 1244 TSimpleMotor{.pf.} = object 1245 constraint: PConstraint 1246 rate: CpFloat 1247 iSum: CpFloat 1248 jAcc: CpFloat 1249 jMax: CpFloat 1250 TDampedSpringForceFunc* = proc (spring: PConstraint; dist: CpFloat): CpFloat{. 1251 cdecl.} 1252 TDampedRotarySpringTorqueFunc* = proc (spring: PConstraint; 1253 relativeAngle: CpFloat): CpFloat {.cdecl.} 1254#/ Destroy a constraint. 1255proc destroy*(constraint: PConstraint){. 1256 cdecl, importc: "cpConstraintDestroy", dynlib: Lib.} 1257#/ Destroy and free a constraint.111 1258proc free*(constraint: PConstraint){. 1259 cdecl, importc: "cpConstraintFree", dynlib: Lib.} 1260 1261#/ @private 1262proc activateBodies(constraint: PConstraint) {.inline.} = 1263 if not constraint.a.isNil: constraint.a.activate() 1264 if not constraint.b.isNil: constraint.b.activate() 1265 1266# /// @private 1267# #define CP_DefineConstraintStructGetter(type, member, name) \ 1268# static inline type cpConstraint##Get##name(const cpConstraint *constraint){return constraint->member;} 1269# /// @private 1270# #define CP_DefineConstraintStructSetter(type, member, name) \ 1271# static inline void cpConstraint##Set##name(cpConstraint *constraint, type value){ \ 1272# cpConstraintActivateBodies(constraint); \ 1273# constraint->member = value; \ 1274# } 1275template defConstraintSetter(memberType: typedesc, member, name: untyped) = 1276 proc `set name`*(constraint: PConstraint, value: memberType) {.cdecl.} = 1277 activateBodies(constraint) 1278 constraint.member = value 1279template defConstraintProp(memberType: typedesc, member, name: untyped) = 1280 defGetter(PConstraint, memberType, member, name) 1281 defConstraintSetter(memberType, member, name) 1282# CP_DefineConstraintStructGetter(cpSpace*, CP_PRIVATE(space), Space) 1283defGetter(PConstraint, PSpace, space, Space) 1284defGetter(PConstraint, PBody, a, A) 1285defGetter(PConstraint, PBody, a, B) 1286defGetter(PConstraint, CpFloat, maxForce, MaxForce) 1287defGetter(PConstraint, CpFloat, errorBias, ErrorBias) 1288defGetter(PConstraint, CpFloat, maxBias, MaxBias) 1289defGetter(PConstraint, TConstraintPreSolveFunc, preSolve, PreSolveFunc) 1290defGetter(PConstraint, TConstraintPostSolveFunc, postSolve, PostSolveFunc) 1291defGetter(PConstraint, CpDataPointer, data, UserData) 1292# Get the last impulse applied by this constraint. 1293proc getImpulse*(constraint: PConstraint): CpFloat {.inline.} = 1294 return constraint.klass.getImpulse(constraint) 1295 1296# #define cpConstraintCheckCast(constraint, struct) \ 1297# cpAssertHard(constraint->CP_PRIVATE(klass) == struct##GetClass(), "Constraint is not a "#struct) 1298# #define CP_DefineConstraintGetter(struct, type, member, name) \ 1299# static inline type struct##Get##name(const cpConstraint *constraint){ \ 1300# cpConstraintCheckCast(constraint, struct); \ 1301# return ((struct *)constraint)->member; \ 1302# } 1303# #define CP_DefineConstraintSetter(struct, type, member, name) \ 1304# static inline void struct##Set##name(cpConstraint *constraint, type value){ \ 1305# cpConstraintCheckCast(constraint, struct); \ 1306# cpConstraintActivateBodies(constraint); \ 1307# ((struct *)constraint)->member = value; \ 1308# } 1309template constraintCheckCast(constraint: PConstraint, ctype: untyped) = 1310 assert(constraint.klass == `ctype getClass`(), "Constraint is the wrong class") 1311template defCGetter(ctype: untyped, memberType: typedesc, member, name: untyped) = 1312 proc `get ctype name`*(constraint: PConstraint): memberType {.cdecl.} = 1313 constraintCheckCast(constraint, ctype) 1314 result = cast[`P ctype`](constraint).member 1315template defCSetter(ctype: untyped, memberType: typedesc, member, name: untyped) = 1316 proc `set ctype name`*(constraint: PConstraint, value: memberType) {.cdecl.} = 1317 constraintCheckCast(constraint, ctype) 1318 activateBodies(constraint) 1319 cast[`P ctype`](constraint).member = value 1320template defCProp(ctype: untyped, memberType: typedesc, member, name: untyped) = 1321 defCGetter(ctype, memberType, member, name) 1322 defCSetter(ctype, memberType, member, name) 1323 1324proc PinJointGetClass*(): PConstraintClass{. 1325 cdecl, importc: "cpPinJointGetClass", dynlib: Lib.} 1326#/ @private 1327 1328#/ Allocate a pin joint. 1329proc AllocPinJoint*(): PPinJoint{. 1330 cdecl, importc: "cpPinJointAlloc", dynlib: Lib.} 1331#/ Initialize a pin joint. 1332proc PinJointInit*(joint: PPinJoint; a: PBody; b: PBody; anchr1: TVector; 1333 anchr2: TVector): PPinJoint{. 1334 cdecl, importc: "cpPinJointInit", dynlib: Lib.} 1335#/ Allocate and initialize a pin joint. 1336proc newPinJoint*(a: PBody; b: PBody; anchr1: TVector; anchr2: TVector): PConstraint{. 1337 cdecl, importc: "cpPinJointNew", dynlib: Lib.} 1338# CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1) 1339defCProp(PinJoint, TVector, anchr1, Anchr1) 1340defCProp(PinJoint, TVector, anchr2, Anchr2) 1341defCProp(PinJoint, CpFloat, dist, Dist) 1342 1343proc SlideJointGetClass*(): PConstraintClass{. 1344 cdecl, importc: "cpSlideJointGetClass", dynlib: Lib.} 1345#/ Allocate a slide joint. 1346proc AllocSlideJoint*(): PSlideJoint{. 1347 cdecl, importc: "cpSlideJointAlloc", dynlib: Lib.} 1348#/ Initialize a slide joint. 1349proc init*(joint: PSlideJoint; a, b: PBody; anchr1, anchr2: TVector; 1350 min, max: CpFloat): PSlideJoint{. 1351 cdecl, importc: "cpSlideJointInit", dynlib: Lib.} 1352#/ Allocate and initialize a slide joint. 1353proc newSlideJoint*(a, b: PBody; anchr1, anchr2: TVector; min, max: CpFloat): PConstraint{. 1354 cdecl, importc: "cpSlideJointNew", dynlib: Lib.} 1355 1356defCProp(SlideJoint, TVector, anchr1, Anchr1) 1357defCProp(SlideJoint, TVector, anchr2, Anchr2) 1358defCProp(SlideJoint, CpFloat, min, Min) 1359defCProp(SlideJoint, CpFloat, max, Max) 1360 1361proc PivotJointGetClass*(): PConstraintClass {. 1362 cdecl, importc: "cpPivotJointGetClass", dynlib: Lib.} 1363 1364#/ Allocate a pivot joint 1365proc allocPivotJoint*(): PPivotJoint{. 1366 cdecl, importc: "cpPivotJointAlloc", dynlib: Lib.} 1367#/ Initialize a pivot joint. 1368proc init*(joint: PPivotJoint; a, b: PBody; anchr1, anchr2: TVector): PPivotJoint{. 1369 cdecl, importc: "cpPivotJointInit", dynlib: Lib.} 1370#/ Allocate and initialize a pivot joint. 1371proc newPivotJoint*(a, b: PBody; pivot: TVector): PConstraint{. 1372 cdecl, importc: "cpPivotJointNew", dynlib: Lib.} 1373#/ Allocate and initialize a pivot joint with specific anchors. 1374proc newPivotJoint*(a, b: PBody; anchr1, anchr2: TVector): PConstraint{. 1375 cdecl, importc: "cpPivotJointNew2", dynlib: Lib.} 1376 1377defCProp(PivotJoint, TVector, anchr1, Anchr1) 1378defCProp(PivotJoint, TVector, anchr2, Anchr2) 1379 1380 1381proc GrooveJointGetClass*(): PConstraintClass{. 1382 cdecl, importc: "cpGrooveJointGetClass", dynlib: Lib.} 1383#/ Allocate a groove joint. 1384proc GrooveJointAlloc*(): ptr TGrooveJoint{. 1385 cdecl, importc: "cpGrooveJointAlloc", dynlib: Lib.} 1386#/ Initialize a groove joint. 1387proc Init*(joint: PGrooveJoint; a, b: PBody; groove_a, groove_b, anchr2: TVector): PGrooveJoint{. 1388 cdecl, importc: "cpGrooveJointInit", dynlib: Lib.} 1389#/ Allocate and initialize a groove joint. 1390proc newGrooveJoint*(a, b: PBody; groove_a, groove_b, anchr2: TVector): PConstraint{. 1391 cdecl, importc: "cpGrooveJointNew", dynlib: Lib.} 1392 1393defCGetter(GrooveJoint, TVector, grv_a, GrooveA) 1394defCGetter(GrooveJoint, TVector, grv_b, GrooveB) 1395# /// Set endpoint a of a groove joint's groove 1396proc SetGrooveA*(constraint: PConstraint, value: TVector) {. 1397 cdecl, importc: "cpGrooveJointSetGrooveA", dynlib: Lib.} 1398# /// Set endpoint b of a groove joint's groove 1399proc SetGrooveB*(constraint: PConstraint, value: TVector) {. 1400 cdecl, importc: "cpGrooveJointSetGrooveB", dynlib: Lib.} 1401defCProp(GrooveJoint, TVector, anchr2, Anchr2) 1402 1403proc DampedSpringGetClass*(): PConstraintClass{. 1404 cdecl, importc: "cpDampedSpringGetClass", dynlib: Lib.} 1405#/ Allocate a damped spring. 1406proc AllocDampedSpring*(): PDampedSpring{. 1407 cdecl, importc: "cpDampedSpringAlloc", dynlib: Lib.} 1408#/ Initialize a damped spring. 1409proc init*(joint: PDampedSpring; a, b: PBody; anchr1, anchr2: TVector; 1410 restLength, stiffness, damping: CpFloat): PDampedSpring{. 1411 cdecl, importc: "cpDampedSpringInit", dynlib: Lib.} 1412#/ Allocate and initialize a damped spring. 1413proc newDampedSpring*(a, b: PBody; anchr1, anchr2: TVector; 1414 restLength, stiffness, damping: CpFloat): PConstraint{. 1415 cdecl, importc: "cpDampedSpringNew", dynlib: Lib.} 1416 1417# CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr1, Anchr1) 1418defCProp(DampedSpring, TVector, anchr1, Anchr1) 1419defCProp(DampedSpring, TVector, anchr2, Anchr2) 1420defCProp(DampedSpring, CpFloat, restLength, RestLength) 1421defCProp(DampedSpring, CpFloat, stiffness, Stiffness) 1422defCProp(DampedSpring, CpFloat, damping, Damping) 1423defCProp(DampedSpring, TDampedSpringForceFunc, springForceFunc, SpringForceFunc) 1424 1425 1426proc DampedRotarySpringGetClass*(): PConstraintClass{. 1427 cdecl, importc: "cpDampedRotarySpringGetClass", dynlib: Lib.} 1428 1429#/ Allocate a damped rotary spring. 1430proc DampedRotarySpringAlloc*(): PDampedRotarySpring{. 1431 cdecl, importc: "cpDampedRotarySpringAlloc", dynlib: Lib.} 1432#/ Initialize a damped rotary spring. 1433proc init*(joint: PDampedRotarySpring; a, b: PBody; 1434 restAngle, stiffness, damping: CpFloat): PDampedRotarySpring{. 1435 cdecl, importc: "cpDampedRotarySpringInit", dynlib: Lib.} 1436#/ Allocate and initialize a damped rotary spring. 1437proc DampedRotarySpringNew*(a, b: PBody; restAngle, stiffness, damping: CpFloat): PConstraint{. 1438 cdecl, importc: "cpDampedRotarySpringNew", dynlib: Lib.} 1439 1440defCProp(DampedRotarySpring, CpFloat, restAngle, RestAngle) 1441defCProp(DampedRotarySpring, CpFloat, stiffness, Stiffness) 1442defCProp(DampedRotarySpring, CpFloat, damping, Damping) 1443defCProp(DampedRotarySpring, TDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc) 1444 1445 1446proc RotaryLimitJointGetClass*(): PConstraintClass{. 1447 cdecl, importc: "cpRotaryLimitJointGetClass", dynlib: Lib.} 1448#/ Allocate a damped rotary limit joint. 1449proc allocRotaryLimitJoint*(): PRotaryLimitJoint{. 1450 cdecl, importc: "cpRotaryLimitJointAlloc", dynlib: Lib.} 1451#/ Initialize a damped rotary limit joint. 1452proc init*(joint: PRotaryLimitJoint; a, b: PBody; min, max: CpFloat): PRotaryLimitJoint{. 1453 cdecl, importc: "cpRotaryLimitJointInit", dynlib: Lib.} 1454#/ Allocate and initialize a damped rotary limit joint. 1455proc newRotaryLimitJoint*(a, b: PBody; min, max: CpFloat): PConstraint{. 1456 cdecl, importc: "cpRotaryLimitJointNew", dynlib: Lib.} 1457 1458defCProp(RotaryLimitJoint, CpFloat, min, Min) 1459defCProp(RotaryLimitJoint, CpFloat, max, Max) 1460 1461 1462proc RatchetJointGetClass*(): PConstraintClass{. 1463 cdecl, importc: "cpRatchetJointGetClass", dynlib: Lib.} 1464#/ Allocate a ratchet joint. 1465proc AllocRatchetJoint*(): PRatchetJoint{. 1466 cdecl, importc: "cpRatchetJointAlloc", dynlib: Lib.} 1467#/ Initialize a ratched joint. 1468proc init*(joint: PRatchetJoint; a, b: PBody; phase, ratchet: CpFloat): PRatchetJoint{. 1469 cdecl, importc: "cpRatchetJointInit", dynlib: Lib.} 1470#/ Allocate and initialize a ratchet joint. 1471proc NewRatchetJoint*(a, b: PBody; phase, ratchet: CpFloat): PConstraint{. 1472 cdecl, importc: "cpRatchetJointNew", dynlib: Lib.} 1473 1474defCProp(RatchetJoint, CpFloat, angle, Angle) 1475defCProp(RatchetJoint, CpFloat, phase, Phase) 1476defCProp(RatchetJoint, CpFloat, ratchet, Ratchet) 1477 1478 1479proc GearJointGetClass*(): PConstraintClass{.cdecl, 1480 importc: "cpGearJointGetClass", dynlib: Lib.} 1481#/ Allocate a gear joint. 1482proc AllocGearJoint*(): PGearJoint{. 1483 cdecl, importc: "cpGearJointAlloc", dynlib: Lib.} 1484#/ Initialize a gear joint. 1485proc init*(joint: PGearJoint; a, b: PBody, phase, ratio: CpFloat): PGearJoint{. 1486 cdecl, importc: "cpGearJointInit", dynlib: Lib.} 1487#/ Allocate and initialize a gear joint. 1488proc NewGearJoint*(a, b: PBody; phase, ratio: CpFloat): PConstraint{. 1489 cdecl, importc: "cpGearJointNew", dynlib: Lib.} 1490 1491defCProp(GearJoint, CpFloat, phase, Phase) 1492defCGetter(GearJoint, CpFloat, ratio, Ratio) 1493#/ Set the ratio of a gear joint. 1494proc GearJointSetRatio*(constraint: PConstraint; value: CpFloat){. 1495 cdecl, importc: "cpGearJointSetRatio", dynlib: Lib.} 1496 1497 1498proc SimpleMotorGetClass*(): PConstraintClass{. 1499 cdecl, importc: "cpSimpleMotorGetClass", dynlib: Lib.} 1500#/ Allocate a simple motor. 1501proc AllocSimpleMotor*(): PSimpleMotor{. 1502 cdecl, importc: "cpSimpleMotorAlloc", dynlib: Lib.} 1503#/ initialize a simple motor. 1504proc init*(joint: PSimpleMotor; a, b: PBody; 1505 rate: CpFloat): PSimpleMotor{. 1506 cdecl, importc: "cpSimpleMotorInit", dynlib: Lib.} 1507#/ Allocate and initialize a simple motor. 1508proc newSimpleMotor*(a, b: PBody; rate: CpFloat): PConstraint{. 1509 cdecl, importc: "cpSimpleMotorNew", dynlib: Lib.} 1510 1511defCProp(SimpleMotor, CpFloat, rate, Rate) 1512 1513 1514 1515