├── requirements.txt ├── .gitignore ├── docs ├── screenshot0001.png └── index.rst ├── examples ├── circle_box │ ├── circle.png │ └── main.py ├── pymunk_logo_googlecode.png ├── demo_cirle.py ├── point_query.py ├── using_sprites_pyglet.py ├── box2d_pyramid.py ├── using_sprites.py ├── spiderweb.py └── balls_and_lines.py ├── cymunk ├── __init__.py ├── core.pxd ├── cymunk.pyx ├── Chipmunk-Physics │ ├── LICENSE.txt │ ├── src │ │ ├── cpBB.c │ │ ├── prime.h │ │ ├── constraints │ │ │ ├── cpConstraint.c │ │ │ ├── cpSimpleMotor.c │ │ │ ├── cpGearJoint.c │ │ │ ├── cpPivotJoint.c │ │ │ ├── cpRotaryLimitJoint.c │ │ │ ├── cpDampedRotarySpring.c │ │ │ ├── cpRatchetJoint.c │ │ │ ├── cpPinJoint.c │ │ │ ├── cpSlideJoint.c │ │ │ ├── cpDampedSpring.c │ │ │ └── cpGrooveJoint.c │ │ ├── CMakeLists.txt │ │ ├── cpVect.c │ │ ├── cpSpatialIndex.c │ │ └── cpArray.c │ ├── include │ │ └── chipmunk │ │ │ ├── constraints │ │ │ ├── cpSimpleMotor.h │ │ │ ├── cpPinJoint.h │ │ │ ├── cpRotaryLimitJoint.h │ │ │ ├── cpGearJoint.h │ │ │ ├── cpRatchetJoint.h │ │ │ ├── cpPivotJoint.h │ │ │ ├── cpSlideJoint.h │ │ │ ├── cpGrooveJoint.h │ │ │ ├── cpDampedRotarySpring.h │ │ │ ├── cpDampedSpring.h │ │ │ └── util.h │ │ │ ├── chipmunk_unsafe.h │ │ │ ├── cpPolyShape.h │ │ │ ├── cpBB.h │ │ │ ├── chipmunk_types.h │ │ │ └── chipmunk_ffi.h │ └── README.textile ├── body.pxd ├── shape.pxd ├── chipmunk │ ├── constraints │ │ ├── cpSimpleMotor.h │ │ ├── cpPinJoint.h │ │ ├── cpRotaryLimitJoint.h │ │ ├── cpGearJoint.h │ │ ├── cpRatchetJoint.h │ │ ├── cpPivotJoint.h │ │ ├── cpSlideJoint.h │ │ ├── cpGrooveJoint.h │ │ ├── cpDampedRotarySpring.h │ │ ├── cpDampedSpring.h │ │ └── util.h │ ├── chipmunk_unsafe.h │ ├── cpPolyShape.h │ ├── cpBB.h │ ├── chipmunk_types.h │ └── chipmunk_ffi.h └── constraint.pxd ├── Makefile ├── README.md ├── LICENSE ├── tests ├── test_space.py └── test_vec2d.py └── setup.py /requirements.txt: -------------------------------------------------------------------------------- 1 | Cython>=0.15 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | cymunk/python/cymunk.c 4 | *.so 5 | build 6 | docs/_build 7 | -------------------------------------------------------------------------------- /docs/screenshot0001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/cymunk/HEAD/docs/screenshot0001.png -------------------------------------------------------------------------------- /examples/circle_box/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/cymunk/HEAD/examples/circle_box/circle.png -------------------------------------------------------------------------------- /examples/pymunk_logo_googlecode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy/cymunk/HEAD/examples/pymunk_logo_googlecode.png -------------------------------------------------------------------------------- /cymunk/__init__.py: -------------------------------------------------------------------------------- 1 | from .cymunk import * 2 | from os import path 3 | 4 | def get_includes(): 5 | return [path.dirname(__file__)] -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: tests build all 2 | 3 | all: build tests 4 | 5 | tests: 6 | py.test tests 7 | 8 | build: 9 | python setup.py build_ext --inplace -f 10 | 11 | -------------------------------------------------------------------------------- /cymunk/core.pxd: -------------------------------------------------------------------------------- 1 | cdef class BB: 2 | cdef cpBB _bb 3 | cdef float l 4 | cdef float b 5 | cdef float r 6 | cdef float t 7 | 8 | cdef class Vec2d: 9 | cdef cpVect v -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cymunk 2 | ====== 3 | 4 | Cymunk is a cython wrapper for [Chipmunk Physics](https://chipmunk-physics.net/) 5 | Some code is ported from [pymunk](https://github.com/viblo/pymunk) and much of the API is compatable 6 | 7 | Cymunk should be significantly faster than pymunk and run on android with [p4a](https://github.com/kivy/python-for-android) - but it is currently less feature complete. 8 | 9 | Check out the examples folder, [cymunk docs](http://cymunk.readthedocs.org/en/latest/) and [pymunk docs](https://pymunk.readthedocs.org/en/latest/) 10 | 11 | To build for windows you should use MinGW - [setup](http://stackoverflow.com/a/5051281/445831) or ```python setup.py build --compiler=mingw32``` 12 | 13 | To install to Python's site-packges 14 | ```python setup.py build_ext --compiler=mingw32 install``` 15 | -------------------------------------------------------------------------------- /cymunk/cymunk.pyx: -------------------------------------------------------------------------------- 1 | include "constraint.pxi" 2 | include "core.pxi" 3 | include "body.pxi" 4 | include "shape.pxi" 5 | include "space.pxi" 6 | 7 | from types import ModuleType 8 | 9 | 10 | # Pymunk API capability hook 11 | # to emulate vec2d module 12 | class Vec2dModule(ModuleType): 13 | pass 14 | 15 | vec2d = Vec2dModule('cymunk.vec2d') 16 | vec2d.Vec2d = Vec2d 17 | 18 | 19 | # Pymunk API capability hook 20 | # to emulate constraint module 21 | class ConstraintsModule(ModuleType): 22 | pass 23 | 24 | constraint = ConstraintsModule('cymunk.constraint') 25 | constraint.Constraint = Constraint 26 | constraint.PivotJoint = PivotJoint 27 | constraint.PinJoint = PinJoint 28 | constraint.GrooveJoint = GrooveJoint 29 | constraint.SlideJoint = SlideJoint 30 | constraint.DampedSpring = DampedSpring 31 | constraint.DampedRotarySpring = DampedRotarySpring 32 | constraint.RotaryLimitJoint = RotaryLimitJoint 33 | constraint.GearJoint = GearJoint 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2017 Kivy Team and other contributors 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 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software 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 | -------------------------------------------------------------------------------- /tests/test_space.py: -------------------------------------------------------------------------------- 1 | import cymunk as cy 2 | import pytest 3 | 4 | def test_space_attributes(): 5 | space = cy.Space() 6 | assert(space is not None) 7 | 8 | assert(space.iterations == 10) 9 | space.iterations = 20 10 | assert(space.iterations == 20) 11 | 12 | assert(len(space.bodies) == 0) 13 | assert(len(space.static_shapes) == 0) 14 | assert(len(space.bodies) == 0) 15 | assert(len(space.constraints) == 0) 16 | assert(space.static_body is not None) 17 | assert(isinstance(space.static_body, cy.Body)) 18 | assert(space.damping == 1.) 19 | assert(space.idle_speed_threshold == 0.) 20 | assert(space.sleep_time_threshold == float('inf')) 21 | assert(space.collision_slop < 0.2) 22 | assert(space.collision_bias < 0.01) 23 | assert(space.collision_persistence == 3L) 24 | assert(space.enable_contact_graph == 0) 25 | 26 | # tests readonly attributes 27 | with pytest.raises(AttributeError): 28 | space.static_body = None 29 | 30 | 31 | def test_space_gravity(): 32 | space = cy.Space() 33 | assert(space.gravity.x == 0.) 34 | assert(space.gravity.y == 0.) 35 | space.gravity = (5, 10) 36 | assert(space.gravity.x == 5) 37 | assert(space.gravity.y == 10) 38 | space.gravity = cy.Vec2d(25, 50) 39 | assert(space.gravity.x == 25) 40 | assert(space.gravity.y == 50) 41 | 42 | -------------------------------------------------------------------------------- /examples/demo_cirle.py: -------------------------------------------------------------------------------- 1 | from cymunk import * 2 | 3 | def mycollide(arbiter): 4 | print "MY COLLIDE CALLED", arbiter 5 | try: 6 | print arbiter.contacts 7 | print arbiter.shapes 8 | except Exception, e: 9 | print e 10 | raise 11 | return True 12 | 13 | # create the main space 14 | space = Space() 15 | space.set_default_collision_handler(begin=mycollide) 16 | space.iterations = 30 17 | space.gravity = (0, -100) 18 | space.sleep_time_threshold = 0.5 19 | space.collision_slop = 0.5 20 | 21 | # create a falling circle 22 | body = Body(100, 1e9) 23 | body.position = (0, 100) 24 | circle = Circle(body, 50) 25 | circle.elasticity = 1.0 26 | circle.friction = 1.0 27 | 28 | # add bounds 29 | seg1 = Segment(space.static_body, Vec2d(-320, -240), Vec2d(-320, 240), 0) 30 | seg1.elasticity = 1.0 31 | seg1.friction = 1.0 32 | 33 | seg2 = Segment(space.static_body, Vec2d(320, -240), Vec2d(320, 240), 0) 34 | seg2.elasticity = 1.0 35 | seg2.friction = 1.0 36 | 37 | seg3 = Segment(space.static_body, Vec2d(-320, -240), Vec2d(320, -240), 0) 38 | seg3.elasticity = 1.0 39 | seg3.friction = 1.0 40 | 41 | # add everything into space 42 | space.add_static(seg1, seg2, seg3) 43 | space.add(circle, body) 44 | 45 | from time import time 46 | start = time() 47 | while time() - start < 1.: 48 | space.step(1 / 30.) 49 | print circle.body.position 50 | 51 | -------------------------------------------------------------------------------- /cymunk/body.pxd: -------------------------------------------------------------------------------- 1 | cdef extern from "chipmunk/chipmunk.h": 2 | cpBody *cpBodyAlloc() 3 | cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i) 4 | cpBody* cpBodyNewStatic() 5 | cpBody *cpBodyNew(cpFloat m, cpFloat i) 6 | 7 | void cpBodyDestroy(cpBody *body) 8 | void cpBodyFree(cpBody *body) 9 | 10 | void cpBodySetMass(cpBody *body, cpFloat m) 11 | void cpBodySetMoment(cpBody *body, cpFloat i) 12 | void cpBodySetAngle(cpBody *body, cpFloat a) 13 | 14 | void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) 15 | void cpBodyUpdatePosition(cpBody *body, cpFloat dt) 16 | void cpBodyApplyImpulse(cpBody *body, cpVect j, cpVect r) 17 | void cpBodyResetForces(cpBody *body) 18 | void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r) 19 | 20 | ctypedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) 21 | cpBodyVelocityFunc velocity_func 22 | 23 | 24 | void cpBodyActivate(cpBody *body) 25 | void cpBodySleep(cpBody *body) 26 | void cpBodySleepWithGroup(cpBody *body, cpBody *group) 27 | 28 | cpBool cpBodyIsSleeping(cpBody *body) 29 | cpBool cpBodyIsRogue(cpBody *body) 30 | cpBool cpBodyIsStatic(cpBody *body) 31 | 32 | cpVect cpBodyLocal2World(cpBody *body, cpVect v) 33 | cpVect cpBodyWorld2Local(cpBody *body, cpVect v) 34 | 35 | 36 | cdef class Body: 37 | cdef cpBody* _body 38 | cdef int automanaged 39 | cdef object _data 40 | cdef list _constraints 41 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/cpBB.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | 24 | cpVect 25 | cpBBWrapVect(const cpBB bb, const cpVect v) 26 | { 27 | cpFloat ix = cpfabs(bb.r - bb.l); 28 | cpFloat modx = cpfmod(v.x - bb.l, ix); 29 | cpFloat x = (modx > 0.0f) ? modx : modx + ix; 30 | 31 | cpFloat iy = cpfabs(bb.t - bb.b); 32 | cpFloat mody = cpfmod(v.y - bb.b, iy); 33 | cpFloat y = (mody > 0.0f) ? mody : mody + iy; 34 | 35 | return cpv(x + bb.l, y + bb.b); 36 | } 37 | -------------------------------------------------------------------------------- /cymunk/shape.pxd: -------------------------------------------------------------------------------- 1 | cdef class Shape: 2 | cdef cpShape* _shape 3 | cdef int automanaged 4 | cdef Body _body 5 | 6 | cdef class Circle(Shape): 7 | cdef float radius 8 | cdef cpVect offset 9 | 10 | cdef class Poly(Shape): 11 | cdef cpVect _offset 12 | cdef cpVect *_vertices 13 | cdef int _vertices_count 14 | cdef tuple offset 15 | 16 | cdef class BoxShape(Poly): 17 | cdef float width 18 | cdef float height 19 | 20 | cdef class Segment(Shape): 21 | cdef cpVect a 22 | cdef cpVect b 23 | cdef float radius 24 | cdef cpSegmentShape* _segment_shape 25 | 26 | cdef extern from "chipmunk/chipmunk.h": 27 | ctypedef struct cpSegmentShape: 28 | cpShape shape 29 | cpVect a, b, n 30 | cpVect ta, tb, tn 31 | cpFloat r 32 | cpVect a_tangent, b_tangent 33 | 34 | void cpShapeDestroy(cpShape *shape) 35 | void cpShapeFree(cpShape *shape) 36 | 37 | cpBB cpShapeCacheBB(cpShape *shape) 38 | cpBool cpShapePointQuery(cpShape *shape, cpVect p) 39 | 40 | cpBool cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info) 41 | 42 | cpShape cpCircleShape 43 | CP_DeclareShapeGetter(cpCircleShape, cpFloat, Radius) 44 | cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset) 45 | void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius) 46 | void cpCircleShapeSetOffset(cpShape *shape, cpVect offset) 47 | 48 | cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat heigth) 49 | 50 | cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius) 51 | 52 | 53 | cpShape* cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset) 54 | 55 | cpBool cpPolyValidate(cpVect *verts, int numVerts) 56 | 57 | cpVect cpPolyShapeGetVert(cpShape* shape, int idx) 58 | 59 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpSimpleMotor.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpSimpleMotor cpSimpleMotor 23 | /// @{ 24 | 25 | const cpConstraintClass *cpSimpleMotorGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpSimpleMotor { 29 | cpConstraint constraint; 30 | cpFloat rate; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat jAcc; 35 | } cpSimpleMotor; 36 | 37 | /// Allocate a simple motor. 38 | cpSimpleMotor* cpSimpleMotorAlloc(void); 39 | /// initialize a simple motor. 40 | cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate); 41 | /// Allocate and initialize a simple motor. 42 | cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate); 43 | 44 | CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate) 45 | 46 | /// @} 47 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpSimpleMotor.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpSimpleMotor cpSimpleMotor 23 | /// @{ 24 | 25 | const cpConstraintClass *cpSimpleMotorGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpSimpleMotor { 29 | cpConstraint constraint; 30 | cpFloat rate; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat jAcc; 35 | } cpSimpleMotor; 36 | 37 | /// Allocate a simple motor. 38 | cpSimpleMotor* cpSimpleMotorAlloc(void); 39 | /// initialize a simple motor. 40 | cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate); 41 | /// Allocate and initialize a simple motor. 42 | cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate); 43 | 44 | CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate) 45 | 46 | /// @} 47 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/prime.h: -------------------------------------------------------------------------------- 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 | // Used for resizing hash tables. 23 | // Values approximately double. 24 | // http://planetmath.org/encyclopedia/GoodHashTablePrimes.html 25 | static int primes[] = { 26 | 5, 27 | 13, 28 | 23, 29 | 47, 30 | 97, 31 | 193, 32 | 389, 33 | 769, 34 | 1543, 35 | 3079, 36 | 6151, 37 | 12289, 38 | 24593, 39 | 49157, 40 | 98317, 41 | 196613, 42 | 393241, 43 | 786433, 44 | 1572869, 45 | 3145739, 46 | 6291469, 47 | 12582917, 48 | 25165843, 49 | 50331653, 50 | 100663319, 51 | 201326611, 52 | 402653189, 53 | 805306457, 54 | 1610612741, 55 | 0, 56 | }; 57 | 58 | static inline int 59 | next_prime(int n) 60 | { 61 | int i = 0; 62 | while(n > primes[i]){ 63 | i++; 64 | cpAssertHard(primes[i], "Tried to resize a hash table to a size greater than 1610612741 O_o"); // realistically this should never happen 65 | } 66 | 67 | return primes[i]; 68 | } 69 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpPinJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPinJoint cpPinJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpPinJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpPinJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | cpFloat dist; 32 | 33 | cpVect r1, r2; 34 | cpVect n; 35 | cpFloat nMass; 36 | 37 | cpFloat jnAcc; 38 | cpFloat bias; 39 | } cpPinJoint; 40 | 41 | /// Allocate a pin joint. 42 | cpPinJoint* cpPinJointAlloc(void); 43 | /// Initialize a pin joint. 44 | cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 45 | /// Allocate and initialize a pin joint. 46 | cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 47 | 48 | CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2) 50 | CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist) 51 | 52 | ///@} 53 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpRotaryLimitJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpRotaryLimitJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpRotaryLimitJoint { 29 | cpConstraint constraint; 30 | cpFloat min, max; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat bias; 35 | cpFloat jAcc; 36 | } cpRotaryLimitJoint; 37 | 38 | /// Allocate a damped rotary limit joint. 39 | cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void); 40 | /// Initialize a damped rotary limit joint. 41 | cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max); 42 | /// Allocate and initialize a damped rotary limit joint. 43 | cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max); 44 | 45 | CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min) 46 | CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max) 47 | 48 | /// @} 49 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpPinJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPinJoint cpPinJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpPinJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpPinJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | cpFloat dist; 32 | 33 | cpVect r1, r2; 34 | cpVect n; 35 | cpFloat nMass; 36 | 37 | cpFloat jnAcc; 38 | cpFloat bias; 39 | } cpPinJoint; 40 | 41 | /// Allocate a pin joint. 42 | cpPinJoint* cpPinJointAlloc(void); 43 | /// Initialize a pin joint. 44 | cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 45 | /// Allocate and initialize a pin joint. 46 | cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 47 | 48 | CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2) 50 | CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist) 51 | 52 | ///@} 53 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpGearJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpGearJoint cpGearJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpGearJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpGearJoint { 29 | cpConstraint constraint; 30 | cpFloat phase, ratio; 31 | cpFloat ratio_inv; 32 | 33 | cpFloat iSum; 34 | 35 | cpFloat bias; 36 | cpFloat jAcc; 37 | } cpGearJoint; 38 | 39 | /// Allocate a gear joint. 40 | cpGearJoint* cpGearJointAlloc(void); 41 | /// Initialize a gear joint. 42 | cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); 43 | /// Allocate and initialize a gear joint. 44 | cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); 45 | 46 | CP_DefineConstraintProperty(cpGearJoint, cpFloat, phase, Phase) 47 | CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio) 48 | /// Set the ratio of a gear joint. 49 | void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value); 50 | 51 | /// @} 52 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpRatchetJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpRatchetJoint cpRatchetJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpRatchetJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpRatchetJoint { 29 | cpConstraint constraint; 30 | cpFloat angle, phase, ratchet; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat bias; 35 | cpFloat jAcc; 36 | } cpRatchetJoint; 37 | 38 | /// Allocate a ratchet joint. 39 | cpRatchetJoint* cpRatchetJointAlloc(void); 40 | /// Initialize a ratched joint. 41 | cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); 42 | /// Allocate and initialize a ratchet joint. 43 | cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); 44 | 45 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle) 46 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase) 47 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet) 48 | 49 | /// @} 50 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpRotaryLimitJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpRotaryLimitJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpRotaryLimitJoint { 29 | cpConstraint constraint; 30 | cpFloat min, max; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat bias; 35 | cpFloat jAcc; 36 | } cpRotaryLimitJoint; 37 | 38 | /// Allocate a damped rotary limit joint. 39 | cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void); 40 | /// Initialize a damped rotary limit joint. 41 | cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max); 42 | /// Allocate and initialize a damped rotary limit joint. 43 | cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max); 44 | 45 | CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min) 46 | CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max) 47 | 48 | /// @} 49 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpConstraint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | // TODO: Comment me! 26 | 27 | void cpConstraintDestroy(cpConstraint *constraint){} 28 | 29 | void 30 | cpConstraintFree(cpConstraint *constraint) 31 | { 32 | if(constraint){ 33 | cpConstraintDestroy(constraint); 34 | cpfree(constraint); 35 | } 36 | } 37 | 38 | // *** declared in util.h TODO move declaration to chipmunk_private.h 39 | 40 | void 41 | cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b) 42 | { 43 | constraint->klass = klass; 44 | 45 | constraint->a = a; 46 | constraint->b = b; 47 | constraint->space = NULL; 48 | 49 | constraint->next_a = NULL; 50 | constraint->next_b = NULL; 51 | 52 | constraint->maxForce = (cpFloat)INFINITY; 53 | constraint->errorBias = cpfpow(1.0f - 0.1f, 60.0f); 54 | constraint->maxBias = (cpFloat)INFINITY; 55 | 56 | constraint->preSolve = NULL; 57 | constraint->postSolve = NULL; 58 | } 59 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpGearJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpGearJoint cpGearJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpGearJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpGearJoint { 29 | cpConstraint constraint; 30 | cpFloat phase, ratio; 31 | cpFloat ratio_inv; 32 | 33 | cpFloat iSum; 34 | 35 | cpFloat bias; 36 | cpFloat jAcc; 37 | } cpGearJoint; 38 | 39 | /// Allocate a gear joint. 40 | cpGearJoint* cpGearJointAlloc(void); 41 | /// Initialize a gear joint. 42 | cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); 43 | /// Allocate and initialize a gear joint. 44 | cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); 45 | 46 | CP_DefineConstraintProperty(cpGearJoint, cpFloat, phase, Phase) 47 | CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio) 48 | /// Set the ratio of a gear joint. 49 | void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value); 50 | 51 | /// @} 52 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpRatchetJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpRatchetJoint cpRatchetJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpRatchetJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpRatchetJoint { 29 | cpConstraint constraint; 30 | cpFloat angle, phase, ratchet; 31 | 32 | cpFloat iSum; 33 | 34 | cpFloat bias; 35 | cpFloat jAcc; 36 | } cpRatchetJoint; 37 | 38 | /// Allocate a ratchet joint. 39 | cpRatchetJoint* cpRatchetJointAlloc(void); 40 | /// Initialize a ratched joint. 41 | cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); 42 | /// Allocate and initialize a ratchet joint. 43 | cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); 44 | 45 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle) 46 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase) 47 | CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet) 48 | 49 | /// @} 50 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB chipmunk_source_files "*.c" "constraints/*.c") 2 | file(GLOB chipmunk_public_header "${chipmunk_SOURCE_DIR}/include/chipmunk/*.h") 3 | file(GLOB chipmunk_constraint_header "${chipmunk_SOURCE_DIR}/include/chipmunk/constraints/*.h") 4 | 5 | include_directories(${chipmunk_SOURCE_DIR}/include/chipmunk) 6 | 7 | if(BUILD_SHARED) 8 | add_library(chipmunk SHARED 9 | ${chipmunk_source_files} 10 | ) 11 | # Tell MSVC to compile the code as C++. 12 | if(MSVC) 13 | set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX) 14 | set_target_properties(chipmunk PROPERTIES LINKER_LANGUAGE CXX) 15 | endif(MSVC) 16 | # set the lib's version number 17 | # But avoid on Android because symlinks to version numbered .so's don't work with Android's Java-side loadLibrary. 18 | if(NOT ANDROID) 19 | set_target_properties(chipmunk PROPERTIES VERSION 6.2.1) 20 | endif(NOT ANDROID) 21 | if(ANDROID) 22 | # need to explicitly link to the math library because the CMake/Android toolchains may not do it automatically 23 | target_link_libraries(chipmunk m) 24 | endif(ANDROID) 25 | install(TARGETS chipmunk RUNTIME DESTINATION lib LIBRARY DESTINATION lib) 26 | endif(BUILD_SHARED) 27 | 28 | if(BUILD_STATIC) 29 | add_library(chipmunk_static STATIC 30 | ${chipmunk_source_files} 31 | ) 32 | # Tell MSVC to compile the code as C++. 33 | if(MSVC) 34 | set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX) 35 | set_target_properties(chipmunk_static PROPERTIES LINKER_LANGUAGE CXX) 36 | endif(MSVC) 37 | # Sets chipmunk_static to output "libchipmunk.a" not "libchipmunk_static.a" 38 | set_target_properties(chipmunk_static PROPERTIES OUTPUT_NAME chipmunk) 39 | if(INSTALL_STATIC) 40 | install(TARGETS chipmunk_static ARCHIVE DESTINATION lib) 41 | endif(INSTALL_STATIC) 42 | endif(BUILD_STATIC) 43 | 44 | if(BUILD_SHARED OR INSTALL_STATIC) 45 | # FIXME: change to PUBLIC_HEADER to allow building frameworks 46 | install(FILES ${chipmunk_public_header} DESTINATION include/chipmunk) 47 | install(FILES ${chipmunk_constraint_header} DESTINATION include/chipmunk/constraints) 48 | endif(BUILD_SHARED OR INSTALL_STATIC) 49 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpPivotJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPivotJoint cpPivotJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpPivotJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpPivotJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | 32 | cpVect r1, r2; 33 | cpMat2x2 k; 34 | 35 | cpVect jAcc; 36 | cpVect bias; 37 | } cpPivotJoint; 38 | 39 | /// Allocate a pivot joint 40 | cpPivotJoint* cpPivotJointAlloc(void); 41 | /// Initialize a pivot joint. 42 | cpPivotJoint* cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 43 | /// Allocate and initialize a pivot joint. 44 | cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot); 45 | /// Allocate and initialize a pivot joint with specific anchors. 46 | cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 47 | 48 | CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2) 50 | 51 | /// @} 52 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpPivotJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPivotJoint cpPivotJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpPivotJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpPivotJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | 32 | cpVect r1, r2; 33 | cpMat2x2 k; 34 | 35 | cpVect jAcc; 36 | cpVect bias; 37 | } cpPivotJoint; 38 | 39 | /// Allocate a pivot joint 40 | cpPivotJoint* cpPivotJointAlloc(void); 41 | /// Initialize a pivot joint. 42 | cpPivotJoint* cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 43 | /// Allocate and initialize a pivot joint. 44 | cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot); 45 | /// Allocate and initialize a pivot joint with specific anchors. 46 | cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); 47 | 48 | CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2) 50 | 51 | /// @} 52 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/cpVect.c: -------------------------------------------------------------------------------- 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 | #include 23 | 24 | #include "chipmunk_private.h" 25 | 26 | cpVect 27 | cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t) 28 | { 29 | cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); 30 | cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); 31 | 32 | if(omega < 1e-3){ 33 | // If the angle between two vectors is very small, lerp instead to avoid precision issues. 34 | return cpvlerp(v1, v2, t); 35 | } else { 36 | cpFloat denom = 1.0f/cpfsin(omega); 37 | return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom)); 38 | } 39 | } 40 | 41 | cpVect 42 | cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a) 43 | { 44 | cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); 45 | cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); 46 | 47 | return cpvslerp(v1, v2, cpfmin(a, omega)/omega); 48 | } 49 | 50 | char* 51 | cpvstr(const cpVect v) 52 | { 53 | static char str[256]; 54 | sprintf(str, "(% .3f, % .3f)", v.x, v.y); 55 | return str; 56 | } 57 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpSlideJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpSlideJoint cpSlideJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpSlideJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpSlideJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | cpFloat min, max; 32 | 33 | cpVect r1, r2; 34 | cpVect n; 35 | cpFloat nMass; 36 | 37 | cpFloat jnAcc; 38 | cpFloat bias; 39 | } cpSlideJoint; 40 | 41 | /// Allocate a slide joint. 42 | cpSlideJoint* cpSlideJointAlloc(void); 43 | /// Initialize a slide joint. 44 | cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); 45 | /// Allocate and initialize a slide joint. 46 | cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); 47 | 48 | CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2) 50 | CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min) 51 | CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max) 52 | 53 | /// @} 54 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpSlideJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpSlideJoint cpSlideJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpSlideJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpSlideJoint { 29 | cpConstraint constraint; 30 | cpVect anchr1, anchr2; 31 | cpFloat min, max; 32 | 33 | cpVect r1, r2; 34 | cpVect n; 35 | cpFloat nMass; 36 | 37 | cpFloat jnAcc; 38 | cpFloat bias; 39 | } cpSlideJoint; 40 | 41 | /// Allocate a slide joint. 42 | cpSlideJoint* cpSlideJointAlloc(void); 43 | /// Initialize a slide joint. 44 | cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); 45 | /// Allocate and initialize a slide joint. 46 | cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); 47 | 48 | CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1) 49 | CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2) 50 | CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min) 51 | CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max) 52 | 53 | /// @} 54 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpGrooveJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpGrooveJoint cpGrooveJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpGrooveJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpGrooveJoint { 29 | cpConstraint constraint; 30 | cpVect grv_n, grv_a, grv_b; 31 | cpVect anchr2; 32 | 33 | cpVect grv_tn; 34 | cpFloat clamp; 35 | cpVect r1, r2; 36 | cpMat2x2 k; 37 | 38 | cpVect jAcc; 39 | cpVect bias; 40 | } cpGrooveJoint; 41 | 42 | /// Allocate a groove joint. 43 | cpGrooveJoint* cpGrooveJointAlloc(void); 44 | /// Initialize a groove joint. 45 | cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); 46 | /// Allocate and initialize a groove joint. 47 | cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); 48 | 49 | CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_a, GrooveA) 50 | /// Set endpoint a of a groove joint's groove 51 | void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value); 52 | CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_b, GrooveB) 53 | /// Set endpoint b of a groove joint's groove 54 | void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value); 55 | CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2) 56 | 57 | /// @} 58 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpGrooveJoint.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpGrooveJoint cpGrooveJoint 23 | /// @{ 24 | 25 | const cpConstraintClass *cpGrooveJointGetClass(void); 26 | 27 | /// @private 28 | typedef struct cpGrooveJoint { 29 | cpConstraint constraint; 30 | cpVect grv_n, grv_a, grv_b; 31 | cpVect anchr2; 32 | 33 | cpVect grv_tn; 34 | cpFloat clamp; 35 | cpVect r1, r2; 36 | cpMat2x2 k; 37 | 38 | cpVect jAcc; 39 | cpVect bias; 40 | } cpGrooveJoint; 41 | 42 | /// Allocate a groove joint. 43 | cpGrooveJoint* cpGrooveJointAlloc(void); 44 | /// Initialize a groove joint. 45 | cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); 46 | /// Allocate and initialize a groove joint. 47 | cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); 48 | 49 | CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_a, GrooveA) 50 | /// Set endpoint a of a groove joint's groove 51 | void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value); 52 | CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_b, GrooveB) 53 | /// Set endpoint b of a groove joint's groove 54 | void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value); 55 | CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2) 56 | 57 | /// @} 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import environ 3 | from os.path import dirname, join 4 | 5 | if environ.get('CYMUNK_USE_SETUPTOOLS'): 6 | from setuptools import setup, Extension 7 | print('Using setuptools') 8 | else: 9 | from distutils.core import setup 10 | from distutils.extension import Extension 11 | print('Using distutils') 12 | 13 | try: 14 | from Cython.Distutils import build_ext 15 | have_cython = True 16 | except ImportError: 17 | have_cython = False 18 | 19 | 20 | platform = sys.platform 21 | if platform == 'win32': 22 | cstdarg = '-std=gnu99' 23 | else: 24 | cstdarg = '-std=c99' 25 | c_chipmunk_root = join(dirname(__file__), 'cymunk', 'Chipmunk-Physics') 26 | c_chipmunk_src = join(c_chipmunk_root, 'src') 27 | c_chipmunk_incs = [join(c_chipmunk_root, 'include'), 28 | join(c_chipmunk_root, 'include', 'chipmunk')] 29 | c_chipmunk_files = [join(c_chipmunk_src, x) for x in ( 30 | 'cpSpatialIndex.c', 'cpSpaceHash.c', 'constraints/cpPivotJoint.c', 31 | 'constraints/cpConstraint.c', 'constraints/cpSlideJoint.c', 32 | 'constraints/cpRotaryLimitJoint.c', 'constraints/cpGrooveJoint.c', 33 | 'constraints/cpGearJoint.c', 'constraints/cpRatchetJoint.c', 34 | 'constraints/cpSimpleMotor.c', 'constraints/cpDampedRotarySpring.c', 35 | 'constraints/cpPinJoint.c', 'constraints/cpDampedSpring.c', 'cpSpaceStep.c', 36 | 'cpArray.c', 'cpArbiter.c', 'cpCollision.c', 'cpBBTree.c', 'cpSweep1D.c', 37 | 'chipmunk.c', 'cpSpaceQuery.c', 'cpBB.c', 'cpShape.c', 'cpSpace.c', 38 | 'cpVect.c', 'cpPolyShape.c', 'cpSpaceComponent.c', 'cpBody.c', 39 | 'cpHashSet.c')] 40 | 41 | if have_cython: 42 | cymunk_files = [ 43 | 'cymunk/constraint.pxi', 44 | 'cymunk/core.pxi', 45 | 'cymunk/space.pxi', 46 | 'cymunk/shape.pxi', 47 | 'cymunk/body.pxi', 48 | 'cymunk/cymunk.pyx' 49 | ] 50 | cmdclass = {'build_ext': build_ext} 51 | else: 52 | cymunk_files = ['cymunk/cymunk.c'] 53 | cmdclass = {} 54 | 55 | ext = Extension('cymunk.cymunk', 56 | cymunk_files + c_chipmunk_files, 57 | include_dirs=c_chipmunk_incs, 58 | extra_compile_args=[cstdarg, '-ffast-math', '-fPIC', '-DCHIPMUNK_FFI']) 59 | 60 | 61 | setup( 62 | name='cymunk', 63 | description='Cython bindings for Chipmunk', 64 | author='Mathieu Virbel and Nicolas Niemczycki', 65 | author_email='mat@kivy.org', 66 | cmdclass=cmdclass, 67 | packages=['cymunk'], 68 | package_data={'cymunk': ['*.pxd', '*.pxi', 'chipmunk/*.h', 69 | 'chipmunk/constraints/*.h']}, 70 | package_dir={'cymunk': 'cymunk'}, 71 | ext_modules=[ext], 72 | version='0.0.0.dev0' 73 | ) 74 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpDampedRotarySpring.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpDampedRotarySpring cpDampedRotarySpring 23 | /// @{ 24 | 25 | typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle); 26 | 27 | const cpConstraintClass *cpDampedRotarySpringGetClass(void); 28 | 29 | /// @private 30 | typedef struct cpDampedRotarySpring { 31 | cpConstraint constraint; 32 | cpFloat restAngle; 33 | cpFloat stiffness; 34 | cpFloat damping; 35 | cpDampedRotarySpringTorqueFunc springTorqueFunc; 36 | 37 | cpFloat target_wrn; 38 | cpFloat w_coef; 39 | 40 | cpFloat iSum; 41 | cpFloat jAcc; 42 | } cpDampedRotarySpring; 43 | 44 | /// Allocate a damped rotary spring. 45 | cpDampedRotarySpring* cpDampedRotarySpringAlloc(void); 46 | /// Initialize a damped rotary spring. 47 | cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 48 | /// Allocate and initialize a damped rotary spring. 49 | cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 50 | 51 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle) 52 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness) 53 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping) 54 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc) 55 | 56 | /// @} 57 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Cymunk's documentation! 2 | ======================= 3 | 4 | .. warning:: 5 | 6 | This extension is still under heavy development, use at your own risks. 7 | 8 | Cymunk is a port of `Chipmunk `_, based on 9 | `Cython `_. It have the same API and documentation as 10 | `Pymunk `_, so all the thanks goes to them in 11 | the first place! 12 | 13 | Why another python extension for Chipmunk? This project is autonomous, and 14 | doesn't use ctypes. It will output a single all-in-one python extension. It aim 15 | to be used as a cross-platform python extension, including android (via `Python 16 | For Android `_) and iOS (via 17 | `Kivy-ios `_). 18 | 19 | .. image:: screenshot0001.png 20 | :align: center 21 | 22 | 23 | Installation 24 | ============ 25 | 26 | :: 27 | 28 | $ python setup.py build_ext --inplace 29 | 30 | API 31 | === 32 | 33 | Functions 34 | --------- 35 | 36 | .. autofunction:: cymunk.moment_for_box 37 | 38 | .. autofunction:: cymunk.moment_for_circle 39 | 40 | .. autofunction:: cymunk.moment_for_segment 41 | 42 | .. autofunction:: cymunk.reset_shapeid_counter 43 | 44 | Variables 45 | --------- 46 | 47 | .. autodata:: cymunk.__version__ 48 | 49 | Arbiter 50 | ------- 51 | 52 | .. autoclass:: cymunk.Arbiter 53 | :members: 54 | :undoc-members: 55 | 56 | BB 57 | -- 58 | 59 | .. autoclass:: cymunk.BB 60 | :members: 61 | :undoc-members: 62 | 63 | Body 64 | ---- 65 | 66 | .. autoclass:: cymunk.Body 67 | :members: 68 | :undoc-members: 69 | 70 | Circle 71 | ------ 72 | 73 | .. autoclass:: cymunk.Circle 74 | :members: 75 | :undoc-members: 76 | 77 | Contact 78 | ------- 79 | 80 | .. autoclass:: cymunk.Contact 81 | :members: 82 | :undoc-members: 83 | 84 | Poly 85 | ---- 86 | 87 | .. autoclass:: cymunk.Poly 88 | :members: 89 | :undoc-members: 90 | 91 | Segment 92 | ------- 93 | 94 | .. autoclass:: cymunk.Segment 95 | :members: 96 | :undoc-members: 97 | 98 | SegmentQueryInfo 99 | ---------------- 100 | 101 | .. autoclass:: cymunk.SegmentQueryInfo 102 | :members: 103 | :undoc-members: 104 | 105 | Shape 106 | ----- 107 | 108 | .. autoclass:: cymunk.Shape 109 | :members: 110 | :undoc-members: 111 | 112 | Space 113 | ----- 114 | 115 | .. autoclass:: cymunk.Space 116 | :members: 117 | :undoc-members: 118 | 119 | 120 | 121 | Indices and tables 122 | ================== 123 | 124 | * :ref:`genindex` 125 | * :ref:`modindex` 126 | * :ref:`search` 127 | 128 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpDampedRotarySpring.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpDampedRotarySpring cpDampedRotarySpring 23 | /// @{ 24 | 25 | typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle); 26 | 27 | const cpConstraintClass *cpDampedRotarySpringGetClass(void); 28 | 29 | /// @private 30 | typedef struct cpDampedRotarySpring { 31 | cpConstraint constraint; 32 | cpFloat restAngle; 33 | cpFloat stiffness; 34 | cpFloat damping; 35 | cpDampedRotarySpringTorqueFunc springTorqueFunc; 36 | 37 | cpFloat target_wrn; 38 | cpFloat w_coef; 39 | 40 | cpFloat iSum; 41 | cpFloat jAcc; 42 | } cpDampedRotarySpring; 43 | 44 | /// Allocate a damped rotary spring. 45 | cpDampedRotarySpring* cpDampedRotarySpringAlloc(void); 46 | /// Initialize a damped rotary spring. 47 | cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 48 | /// Allocate and initialize a damped rotary spring. 49 | cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); 50 | 51 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle) 52 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness) 53 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping) 54 | CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc) 55 | 56 | /// @} 57 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/cpSpatialIndex.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010 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 | #include "chipmunk_private.h" 23 | 24 | void 25 | cpSpatialIndexFree(cpSpatialIndex *index) 26 | { 27 | if(index){ 28 | cpSpatialIndexDestroy(index); 29 | cpfree(index); 30 | } 31 | } 32 | 33 | cpSpatialIndex * 34 | cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) 35 | { 36 | index->klass = klass; 37 | index->bbfunc = bbfunc; 38 | index->staticIndex = staticIndex; 39 | 40 | if(staticIndex){ 41 | cpAssertHard(!staticIndex->dynamicIndex, "This static index is already associated with a dynamic index."); 42 | staticIndex->dynamicIndex = index; 43 | } 44 | 45 | return index; 46 | } 47 | 48 | typedef struct dynamicToStaticContext { 49 | cpSpatialIndexBBFunc bbfunc; 50 | cpSpatialIndex *staticIndex; 51 | cpSpatialIndexQueryFunc queryFunc; 52 | void *data; 53 | } dynamicToStaticContext; 54 | 55 | static void 56 | dynamicToStaticIter(void *obj, dynamicToStaticContext *context) 57 | { 58 | cpSpatialIndexQuery(context->staticIndex, obj, context->bbfunc(obj), context->queryFunc, context->data); 59 | } 60 | 61 | void 62 | cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data) 63 | { 64 | if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){ 65 | dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data}; 66 | cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/cpDampedSpring.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpDampedSpring cpDampedSpring 23 | /// @{ 24 | 25 | typedef struct cpDampedSpring cpDampedSpring; 26 | 27 | typedef cpFloat (*cpDampedSpringForceFunc)(cpConstraint *spring, cpFloat dist); 28 | 29 | const cpConstraintClass *cpDampedSpringGetClass(void); 30 | 31 | /// @private 32 | struct cpDampedSpring { 33 | cpConstraint constraint; 34 | cpVect anchr1, anchr2; 35 | cpFloat restLength; 36 | cpFloat stiffness; 37 | cpFloat damping; 38 | cpDampedSpringForceFunc springForceFunc; 39 | 40 | cpFloat target_vrn; 41 | cpFloat v_coef; 42 | 43 | cpVect r1, r2; 44 | cpFloat nMass; 45 | cpVect n; 46 | 47 | cpFloat jAcc; 48 | }; 49 | 50 | /// Allocate a damped spring. 51 | cpDampedSpring* cpDampedSpringAlloc(void); 52 | /// Initialize a damped spring. 53 | cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping); 54 | /// Allocate and initialize a damped spring. 55 | cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping); 56 | 57 | CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr1, Anchr1) 58 | CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2) 59 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength) 60 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness) 61 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping) 62 | CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc) 63 | 64 | /// @} 65 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/cpDampedSpring.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpDampedSpring cpDampedSpring 23 | /// @{ 24 | 25 | typedef struct cpDampedSpring cpDampedSpring; 26 | 27 | typedef cpFloat (*cpDampedSpringForceFunc)(cpConstraint *spring, cpFloat dist); 28 | 29 | const cpConstraintClass *cpDampedSpringGetClass(void); 30 | 31 | /// @private 32 | struct cpDampedSpring { 33 | cpConstraint constraint; 34 | cpVect anchr1, anchr2; 35 | cpFloat restLength; 36 | cpFloat stiffness; 37 | cpFloat damping; 38 | cpDampedSpringForceFunc springForceFunc; 39 | 40 | cpFloat target_vrn; 41 | cpFloat v_coef; 42 | 43 | cpVect r1, r2; 44 | cpFloat nMass; 45 | cpVect n; 46 | 47 | cpFloat jAcc; 48 | }; 49 | 50 | /// Allocate a damped spring. 51 | cpDampedSpring* cpDampedSpringAlloc(void); 52 | /// Initialize a damped spring. 53 | cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping); 54 | /// Allocate and initialize a damped spring. 55 | cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping); 56 | 57 | CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr1, Anchr1) 58 | CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2) 59 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength) 60 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness) 61 | CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping) 62 | CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc) 63 | 64 | /// @} 65 | -------------------------------------------------------------------------------- /cymunk/chipmunk/chipmunk_unsafe.h: -------------------------------------------------------------------------------- 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 | /* This header defines a number of "unsafe" operations on Chipmunk objects. 23 | * In this case "unsafe" is referring to operations which may reduce the 24 | * physical accuracy or numerical stability of the simulation, but will not 25 | * cause crashes. 26 | * 27 | * The prime example is mutating collision shapes. Chipmunk does not support 28 | * this directly. Mutating shapes using this API will caused objects in contact 29 | * to be pushed apart using Chipmunk's overlap solver, but not using real 30 | * persistent velocities. Probably not what you meant, but perhaps close enough. 31 | */ 32 | 33 | /// @defgroup unsafe Chipmunk Unsafe Shape Operations 34 | /// These functions are used for mutating collision shapes. 35 | /// Chipmunk does not have any way to get velocity information on changing shapes, 36 | /// so the results will be unrealistic. You must explicity include the chipmunk_unsafe.h header to use them. 37 | /// @{ 38 | 39 | #ifndef CHIPMUNK_UNSAFE_HEADER 40 | #define CHIPMUNK_UNSAFE_HEADER 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | /// Set the radius of a circle shape. 47 | void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius); 48 | /// Set the offset of a circle shape. 49 | void cpCircleShapeSetOffset(cpShape *shape, cpVect offset); 50 | 51 | /// Set the endpoints of a segment shape. 52 | void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b); 53 | /// Set the radius of a segment shape. 54 | void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius); 55 | 56 | /// Set the vertexes of a poly shape. 57 | void cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset); 58 | /// Set the radius of a poly shape. 59 | void cpPolyShapeSetRadius(cpShape *shape, cpFloat radius); 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | #endif 65 | /// @} 66 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/chipmunk_unsafe.h: -------------------------------------------------------------------------------- 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 | /* This header defines a number of "unsafe" operations on Chipmunk objects. 23 | * In this case "unsafe" is referring to operations which may reduce the 24 | * physical accuracy or numerical stability of the simulation, but will not 25 | * cause crashes. 26 | * 27 | * The prime example is mutating collision shapes. Chipmunk does not support 28 | * this directly. Mutating shapes using this API will caused objects in contact 29 | * to be pushed apart using Chipmunk's overlap solver, but not using real 30 | * persistent velocities. Probably not what you meant, but perhaps close enough. 31 | */ 32 | 33 | /// @defgroup unsafe Chipmunk Unsafe Shape Operations 34 | /// These functions are used for mutating collision shapes. 35 | /// Chipmunk does not have any way to get velocity information on changing shapes, 36 | /// so the results will be unrealistic. You must explicity include the chipmunk_unsafe.h header to use them. 37 | /// @{ 38 | 39 | #ifndef CHIPMUNK_UNSAFE_HEADER 40 | #define CHIPMUNK_UNSAFE_HEADER 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | /// Set the radius of a circle shape. 47 | void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius); 48 | /// Set the offset of a circle shape. 49 | void cpCircleShapeSetOffset(cpShape *shape, cpVect offset); 50 | 51 | /// Set the endpoints of a segment shape. 52 | void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b); 53 | /// Set the radius of a segment shape. 54 | void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius); 55 | 56 | /// Set the vertexes of a poly shape. 57 | void cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset); 58 | /// Set the radius of a poly shape. 59 | void cpPolyShapeSetRadius(cpShape *shape, cpFloat radius); 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | #endif 65 | /// @} 66 | -------------------------------------------------------------------------------- /tests/test_vec2d.py: -------------------------------------------------------------------------------- 1 | import cymunk as cy 2 | import pytest 3 | 4 | def test_vec2d(): 5 | v = cy.Vec2d(1, 2) 6 | assert(v is not None) 7 | assert(v.x == 1) 8 | assert(v.y == 2) 9 | assert(v[0] == 1) 10 | assert(v[1] == 2) 11 | 12 | v.x = 3 13 | v.y = 4 14 | assert(v.x == 3) 15 | assert(v.y == 4) 16 | assert(v[0] == 3) 17 | assert(v[1] == 4) 18 | 19 | v[0] = 5 20 | assert(v.x == 5) 21 | assert(v.y == 4) 22 | assert(v[0] == 5) 23 | assert(v[1] == 4) 24 | 25 | v[1] = 6 26 | assert(v.x == 5) 27 | assert(v.y == 6) 28 | assert(v[0] == 5) 29 | assert(v[1] == 6) 30 | 31 | assert v == (5,6) 32 | assert (5,6) == v 33 | assert v != (3,6) 34 | assert (3,6) != v 35 | 36 | 37 | def test_vec2d_magic_math(): 38 | import operator 39 | params = ( 40 | (cy.Vec2d(2.1, 7), 3.2), 41 | (cy.Vec2d(2.3, 7), (3., 5.7)), 42 | (cy.Vec2d(-2.3, 7), cy.Vec2d(0.3, 5.7)), 43 | ) 44 | ops = ( 45 | operator.add, operator.sub, operator.mul, 46 | operator.div, operator.floordiv, operator.truediv, 47 | operator.mod, 48 | ) 49 | for left, right in params: 50 | tright = right if hasattr(right, '__getitem__') else (right, right) 51 | for op in ops: 52 | # test op(left, right) 53 | msg = "%s( %s , %s )" % (op.__name__, left, right) 54 | tres = (op(left.x, tright[0]), op(left.y, tright[1])) 55 | res = op(left, right) 56 | assert tuple(res) == pytest.approx(tres), msg 57 | # test op(right, left) 58 | msg = "%s( %s , %s )" % (op.__name__, right, left) 59 | tres = (op(tright[0], left.x), op(tright[1], left.y)) 60 | res = op(right, left) 61 | assert tuple(res) == pytest.approx(tres), msg 62 | 63 | 64 | def test_vec2d_magic_math_inplace(): 65 | import operator 66 | params = ( 67 | (cy.Vec2d(2.1, 7), 3.2), 68 | (cy.Vec2d(2.3, 7), (3., 5.7)), 69 | (cy.Vec2d(-2.3, 7), cy.Vec2d(0.3, 5.7)) 70 | ) 71 | ops = ( 72 | operator.iadd, operator.isub, operator.imul, 73 | operator.idiv, operator.ifloordiv, operator.itruediv, 74 | operator.imod 75 | ) 76 | for left, right in params: 77 | tright = right if hasattr(right, '__getitem__') else (right, right) 78 | for op in ops: 79 | left = cy.Vec2d(left) 80 | tres = (op(left.x, tright[0]), op(left.y, tright[1])) 81 | op(left, right) 82 | msg = "%s( %s , %s )" % (op.__name__, left, right) 83 | assert tuple(left) == pytest.approx(tres), msg 84 | 85 | 86 | def test_vec2d_magic_unary(): 87 | import operator 88 | assert tuple(operator.neg(cy.Vec2d(-1,1))) == pytest.approx((1,-1)) 89 | assert tuple(operator.pos(cy.Vec2d(-1,1))) == pytest.approx((-1,1)) 90 | assert tuple(operator.abs(cy.Vec2d(-1,1))) == pytest.approx((1,1)) 91 | 92 | 93 | def test_vec2d_indexerror(): 94 | v = cy.Vec2d(1, 2) 95 | with pytest.raises(IndexError): 96 | v[2] = 1 97 | -------------------------------------------------------------------------------- /examples/point_query.py: -------------------------------------------------------------------------------- 1 | """This example showcase point queries by highlighting the shape under the 2 | mouse pointer. 3 | """ 4 | 5 | __version__ = "$Id:$" 6 | __docformat__ = "reStructuredText" 7 | 8 | import random 9 | import sys 10 | 11 | import pygame 12 | from pygame.locals import * 13 | from pygame.color import * 14 | 15 | import cymunk as pm 16 | from cymunk import Vec2d 17 | import pygame_util 18 | 19 | 20 | def main(): 21 | pygame.init() 22 | screen = pygame.display.set_mode((600, 600)) 23 | clock = pygame.time.Clock() 24 | running = True 25 | 26 | ### Physics stuff 27 | space = pm.Space() 28 | space.gravity = Vec2d(0.0, -900.0) 29 | 30 | ## Balls 31 | balls = [] 32 | 33 | ### walls 34 | static_lines = [pm.Segment(space.static_body, Vec2d(111.0, 280.0), Vec2d(407.0, 246.0), 1.0) 35 | ,pm.Segment(space.static_body, Vec2d(407.0, 246.0), Vec2d(407.0, 343.0), 1.0) 36 | ] 37 | space.add(static_lines) 38 | 39 | ticks_to_next_ball = 10 40 | 41 | 42 | while running: 43 | for event in pygame.event.get(): 44 | if event.type == QUIT: 45 | running = False 46 | elif event.type == KEYDOWN and event.key == K_ESCAPE: 47 | running = False 48 | elif event.type == KEYDOWN and event.key == K_p: 49 | pygame.image.save(screen, "point_query.png") 50 | 51 | ticks_to_next_ball -= 1 52 | if ticks_to_next_ball <= 0: 53 | ticks_to_next_ball = 100 54 | mass = 10 55 | radius = 25 56 | inertia = pm.moment_for_circle(mass, 0, radius, Vec2d(0,0)) 57 | body = pm.Body(mass, inertia) 58 | x = random.randint(115,350) 59 | body.position = x, 400 60 | shape = pm.Circle(body, radius, Vec2d(0,0)) 61 | #shape.color = THECOLORS["lightgrey"] 62 | space.add(body, shape) 63 | balls.append(shape) 64 | 65 | ### Clear screen 66 | screen.fill(THECOLORS["white"]) 67 | 68 | ### Draw stuff 69 | pygame_util.draw(screen, space) 70 | 71 | balls_to_remove = [] 72 | for ball in balls: 73 | if ball.body.position.y < 200: balls_to_remove.append(ball) 74 | 75 | for ball in balls_to_remove: 76 | space.remove(ball, ball.body) 77 | balls.remove(ball) 78 | 79 | mouse_pos = pygame_util.get_mouse_pos(screen) 80 | 81 | shape = space.point_query_first(Vec2d(mouse_pos)) 82 | if shape is not None: 83 | if hasattr(shape, "radius"): 84 | r = shape.radius + 4 85 | else: 86 | r = 10 87 | p = pygame_util.to_pygame(shape.body.position, screen) 88 | pygame.draw.circle(screen, THECOLORS["red"], p, int(r), 2) 89 | 90 | ### Update physics 91 | dt = 1.0/60.0 92 | for x in range(1): 93 | space.step(dt) 94 | 95 | 96 | 97 | ### Flip screen 98 | pygame.display.flip() 99 | clock.tick(50) 100 | pygame.display.set_caption("fps: " + str(clock.get_fps())) 101 | 102 | if __name__ == '__main__': 103 | sys.exit(main()) 104 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/cpArray.c: -------------------------------------------------------------------------------- 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 | #include 23 | 24 | #include "chipmunk_private.h" 25 | 26 | 27 | cpArray * 28 | cpArrayNew(int size) 29 | { 30 | cpArray *arr = (cpArray *)cpcalloc(1, sizeof(cpArray)); 31 | 32 | arr->num = 0; 33 | arr->max = (size ? size : 4); 34 | arr->arr = (void **)cpcalloc(arr->max, sizeof(void**)); 35 | 36 | return arr; 37 | } 38 | 39 | void 40 | cpArrayFree(cpArray *arr) 41 | { 42 | if(arr){ 43 | cpfree(arr->arr); 44 | arr->arr = NULL; 45 | 46 | cpfree(arr); 47 | } 48 | } 49 | 50 | void 51 | cpArrayPush(cpArray *arr, void *object) 52 | { 53 | if(arr->num == arr->max){ 54 | arr->max *= 2; 55 | arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void**)); 56 | } 57 | 58 | arr->arr[arr->num] = object; 59 | arr->num++; 60 | } 61 | 62 | void * 63 | cpArrayPop(cpArray *arr) 64 | { 65 | arr->num--; 66 | 67 | void *value = arr->arr[arr->num]; 68 | arr->arr[arr->num] = NULL; 69 | 70 | return value; 71 | } 72 | 73 | //static void 74 | //cpArrayDeleteIndex(cpArray *arr, int idx) 75 | //{ 76 | // arr->num--; 77 | // 78 | // arr->arr[idx] = arr->arr[arr->num]; 79 | // arr->arr[arr->num] = NULL; 80 | //} 81 | 82 | void 83 | cpArrayDeleteObj(cpArray *arr, void *obj) 84 | { 85 | for(int i=0; inum; i++){ 86 | if(arr->arr[i] == obj){ 87 | arr->num--; 88 | 89 | arr->arr[i] = arr->arr[arr->num]; 90 | arr->arr[arr->num] = NULL; 91 | 92 | return; 93 | } 94 | } 95 | } 96 | 97 | //void 98 | //cpArrayAppend(cpArray *arr, cpArray *other) 99 | //{ 100 | // void *tail = &arr->arr[arr->num]; 101 | // 102 | // arr->num += other->num; 103 | // if(arr->num >= arr->max){ 104 | // arr->max = arr->num; 105 | // arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void**)); 106 | // } 107 | // 108 | // memcpy(tail, other->arr, other->num*sizeof(void**)); 109 | //} 110 | 111 | void 112 | cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*)) 113 | { 114 | for(int i=0; inum; i++) freeFunc(arr->arr[i]); 115 | } 116 | 117 | cpBool 118 | cpArrayContains(cpArray *arr, void *ptr) 119 | { 120 | for(int i=0; inum; i++) 121 | if(arr->arr[i] == ptr) return cpTrue; 122 | 123 | return cpFalse; 124 | } 125 | -------------------------------------------------------------------------------- /examples/using_sprites_pyglet.py: -------------------------------------------------------------------------------- 1 | """This example is a clone of the using_sprites example with the difference 2 | that it uses pyglet instead of pygame to showcase sprite drawing. 3 | """ 4 | 5 | __version__ = "$Id:$" 6 | __docformat__ = "reStructuredText" 7 | 8 | import math, random 9 | 10 | import pyglet 11 | 12 | import cymunk as pymunk 13 | from cymunk import Vec2d 14 | 15 | window = pyglet.window.Window(width=600,height=600) 16 | 17 | fps_display = pyglet.clock.ClockDisplay() 18 | 19 | logo_img = pyglet.resource.image('pymunk_logo_googlecode.png') 20 | logo_img.anchor_x = logo_img.width/2 21 | logo_img.anchor_y = logo_img.height/2 22 | logos = [] 23 | batch = pyglet.graphics.Batch() 24 | 25 | ### Physics stuff 26 | space = pymunk.Space() 27 | space.gravity = Vec2d(0.0, -900.0) 28 | 29 | ### Static line 30 | static_body = pymunk.Body() 31 | static_lines = [pymunk.Segment(static_body, (11.0, 280.0), (407.0, 246.0), 0.0) 32 | ,pymunk.Segment(static_body, (407.0, 246.0), (407.0, 343.0), 0.0) 33 | ] 34 | for l in static_lines: 35 | l.friction = 0.5 36 | space.add(static_lines) 37 | 38 | @window.event 39 | def on_key_press(symbol, modifiers): 40 | if symbol == pyglet.window.key.P: 41 | pyglet.image.get_buffer_manager().get_color_buffer().save('using_sprites_pyglet.png') 42 | 43 | @window.event 44 | def on_draw(): 45 | window.clear() 46 | 47 | fps_display.draw() 48 | 49 | for line in static_lines: 50 | body = line.body 51 | 52 | pv1 = body.position + line.a.rotated(body.angle) 53 | pv2 = body.position + line.b.rotated(body.angle) 54 | pyglet.graphics.draw(2, pyglet.gl.GL_LINES, 55 | ('v2f', (pv1.x,pv1.y,pv2.x,pv2.y)), 56 | ('c3f', (.8,.8,.8)*2) 57 | ) 58 | batch.draw() 59 | 60 | #debug draw 61 | for logo_sprite in logos: 62 | 63 | ps = logo_sprite.shape.get_vertices() 64 | n = len(ps) 65 | ps = [c for p in ps for c in p] 66 | 67 | pyglet.graphics.draw(n, pyglet.gl.GL_LINE_LOOP, 68 | ('v2f', ps), 69 | ('c3f', (1,0,0)*n) 70 | ) 71 | 72 | def update(dt): 73 | dt = 1.0/60. #override dt to keep physics simulation stable 74 | space.step(dt) 75 | 76 | for sprite in logos: 77 | # We need to rotate the image 180 degrees because we have y pointing 78 | # up in pymunk coords. 79 | sprite.rotation = math.degrees(-sprite.body.angle) + 180 80 | sprite.set_position(sprite.body.position.x, sprite.body.position.y) 81 | 82 | def spawn_logo(dt): 83 | x = random.randint(20,400) 84 | y = 500 85 | angle = random.random() * math.pi 86 | vs = [(-23,26), (23,26), (0,-26)] 87 | mass = 10 88 | moment = pymunk.moment_for_poly(mass, vs) 89 | body = pymunk.Body(mass, moment) 90 | shape = pymunk.Poly(body, vs) 91 | shape.friction = 0.5 92 | body.position = x, y 93 | body.angle = angle 94 | 95 | space.add(body, shape) 96 | 97 | sprite = pyglet.sprite.Sprite(logo_img, batch=batch) 98 | sprite.shape = shape 99 | sprite.body = body 100 | logos.append(sprite) 101 | 102 | pyglet.clock.schedule_interval(update, 1/60.) 103 | pyglet.clock.schedule_once(spawn_logo, .1) 104 | pyglet.clock.schedule_interval(spawn_logo, 10/6.) 105 | pyglet.app.run() 106 | 107 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpSimpleMotor.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpSimpleMotor *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | // calculate moment of inertia coefficient. 32 | joint->iSum = 1.0f/(a->i_inv + b->i_inv); 33 | } 34 | 35 | static void 36 | applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef) 37 | { 38 | cpBody *a = joint->constraint.a; 39 | cpBody *b = joint->constraint.b; 40 | 41 | cpFloat j = joint->jAcc*dt_coef; 42 | a->w -= j*a->i_inv; 43 | b->w += j*b->i_inv; 44 | } 45 | 46 | static void 47 | applyImpulse(cpSimpleMotor *joint, cpFloat dt) 48 | { 49 | cpBody *a = joint->constraint.a; 50 | cpBody *b = joint->constraint.b; 51 | 52 | // compute relative rotational velocity 53 | cpFloat wr = b->w - a->w + joint->rate; 54 | 55 | cpFloat jMax = joint->constraint.maxForce*dt; 56 | 57 | // compute normal impulse 58 | cpFloat j = -wr*joint->iSum; 59 | cpFloat jOld = joint->jAcc; 60 | joint->jAcc = cpfclamp(jOld + j, -jMax, jMax); 61 | j = joint->jAcc - jOld; 62 | 63 | // apply impulse 64 | a->w -= j*a->i_inv; 65 | b->w += j*b->i_inv; 66 | } 67 | 68 | static cpFloat 69 | getImpulse(cpSimpleMotor *joint) 70 | { 71 | return cpfabs(joint->jAcc); 72 | } 73 | 74 | static const cpConstraintClass klass = { 75 | (cpConstraintPreStepImpl)preStep, 76 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 77 | (cpConstraintApplyImpulseImpl)applyImpulse, 78 | (cpConstraintGetImpulseImpl)getImpulse, 79 | }; 80 | CP_DefineClassGetter(cpSimpleMotor) 81 | 82 | cpSimpleMotor * 83 | cpSimpleMotorAlloc(void) 84 | { 85 | return (cpSimpleMotor *)cpcalloc(1, sizeof(cpSimpleMotor)); 86 | } 87 | 88 | cpSimpleMotor * 89 | cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate) 90 | { 91 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 92 | 93 | joint->rate = rate; 94 | 95 | joint->jAcc = 0.0f; 96 | 97 | return joint; 98 | } 99 | 100 | cpConstraint * 101 | cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate) 102 | { 103 | return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate); 104 | } 105 | -------------------------------------------------------------------------------- /cymunk/chipmunk/cpPolyShape.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPolyShape cpPolyShape 23 | /// @{ 24 | 25 | /// @private 26 | typedef struct cpSplittingPlane { 27 | cpVect n; 28 | cpFloat d; 29 | } cpSplittingPlane; 30 | 31 | /// @private 32 | typedef struct cpPolyShape { 33 | cpShape shape; 34 | 35 | int numVerts; 36 | cpVect *verts, *tVerts; 37 | cpSplittingPlane *planes, *tPlanes; 38 | 39 | cpFloat r; 40 | } cpPolyShape; 41 | 42 | /// Allocate a polygon shape. 43 | cpPolyShape* cpPolyShapeAlloc(void); 44 | /// Initialize a polygon shape. 45 | /// A convex hull will be created from the vertexes. 46 | cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset); 47 | /// Initialize a polygon shape. 48 | /// A convex hull will be created from the vertexes. 49 | cpPolyShape* cpPolyShapeInit2(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset, cpFloat radius); 50 | /// Allocate and initialize a polygon shape. 51 | /// A convex hull will be created from the vertexes. 52 | cpShape* cpPolyShapeNew(cpBody *body, int numVerts, const cpVect *verts, cpVect offset); 53 | /// Allocate and initialize a polygon shape. 54 | /// A convex hull will be created from the vertexes. 55 | cpShape* cpPolyShapeNew2(cpBody *body, int numVerts, const cpVect *verts, cpVect offset, cpFloat radius); 56 | 57 | /// Initialize a box shaped polygon shape. 58 | cpPolyShape* cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height); 59 | /// Initialize an offset box shaped polygon shape. 60 | cpPolyShape* cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box); 61 | /// Initialize an offset box shaped polygon shape. 62 | cpPolyShape* cpBoxShapeInit3(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius); 63 | /// Allocate and initialize a box shaped polygon shape. 64 | cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height); 65 | /// Allocate and initialize an offset box shaped polygon shape. 66 | cpShape* cpBoxShapeNew2(cpBody *body, cpBB box); 67 | /// Allocate and initialize an offset box shaped polygon shape. 68 | cpShape* cpBoxShapeNew3(cpBody *body, cpBB box, cpFloat radius); 69 | 70 | /// Check that a set of vertexes is convex and has a clockwise winding. 71 | /// NOTE: Due to floating point precision issues, hulls created with cpQuickHull() are not guaranteed to validate! 72 | cpBool cpPolyValidate(const cpVect *verts, const int numVerts); 73 | 74 | /// Get the number of verts in a polygon shape. 75 | int cpPolyShapeGetNumVerts(const cpShape *shape); 76 | /// Get the @c ith vertex of a polygon shape. 77 | cpVect cpPolyShapeGetVert(const cpShape *shape, int idx); 78 | /// Get the radius of a polygon shape. 79 | cpFloat cpPolyShapeGetRadius(const cpShape *shape); 80 | 81 | /// @} 82 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/cpPolyShape.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpPolyShape cpPolyShape 23 | /// @{ 24 | 25 | /// @private 26 | typedef struct cpSplittingPlane { 27 | cpVect n; 28 | cpFloat d; 29 | } cpSplittingPlane; 30 | 31 | /// @private 32 | typedef struct cpPolyShape { 33 | cpShape shape; 34 | 35 | int numVerts; 36 | cpVect *verts, *tVerts; 37 | cpSplittingPlane *planes, *tPlanes; 38 | 39 | cpFloat r; 40 | } cpPolyShape; 41 | 42 | /// Allocate a polygon shape. 43 | cpPolyShape* cpPolyShapeAlloc(void); 44 | /// Initialize a polygon shape. 45 | /// A convex hull will be created from the vertexes. 46 | cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset); 47 | /// Initialize a polygon shape. 48 | /// A convex hull will be created from the vertexes. 49 | cpPolyShape* cpPolyShapeInit2(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset, cpFloat radius); 50 | /// Allocate and initialize a polygon shape. 51 | /// A convex hull will be created from the vertexes. 52 | cpShape* cpPolyShapeNew(cpBody *body, int numVerts, const cpVect *verts, cpVect offset); 53 | /// Allocate and initialize a polygon shape. 54 | /// A convex hull will be created from the vertexes. 55 | cpShape* cpPolyShapeNew2(cpBody *body, int numVerts, const cpVect *verts, cpVect offset, cpFloat radius); 56 | 57 | /// Initialize a box shaped polygon shape. 58 | cpPolyShape* cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height); 59 | /// Initialize an offset box shaped polygon shape. 60 | cpPolyShape* cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box); 61 | /// Initialize an offset box shaped polygon shape. 62 | cpPolyShape* cpBoxShapeInit3(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius); 63 | /// Allocate and initialize a box shaped polygon shape. 64 | cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height); 65 | /// Allocate and initialize an offset box shaped polygon shape. 66 | cpShape* cpBoxShapeNew2(cpBody *body, cpBB box); 67 | /// Allocate and initialize an offset box shaped polygon shape. 68 | cpShape* cpBoxShapeNew3(cpBody *body, cpBB box, cpFloat radius); 69 | 70 | /// Check that a set of vertexes is convex and has a clockwise winding. 71 | /// NOTE: Due to floating point precision issues, hulls created with cpQuickHull() are not guaranteed to validate! 72 | cpBool cpPolyValidate(const cpVect *verts, const int numVerts); 73 | 74 | /// Get the number of verts in a polygon shape. 75 | int cpPolyShapeGetNumVerts(const cpShape *shape); 76 | /// Get the @c ith vertex of a polygon shape. 77 | cpVect cpPolyShapeGetVert(const cpShape *shape, int idx); 78 | /// Get the radius of a polygon shape. 79 | cpFloat cpPolyShapeGetRadius(const cpShape *shape); 80 | 81 | /// @} 82 | -------------------------------------------------------------------------------- /examples/box2d_pyramid.py: -------------------------------------------------------------------------------- 1 | """ 2 | Remake of the pyramid demo from the box2d testbed. 3 | """ 4 | 5 | import pygame 6 | from pygame.locals import * 7 | from pygame.color import * 8 | import cymunk as pymunk 9 | from cymunk import Vec2d 10 | 11 | 12 | class PyramidDemo: 13 | def flipyv(self, v): 14 | return v[0], -v[1]+self.h 15 | 16 | def __init__(self): 17 | self.running = True 18 | self.drawing = True 19 | self.w, self.h = 600,600 20 | self.screen = pygame.display.set_mode((self.w, self.h)) 21 | self.clock = pygame.time.Clock() 22 | 23 | ### Init pymunk and create space 24 | self.space = pymunk.Space() 25 | self.space.gravity = (0.0, -900.0) 26 | ### ground 27 | body = pymunk.Body() 28 | shape = pymunk.Segment(body, (50, 100), (550,100), .0) 29 | shape.friction = 1.0 30 | self.space.add(shape) 31 | 32 | ### pyramid 33 | x=Vec2d(-100, 7.5) + (300,100) 34 | y=Vec2d(0,0) 35 | deltaX=Vec2d(0.5625, 2.0)*10 36 | deltaY=Vec2d(1.125, 0.0)*10 37 | 38 | for i in range(25): 39 | y = Vec2d(x) 40 | for j in range(i, 25): 41 | size= 5 42 | points = [(-size, -size), (-size, size), (size,size), (size, -size)] 43 | mass = 1.0 44 | moment = pymunk.moment_for_poly(mass, points, (0,0)) 45 | body = pymunk.Body(mass, moment) 46 | body.position = y 47 | shape = pymunk.Poly(body, points, (0,0)) 48 | shape.friction = 1 49 | self.space.add(body,shape) 50 | 51 | y += deltaY 52 | 53 | x += deltaX 54 | 55 | def run(self): 56 | while self.running: 57 | self.loop() 58 | 59 | 60 | def loop(self): 61 | for event in pygame.event.get(): 62 | if event.type == QUIT: 63 | self.running = False 64 | elif event.type == KEYDOWN and event.key == K_ESCAPE: 65 | self.running = False 66 | elif event.type == KEYDOWN and event.key == K_p: 67 | pygame.image.save(self.screen, "box2d_pyramid.png") 68 | elif event.type == KEYDOWN and event.key == K_d: 69 | self.drawing = not self.drawing 70 | 71 | steps = 3 72 | dt = 1.0/120.0/steps 73 | for x in range(steps): 74 | self.space.step(dt) 75 | if self.drawing: 76 | self.draw() 77 | 78 | ### Tick clock and update fps in title 79 | self.clock.tick(30) 80 | pygame.display.set_caption("fps: " + str(self.clock.get_fps())) 81 | 82 | def draw(self): 83 | ### Clear the screen 84 | self.screen.fill(THECOLORS["white"]) 85 | 86 | for shape in self.space.shapes.itervalues(): 87 | if shape.body.is_static: 88 | body = shape.body 89 | pv1 = self.flipyv(body.position + shape.a.cpvrotate(body.rotation_vector)) 90 | pv2 = self.flipyv(body.position + shape.b.cpvrotate(body.rotation_vector)) 91 | pygame.draw.lines(self.screen, THECOLORS["lightgray"], False, [pv1,pv2]) 92 | else: 93 | if shape.body.is_sleeping: 94 | continue 95 | ps = shape.get_vertices() 96 | ps.append(ps[0]) 97 | ps = map(self.flipyv, ps) 98 | #pygame.draw.lines(self.screen, color, False, ps, 1) 99 | pygame.draw.polygon(self.screen, THECOLORS["lightgray"], ps) 100 | pygame.draw.polygon(self.screen, THECOLORS["darkgrey"], ps,1) 101 | 102 | ### All done, lets flip the display 103 | pygame.display.flip() 104 | 105 | def main(): 106 | demo = PyramidDemo() 107 | demo.run() 108 | 109 | if __name__ == '__main__': 110 | main() -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpGearJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpGearJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | // calculate moment of inertia coefficient. 32 | joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv); 33 | 34 | // calculate bias velocity 35 | cpFloat maxBias = joint->constraint.maxBias; 36 | joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias); 37 | } 38 | 39 | static void 40 | applyCachedImpulse(cpGearJoint *joint, cpFloat dt_coef) 41 | { 42 | cpBody *a = joint->constraint.a; 43 | cpBody *b = joint->constraint.b; 44 | 45 | cpFloat j = joint->jAcc*dt_coef; 46 | a->w -= j*a->i_inv*joint->ratio_inv; 47 | b->w += j*b->i_inv; 48 | } 49 | 50 | static void 51 | applyImpulse(cpGearJoint *joint, cpFloat dt) 52 | { 53 | cpBody *a = joint->constraint.a; 54 | cpBody *b = joint->constraint.b; 55 | 56 | // compute relative rotational velocity 57 | cpFloat wr = b->w*joint->ratio - a->w; 58 | 59 | cpFloat jMax = joint->constraint.maxForce*dt; 60 | 61 | // compute normal impulse 62 | cpFloat j = (joint->bias - wr)*joint->iSum; 63 | cpFloat jOld = joint->jAcc; 64 | joint->jAcc = cpfclamp(jOld + j, -jMax, jMax); 65 | j = joint->jAcc - jOld; 66 | 67 | // apply impulse 68 | a->w -= j*a->i_inv*joint->ratio_inv; 69 | b->w += j*b->i_inv; 70 | } 71 | 72 | static cpFloat 73 | getImpulse(cpGearJoint *joint) 74 | { 75 | return cpfabs(joint->jAcc); 76 | } 77 | 78 | static const cpConstraintClass klass = { 79 | (cpConstraintPreStepImpl)preStep, 80 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 81 | (cpConstraintApplyImpulseImpl)applyImpulse, 82 | (cpConstraintGetImpulseImpl)getImpulse, 83 | }; 84 | CP_DefineClassGetter(cpGearJoint) 85 | 86 | cpGearJoint * 87 | cpGearJointAlloc(void) 88 | { 89 | return (cpGearJoint *)cpcalloc(1, sizeof(cpGearJoint)); 90 | } 91 | 92 | cpGearJoint * 93 | cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio) 94 | { 95 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 96 | 97 | joint->phase = phase; 98 | joint->ratio = ratio; 99 | joint->ratio_inv = 1.0f/ratio; 100 | 101 | joint->jAcc = 0.0f; 102 | 103 | return joint; 104 | } 105 | 106 | cpConstraint * 107 | cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio) 108 | { 109 | return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio); 110 | } 111 | 112 | void 113 | cpGearJointSetRatio(cpConstraint *constraint, cpFloat value) 114 | { 115 | cpConstraintCheckCast(constraint, cpGearJoint); 116 | ((cpGearJoint *)constraint)->ratio = value; 117 | ((cpGearJoint *)constraint)->ratio_inv = 1.0f/value; 118 | cpConstraintActivateBodies(constraint); 119 | } 120 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpPivotJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpPivotJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | joint->r1 = cpvrotate(joint->anchr1, a->rot); 32 | joint->r2 = cpvrotate(joint->anchr2, b->rot); 33 | 34 | // Calculate mass tensor 35 | joint-> k = k_tensor(a, b, joint->r1, joint->r2); 36 | 37 | // calculate bias velocity 38 | cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); 39 | joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias); 40 | } 41 | 42 | static void 43 | applyCachedImpulse(cpPivotJoint *joint, cpFloat dt_coef) 44 | { 45 | cpBody *a = joint->constraint.a; 46 | cpBody *b = joint->constraint.b; 47 | 48 | apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef)); 49 | } 50 | 51 | static void 52 | applyImpulse(cpPivotJoint *joint, cpFloat dt) 53 | { 54 | cpBody *a = joint->constraint.a; 55 | cpBody *b = joint->constraint.b; 56 | 57 | cpVect r1 = joint->r1; 58 | cpVect r2 = joint->r2; 59 | 60 | // compute relative velocity 61 | cpVect vr = relative_velocity(a, b, r1, r2); 62 | 63 | // compute normal impulse 64 | cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr)); 65 | cpVect jOld = joint->jAcc; 66 | joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->constraint.maxForce*dt); 67 | j = cpvsub(joint->jAcc, jOld); 68 | 69 | // apply impulse 70 | apply_impulses(a, b, joint->r1, joint->r2, j); 71 | } 72 | 73 | static cpFloat 74 | getImpulse(cpConstraint *joint) 75 | { 76 | return cpvlength(((cpPivotJoint *)joint)->jAcc); 77 | } 78 | 79 | static const cpConstraintClass klass = { 80 | (cpConstraintPreStepImpl)preStep, 81 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 82 | (cpConstraintApplyImpulseImpl)applyImpulse, 83 | (cpConstraintGetImpulseImpl)getImpulse, 84 | }; 85 | CP_DefineClassGetter(cpPivotJoint) 86 | 87 | cpPivotJoint * 88 | cpPivotJointAlloc(void) 89 | { 90 | return (cpPivotJoint *)cpcalloc(1, sizeof(cpPivotJoint)); 91 | } 92 | 93 | cpPivotJoint * 94 | cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) 95 | { 96 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 97 | 98 | joint->anchr1 = anchr1; 99 | joint->anchr2 = anchr2; 100 | 101 | joint->jAcc = cpvzero; 102 | 103 | return joint; 104 | } 105 | 106 | cpConstraint * 107 | cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) 108 | { 109 | return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchr1, anchr2); 110 | } 111 | 112 | cpConstraint * 113 | cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot) 114 | { 115 | cpVect anchr1 = (a ? cpBodyWorld2Local(a, pivot) : pivot); 116 | cpVect anchr2 = (b ? cpBodyWorld2Local(b, pivot) : pivot); 117 | return cpPivotJointNew2(a, b, anchr1, anchr2); 118 | } 119 | -------------------------------------------------------------------------------- /examples/using_sprites.py: -------------------------------------------------------------------------------- 1 | """Very basic example of using a sprite image to draw a shape more similar 2 | how you would do it in a real game instead of the simple line drawings used 3 | by the other examples. 4 | """ 5 | 6 | __version__ = "$Id:$" 7 | __docformat__ = "reStructuredText" 8 | 9 | import math, random 10 | 11 | import pygame 12 | from pygame.locals import * 13 | from pygame.color import * 14 | 15 | import cymunk as pymunk 16 | from cymunk import Vec2d 17 | 18 | def flipy(y): 19 | """Small hack to convert chipmunk physics to pygame coordinates""" 20 | return -y+600 21 | 22 | def main(): 23 | 24 | pygame.init() 25 | screen = pygame.display.set_mode((600, 600)) 26 | clock = pygame.time.Clock() 27 | running = True 28 | 29 | ### Physics stuff 30 | space = pymunk.Space() 31 | space.gravity = Vec2d(0.0, -900.0) 32 | 33 | ## logo 34 | logo_img = pygame.image.load("pymunk_logo_googlecode.png") 35 | logos = [] 36 | 37 | 38 | ### Static line 39 | static_body = pymunk.Body() 40 | static_lines = [pymunk.Segment(static_body, (11.0, 280.0), (407.0, 246.0), 0.0) 41 | ,pymunk.Segment(static_body, (407.0, 246.0), (407.0, 343.0), 0.0) 42 | ] 43 | for l in static_lines: 44 | l.friction = 0.5 45 | space.add(static_lines) 46 | 47 | ticks_to_next_spawn = 10 48 | 49 | while running: 50 | for event in pygame.event.get(): 51 | if event.type == QUIT: 52 | running = False 53 | elif event.type == KEYDOWN and event.key == K_ESCAPE: 54 | running = False 55 | elif event.type == KEYDOWN and event.key == K_p: 56 | pygame.image.save(screen, "using_sprites.png") 57 | 58 | ticks_to_next_spawn -= 1 59 | if ticks_to_next_spawn <= 0: 60 | ticks_to_next_spawn = 100 61 | x = random.randint(20,400) 62 | y = 500 63 | angle = random.random() * math.pi 64 | vs = [(-23,26), (23,26), (0,-26)] 65 | mass = 10 66 | moment = pymunk.moment_for_poly(mass, vs) 67 | body = pymunk.Body(mass, moment) 68 | shape = pymunk.Poly(body, vs) 69 | shape.friction = 0.5 70 | body.position = x, y 71 | body.angle = angle 72 | 73 | space.add(body, shape) 74 | logos.append(shape) 75 | 76 | ### Update physics 77 | dt = 1.0/60.0 78 | for x in range(1): 79 | space.step(dt) 80 | 81 | ### Draw stuff 82 | screen.fill(THECOLORS["black"]) 83 | 84 | for logo_shape in logos: 85 | # image draw 86 | p = logo_shape.body.position 87 | p = Vec2d(p.x, flipy(p.y)) 88 | 89 | # we need to rotate 180 degrees because of the y coordinate flip 90 | angle_degrees = math.degrees(logo_shape.body.angle) + 180 91 | rotated_logo_img = pygame.transform.rotate(logo_img, angle_degrees) 92 | 93 | offset = Vec2d(rotated_logo_img.get_size()) / 2. 94 | p = p - offset 95 | 96 | screen.blit(rotated_logo_img, (p.x,p.y)) 97 | 98 | # debug draw 99 | ps = logo_shape.get_vertices() 100 | ps = [(p.x, flipy(p.y)) for p in ps] 101 | ps += [ps[0]] 102 | pygame.draw.lines(screen, THECOLORS["red"], False, ps, 1) 103 | 104 | 105 | for line in static_lines: 106 | body = line.body 107 | 108 | pv1 = body.position + line.a.rotated(body.angle) 109 | pv2 = body.position + line.b.rotated(body.angle) 110 | p1 = pv1.x, flipy(pv1.y) 111 | p2 = pv2.x, flipy(pv2.y) 112 | pygame.draw.lines(screen, THECOLORS["lightgray"], False, [p1,p2], 2) 113 | 114 | ### Flip screen 115 | pygame.display.flip() 116 | clock.tick(50) 117 | pygame.display.set_caption("fps: " + str(clock.get_fps())) 118 | 119 | if __name__ == '__main__': 120 | main() 121 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpRotaryLimitJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpRotaryLimitJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | cpFloat dist = b->a - a->a; 32 | cpFloat pdist = 0.0f; 33 | if(dist > joint->max) { 34 | pdist = joint->max - dist; 35 | } else if(dist < joint->min) { 36 | pdist = joint->min - dist; 37 | } 38 | 39 | // calculate moment of inertia coefficient. 40 | joint->iSum = 1.0f/(a->i_inv + b->i_inv); 41 | 42 | // calculate bias velocity 43 | cpFloat maxBias = joint->constraint.maxBias; 44 | joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); 45 | 46 | // If the bias is 0, the joint is not at a limit. Reset the impulse. 47 | if(!joint->bias) joint->jAcc = 0.0f; 48 | } 49 | 50 | static void 51 | applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef) 52 | { 53 | cpBody *a = joint->constraint.a; 54 | cpBody *b = joint->constraint.b; 55 | 56 | cpFloat j = joint->jAcc*dt_coef; 57 | a->w -= j*a->i_inv; 58 | b->w += j*b->i_inv; 59 | } 60 | 61 | static void 62 | applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt) 63 | { 64 | if(!joint->bias) return; // early exit 65 | 66 | cpBody *a = joint->constraint.a; 67 | cpBody *b = joint->constraint.b; 68 | 69 | // compute relative rotational velocity 70 | cpFloat wr = b->w - a->w; 71 | 72 | cpFloat jMax = joint->constraint.maxForce*dt; 73 | 74 | // compute normal impulse 75 | cpFloat j = -(joint->bias + wr)*joint->iSum; 76 | cpFloat jOld = joint->jAcc; 77 | if(joint->bias < 0.0f){ 78 | joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax); 79 | } else { 80 | joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f); 81 | } 82 | j = joint->jAcc - jOld; 83 | 84 | // apply impulse 85 | a->w -= j*a->i_inv; 86 | b->w += j*b->i_inv; 87 | } 88 | 89 | static cpFloat 90 | getImpulse(cpRotaryLimitJoint *joint) 91 | { 92 | return cpfabs(joint->jAcc); 93 | } 94 | 95 | static const cpConstraintClass klass = { 96 | (cpConstraintPreStepImpl)preStep, 97 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 98 | (cpConstraintApplyImpulseImpl)applyImpulse, 99 | (cpConstraintGetImpulseImpl)getImpulse, 100 | }; 101 | CP_DefineClassGetter(cpRotaryLimitJoint) 102 | 103 | cpRotaryLimitJoint * 104 | cpRotaryLimitJointAlloc(void) 105 | { 106 | return (cpRotaryLimitJoint *)cpcalloc(1, sizeof(cpRotaryLimitJoint)); 107 | } 108 | 109 | cpRotaryLimitJoint * 110 | cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max) 111 | { 112 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 113 | 114 | joint->min = min; 115 | joint->max = max; 116 | 117 | joint->jAcc = 0.0f; 118 | 119 | return joint; 120 | } 121 | 122 | cpConstraint * 123 | cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max) 124 | { 125 | return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max); 126 | } 127 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpDampedRotarySpring.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static cpFloat 26 | defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){ 27 | return (relativeAngle - spring->restAngle)*spring->stiffness; 28 | } 29 | 30 | static void 31 | preStep(cpDampedRotarySpring *spring, cpFloat dt) 32 | { 33 | cpBody *a = spring->constraint.a; 34 | cpBody *b = spring->constraint.b; 35 | 36 | cpFloat moment = a->i_inv + b->i_inv; 37 | cpAssertSoft(moment != 0.0, "Unsolvable spring."); 38 | spring->iSum = 1.0f/moment; 39 | 40 | spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment); 41 | spring->target_wrn = 0.0f; 42 | 43 | // apply spring torque 44 | cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt; 45 | spring->jAcc = j_spring; 46 | 47 | a->w -= j_spring*a->i_inv; 48 | b->w += j_spring*b->i_inv; 49 | } 50 | 51 | static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){} 52 | 53 | static void 54 | applyImpulse(cpDampedRotarySpring *spring, cpFloat dt) 55 | { 56 | cpBody *a = spring->constraint.a; 57 | cpBody *b = spring->constraint.b; 58 | 59 | // compute relative velocity 60 | cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn; 61 | 62 | // compute velocity loss from drag 63 | // not 100% certain this is derived correctly, though it makes sense 64 | cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef; 65 | spring->target_wrn = wrn + w_damp; 66 | 67 | //apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass)); 68 | cpFloat j_damp = w_damp*spring->iSum; 69 | spring->jAcc += j_damp; 70 | 71 | a->w += j_damp*a->i_inv; 72 | b->w -= j_damp*b->i_inv; 73 | } 74 | 75 | static cpFloat 76 | getImpulse(cpDampedRotarySpring *spring) 77 | { 78 | return spring->jAcc; 79 | } 80 | 81 | static const cpConstraintClass klass = { 82 | (cpConstraintPreStepImpl)preStep, 83 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 84 | (cpConstraintApplyImpulseImpl)applyImpulse, 85 | (cpConstraintGetImpulseImpl)getImpulse, 86 | }; 87 | CP_DefineClassGetter(cpDampedRotarySpring) 88 | 89 | cpDampedRotarySpring * 90 | cpDampedRotarySpringAlloc(void) 91 | { 92 | return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring)); 93 | } 94 | 95 | cpDampedRotarySpring * 96 | cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping) 97 | { 98 | cpConstraintInit((cpConstraint *)spring, &klass, a, b); 99 | 100 | spring->restAngle = restAngle; 101 | spring->stiffness = stiffness; 102 | spring->damping = damping; 103 | spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque; 104 | 105 | spring->jAcc = 0.0f; 106 | 107 | return spring; 108 | } 109 | 110 | cpConstraint * 111 | cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping) 112 | { 113 | return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping); 114 | } 115 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpRatchetJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpRatchetJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | cpFloat angle = joint->angle; 32 | cpFloat phase = joint->phase; 33 | cpFloat ratchet = joint->ratchet; 34 | 35 | cpFloat delta = b->a - a->a; 36 | cpFloat diff = angle - delta; 37 | cpFloat pdist = 0.0f; 38 | 39 | if(diff*ratchet > 0.0f){ 40 | pdist = diff; 41 | } else { 42 | joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase; 43 | } 44 | 45 | // calculate moment of inertia coefficient. 46 | joint->iSum = 1.0f/(a->i_inv + b->i_inv); 47 | 48 | // calculate bias velocity 49 | cpFloat maxBias = joint->constraint.maxBias; 50 | joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); 51 | 52 | // If the bias is 0, the joint is not at a limit. Reset the impulse. 53 | if(!joint->bias) joint->jAcc = 0.0f; 54 | } 55 | 56 | static void 57 | applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef) 58 | { 59 | cpBody *a = joint->constraint.a; 60 | cpBody *b = joint->constraint.b; 61 | 62 | cpFloat j = joint->jAcc*dt_coef; 63 | a->w -= j*a->i_inv; 64 | b->w += j*b->i_inv; 65 | } 66 | 67 | static void 68 | applyImpulse(cpRatchetJoint *joint, cpFloat dt) 69 | { 70 | if(!joint->bias) return; // early exit 71 | 72 | cpBody *a = joint->constraint.a; 73 | cpBody *b = joint->constraint.b; 74 | 75 | // compute relative rotational velocity 76 | cpFloat wr = b->w - a->w; 77 | cpFloat ratchet = joint->ratchet; 78 | 79 | cpFloat jMax = joint->constraint.maxForce*dt; 80 | 81 | // compute normal impulse 82 | cpFloat j = -(joint->bias + wr)*joint->iSum; 83 | cpFloat jOld = joint->jAcc; 84 | joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet; 85 | j = joint->jAcc - jOld; 86 | 87 | // apply impulse 88 | a->w -= j*a->i_inv; 89 | b->w += j*b->i_inv; 90 | } 91 | 92 | static cpFloat 93 | getImpulse(cpRatchetJoint *joint) 94 | { 95 | return cpfabs(joint->jAcc); 96 | } 97 | 98 | static const cpConstraintClass klass = { 99 | (cpConstraintPreStepImpl)preStep, 100 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 101 | (cpConstraintApplyImpulseImpl)applyImpulse, 102 | (cpConstraintGetImpulseImpl)getImpulse, 103 | }; 104 | CP_DefineClassGetter(cpRatchetJoint) 105 | 106 | cpRatchetJoint * 107 | cpRatchetJointAlloc(void) 108 | { 109 | return (cpRatchetJoint *)cpcalloc(1, sizeof(cpRatchetJoint)); 110 | } 111 | 112 | cpRatchetJoint * 113 | cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet) 114 | { 115 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 116 | 117 | joint->angle = 0.0f; 118 | joint->phase = phase; 119 | joint->ratchet = ratchet; 120 | 121 | // STATIC_BODY_CHECK 122 | joint->angle = (b ? b->a : 0.0f) - (a ? a->a : 0.0f); 123 | 124 | return joint; 125 | } 126 | 127 | cpConstraint * 128 | cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet) 129 | { 130 | return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet); 131 | } 132 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpPinJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpPinJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | joint->r1 = cpvrotate(joint->anchr1, a->rot); 32 | joint->r2 = cpvrotate(joint->anchr2, b->rot); 33 | 34 | cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); 35 | cpFloat dist = cpvlength(delta); 36 | joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY)); 37 | 38 | // calculate mass normal 39 | joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n); 40 | 41 | // calculate bias velocity 42 | cpFloat maxBias = joint->constraint.maxBias; 43 | joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias); 44 | } 45 | 46 | static void 47 | applyCachedImpulse(cpPinJoint *joint, cpFloat dt_coef) 48 | { 49 | cpBody *a = joint->constraint.a; 50 | cpBody *b = joint->constraint.b; 51 | 52 | cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef); 53 | apply_impulses(a, b, joint->r1, joint->r2, j); 54 | } 55 | 56 | static void 57 | applyImpulse(cpPinJoint *joint, cpFloat dt) 58 | { 59 | cpBody *a = joint->constraint.a; 60 | cpBody *b = joint->constraint.b; 61 | cpVect n = joint->n; 62 | 63 | // compute relative velocity 64 | cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n); 65 | 66 | cpFloat jnMax = joint->constraint.maxForce*dt; 67 | 68 | // compute normal impulse 69 | cpFloat jn = (joint->bias - vrn)*joint->nMass; 70 | cpFloat jnOld = joint->jnAcc; 71 | joint->jnAcc = cpfclamp(jnOld + jn, -jnMax, jnMax); 72 | jn = joint->jnAcc - jnOld; 73 | 74 | // apply impulse 75 | apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn)); 76 | } 77 | 78 | static cpFloat 79 | getImpulse(cpPinJoint *joint) 80 | { 81 | return cpfabs(joint->jnAcc); 82 | } 83 | 84 | static const cpConstraintClass klass = { 85 | (cpConstraintPreStepImpl)preStep, 86 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 87 | (cpConstraintApplyImpulseImpl)applyImpulse, 88 | (cpConstraintGetImpulseImpl)getImpulse, 89 | }; 90 | CP_DefineClassGetter(cpPinJoint) 91 | 92 | 93 | cpPinJoint * 94 | cpPinJointAlloc(void) 95 | { 96 | return (cpPinJoint *)cpcalloc(1, sizeof(cpPinJoint)); 97 | } 98 | 99 | cpPinJoint * 100 | cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) 101 | { 102 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 103 | 104 | joint->anchr1 = anchr1; 105 | joint->anchr2 = anchr2; 106 | 107 | // STATIC_BODY_CHECK 108 | cpVect p1 = (a ? cpvadd(a->p, cpvrotate(anchr1, a->rot)) : anchr1); 109 | cpVect p2 = (b ? cpvadd(b->p, cpvrotate(anchr2, b->rot)) : anchr2); 110 | joint->dist = cpvlength(cpvsub(p2, p1)); 111 | 112 | cpAssertWarn(joint->dist > 0.0, "You created a 0 length pin joint. A pivot joint will be much more stable."); 113 | 114 | joint->jnAcc = 0.0f; 115 | 116 | return joint; 117 | } 118 | 119 | cpConstraint * 120 | cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) 121 | { 122 | return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2); 123 | } 124 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpSlideJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpSlideJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | joint->r1 = cpvrotate(joint->anchr1, a->rot); 32 | joint->r2 = cpvrotate(joint->anchr2, b->rot); 33 | 34 | cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); 35 | cpFloat dist = cpvlength(delta); 36 | cpFloat pdist = 0.0f; 37 | if(dist > joint->max) { 38 | pdist = dist - joint->max; 39 | joint->n = cpvnormalize_safe(delta); 40 | } else if(dist < joint->min) { 41 | pdist = joint->min - dist; 42 | joint->n = cpvneg(cpvnormalize_safe(delta)); 43 | } else { 44 | joint->n = cpvzero; 45 | joint->jnAcc = 0.0f; 46 | } 47 | 48 | // calculate mass normal 49 | joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n); 50 | 51 | // calculate bias velocity 52 | cpFloat maxBias = joint->constraint.maxBias; 53 | joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); 54 | } 55 | 56 | static void 57 | applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef) 58 | { 59 | cpBody *a = joint->constraint.a; 60 | cpBody *b = joint->constraint.b; 61 | 62 | cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef); 63 | apply_impulses(a, b, joint->r1, joint->r2, j); 64 | } 65 | 66 | static void 67 | applyImpulse(cpSlideJoint *joint, cpFloat dt) 68 | { 69 | if(cpveql(joint->n, cpvzero)) return; // early exit 70 | 71 | cpBody *a = joint->constraint.a; 72 | cpBody *b = joint->constraint.b; 73 | 74 | cpVect n = joint->n; 75 | cpVect r1 = joint->r1; 76 | cpVect r2 = joint->r2; 77 | 78 | // compute relative velocity 79 | cpVect vr = relative_velocity(a, b, r1, r2); 80 | cpFloat vrn = cpvdot(vr, n); 81 | 82 | // compute normal impulse 83 | cpFloat jn = (joint->bias - vrn)*joint->nMass; 84 | cpFloat jnOld = joint->jnAcc; 85 | joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f); 86 | jn = joint->jnAcc - jnOld; 87 | 88 | // apply impulse 89 | apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn)); 90 | } 91 | 92 | static cpFloat 93 | getImpulse(cpConstraint *joint) 94 | { 95 | return cpfabs(((cpSlideJoint *)joint)->jnAcc); 96 | } 97 | 98 | static const cpConstraintClass klass = { 99 | (cpConstraintPreStepImpl)preStep, 100 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 101 | (cpConstraintApplyImpulseImpl)applyImpulse, 102 | (cpConstraintGetImpulseImpl)getImpulse, 103 | }; 104 | CP_DefineClassGetter(cpSlideJoint) 105 | 106 | cpSlideJoint * 107 | cpSlideJointAlloc(void) 108 | { 109 | return (cpSlideJoint *)cpcalloc(1, sizeof(cpSlideJoint)); 110 | } 111 | 112 | cpSlideJoint * 113 | cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max) 114 | { 115 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 116 | 117 | joint->anchr1 = anchr1; 118 | joint->anchr2 = anchr2; 119 | joint->min = min; 120 | joint->max = max; 121 | 122 | joint->jnAcc = 0.0f; 123 | 124 | return joint; 125 | } 126 | 127 | cpConstraint * 128 | cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max) 129 | { 130 | return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max); 131 | } 132 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpDampedSpring.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static cpFloat 26 | defaultSpringForce(cpDampedSpring *spring, cpFloat dist){ 27 | return (spring->restLength - dist)*spring->stiffness; 28 | } 29 | 30 | static void 31 | preStep(cpDampedSpring *spring, cpFloat dt) 32 | { 33 | cpBody *a = spring->constraint.a; 34 | cpBody *b = spring->constraint.b; 35 | 36 | spring->r1 = cpvrotate(spring->anchr1, a->rot); 37 | spring->r2 = cpvrotate(spring->anchr2, b->rot); 38 | 39 | cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1)); 40 | cpFloat dist = cpvlength(delta); 41 | spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY)); 42 | 43 | cpFloat k = k_scalar(a, b, spring->r1, spring->r2, spring->n); 44 | cpAssertSoft(k != 0.0, "Unsolvable spring."); 45 | spring->nMass = 1.0f/k; 46 | 47 | spring->target_vrn = 0.0f; 48 | spring->v_coef = 1.0f - cpfexp(-spring->damping*dt*k); 49 | 50 | // apply spring force 51 | cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist); 52 | cpFloat j_spring = spring->jAcc = f_spring*dt; 53 | apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_spring)); 54 | } 55 | 56 | static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){} 57 | 58 | static void 59 | applyImpulse(cpDampedSpring *spring, cpFloat dt) 60 | { 61 | cpBody *a = spring->constraint.a; 62 | cpBody *b = spring->constraint.b; 63 | 64 | cpVect n = spring->n; 65 | cpVect r1 = spring->r1; 66 | cpVect r2 = spring->r2; 67 | 68 | // compute relative velocity 69 | cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n); 70 | 71 | // compute velocity loss from drag 72 | cpFloat v_damp = (spring->target_vrn - vrn)*spring->v_coef; 73 | spring->target_vrn = vrn + v_damp; 74 | 75 | cpFloat j_damp = v_damp*spring->nMass; 76 | spring->jAcc += j_damp; 77 | apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_damp)); 78 | } 79 | 80 | static cpFloat 81 | getImpulse(cpDampedSpring *spring) 82 | { 83 | return spring->jAcc; 84 | } 85 | 86 | static const cpConstraintClass klass = { 87 | (cpConstraintPreStepImpl)preStep, 88 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 89 | (cpConstraintApplyImpulseImpl)applyImpulse, 90 | (cpConstraintGetImpulseImpl)getImpulse, 91 | }; 92 | CP_DefineClassGetter(cpDampedSpring) 93 | 94 | cpDampedSpring * 95 | cpDampedSpringAlloc(void) 96 | { 97 | return (cpDampedSpring *)cpcalloc(1, sizeof(cpDampedSpring)); 98 | } 99 | 100 | cpDampedSpring * 101 | cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping) 102 | { 103 | cpConstraintInit((cpConstraint *)spring, cpDampedSpringGetClass(), a, b); 104 | 105 | spring->anchr1 = anchr1; 106 | spring->anchr2 = anchr2; 107 | 108 | spring->restLength = restLength; 109 | spring->stiffness = stiffness; 110 | spring->damping = damping; 111 | spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce; 112 | 113 | spring->jAcc = 0.0f; 114 | 115 | return spring; 116 | } 117 | 118 | cpConstraint * 119 | cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping) 120 | { 121 | return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchr1, anchr2, restLength, stiffness, damping); 122 | } 123 | -------------------------------------------------------------------------------- /cymunk/chipmunk/constraints/util.h: -------------------------------------------------------------------------------- 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 | // These are utility routines to use when creating custom constraints. 23 | // I'm not sure if this should be part of the private API or not. 24 | // I should probably clean up the naming conventions if it is... 25 | 26 | #define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(void){return (cpConstraintClass *)&klass;} 27 | 28 | void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b); 29 | 30 | static inline cpVect 31 | relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){ 32 | cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); 33 | cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); 34 | 35 | return cpvsub(v2_sum, v1_sum); 36 | } 37 | 38 | static inline cpFloat 39 | normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){ 40 | return cpvdot(relative_velocity(a, b, r1, r2), n); 41 | } 42 | 43 | static inline void 44 | apply_impulse(cpBody *body, cpVect j, cpVect r){ 45 | body->v = cpvadd(body->v, cpvmult(j, body->m_inv)); 46 | body->w += body->i_inv*cpvcross(r, j); 47 | } 48 | 49 | static inline void 50 | apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) 51 | { 52 | apply_impulse(a, cpvneg(j), r1); 53 | apply_impulse(b, j, r2); 54 | } 55 | 56 | static inline void 57 | apply_bias_impulse(cpBody *body, cpVect j, cpVect r) 58 | { 59 | body->CP_PRIVATE(v_bias) = cpvadd(body->CP_PRIVATE(v_bias), cpvmult(j, body->m_inv)); 60 | body->CP_PRIVATE(w_bias) += body->i_inv*cpvcross(r, j); 61 | } 62 | 63 | static inline void 64 | apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) 65 | { 66 | apply_bias_impulse(a, cpvneg(j), r1); 67 | apply_bias_impulse(b, j, r2); 68 | } 69 | 70 | static inline cpFloat 71 | k_scalar_body(cpBody *body, cpVect r, cpVect n) 72 | { 73 | cpFloat rcn = cpvcross(r, n); 74 | return body->m_inv + body->i_inv*rcn*rcn; 75 | } 76 | 77 | static inline cpFloat 78 | k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n) 79 | { 80 | cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n); 81 | cpAssertSoft(value != 0.0, "Unsolvable collision or constraint."); 82 | 83 | return value; 84 | } 85 | 86 | static inline cpMat2x2 87 | k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2) 88 | { 89 | cpFloat m_sum = a->m_inv + b->m_inv; 90 | 91 | // start with Identity*m_sum 92 | cpFloat k11 = m_sum, k12 = 0.0f; 93 | cpFloat k21 = 0.0f, k22 = m_sum; 94 | 95 | // add the influence from r1 96 | cpFloat a_i_inv = a->i_inv; 97 | cpFloat r1xsq = r1.x * r1.x * a_i_inv; 98 | cpFloat r1ysq = r1.y * r1.y * a_i_inv; 99 | cpFloat r1nxy = -r1.x * r1.y * a_i_inv; 100 | k11 += r1ysq; k12 += r1nxy; 101 | k21 += r1nxy; k22 += r1xsq; 102 | 103 | // add the influnce from r2 104 | cpFloat b_i_inv = b->i_inv; 105 | cpFloat r2xsq = r2.x * r2.x * b_i_inv; 106 | cpFloat r2ysq = r2.y * r2.y * b_i_inv; 107 | cpFloat r2nxy = -r2.x * r2.y * b_i_inv; 108 | k11 += r2ysq; k12 += r2nxy; 109 | k21 += r2nxy; k22 += r2xsq; 110 | 111 | // invert 112 | cpFloat det = k11*k22 - k12*k21; 113 | cpAssertSoft(det != 0.0, "Unsolvable constraint."); 114 | 115 | cpFloat det_inv = 1.0f/det; 116 | return cpMat2x2New( 117 | k22*det_inv, -k12*det_inv, 118 | -k21*det_inv, k11*det_inv 119 | ); 120 | } 121 | 122 | static inline cpFloat 123 | bias_coef(cpFloat errorBias, cpFloat dt) 124 | { 125 | return 1.0f - cpfpow(errorBias, dt); 126 | } 127 | -------------------------------------------------------------------------------- /examples/circle_box/main.py: -------------------------------------------------------------------------------- 1 | import cymunk as cy 2 | from os.path import dirname, join 3 | from kivy.clock import Clock 4 | from kivy.app import App 5 | from kivy.graphics import Color, Rectangle 6 | from kivy.uix.widget import Widget 7 | from kivy.properties import DictProperty, ListProperty 8 | from kivy.core.image import Image 9 | from random import random 10 | from kivy.lang import Builder 11 | 12 | Builder.load_string(''' 13 | : 14 | Label: 15 | text: 'circles: %d' % len(root.blist) 16 | ''') 17 | 18 | class Playground(Widget): 19 | 20 | cbounds = ListProperty([]) 21 | cmap = DictProperty({}) 22 | blist = ListProperty([]) 23 | 24 | def __init__(self, **kwargs): 25 | self._hue = 0 26 | super(Playground, self).__init__(**kwargs) 27 | self.init_physics() 28 | self.bind(size=self.update_bounds, pos=self.update_bounds) 29 | self.texture = Image(join(dirname(__file__), 'circle.png'), mipmap=True).texture 30 | Clock.schedule_interval(self.step, 1 / 30.) 31 | 32 | def init_physics(self): 33 | # create the space for physics simulation 34 | self.space = space = cy.Space() 35 | space.iterations = 30 36 | space.gravity = (0, -700) 37 | space.sleep_time_threshold = 0.5 38 | space.collision_slop = 0.5 39 | 40 | # create 4 segments that will act as a bounds 41 | for x in xrange(4): 42 | seg = cy.Segment(space.static_body, 43 | cy.Vec2d(0, 0), cy.Vec2d(0, 0), 0) 44 | seg.elasticity = 0.6 45 | #seg.friction = 1.0 46 | self.cbounds.append(seg) 47 | space.add_static(seg) 48 | 49 | # update bounds with good positions 50 | self.update_bounds() 51 | 52 | def update_bounds(self, *largs): 53 | assert(len(self.cbounds) == 4) 54 | a, b, c, d = self.cbounds 55 | x0, y0 = self.pos 56 | x1 = self.right 57 | y1 = self.top 58 | 59 | self.space.remove_static(a) 60 | self.space.remove_static(b) 61 | self.space.remove_static(c) 62 | self.space.remove_static(d) 63 | a.a = (x0, y0) 64 | a.b = (x1, y0) 65 | b.a = (x1, y0) 66 | b.b = (x1, y1) 67 | c.a = (x1, y1) 68 | c.b = (x0, y1) 69 | d.a = (x0, y1) 70 | d.b = (x0, y0) 71 | self.space.add_static(a) 72 | self.space.add_static(b) 73 | self.space.add_static(c) 74 | self.space.add_static(d) 75 | 76 | def step(self, dt): 77 | self.space.step(1 / 30.) 78 | self.update_objects() 79 | 80 | def update_objects(self): 81 | for body, obj in self.cmap.iteritems(): 82 | p = body.position 83 | radius, color, rect = obj 84 | rect.pos = p.x - radius, p.y - radius 85 | rect.size = radius * 2, radius * 2 86 | 87 | def add_random_circle(self): 88 | self.add_circle( 89 | self.x + random() * self.width, 90 | self.y + random() * self.height, 91 | 10 + random() * 50) 92 | 93 | def add_circle(self, x, y, radius): 94 | # create a falling circle 95 | body = cy.Body(100, 1e9) 96 | body.position = x, y 97 | circle = cy.Circle(body, radius) 98 | circle.elasticity = 0.6 99 | #circle.friction = 1.0 100 | self.space.add(body, circle) 101 | 102 | with self.canvas.before: 103 | self._hue = (self._hue + 0.01) % 1 104 | color = Color(self._hue, 1, 1, mode='hsv') 105 | rect = Rectangle( 106 | texture=self.texture, 107 | pos=(self.x - radius, self.y - radius), 108 | size=(radius * 2, radius * 2)) 109 | self.cmap[body] = (radius, color, rect) 110 | 111 | # remove the oldest one 112 | self.blist.append((body, circle)) 113 | if len(self.blist) > 200: 114 | body, circle = self.blist.pop(0) 115 | self.space.remove(body) 116 | self.space.remove(circle) 117 | radius, color, rect = self.cmap.pop(body) 118 | self.canvas.before.remove(color) 119 | self.canvas.before.remove(rect) 120 | 121 | def on_touch_down(self, touch): 122 | self.add_circle(touch.x, touch.y, 10 + random() * 20) 123 | 124 | def on_touch_move(self, touch): 125 | self.add_circle(touch.x, touch.y, 10 + random() * 20) 126 | 127 | class PhysicsApp(App): 128 | def build(self): 129 | return Playground() 130 | 131 | if __name__ == '__main__': 132 | PhysicsApp().run() 133 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/constraints/util.h: -------------------------------------------------------------------------------- 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 | // These are utility routines to use when creating custom constraints. 23 | // I'm not sure if this should be part of the private API or not. 24 | // I should probably clean up the naming conventions if it is... 25 | 26 | #define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(void){return (cpConstraintClass *)&klass;} 27 | 28 | void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b); 29 | 30 | static inline cpVect 31 | relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){ 32 | cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); 33 | cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); 34 | 35 | return cpvsub(v2_sum, v1_sum); 36 | } 37 | 38 | static inline cpFloat 39 | normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){ 40 | return cpvdot(relative_velocity(a, b, r1, r2), n); 41 | } 42 | 43 | static inline void 44 | apply_impulse(cpBody *body, cpVect j, cpVect r){ 45 | body->v = cpvadd(body->v, cpvmult(j, body->m_inv)); 46 | body->w += body->i_inv*cpvcross(r, j); 47 | } 48 | 49 | static inline void 50 | apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) 51 | { 52 | apply_impulse(a, cpvneg(j), r1); 53 | apply_impulse(b, j, r2); 54 | } 55 | 56 | static inline void 57 | apply_bias_impulse(cpBody *body, cpVect j, cpVect r) 58 | { 59 | body->CP_PRIVATE(v_bias) = cpvadd(body->CP_PRIVATE(v_bias), cpvmult(j, body->m_inv)); 60 | body->CP_PRIVATE(w_bias) += body->i_inv*cpvcross(r, j); 61 | } 62 | 63 | static inline void 64 | apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) 65 | { 66 | apply_bias_impulse(a, cpvneg(j), r1); 67 | apply_bias_impulse(b, j, r2); 68 | } 69 | 70 | static inline cpFloat 71 | k_scalar_body(cpBody *body, cpVect r, cpVect n) 72 | { 73 | cpFloat rcn = cpvcross(r, n); 74 | return body->m_inv + body->i_inv*rcn*rcn; 75 | } 76 | 77 | static inline cpFloat 78 | k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n) 79 | { 80 | cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n); 81 | cpAssertSoft(value != 0.0, "Unsolvable collision or constraint."); 82 | 83 | return value; 84 | } 85 | 86 | static inline cpMat2x2 87 | k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2) 88 | { 89 | cpFloat m_sum = a->m_inv + b->m_inv; 90 | 91 | // start with Identity*m_sum 92 | cpFloat k11 = m_sum, k12 = 0.0f; 93 | cpFloat k21 = 0.0f, k22 = m_sum; 94 | 95 | // add the influence from r1 96 | cpFloat a_i_inv = a->i_inv; 97 | cpFloat r1xsq = r1.x * r1.x * a_i_inv; 98 | cpFloat r1ysq = r1.y * r1.y * a_i_inv; 99 | cpFloat r1nxy = -r1.x * r1.y * a_i_inv; 100 | k11 += r1ysq; k12 += r1nxy; 101 | k21 += r1nxy; k22 += r1xsq; 102 | 103 | // add the influnce from r2 104 | cpFloat b_i_inv = b->i_inv; 105 | cpFloat r2xsq = r2.x * r2.x * b_i_inv; 106 | cpFloat r2ysq = r2.y * r2.y * b_i_inv; 107 | cpFloat r2nxy = -r2.x * r2.y * b_i_inv; 108 | k11 += r2ysq; k12 += r2nxy; 109 | k21 += r2nxy; k22 += r2xsq; 110 | 111 | // invert 112 | cpFloat det = k11*k22 - k12*k21; 113 | cpAssertSoft(det != 0.0, "Unsolvable constraint."); 114 | 115 | cpFloat det_inv = 1.0f/det; 116 | return cpMat2x2New( 117 | k22*det_inv, -k12*det_inv, 118 | -k21*det_inv, k11*det_inv 119 | ); 120 | } 121 | 122 | static inline cpFloat 123 | bias_coef(cpFloat errorBias, cpFloat dt) 124 | { 125 | return 1.0f - cpfpow(errorBias, dt); 126 | } 127 | -------------------------------------------------------------------------------- /cymunk/constraint.pxd: -------------------------------------------------------------------------------- 1 | cdef extern from "chipmunk/chipmunk.h": 2 | 3 | void cpConstraintDestroy (cpConstraint *constraint) 4 | void cpConstraintFree (cpConstraint *constraint) 5 | 6 | inline cpFloat cpConstraintGetImpulse(cpConstraint *constraint) 7 | 8 | # Callback function type that gets called before solving a joint. 9 | ctypedef void(* cpConstraintPreSolveFunc )(cpConstraint *constraint, cpSpace *space) 10 | 11 | # Callback function type that gets called after solving a joint. 12 | ctypedef void(* cpConstraintPostSolveFunc )(cpConstraint *constraint, cpSpace *space) 13 | 14 | ctypedef struct cpConstraint: 15 | cpBody * a 16 | cpBody * b 17 | cpFloat maxForce 18 | cpFloat errorBias 19 | cpFloat maxBias 20 | cpConstraintPreSolveFunc preSolve 21 | cpConstraintPostSolveFunc postSolve 22 | cpDataPointer data 23 | 24 | ctypedef struct cpPivotJoint: 25 | cpConstraint constraint 26 | cpVect anchr1 27 | cpVect anchr2 28 | 29 | ctypedef struct cpSlideJoint: 30 | cpConstraint constraint 31 | cpVect anchr1 32 | cpVect anchr2 33 | cpFloat min 34 | cpFloat max 35 | 36 | ctypedef struct cpDampedSpring: 37 | cpConstraint constraint 38 | cpVect anchr1 39 | cpVect anchr2 40 | cpFloat restLength 41 | cpFloat stiffness 42 | cpFloat damping 43 | 44 | ctypedef struct cpDampedRotarySpring: 45 | cpConstraint constraint 46 | cpFloat restAngle 47 | cpFloat stiffness 48 | cpFloat damping 49 | 50 | ctypedef struct cpRotaryLimitJoint: 51 | cpConstraint constraint 52 | cpFloat min 53 | cpFloat max 54 | 55 | ctypedef struct cpPinJoint: 56 | cpConstraint constraint 57 | cpVect anchr1 58 | cpVect anchr2 59 | cpFloat dist 60 | 61 | ctypedef struct cpGrooveJoint: 62 | cpConstraint constraint 63 | cpVect grv_a 64 | cpVect grv_b 65 | cpVect anchr2 66 | 67 | ctypedef struct cpGearJoint: 68 | cpConstraint constraint 69 | cpFloat phase 70 | cpFloat ratio 71 | 72 | cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, 73 | cpVect anchr2) 74 | cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot) 75 | cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, 76 | cpVect anchr2) 77 | cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, 78 | cpVect anchr2, cpFloat min, cpFloat max) 79 | cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, 80 | cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping) 81 | cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, 82 | cpFloat restAngle, cpFloat stiffness, cpFloat damping) 83 | cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, 84 | cpFloat min, cpFloat max) 85 | cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, 86 | cpVect groove_b, cpVect anchr2) 87 | cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, 88 | cpFloat ratio) 89 | 90 | cdef class Constraint: 91 | cdef cpConstraint *_constraint 92 | cdef object _a 93 | cdef object _b 94 | cdef int automanaged 95 | 96 | cdef class GrooveJoint(Constraint): 97 | cdef cpGrooveJoint *_groovejoint 98 | cdef tuple groove_b 99 | cdef tuple groove_a 100 | cdef tuple anchor2 101 | 102 | cdef class PinJoint(Constraint): 103 | cdef cpPinJoint *_pinjoint 104 | cdef tuple anchor1 105 | cdef tuple anchor2 106 | 107 | cdef class PivotJoint(Constraint): 108 | cdef cpPivotJoint *_pivotjoint 109 | cdef tuple anchor1 110 | cdef tuple anchor2 111 | 112 | cdef class SlideJoint(Constraint): 113 | cdef cpSlideJoint *_slidejoint 114 | cdef tuple anchor1 115 | cdef tuple anchor2 116 | cdef float min 117 | cdef float max 118 | 119 | cdef class DampedSpring(Constraint): 120 | cdef cpDampedSpring *_dampedspring 121 | cdef tuple anchor1 122 | cdef tuple anchor2 123 | cdef float rest_length 124 | cdef float stiffness 125 | cdef float damping 126 | 127 | cdef class DampedRotarySpring(Constraint): 128 | cdef cpDampedRotarySpring *_dampedspring 129 | cdef float rest_angle 130 | cdef float stiffness 131 | cdef float damping 132 | 133 | cdef class RotaryLimitJoint(Constraint): 134 | cdef cpRotaryLimitJoint *_rotaryLimitJoint 135 | cdef float min 136 | cdef float max 137 | 138 | cdef class GearJoint(Constraint): 139 | cdef cpGearJoint *_gearjoint 140 | cdef float phase 141 | cdef float ratio -------------------------------------------------------------------------------- /cymunk/chipmunk/cpBB.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpBBB cpBB 23 | /// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines. 24 | /// @{ 25 | 26 | /// Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top) 27 | typedef struct cpBB{ 28 | cpFloat l, b, r ,t; 29 | } cpBB; 30 | 31 | /// Convenience constructor for cpBB structs. 32 | static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) 33 | { 34 | cpBB bb = {l, b, r, t}; 35 | return bb; 36 | } 37 | 38 | /// Constructs a cpBB for a circle with the given position and radius. 39 | static inline cpBB cpBBNewForCircle(const cpVect p, const cpFloat r) 40 | { 41 | return cpBBNew(p.x - r, p.y - r, p.x + r, p.y + r); 42 | } 43 | 44 | /// Returns true if @c a and @c b intersect. 45 | static inline cpBool cpBBIntersects(const cpBB a, const cpBB b) 46 | { 47 | return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t); 48 | } 49 | 50 | /// Returns true if @c other lies completely within @c bb. 51 | static inline cpBool cpBBContainsBB(const cpBB bb, const cpBB other) 52 | { 53 | return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t); 54 | } 55 | 56 | /// Returns true if @c bb contains @c v. 57 | static inline cpBool cpBBContainsVect(const cpBB bb, const cpVect v) 58 | { 59 | return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y); 60 | } 61 | 62 | /// Returns a bounding box that holds both bounding boxes. 63 | static inline cpBB cpBBMerge(const cpBB a, const cpBB b){ 64 | return cpBBNew( 65 | cpfmin(a.l, b.l), 66 | cpfmin(a.b, b.b), 67 | cpfmax(a.r, b.r), 68 | cpfmax(a.t, b.t) 69 | ); 70 | } 71 | 72 | /// Returns a bounding box that holds both @c bb and @c v. 73 | static inline cpBB cpBBExpand(const cpBB bb, const cpVect v){ 74 | return cpBBNew( 75 | cpfmin(bb.l, v.x), 76 | cpfmin(bb.b, v.y), 77 | cpfmax(bb.r, v.x), 78 | cpfmax(bb.t, v.y) 79 | ); 80 | } 81 | 82 | /// Returns the center of a bounding box. 83 | static inline cpVect 84 | cpBBCenter(cpBB bb) 85 | { 86 | return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f); 87 | } 88 | 89 | /// Returns the area of the bounding box. 90 | static inline cpFloat cpBBArea(cpBB bb) 91 | { 92 | return (bb.r - bb.l)*(bb.t - bb.b); 93 | } 94 | 95 | /// Merges @c a and @c b and returns the area of the merged bounding box. 96 | static inline cpFloat cpBBMergedArea(cpBB a, cpBB b) 97 | { 98 | return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b)); 99 | } 100 | 101 | /// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit. 102 | static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b) 103 | { 104 | cpFloat idx = 1.0f/(b.x - a.x); 105 | cpFloat tx1 = (bb.l == a.x ? -INFINITY : (bb.l - a.x)*idx); 106 | cpFloat tx2 = (bb.r == a.x ? INFINITY : (bb.r - a.x)*idx); 107 | cpFloat txmin = cpfmin(tx1, tx2); 108 | cpFloat txmax = cpfmax(tx1, tx2); 109 | 110 | cpFloat idy = 1.0f/(b.y - a.y); 111 | cpFloat ty1 = (bb.b == a.y ? -INFINITY : (bb.b - a.y)*idy); 112 | cpFloat ty2 = (bb.t == a.y ? INFINITY : (bb.t - a.y)*idy); 113 | cpFloat tymin = cpfmin(ty1, ty2); 114 | cpFloat tymax = cpfmax(ty1, ty2); 115 | 116 | if(tymin <= txmax && txmin <= tymax){ 117 | cpFloat min = cpfmax(txmin, tymin); 118 | cpFloat max = cpfmin(txmax, tymax); 119 | 120 | if(0.0 <= max && min <= 1.0) return cpfmax(min, 0.0); 121 | } 122 | 123 | return INFINITY; 124 | } 125 | 126 | /// Return true if the bounding box intersects the line segment with ends @c a and @c b. 127 | static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b) 128 | { 129 | return (cpBBSegmentQuery(bb, a, b) != INFINITY); 130 | } 131 | 132 | /// Clamp a vector to a bounding box. 133 | static inline cpVect 134 | cpBBClampVect(const cpBB bb, const cpVect v) 135 | { 136 | return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t)); 137 | } 138 | 139 | // TODO edge case issue 140 | /// Wrap a vector to a bounding box. 141 | cpVect cpBBWrapVect(const cpBB bb, const cpVect v); // wrap a vector to a bbox 142 | 143 | ///@} 144 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/cpBB.h: -------------------------------------------------------------------------------- 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 | /// @defgroup cpBBB cpBB 23 | /// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines. 24 | /// @{ 25 | 26 | /// Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top) 27 | typedef struct cpBB{ 28 | cpFloat l, b, r ,t; 29 | } cpBB; 30 | 31 | /// Convenience constructor for cpBB structs. 32 | static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) 33 | { 34 | cpBB bb = {l, b, r, t}; 35 | return bb; 36 | } 37 | 38 | /// Constructs a cpBB for a circle with the given position and radius. 39 | static inline cpBB cpBBNewForCircle(const cpVect p, const cpFloat r) 40 | { 41 | return cpBBNew(p.x - r, p.y - r, p.x + r, p.y + r); 42 | } 43 | 44 | /// Returns true if @c a and @c b intersect. 45 | static inline cpBool cpBBIntersects(const cpBB a, const cpBB b) 46 | { 47 | return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t); 48 | } 49 | 50 | /// Returns true if @c other lies completely within @c bb. 51 | static inline cpBool cpBBContainsBB(const cpBB bb, const cpBB other) 52 | { 53 | return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t); 54 | } 55 | 56 | /// Returns true if @c bb contains @c v. 57 | static inline cpBool cpBBContainsVect(const cpBB bb, const cpVect v) 58 | { 59 | return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y); 60 | } 61 | 62 | /// Returns a bounding box that holds both bounding boxes. 63 | static inline cpBB cpBBMerge(const cpBB a, const cpBB b){ 64 | return cpBBNew( 65 | cpfmin(a.l, b.l), 66 | cpfmin(a.b, b.b), 67 | cpfmax(a.r, b.r), 68 | cpfmax(a.t, b.t) 69 | ); 70 | } 71 | 72 | /// Returns a bounding box that holds both @c bb and @c v. 73 | static inline cpBB cpBBExpand(const cpBB bb, const cpVect v){ 74 | return cpBBNew( 75 | cpfmin(bb.l, v.x), 76 | cpfmin(bb.b, v.y), 77 | cpfmax(bb.r, v.x), 78 | cpfmax(bb.t, v.y) 79 | ); 80 | } 81 | 82 | /// Returns the center of a bounding box. 83 | static inline cpVect 84 | cpBBCenter(cpBB bb) 85 | { 86 | return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f); 87 | } 88 | 89 | /// Returns the area of the bounding box. 90 | static inline cpFloat cpBBArea(cpBB bb) 91 | { 92 | return (bb.r - bb.l)*(bb.t - bb.b); 93 | } 94 | 95 | /// Merges @c a and @c b and returns the area of the merged bounding box. 96 | static inline cpFloat cpBBMergedArea(cpBB a, cpBB b) 97 | { 98 | return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b)); 99 | } 100 | 101 | /// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit. 102 | static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b) 103 | { 104 | cpFloat idx = 1.0f/(b.x - a.x); 105 | cpFloat tx1 = (bb.l == a.x ? -INFINITY : (bb.l - a.x)*idx); 106 | cpFloat tx2 = (bb.r == a.x ? INFINITY : (bb.r - a.x)*idx); 107 | cpFloat txmin = cpfmin(tx1, tx2); 108 | cpFloat txmax = cpfmax(tx1, tx2); 109 | 110 | cpFloat idy = 1.0f/(b.y - a.y); 111 | cpFloat ty1 = (bb.b == a.y ? -INFINITY : (bb.b - a.y)*idy); 112 | cpFloat ty2 = (bb.t == a.y ? INFINITY : (bb.t - a.y)*idy); 113 | cpFloat tymin = cpfmin(ty1, ty2); 114 | cpFloat tymax = cpfmax(ty1, ty2); 115 | 116 | if(tymin <= txmax && txmin <= tymax){ 117 | cpFloat min = cpfmax(txmin, tymin); 118 | cpFloat max = cpfmin(txmax, tymax); 119 | 120 | if(0.0 <= max && min <= 1.0) return cpfmax(min, 0.0); 121 | } 122 | 123 | return INFINITY; 124 | } 125 | 126 | /// Return true if the bounding box intersects the line segment with ends @c a and @c b. 127 | static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b) 128 | { 129 | return (cpBBSegmentQuery(bb, a, b) != INFINITY); 130 | } 131 | 132 | /// Clamp a vector to a bounding box. 133 | static inline cpVect 134 | cpBBClampVect(const cpBB bb, const cpVect v) 135 | { 136 | return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t)); 137 | } 138 | 139 | // TODO edge case issue 140 | /// Wrap a vector to a bounding box. 141 | cpVect cpBBWrapVect(const cpBB bb, const cpVect v); // wrap a vector to a bbox 142 | 143 | ///@} 144 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/README.textile: -------------------------------------------------------------------------------- 1 | !http://files.slembcke.net/chipmunk/logo/logo1_med.png! 2 | 3 | h2. ABOUT: 4 | 5 | Chipmunk2D is a simple, lightweight, fast and portable 2D rigid body physics library written in C. It's licensed under the unrestrictive, OSI approved MIT license. My aim is to give 2D developers access to the same quality of physics you find in newer 3D games. I hope you enjoy using Chipmunk2D, and please consider donating to help make it worth our time to continue to support Chipmunk2D with great new features. 6 | 7 | h2. FEATURES: 8 | 9 | * Designed specifically for 2D video games. 10 | * Circle, convex polygon, and beveled line segment collision primitives. 11 | * Multiple collision primitives can be attached to a single rigid body. 12 | * Fast broad phase collision detection by using a bounding box tree with great temporal coherence or a spatial hash. 13 | * Extremely fast impulse solving by utilizing Erin Catto's contact persistence algorithm. 14 | * Supports sleeping objects that have come to rest to reduce the CPU load. 15 | * Support for collision event callbacks based on user definable object types types. 16 | * Flexible collision filtering system with layers, exclusion groups and callbacks. 17 | ** Can be used to create all sorts of effects like one way platforms or buoyancy areas. (Examples included) 18 | * Supports nearest point, segment (raycasting), shape and bounding box queries to the collision detection system. 19 | * Collision impulses amounts can be retrieved for gameplay effects, sound effects, etc. 20 | * Large variety of joints - easily make vehicles, ragdolls, and more. 21 | * Joint callbacks. 22 | ** Can be used to easily implement breakable or animated joints. (Examples included) 23 | * Maintains a contact graph of all colliding objects. 24 | * Lightweight C99 implementation with no external dependencies outside of the Std. C library. 25 | * "Many language bindings available":http://chipmunk2d.net/bindingsAndPorts.php. 26 | * Simple, read the "documentation":http://chipmunk2d.net/documentation.php and see! 27 | * Unrestrictive MIT license 28 | 29 | 30 | h2. CHIPMUNK PRO: 31 | 32 | We also make a bunch of extra for Chipmunk called "Chipmunk Pro":http://chipmunk2d.net/chipmunkPro.php. Currently we have a nice Objective-C wrapper that should be of particular interest to Mac and iPhone developers. It also offers auto-geometry features and multithreading/SIMD optimizations as well. Check out the link above for more information! 33 | 34 | 35 | h2. CONTRACTING: 36 | 37 | Howling Moon Software (my company) is available for contracting if you want to make the physics in your game really stand out. Given our unique experience with the library, we can help you use Chipmunk to it's fullest potential. Feel free to contact us through our webpage: http://howlingmoonsoftware.com/contracting.php 38 | 39 | 40 | h2. BUILDING: 41 | 42 | Mac OS X: There is an included XCode project file for building the static library and demo application. Alternatively you could use the CMake files or the macstatic.command script to build a static lib and package up the headers for you. 43 | 44 | iPhone: If you want a native Objective-C API, check out Chipmunk Pro on the Chipmunk website. It is inexpensive to license and will save you a lot of time. Otherwise, the XCode project can build a static library with all the proper compiler settings. Alternatively, you can just run iphonestatic.command in the macosx/ directory. It will build you a fat library compiled as release for the device and debug for the simulator. After running it, you can simply drop the Chipmunk-iPhone directory into your iPhone project! 45 | 46 | UNIXes: A forum user was kind enough to make a set of CMake files for Chipmunk. This will require you to have CMake installed. To build run 'cmake .' then 'make'. This should build a dynamic library, a static library, and the demo application. A number of people have had build errors on Ubuntu due to not having GLUT or libxmu installed. 47 | 48 | Windows: Visual Studio projects are included in the msvc/ directory. While I try to make sure the MSVC 10 project is up to date, I don't have MSVC 9 to keep that project updated regularly. It may not work. I'd appreciate a hand fixing it if that's the case. 49 | 50 | 51 | h2. GET UP TO DATE: 52 | 53 | If you got the source from a point release download, you might want to consider getting the latest source from GitHub. Bugs are fixed and new features are added regularly. Big changes are done in branches and tested before merging them in it's rare for the point release downloads to be better or more bug free than the latest code. 54 | 55 | Head on over to "GitHub":https://github.com/slembcke/Chipmunk2D and experience the future TODAY! (Okay, so maybe it's not that exciting.) 56 | 57 | 58 | h2. GETTING STARTED: 59 | 60 | First of all, you can find the C API documentation in the doc/ directory. 61 | 62 | A good starting point is to take a look at the included Demo application. The demos all just set up a Chipmunk simulation space and the demo app draws the graphics directly out of that. This makes it easy to see how the Chipmunk API works without worrying about the graphics code. You are free to use the demo drawing routines in your own projects, though it is certainly not the recommended way of drawing Chipmunk objects as it pokes around at the undocumented/private APIs of Chipmunk. 63 | 64 | 65 | h2. SUPPORT: 66 | 67 | The best way to get support is to visit the "Chipmunk Forums":http://chipmunk2d.net/forum/. There are plenty of people around using Chipmunk on the just about every platform I've ever heard of. If you are working on a commercial project and want some more direct help, Howling Moon Software is also available for "contracting":http://howlingmoonsoftware.com/contracting.php. 68 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/src/constraints/cpGrooveJoint.c: -------------------------------------------------------------------------------- 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 | #include "chipmunk_private.h" 23 | #include "constraints/util.h" 24 | 25 | static void 26 | preStep(cpGrooveJoint *joint, cpFloat dt) 27 | { 28 | cpBody *a = joint->constraint.a; 29 | cpBody *b = joint->constraint.b; 30 | 31 | // calculate endpoints in worldspace 32 | cpVect ta = cpBodyLocal2World(a, joint->grv_a); 33 | cpVect tb = cpBodyLocal2World(a, joint->grv_b); 34 | 35 | // calculate axis 36 | cpVect n = cpvrotate(joint->grv_n, a->rot); 37 | cpFloat d = cpvdot(ta, n); 38 | 39 | joint->grv_tn = n; 40 | joint->r2 = cpvrotate(joint->anchr2, b->rot); 41 | 42 | // calculate tangential distance along the axis of r2 43 | cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n); 44 | // calculate clamping factor and r2 45 | if(td <= cpvcross(ta, n)){ 46 | joint->clamp = 1.0f; 47 | joint->r1 = cpvsub(ta, a->p); 48 | } else if(td >= cpvcross(tb, n)){ 49 | joint->clamp = -1.0f; 50 | joint->r1 = cpvsub(tb, a->p); 51 | } else { 52 | joint->clamp = 0.0f; 53 | joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p); 54 | } 55 | 56 | // Calculate mass tensor 57 | joint->k = k_tensor(a, b, joint->r1, joint->r2); 58 | 59 | // calculate bias velocity 60 | cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); 61 | joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias); 62 | } 63 | 64 | static void 65 | applyCachedImpulse(cpGrooveJoint *joint, cpFloat dt_coef) 66 | { 67 | cpBody *a = joint->constraint.a; 68 | cpBody *b = joint->constraint.b; 69 | 70 | apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef)); 71 | } 72 | 73 | static inline cpVect 74 | grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){ 75 | cpVect n = joint->grv_tn; 76 | cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n); 77 | return cpvclamp(jClamp, joint->constraint.maxForce*dt); 78 | } 79 | 80 | static void 81 | applyImpulse(cpGrooveJoint *joint, cpFloat dt) 82 | { 83 | cpBody *a = joint->constraint.a; 84 | cpBody *b = joint->constraint.b; 85 | 86 | cpVect r1 = joint->r1; 87 | cpVect r2 = joint->r2; 88 | 89 | // compute impulse 90 | cpVect vr = relative_velocity(a, b, r1, r2); 91 | 92 | cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr)); 93 | cpVect jOld = joint->jAcc; 94 | joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt); 95 | j = cpvsub(joint->jAcc, jOld); 96 | 97 | // apply impulse 98 | apply_impulses(a, b, joint->r1, joint->r2, j); 99 | } 100 | 101 | static cpFloat 102 | getImpulse(cpGrooveJoint *joint) 103 | { 104 | return cpvlength(joint->jAcc); 105 | } 106 | 107 | static const cpConstraintClass klass = { 108 | (cpConstraintPreStepImpl)preStep, 109 | (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, 110 | (cpConstraintApplyImpulseImpl)applyImpulse, 111 | (cpConstraintGetImpulseImpl)getImpulse, 112 | }; 113 | CP_DefineClassGetter(cpGrooveJoint) 114 | 115 | cpGrooveJoint * 116 | cpGrooveJointAlloc(void) 117 | { 118 | return (cpGrooveJoint *)cpcalloc(1, sizeof(cpGrooveJoint)); 119 | } 120 | 121 | cpGrooveJoint * 122 | cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2) 123 | { 124 | cpConstraintInit((cpConstraint *)joint, &klass, a, b); 125 | 126 | joint->grv_a = groove_a; 127 | joint->grv_b = groove_b; 128 | joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a))); 129 | joint->anchr2 = anchr2; 130 | 131 | joint->jAcc = cpvzero; 132 | 133 | return joint; 134 | } 135 | 136 | cpConstraint * 137 | cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2) 138 | { 139 | return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2); 140 | } 141 | 142 | void 143 | cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value) 144 | { 145 | cpGrooveJoint *g = (cpGrooveJoint *)constraint; 146 | cpConstraintCheckCast(constraint, cpGrooveJoint); 147 | 148 | g->grv_a = value; 149 | g->grv_n = cpvperp(cpvnormalize(cpvsub(g->grv_b, value))); 150 | 151 | cpConstraintActivateBodies(constraint); 152 | } 153 | 154 | void 155 | cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value) 156 | { 157 | cpGrooveJoint *g = (cpGrooveJoint *)constraint; 158 | cpConstraintCheckCast(constraint, cpGrooveJoint); 159 | 160 | g->grv_b = value; 161 | g->grv_n = cpvperp(cpvnormalize(cpvsub(value, g->grv_a))); 162 | 163 | cpConstraintActivateBodies(constraint); 164 | } 165 | 166 | -------------------------------------------------------------------------------- /cymunk/chipmunk/chipmunk_types.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __APPLE__ 5 | #include "TargetConditionals.h" 6 | #endif 7 | 8 | #if ((TARGET_OS_IPHONE == 1) || (TARGET_OS_MAC == 1)) && (!defined CP_USE_CGPOINTS) 9 | #define CP_USE_CGPOINTS 1 10 | #endif 11 | 12 | #if CP_USE_CGPOINTS == 1 13 | #if TARGET_OS_IPHONE 14 | #import 15 | #elif TARGET_OS_MAC 16 | #include 17 | #endif 18 | 19 | #if defined(__LP64__) && __LP64__ 20 | #define CP_USE_DOUBLES 1 21 | #else 22 | #define CP_USE_DOUBLES 0 23 | #endif 24 | #endif 25 | 26 | #ifndef CP_USE_DOUBLES 27 | // use doubles by default for higher precision 28 | #define CP_USE_DOUBLES 1 29 | #endif 30 | 31 | /// @defgroup basicTypes Basic Types 32 | /// Most of these types can be configured at compile time. 33 | /// @{ 34 | 35 | #if CP_USE_DOUBLES 36 | /// Chipmunk's floating point type. 37 | /// Can be reconfigured at compile time. 38 | typedef double cpFloat; 39 | #define cpfsqrt sqrt 40 | #define cpfsin sin 41 | #define cpfcos cos 42 | #define cpfacos acos 43 | #define cpfatan2 atan2 44 | #define cpfmod fmod 45 | #define cpfexp exp 46 | #define cpfpow pow 47 | #define cpffloor floor 48 | #define cpfceil ceil 49 | #define CPFLOAT_MIN DBL_MIN 50 | #else 51 | typedef float cpFloat; 52 | #define cpfsqrt sqrtf 53 | #define cpfsin sinf 54 | #define cpfcos cosf 55 | #define cpfacos acosf 56 | #define cpfatan2 atan2f 57 | #define cpfmod fmodf 58 | #define cpfexp expf 59 | #define cpfpow powf 60 | #define cpffloor floorf 61 | #define cpfceil ceilf 62 | #define CPFLOAT_MIN FLT_MIN 63 | #endif 64 | 65 | #ifndef INFINITY 66 | #ifdef _MSC_VER 67 | union MSVC_EVIL_FLOAT_HACK 68 | { 69 | unsigned __int8 Bytes[4]; 70 | float Value; 71 | }; 72 | static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; 73 | #define INFINITY (INFINITY_HACK.Value) 74 | #endif 75 | 76 | #ifdef __GNUC__ 77 | #define INFINITY (__builtin_inf()) 78 | #endif 79 | 80 | #ifndef INFINITY 81 | #define INFINITY (1e1000) 82 | #endif 83 | #endif 84 | 85 | #ifndef M_PI 86 | #define M_PI 3.14159265358979323846264338327950288 87 | #endif 88 | 89 | #ifndef M_E 90 | #define M_E 2.71828182845904523536028747135266250 91 | #endif 92 | 93 | 94 | /// Return the max of two cpFloats. 95 | static inline cpFloat cpfmax(cpFloat a, cpFloat b) 96 | { 97 | return (a > b) ? a : b; 98 | } 99 | 100 | /// Return the min of two cpFloats. 101 | static inline cpFloat cpfmin(cpFloat a, cpFloat b) 102 | { 103 | return (a < b) ? a : b; 104 | } 105 | 106 | /// Return the absolute value of a cpFloat. 107 | static inline cpFloat cpfabs(cpFloat f) 108 | { 109 | return (f < 0) ? -f : f; 110 | } 111 | 112 | /// Clamp @c f to be between @c min and @c max. 113 | static inline cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max) 114 | { 115 | return cpfmin(cpfmax(f, min), max); 116 | } 117 | 118 | /// Clamp @c f to be between 0 and 1. 119 | static inline cpFloat cpfclamp01(cpFloat f) 120 | { 121 | return cpfmax(0.0f, cpfmin(f, 1.0f)); 122 | } 123 | 124 | 125 | 126 | /// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent. 127 | static inline 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 inline cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d) 134 | { 135 | return f1 + cpfclamp(f2 - f1, -d, d); 136 | } 137 | 138 | /// Hash value type. 139 | typedef uintptr_t cpHashValue; 140 | 141 | /// Type used internally to cache colliding object info for cpCollideShapes(). 142 | /// Should be at least 32 bits. 143 | typedef uint32_t cpCollisionID; 144 | 145 | // Oh C, how we love to define our own boolean types to get compiler compatibility 146 | /// Chipmunk's boolean type. 147 | #ifdef CP_BOOL_TYPE 148 | typedef CP_BOOL_TYPE cpBool; 149 | #else 150 | typedef int cpBool; 151 | #endif 152 | 153 | #ifndef cpTrue 154 | /// true value. 155 | #define cpTrue 1 156 | #endif 157 | 158 | #ifndef cpFalse 159 | /// false value. 160 | #define cpFalse 0 161 | #endif 162 | 163 | #ifdef CP_DATA_POINTER_TYPE 164 | typedef CP_DATA_POINTER_TYPE cpDataPointer; 165 | #else 166 | /// Type used for user data pointers. 167 | typedef void * cpDataPointer; 168 | #endif 169 | 170 | #ifdef CP_COLLISION_TYPE_TYPE 171 | typedef CP_COLLISION_TYPE_TYPE cpCollisionType; 172 | #else 173 | /// Type used for cpSpace.collision_type. 174 | typedef uintptr_t cpCollisionType; 175 | #endif 176 | 177 | #ifdef CP_GROUP_TYPE 178 | typedef CP_GROUP_TYPE cpGroup; 179 | #else 180 | /// Type used for cpShape.group. 181 | typedef uintptr_t cpGroup; 182 | #endif 183 | 184 | #ifdef CP_LAYERS_TYPE 185 | typedef CP_LAYERS_TYPE cpLayers; 186 | #else 187 | /// Type used for cpShape.layers. 188 | typedef unsigned int cpLayers; 189 | #endif 190 | 191 | #ifdef CP_TIMESTAMP_TYPE 192 | typedef CP_TIMESTAMP_TYPE cpTimestamp; 193 | #else 194 | /// Type used for various timestamps in Chipmunk. 195 | typedef unsigned int cpTimestamp; 196 | #endif 197 | 198 | #ifndef CP_NO_GROUP 199 | /// Value for cpShape.group signifying that a shape is in no group. 200 | #define CP_NO_GROUP ((cpGroup)0) 201 | #endif 202 | 203 | #ifndef CP_ALL_LAYERS 204 | /// Value for cpShape.layers signifying that a shape is in every layer. 205 | #define CP_ALL_LAYERS (~(cpLayers)0) 206 | #endif 207 | /// @} 208 | 209 | // CGPoints are structurally the same, and allow 210 | // easy interoperability with other Cocoa libraries 211 | #if CP_USE_CGPOINTS 212 | typedef CGPoint cpVect; 213 | #else 214 | /// Chipmunk's 2D vector type. 215 | /// @addtogroup cpVect 216 | typedef struct cpVect{cpFloat x,y;} cpVect; 217 | #endif 218 | 219 | typedef struct cpMat2x2 { 220 | // Row major [[a, b][c d]] 221 | cpFloat a, b, c, d; 222 | } cpMat2x2; 223 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/chipmunk_types.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __APPLE__ 5 | #include "TargetConditionals.h" 6 | #endif 7 | 8 | #if ((TARGET_OS_IPHONE == 1) || (TARGET_OS_MAC == 1)) && (!defined CP_USE_CGPOINTS) 9 | #define CP_USE_CGPOINTS 1 10 | #endif 11 | 12 | #if CP_USE_CGPOINTS == 1 13 | #if TARGET_OS_IPHONE 14 | #import 15 | #elif TARGET_OS_MAC 16 | #include 17 | #endif 18 | 19 | #if defined(__LP64__) && __LP64__ 20 | #define CP_USE_DOUBLES 1 21 | #else 22 | #define CP_USE_DOUBLES 0 23 | #endif 24 | #endif 25 | 26 | #ifndef CP_USE_DOUBLES 27 | // use doubles by default for higher precision 28 | #define CP_USE_DOUBLES 1 29 | #endif 30 | 31 | /// @defgroup basicTypes Basic Types 32 | /// Most of these types can be configured at compile time. 33 | /// @{ 34 | 35 | #if CP_USE_DOUBLES 36 | /// Chipmunk's floating point type. 37 | /// Can be reconfigured at compile time. 38 | typedef double cpFloat; 39 | #define cpfsqrt sqrt 40 | #define cpfsin sin 41 | #define cpfcos cos 42 | #define cpfacos acos 43 | #define cpfatan2 atan2 44 | #define cpfmod fmod 45 | #define cpfexp exp 46 | #define cpfpow pow 47 | #define cpffloor floor 48 | #define cpfceil ceil 49 | #define CPFLOAT_MIN DBL_MIN 50 | #else 51 | typedef float cpFloat; 52 | #define cpfsqrt sqrtf 53 | #define cpfsin sinf 54 | #define cpfcos cosf 55 | #define cpfacos acosf 56 | #define cpfatan2 atan2f 57 | #define cpfmod fmodf 58 | #define cpfexp expf 59 | #define cpfpow powf 60 | #define cpffloor floorf 61 | #define cpfceil ceilf 62 | #define CPFLOAT_MIN FLT_MIN 63 | #endif 64 | 65 | #ifndef INFINITY 66 | #ifdef _MSC_VER 67 | union MSVC_EVIL_FLOAT_HACK 68 | { 69 | unsigned __int8 Bytes[4]; 70 | float Value; 71 | }; 72 | static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; 73 | #define INFINITY (INFINITY_HACK.Value) 74 | #endif 75 | 76 | #ifdef __GNUC__ 77 | #define INFINITY (__builtin_inf()) 78 | #endif 79 | 80 | #ifndef INFINITY 81 | #define INFINITY (1e1000) 82 | #endif 83 | #endif 84 | 85 | #ifndef M_PI 86 | #define M_PI 3.14159265358979323846264338327950288 87 | #endif 88 | 89 | #ifndef M_E 90 | #define M_E 2.71828182845904523536028747135266250 91 | #endif 92 | 93 | 94 | /// Return the max of two cpFloats. 95 | static inline cpFloat cpfmax(cpFloat a, cpFloat b) 96 | { 97 | return (a > b) ? a : b; 98 | } 99 | 100 | /// Return the min of two cpFloats. 101 | static inline cpFloat cpfmin(cpFloat a, cpFloat b) 102 | { 103 | return (a < b) ? a : b; 104 | } 105 | 106 | /// Return the absolute value of a cpFloat. 107 | static inline cpFloat cpfabs(cpFloat f) 108 | { 109 | return (f < 0) ? -f : f; 110 | } 111 | 112 | /// Clamp @c f to be between @c min and @c max. 113 | static inline cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max) 114 | { 115 | return cpfmin(cpfmax(f, min), max); 116 | } 117 | 118 | /// Clamp @c f to be between 0 and 1. 119 | static inline cpFloat cpfclamp01(cpFloat f) 120 | { 121 | return cpfmax(0.0f, cpfmin(f, 1.0f)); 122 | } 123 | 124 | 125 | 126 | /// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent. 127 | static inline 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 inline cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d) 134 | { 135 | return f1 + cpfclamp(f2 - f1, -d, d); 136 | } 137 | 138 | /// Hash value type. 139 | typedef uintptr_t cpHashValue; 140 | 141 | /// Type used internally to cache colliding object info for cpCollideShapes(). 142 | /// Should be at least 32 bits. 143 | typedef uint32_t cpCollisionID; 144 | 145 | // Oh C, how we love to define our own boolean types to get compiler compatibility 146 | /// Chipmunk's boolean type. 147 | #ifdef CP_BOOL_TYPE 148 | typedef CP_BOOL_TYPE cpBool; 149 | #else 150 | typedef int cpBool; 151 | #endif 152 | 153 | #ifndef cpTrue 154 | /// true value. 155 | #define cpTrue 1 156 | #endif 157 | 158 | #ifndef cpFalse 159 | /// false value. 160 | #define cpFalse 0 161 | #endif 162 | 163 | #ifdef CP_DATA_POINTER_TYPE 164 | typedef CP_DATA_POINTER_TYPE cpDataPointer; 165 | #else 166 | /// Type used for user data pointers. 167 | typedef void * cpDataPointer; 168 | #endif 169 | 170 | #ifdef CP_COLLISION_TYPE_TYPE 171 | typedef CP_COLLISION_TYPE_TYPE cpCollisionType; 172 | #else 173 | /// Type used for cpSpace.collision_type. 174 | typedef uintptr_t cpCollisionType; 175 | #endif 176 | 177 | #ifdef CP_GROUP_TYPE 178 | typedef CP_GROUP_TYPE cpGroup; 179 | #else 180 | /// Type used for cpShape.group. 181 | typedef uintptr_t cpGroup; 182 | #endif 183 | 184 | #ifdef CP_LAYERS_TYPE 185 | typedef CP_LAYERS_TYPE cpLayers; 186 | #else 187 | /// Type used for cpShape.layers. 188 | typedef unsigned int cpLayers; 189 | #endif 190 | 191 | #ifdef CP_TIMESTAMP_TYPE 192 | typedef CP_TIMESTAMP_TYPE cpTimestamp; 193 | #else 194 | /// Type used for various timestamps in Chipmunk. 195 | typedef unsigned int cpTimestamp; 196 | #endif 197 | 198 | #ifndef CP_NO_GROUP 199 | /// Value for cpShape.group signifying that a shape is in no group. 200 | #define CP_NO_GROUP ((cpGroup)0) 201 | #endif 202 | 203 | #ifndef CP_ALL_LAYERS 204 | /// Value for cpShape.layers signifying that a shape is in every layer. 205 | #define CP_ALL_LAYERS (~(cpLayers)0) 206 | #endif 207 | /// @} 208 | 209 | // CGPoints are structurally the same, and allow 210 | // easy interoperability with other Cocoa libraries 211 | #if CP_USE_CGPOINTS 212 | typedef CGPoint cpVect; 213 | #else 214 | /// Chipmunk's 2D vector type. 215 | /// @addtogroup cpVect 216 | typedef struct cpVect{cpFloat x,y;} cpVect; 217 | #endif 218 | 219 | typedef struct cpMat2x2 { 220 | // Row major [[a, b][c d]] 221 | cpFloat a, b, c, d; 222 | } cpMat2x2; 223 | -------------------------------------------------------------------------------- /examples/spiderweb.py: -------------------------------------------------------------------------------- 1 | """Showcase of a elastic spiderweb (drawing with pyglet) 2 | 3 | It is possible to grab one of the crossings with the mouse 4 | """ 5 | 6 | __version__ = "$Id:$" 7 | __docformat__ = "reStructuredText" 8 | 9 | import math, random 10 | 11 | import pyglet 12 | 13 | import cymunk as pymunk 14 | from cymunk import Vec2d 15 | from pyglet_util import draw 16 | 17 | config = pyglet.gl.Config(sample_buffers=1, samples=2, double_buffer=True) 18 | window = pyglet.window.Window(config=config, vsync = False) 19 | space = pymunk.Space() 20 | 21 | space.gravity = 0,-900 22 | space.damping = .999 23 | c = Vec2d(window.width /2., window.height / 2.) 24 | 25 | ### CONTAINER 26 | ss = [ 27 | pymunk.Segment(space.static_body, (0,0), (window.width,0),5) 28 | ,pymunk.Segment(space.static_body, (window.width,0), (window.width,window.height),5) 29 | ,pymunk.Segment(space.static_body, (window.width,window.height), (0,window.height),5) 30 | ,pymunk.Segment(space.static_body, (0,window.height), (0,0),5) 31 | ] 32 | 33 | for s in ss: 34 | s.friction = .5 35 | s.layers = s.layers ^ 0b100 36 | 37 | space.add(ss) 38 | 39 | 40 | ### WEB 41 | web_group = 1 42 | web_collision_type = 1 43 | web_layers = 0b101 44 | bs = [] 45 | dist = .3 46 | 47 | cb = pymunk.Body(1,1) 48 | cb.position = c 49 | s = pymunk.Circle(cb, 15) # to have something to grab 50 | s.group = web_group 51 | s.layers = web_layers 52 | s.collision_type = web_collision_type 53 | #s.ignore_draw = True 54 | space.add(cb, s) 55 | 56 | 57 | #generate each crossing in the net 58 | for x in range(0,101): 59 | b = pymunk.Body(1, 1) 60 | v = Vec2d.unit() 61 | v.angle_degrees = x*18 62 | scale = window.height / 2. / 6. * .5 63 | 64 | dist += 1/18. 65 | dist = dist ** 1.005 66 | 67 | offset = 0 68 | offset = [0.0, -0.80, -1.0, -0.80][((x*18) % 360)/18 % 4] 69 | offset = .8 + offset 70 | 71 | offset *= dist**2.8 / 100. 72 | 73 | #print "offset", offset 74 | 75 | v.length = scale * (dist + offset) 76 | 77 | b.position = c + v 78 | s = pymunk.Circle(b, 15) 79 | s.group = web_group 80 | s.layers = web_layers 81 | s.collision_type = web_collision_type 82 | #s.ignore_draw = True 83 | space.add(b,s) 84 | bs.append(b) 85 | 86 | def add_joint(a,b): 87 | rl = a.position.get_distance(b.position) * 0.9 88 | stiffness = 5000. 89 | damping = 100 90 | j = pymunk.DampedSpring(a, b, (0,0), (0,0), rl, stiffness, damping) 91 | j.max_bias = 1000 92 | #j.max_force = 50000 93 | space.add(j) 94 | 95 | for b in bs[:20]: 96 | add_joint(cb,b) 97 | 98 | for i in range(len(bs)-1): 99 | add_joint(bs[i], bs[i+1]) 100 | 101 | i2 = i+20 102 | if len(bs) > i2: 103 | add_joint(bs[i], bs[i2]) 104 | 105 | 106 | ### WEB ATTACH POINTS 107 | static_bs = [] 108 | for b in bs[-17::4]: 109 | static_body = pymunk.Body() 110 | static_body.position = b.position 111 | static_bs.append(static_body) 112 | 113 | j = pymunk.PivotJoint(static_body, b, static_body.position) 114 | j = pymunk.DampedSpring(static_body, b, (0,0), (0,0), 0, 0, 0) 115 | j.damping = 100 116 | j.stiffness = 20000 117 | space.add(j) 118 | 119 | ### ALL SETUP DONE 120 | 121 | def update(dt): 122 | # Note that we dont use dt as input into step. That is because the 123 | # simulation will behave much better if the step size doesnt change 124 | # between frames. 125 | r = 10 126 | for x in range(r): 127 | space.step(1./30./r) 128 | 129 | pyglet.clock.schedule_interval(update, 1/30.) 130 | 131 | selected = None 132 | selected_joint = None 133 | mouse_body = pymunk.Body() 134 | 135 | @window.event 136 | def on_mouse_press(x, y, button, modifiers): 137 | mouse_body.position = x,y 138 | hit = space.nearest_point_query_nearest(Vec2d(x,y),10) 139 | if hit != None: 140 | global selected 141 | body = hit.body 142 | rest_length = mouse_body.position.get_distance(body.position) 143 | stiffness = 1000 144 | damping = 10 145 | selected = pymunk.DampedSpring(mouse_body, body, (0,0), (0,0), rest_length, stiffness, damping) 146 | space.add(selected) 147 | 148 | @window.event 149 | def on_mouse_release(x, y, button, modifiers): 150 | global selected 151 | if selected != None: 152 | space.remove(selected) 153 | selected = None 154 | 155 | @window.event 156 | def on_mouse_drag(x, y, dx, dy, buttons, modifiers): 157 | mouse_body.position = x,y 158 | 159 | @window.event 160 | def on_key_press(symbol, modifiers): 161 | if symbol == pyglet.window.key.P: 162 | pyglet.image.get_buffer_manager().get_color_buffer().save('spiderweb.png') 163 | 164 | 165 | fps_display = pyglet.clock.ClockDisplay() 166 | 167 | @window.event 168 | def on_draw(): 169 | pyglet.gl.glClearColor(240,240,240,255) 170 | window.clear() 171 | 172 | fps_display.draw() 173 | 174 | # static attach points 175 | pyglet.gl.glColor3f(1,0,1) 176 | pyglet.gl.glPointSize(6) 177 | a = [] 178 | for b in static_bs: 179 | a += [b.position.x, b.position.y] 180 | pyglet.graphics.draw(len(a)/2, pyglet.gl.GL_POINTS, ('v2f',a)) 181 | 182 | # web crossings / bodies 183 | pyglet.gl.glColor3f(.8,.8,.8) 184 | a = [] 185 | for b in bs: 186 | a += [b.position.x, b.position.y] 187 | pyglet.gl.glPointSize(4) 188 | pyglet.graphics.draw(len(a)/2, pyglet.gl.GL_POINTS, ('v2f',a)) 189 | 190 | 191 | # web net / constraints 192 | a = [] 193 | for j in space.constraints: 194 | a += [j.a.position.x, j.a.position.y, j.b.position.x, j.b.position.y] 195 | pass 196 | 197 | pyglet.graphics.draw(len(a)/2, pyglet.gl.GL_LINES, ('v2f',a)) 198 | 199 | # anything else 200 | draw(space) 201 | 202 | pyglet.app.run() -------------------------------------------------------------------------------- /cymunk/chipmunk/chipmunk_ffi.h: -------------------------------------------------------------------------------- 1 | #ifdef CHIPMUNK_FFI 2 | 3 | // Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs 4 | // This file should only be included in chipmunk.c 5 | 6 | #ifdef _MSC_VER 7 | #if _MSC_VER >= 1600 8 | #define MAKE_REF(name) decltype(name) *_##name = name 9 | #else 10 | #define MAKE_REF(name) 11 | #endif 12 | #else 13 | #define MAKE_REF(name) __typeof__(name) *_##name = name 14 | #endif 15 | 16 | #define MAKE_PROPERTIES_REF(struct, property) \ 17 | MAKE_REF(struct##Get##property); MAKE_REF(struct##Set##property) 18 | 19 | MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv() 20 | MAKE_REF(cpveql); 21 | MAKE_REF(cpvadd); 22 | MAKE_REF(cpvneg); 23 | MAKE_REF(cpvsub); 24 | MAKE_REF(cpvmult); 25 | MAKE_REF(cpvdot); 26 | MAKE_REF(cpvcross); 27 | MAKE_REF(cpvperp); 28 | MAKE_REF(cpvrperp); 29 | MAKE_REF(cpvproject); 30 | MAKE_REF(cpvforangle); 31 | MAKE_REF(cpvtoangle); 32 | MAKE_REF(cpvrotate); 33 | MAKE_REF(cpvunrotate); 34 | MAKE_REF(cpvlengthsq); 35 | MAKE_REF(cpvlength); 36 | MAKE_REF(cpvlerp); 37 | MAKE_REF(cpvnormalize); 38 | MAKE_REF(cpvnormalize_safe); 39 | MAKE_REF(cpvclamp); 40 | MAKE_REF(cpvlerpconst); 41 | MAKE_REF(cpvdist); 42 | MAKE_REF(cpvdistsq); 43 | MAKE_REF(cpvnear); 44 | 45 | MAKE_REF(cpfmax); 46 | MAKE_REF(cpfmin); 47 | MAKE_REF(cpfabs); 48 | MAKE_REF(cpfclamp); 49 | MAKE_REF(cpflerp); 50 | MAKE_REF(cpflerpconst); 51 | 52 | MAKE_REF(cpBBNew); 53 | MAKE_REF(cpBBNewForCircle); 54 | MAKE_REF(cpBBIntersects); 55 | MAKE_REF(cpBBContainsBB); 56 | MAKE_REF(cpBBContainsVect); 57 | MAKE_REF(cpBBMerge); 58 | MAKE_REF(cpBBExpand); 59 | MAKE_REF(cpBBArea); 60 | MAKE_REF(cpBBMergedArea); 61 | MAKE_REF(cpBBSegmentQuery); 62 | MAKE_REF(cpBBIntersectsSegment); 63 | MAKE_REF(cpBBClampVect); 64 | 65 | MAKE_REF(cpBodyGetMass); 66 | MAKE_REF(cpBodyGetMoment); 67 | MAKE_REF(cpBodyGetPos); 68 | MAKE_REF(cpBodyGetAngle); 69 | MAKE_REF(cpBodyGetRot); 70 | MAKE_PROPERTIES_REF(cpBody, Vel); 71 | MAKE_PROPERTIES_REF(cpBody, Force); 72 | MAKE_PROPERTIES_REF(cpBody, AngVel); 73 | MAKE_PROPERTIES_REF(cpBody, Torque); 74 | MAKE_PROPERTIES_REF(cpBody, VelLimit); 75 | MAKE_PROPERTIES_REF(cpBody, AngVelLimit); 76 | MAKE_PROPERTIES_REF(cpBody, UserData); 77 | MAKE_REF(cpBodyIsSleeping); 78 | MAKE_REF(cpBodyIsStatic); 79 | MAKE_REF(cpBodyIsRogue); 80 | MAKE_REF(cpBodyLocal2World); 81 | MAKE_REF(cpBodyWorld2Local); 82 | MAKE_REF(cpBodyKineticEnergy); 83 | 84 | MAKE_REF(cpShapeGetBB); 85 | MAKE_PROPERTIES_REF(cpShape, Body); 86 | MAKE_PROPERTIES_REF(cpShape, Sensor); 87 | MAKE_PROPERTIES_REF(cpShape, Elasticity); 88 | MAKE_PROPERTIES_REF(cpShape, Friction); 89 | MAKE_PROPERTIES_REF(cpShape, SurfaceVelocity); 90 | MAKE_PROPERTIES_REF(cpShape, UserData); 91 | MAKE_PROPERTIES_REF(cpShape, CollisionType); 92 | MAKE_PROPERTIES_REF(cpShape, Group); 93 | MAKE_PROPERTIES_REF(cpShape, Layers); 94 | 95 | MAKE_REF(cpArbiterGetShapes); 96 | MAKE_REF(cpArbiterGetBodies); 97 | MAKE_REF(cpArbiterIsFirstContact); 98 | MAKE_REF(cpArbiterGetCount); 99 | 100 | MAKE_REF(cpConstraintGetA); 101 | MAKE_REF(cpConstraintGetB); 102 | MAKE_PROPERTIES_REF(cpConstraint, MaxForce); 103 | MAKE_PROPERTIES_REF(cpConstraint, ErrorBias); 104 | MAKE_PROPERTIES_REF(cpConstraint, MaxBias); 105 | MAKE_PROPERTIES_REF(cpConstraint, UserData); 106 | MAKE_REF(cpConstraintGetImpulse); 107 | 108 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, RestAngle); 109 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, Stiffness); 110 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, Damping); 111 | //MAKE_PROPERTIES_REF(cpDampedRotarySpring, SpringTorqueFunc); 112 | 113 | MAKE_PROPERTIES_REF(cpDampedSpring, Anchr1); 114 | MAKE_PROPERTIES_REF(cpDampedSpring, Anchr2); 115 | MAKE_PROPERTIES_REF(cpDampedSpring, RestLength); 116 | MAKE_PROPERTIES_REF(cpDampedSpring, Stiffness); 117 | MAKE_PROPERTIES_REF(cpDampedSpring, Damping); 118 | //MAKE_PROPERTIES_REF(cpDampedSpring, SpringForceFunc); 119 | 120 | MAKE_PROPERTIES_REF(cpGearJoint, Phase); 121 | MAKE_REF(cpGearJointGetRatio); 122 | 123 | MAKE_PROPERTIES_REF(cpGrooveJoint, Anchr2); 124 | MAKE_REF(cpGrooveJointGetGrooveA); 125 | MAKE_REF(cpGrooveJointGetGrooveB); 126 | 127 | MAKE_PROPERTIES_REF(cpPinJoint, Anchr1); 128 | MAKE_PROPERTIES_REF(cpPinJoint, Anchr2); 129 | MAKE_PROPERTIES_REF(cpPinJoint, Dist); 130 | 131 | MAKE_PROPERTIES_REF(cpPivotJoint, Anchr1); 132 | MAKE_PROPERTIES_REF(cpPivotJoint, Anchr2); 133 | 134 | MAKE_PROPERTIES_REF(cpRatchetJoint, Angle); 135 | MAKE_PROPERTIES_REF(cpRatchetJoint, Phase); 136 | MAKE_PROPERTIES_REF(cpRatchetJoint, Ratchet); 137 | 138 | MAKE_PROPERTIES_REF(cpRotaryLimitJoint, Min); 139 | MAKE_PROPERTIES_REF(cpRotaryLimitJoint, Max); 140 | 141 | MAKE_PROPERTIES_REF(cpSimpleMotor, Rate); 142 | 143 | MAKE_PROPERTIES_REF(cpSlideJoint, Anchr1); 144 | MAKE_PROPERTIES_REF(cpSlideJoint, Anchr2); 145 | MAKE_PROPERTIES_REF(cpSlideJoint, Min); 146 | MAKE_PROPERTIES_REF(cpSlideJoint, Max); 147 | 148 | MAKE_REF(cpSegmentQueryHitPoint); 149 | MAKE_REF(cpSegmentQueryHitDist); 150 | 151 | MAKE_REF(cpSpatialIndexDestroy); 152 | MAKE_REF(cpSpatialIndexCount); 153 | MAKE_REF(cpSpatialIndexEach); 154 | MAKE_REF(cpSpatialIndexContains); 155 | MAKE_REF(cpSpatialIndexInsert); 156 | MAKE_REF(cpSpatialIndexRemove); 157 | MAKE_REF(cpSpatialIndexReindex); 158 | MAKE_REF(cpSpatialIndexReindexObject); 159 | MAKE_REF(cpSpatialIndexSegmentQuery); 160 | MAKE_REF(cpSpatialIndexQuery); 161 | MAKE_REF(cpSpatialIndexReindexQuery); 162 | 163 | MAKE_PROPERTIES_REF(cpSpace, Iterations); 164 | MAKE_PROPERTIES_REF(cpSpace, Gravity); 165 | MAKE_PROPERTIES_REF(cpSpace, Damping); 166 | MAKE_PROPERTIES_REF(cpSpace, IdleSpeedThreshold); 167 | MAKE_PROPERTIES_REF(cpSpace, SleepTimeThreshold); 168 | MAKE_PROPERTIES_REF(cpSpace, CollisionSlop); 169 | MAKE_PROPERTIES_REF(cpSpace, CollisionBias); 170 | MAKE_PROPERTIES_REF(cpSpace, CollisionPersistence); 171 | MAKE_PROPERTIES_REF(cpSpace, EnableContactGraph); 172 | MAKE_PROPERTIES_REF(cpSpace, UserData); 173 | MAKE_REF(cpSpaceGetStaticBody); 174 | MAKE_REF(cpSpaceGetCurrentTimeStep); 175 | MAKE_REF(cpSpaceIsLocked); 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /cymunk/Chipmunk-Physics/include/chipmunk/chipmunk_ffi.h: -------------------------------------------------------------------------------- 1 | #ifdef CHIPMUNK_FFI 2 | 3 | // Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs 4 | // This file should only be included in chipmunk.c 5 | 6 | #ifdef _MSC_VER 7 | #if _MSC_VER >= 1600 8 | #define MAKE_REF(name) decltype(name) *_##name = name 9 | #else 10 | #define MAKE_REF(name) 11 | #endif 12 | #else 13 | #define MAKE_REF(name) __typeof__(name) *_##name = name 14 | #endif 15 | 16 | #define MAKE_PROPERTIES_REF(struct, property) \ 17 | MAKE_REF(struct##Get##property); MAKE_REF(struct##Set##property) 18 | 19 | MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv() 20 | MAKE_REF(cpveql); 21 | MAKE_REF(cpvadd); 22 | MAKE_REF(cpvneg); 23 | MAKE_REF(cpvsub); 24 | MAKE_REF(cpvmult); 25 | MAKE_REF(cpvdot); 26 | MAKE_REF(cpvcross); 27 | MAKE_REF(cpvperp); 28 | MAKE_REF(cpvrperp); 29 | MAKE_REF(cpvproject); 30 | MAKE_REF(cpvforangle); 31 | MAKE_REF(cpvtoangle); 32 | MAKE_REF(cpvrotate); 33 | MAKE_REF(cpvunrotate); 34 | MAKE_REF(cpvlengthsq); 35 | MAKE_REF(cpvlength); 36 | MAKE_REF(cpvlerp); 37 | MAKE_REF(cpvnormalize); 38 | MAKE_REF(cpvnormalize_safe); 39 | MAKE_REF(cpvclamp); 40 | MAKE_REF(cpvlerpconst); 41 | MAKE_REF(cpvdist); 42 | MAKE_REF(cpvdistsq); 43 | MAKE_REF(cpvnear); 44 | 45 | MAKE_REF(cpfmax); 46 | MAKE_REF(cpfmin); 47 | MAKE_REF(cpfabs); 48 | MAKE_REF(cpfclamp); 49 | MAKE_REF(cpflerp); 50 | MAKE_REF(cpflerpconst); 51 | 52 | MAKE_REF(cpBBNew); 53 | MAKE_REF(cpBBNewForCircle); 54 | MAKE_REF(cpBBIntersects); 55 | MAKE_REF(cpBBContainsBB); 56 | MAKE_REF(cpBBContainsVect); 57 | MAKE_REF(cpBBMerge); 58 | MAKE_REF(cpBBExpand); 59 | MAKE_REF(cpBBArea); 60 | MAKE_REF(cpBBMergedArea); 61 | MAKE_REF(cpBBSegmentQuery); 62 | MAKE_REF(cpBBIntersectsSegment); 63 | MAKE_REF(cpBBClampVect); 64 | 65 | MAKE_REF(cpBodyGetMass); 66 | MAKE_REF(cpBodyGetMoment); 67 | MAKE_REF(cpBodyGetPos); 68 | MAKE_REF(cpBodyGetAngle); 69 | MAKE_REF(cpBodyGetRot); 70 | MAKE_PROPERTIES_REF(cpBody, Vel); 71 | MAKE_PROPERTIES_REF(cpBody, Force); 72 | MAKE_PROPERTIES_REF(cpBody, AngVel); 73 | MAKE_PROPERTIES_REF(cpBody, Torque); 74 | MAKE_PROPERTIES_REF(cpBody, VelLimit); 75 | MAKE_PROPERTIES_REF(cpBody, AngVelLimit); 76 | MAKE_PROPERTIES_REF(cpBody, UserData); 77 | MAKE_REF(cpBodyIsSleeping); 78 | MAKE_REF(cpBodyIsStatic); 79 | MAKE_REF(cpBodyIsRogue); 80 | MAKE_REF(cpBodyLocal2World); 81 | MAKE_REF(cpBodyWorld2Local); 82 | MAKE_REF(cpBodyKineticEnergy); 83 | 84 | MAKE_REF(cpShapeGetBB); 85 | MAKE_PROPERTIES_REF(cpShape, Body); 86 | MAKE_PROPERTIES_REF(cpShape, Sensor); 87 | MAKE_PROPERTIES_REF(cpShape, Elasticity); 88 | MAKE_PROPERTIES_REF(cpShape, Friction); 89 | MAKE_PROPERTIES_REF(cpShape, SurfaceVelocity); 90 | MAKE_PROPERTIES_REF(cpShape, UserData); 91 | MAKE_PROPERTIES_REF(cpShape, CollisionType); 92 | MAKE_PROPERTIES_REF(cpShape, Group); 93 | MAKE_PROPERTIES_REF(cpShape, Layers); 94 | 95 | MAKE_REF(cpArbiterGetShapes); 96 | MAKE_REF(cpArbiterGetBodies); 97 | MAKE_REF(cpArbiterIsFirstContact); 98 | MAKE_REF(cpArbiterGetCount); 99 | 100 | MAKE_REF(cpConstraintGetA); 101 | MAKE_REF(cpConstraintGetB); 102 | MAKE_PROPERTIES_REF(cpConstraint, MaxForce); 103 | MAKE_PROPERTIES_REF(cpConstraint, ErrorBias); 104 | MAKE_PROPERTIES_REF(cpConstraint, MaxBias); 105 | MAKE_PROPERTIES_REF(cpConstraint, UserData); 106 | MAKE_REF(cpConstraintGetImpulse); 107 | 108 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, RestAngle); 109 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, Stiffness); 110 | MAKE_PROPERTIES_REF(cpDampedRotarySpring, Damping); 111 | //MAKE_PROPERTIES_REF(cpDampedRotarySpring, SpringTorqueFunc); 112 | 113 | MAKE_PROPERTIES_REF(cpDampedSpring, Anchr1); 114 | MAKE_PROPERTIES_REF(cpDampedSpring, Anchr2); 115 | MAKE_PROPERTIES_REF(cpDampedSpring, RestLength); 116 | MAKE_PROPERTIES_REF(cpDampedSpring, Stiffness); 117 | MAKE_PROPERTIES_REF(cpDampedSpring, Damping); 118 | //MAKE_PROPERTIES_REF(cpDampedSpring, SpringForceFunc); 119 | 120 | MAKE_PROPERTIES_REF(cpGearJoint, Phase); 121 | MAKE_REF(cpGearJointGetRatio); 122 | 123 | MAKE_PROPERTIES_REF(cpGrooveJoint, Anchr2); 124 | MAKE_REF(cpGrooveJointGetGrooveA); 125 | MAKE_REF(cpGrooveJointGetGrooveB); 126 | 127 | MAKE_PROPERTIES_REF(cpPinJoint, Anchr1); 128 | MAKE_PROPERTIES_REF(cpPinJoint, Anchr2); 129 | MAKE_PROPERTIES_REF(cpPinJoint, Dist); 130 | 131 | MAKE_PROPERTIES_REF(cpPivotJoint, Anchr1); 132 | MAKE_PROPERTIES_REF(cpPivotJoint, Anchr2); 133 | 134 | MAKE_PROPERTIES_REF(cpRatchetJoint, Angle); 135 | MAKE_PROPERTIES_REF(cpRatchetJoint, Phase); 136 | MAKE_PROPERTIES_REF(cpRatchetJoint, Ratchet); 137 | 138 | MAKE_PROPERTIES_REF(cpRotaryLimitJoint, Min); 139 | MAKE_PROPERTIES_REF(cpRotaryLimitJoint, Max); 140 | 141 | MAKE_PROPERTIES_REF(cpSimpleMotor, Rate); 142 | 143 | MAKE_PROPERTIES_REF(cpSlideJoint, Anchr1); 144 | MAKE_PROPERTIES_REF(cpSlideJoint, Anchr2); 145 | MAKE_PROPERTIES_REF(cpSlideJoint, Min); 146 | MAKE_PROPERTIES_REF(cpSlideJoint, Max); 147 | 148 | MAKE_REF(cpSegmentQueryHitPoint); 149 | MAKE_REF(cpSegmentQueryHitDist); 150 | 151 | MAKE_REF(cpSpatialIndexDestroy); 152 | MAKE_REF(cpSpatialIndexCount); 153 | MAKE_REF(cpSpatialIndexEach); 154 | MAKE_REF(cpSpatialIndexContains); 155 | MAKE_REF(cpSpatialIndexInsert); 156 | MAKE_REF(cpSpatialIndexRemove); 157 | MAKE_REF(cpSpatialIndexReindex); 158 | MAKE_REF(cpSpatialIndexReindexObject); 159 | MAKE_REF(cpSpatialIndexSegmentQuery); 160 | MAKE_REF(cpSpatialIndexQuery); 161 | MAKE_REF(cpSpatialIndexReindexQuery); 162 | 163 | MAKE_PROPERTIES_REF(cpSpace, Iterations); 164 | MAKE_PROPERTIES_REF(cpSpace, Gravity); 165 | MAKE_PROPERTIES_REF(cpSpace, Damping); 166 | MAKE_PROPERTIES_REF(cpSpace, IdleSpeedThreshold); 167 | MAKE_PROPERTIES_REF(cpSpace, SleepTimeThreshold); 168 | MAKE_PROPERTIES_REF(cpSpace, CollisionSlop); 169 | MAKE_PROPERTIES_REF(cpSpace, CollisionBias); 170 | MAKE_PROPERTIES_REF(cpSpace, CollisionPersistence); 171 | MAKE_PROPERTIES_REF(cpSpace, EnableContactGraph); 172 | MAKE_PROPERTIES_REF(cpSpace, UserData); 173 | MAKE_REF(cpSpaceGetStaticBody); 174 | MAKE_REF(cpSpaceGetCurrentTimeStep); 175 | MAKE_REF(cpSpaceIsLocked); 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /examples/balls_and_lines.py: -------------------------------------------------------------------------------- 1 | """This example lets you dynamically create static walls and dynamic balls 2 | 3 | """ 4 | __version__ = "$Id:$" 5 | __docformat__ = "reStructuredText" 6 | 7 | import pygame 8 | from pygame.locals import * 9 | from pygame.color import * 10 | 11 | import cymunk as pm 12 | from cymunk import Vec2d 13 | 14 | 15 | X,Y = 0,1 16 | ### Physics collision types 17 | COLLTYPE_DEFAULT = 0 18 | COLLTYPE_MOUSE = 1 19 | COLLTYPE_BALL = 2 20 | 21 | 22 | def flipy(y): 23 | """Small hack to convert chipmunk physics to pygame coordinates""" 24 | return -y+600 25 | 26 | def mouse_coll_func(space, arbiter): 27 | """Simple callback that increases the radius of circles touching the mouse""" 28 | s1,s2 = arbiter.shapes 29 | s2.unsafe_set_radius(s2.radius + 0.15) 30 | return False 31 | 32 | def main(): 33 | 34 | pygame.init() 35 | screen = pygame.display.set_mode((600, 600)) 36 | clock = pygame.time.Clock() 37 | running = True 38 | 39 | ### Physics stuff 40 | space = pm.Space() 41 | space.gravity = Vec2d(0.0, -900.0) 42 | 43 | ## Balls 44 | balls = [] 45 | 46 | ### Mouse 47 | mouse_body = pm.Body() 48 | mouse_shape = pm.Circle(mouse_body, 3, Vec2d(0,0)) 49 | mouse_shape.collision_type = COLLTYPE_MOUSE 50 | space.add(mouse_shape) 51 | 52 | space.add_collision_handler(COLLTYPE_MOUSE, COLLTYPE_BALL, None, mouse_coll_func, None, None) 53 | 54 | ### Static line 55 | line_point1 = None 56 | static_lines = [] 57 | run_physics = True 58 | 59 | while running: 60 | for event in pygame.event.get(): 61 | if event.type == QUIT: 62 | running = False 63 | elif event.type == KEYDOWN and event.key == K_ESCAPE: 64 | running = False 65 | elif event.type == KEYDOWN and event.key == K_p: 66 | pygame.image.save(screen, "balls_and_lines.png") 67 | elif event.type == MOUSEBUTTONDOWN and event.button == 1: 68 | p = event.pos[X], flipy(event.pos[Y]) 69 | body = pm.Body(10, 100) 70 | body.position = p 71 | shape = pm.Circle(body, 10, (0,0)) 72 | shape.friction = 0.5 73 | shape.collision_type = COLLTYPE_BALL 74 | space.add(body, shape) 75 | balls.append(shape) 76 | 77 | elif event.type == MOUSEBUTTONDOWN and event.button == 3: 78 | if line_point1 is None: 79 | line_point1 = Vec2d(event.pos[X], flipy(event.pos[Y])) 80 | elif event.type == MOUSEBUTTONUP and event.button == 3: 81 | if line_point1 is not None: 82 | 83 | line_point2 = Vec2d(event.pos[X], flipy(event.pos[Y])) 84 | print line_point1, line_point2 85 | body = pm.Body() 86 | shape= pm.Segment(body, line_point1, line_point2, 0.0) 87 | shape.friction = 0.99 88 | space.add(shape) 89 | static_lines.append(shape) 90 | line_point1 = None 91 | 92 | elif event.type == KEYDOWN and event.key == K_SPACE: 93 | run_physics = not run_physics 94 | 95 | p = pygame.mouse.get_pos() 96 | mouse_pos = Vec2d(p[X],flipy(p[Y])) 97 | mouse_body.position = mouse_pos 98 | 99 | 100 | if pygame.key.get_mods() & KMOD_SHIFT and pygame.mouse.get_pressed()[0]: 101 | body = pm.Body(10, 10) 102 | body.position = mouse_pos 103 | shape = pm.Circle(body, 10, (0,0)) 104 | shape.collision_type = COLLTYPE_BALL 105 | space.add(body, shape) 106 | balls.append(shape) 107 | 108 | ### Update physics 109 | if run_physics: 110 | dt = 1.0/60.0 111 | for x in range(1): 112 | space.step(dt) 113 | 114 | ### Draw stuff 115 | screen.fill(THECOLORS["white"]) 116 | 117 | # Display some text 118 | font = pygame.font.Font(None, 16) 119 | text = """LMB: Create ball 120 | LMB + Shift: Create many balls 121 | RMB: Drag to create wall, release to finish 122 | Space: Pause physics simulation""" 123 | y = 5 124 | for line in text.splitlines(): 125 | text = font.render(line, 1,THECOLORS["black"]) 126 | screen.blit(text, (5,y)) 127 | y += 10 128 | 129 | for ball in balls: 130 | r = ball.radius 131 | v = ball.body.position 132 | rot = ball.body.rotation_vector 133 | p = int(v.x), int(flipy(v.y)) 134 | p2 = Vec2d(rot.x, -rot.y) * r * 0.9 135 | pygame.draw.circle(screen, THECOLORS["blue"], p, int(r), 2) 136 | pygame.draw.line(screen, THECOLORS["red"], p, p+p2) 137 | 138 | if line_point1 is not None: 139 | p1 = line_point1.x, flipy(line_point1.y) 140 | p2 = mouse_pos.x, flipy(mouse_pos.y) 141 | pygame.draw.lines(screen, THECOLORS["black"], False, [p1,p2]) 142 | 143 | for line in static_lines: 144 | body = line.body 145 | 146 | pv1 = body.position + line.a.rotated(body.angle) 147 | pv2 = body.position + line.b.rotated(body.angle) 148 | p1 = pv1.x, flipy(pv1.y) 149 | p2 = pv2.x, flipy(pv2.y) 150 | pygame.draw.lines(screen, THECOLORS["lightgray"], False, [p1,p2]) 151 | 152 | ### Flip screen 153 | pygame.display.flip() 154 | clock.tick(50) 155 | pygame.display.set_caption("fps: " + str(clock.get_fps())) 156 | 157 | if __name__ == '__main__': 158 | doprof = 0 159 | if not doprof: 160 | main() 161 | else: 162 | import cProfile, pstats 163 | 164 | prof = cProfile.run("main()", "profile.prof") 165 | stats = pstats.Stats("profile.prof") 166 | stats.strip_dirs() 167 | stats.sort_stats('cumulative', 'time', 'calls') 168 | stats.print_stats(30) 169 | --------------------------------------------------------------------------------