--- /dev/null
+Box2D/
+Contributions/
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 491330C81372616300DFB46D /* Box2D.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913307B1372616300DFB46D /* Box2D.h */; };
+ 491330C91372616300DFB46D /* b2BroadPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913307D1372616300DFB46D /* b2BroadPhase.cpp */; };
+ 491330CA1372616300DFB46D /* b2BroadPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913307E1372616300DFB46D /* b2BroadPhase.h */; };
+ 491330CB1372616300DFB46D /* b2CollideCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913307F1372616300DFB46D /* b2CollideCircle.cpp */; };
+ 491330CC1372616300DFB46D /* b2CollidePolygon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330801372616300DFB46D /* b2CollidePolygon.cpp */; };
+ 491330CD1372616300DFB46D /* b2Collision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330811372616300DFB46D /* b2Collision.cpp */; };
+ 491330CE1372616300DFB46D /* b2Collision.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330821372616300DFB46D /* b2Collision.h */; };
+ 491330CF1372616300DFB46D /* b2Distance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330831372616300DFB46D /* b2Distance.cpp */; };
+ 491330D01372616300DFB46D /* b2Distance.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330841372616300DFB46D /* b2Distance.h */; };
+ 491330D11372616300DFB46D /* b2DynamicTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330851372616300DFB46D /* b2DynamicTree.cpp */; };
+ 491330D21372616300DFB46D /* b2DynamicTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330861372616300DFB46D /* b2DynamicTree.h */; };
+ 491330D31372616300DFB46D /* b2TimeOfImpact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330871372616300DFB46D /* b2TimeOfImpact.cpp */; };
+ 491330D41372616300DFB46D /* b2TimeOfImpact.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330881372616300DFB46D /* b2TimeOfImpact.h */; };
+ 491330D51372616300DFB46D /* b2CircleShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913308A1372616300DFB46D /* b2CircleShape.cpp */; };
+ 491330D61372616300DFB46D /* b2CircleShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913308B1372616300DFB46D /* b2CircleShape.h */; };
+ 491330D71372616300DFB46D /* b2PolygonShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913308C1372616300DFB46D /* b2PolygonShape.cpp */; };
+ 491330D81372616300DFB46D /* b2PolygonShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913308D1372616300DFB46D /* b2PolygonShape.h */; };
+ 491330D91372616300DFB46D /* b2Shape.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913308E1372616300DFB46D /* b2Shape.h */; };
+ 491330DA1372616300DFB46D /* b2BlockAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330901372616300DFB46D /* b2BlockAllocator.cpp */; };
+ 491330DB1372616300DFB46D /* b2BlockAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330911372616300DFB46D /* b2BlockAllocator.h */; };
+ 491330DC1372616300DFB46D /* b2Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330921372616300DFB46D /* b2Math.cpp */; };
+ 491330DD1372616300DFB46D /* b2Math.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330931372616300DFB46D /* b2Math.h */; };
+ 491330DE1372616300DFB46D /* b2Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330941372616300DFB46D /* b2Settings.cpp */; };
+ 491330DF1372616300DFB46D /* b2Settings.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330951372616300DFB46D /* b2Settings.h */; };
+ 491330E01372616300DFB46D /* b2StackAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330961372616300DFB46D /* b2StackAllocator.cpp */; };
+ 491330E11372616300DFB46D /* b2StackAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330971372616300DFB46D /* b2StackAllocator.h */; };
+ 491330E21372616300DFB46D /* b2Body.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330991372616300DFB46D /* b2Body.cpp */; };
+ 491330E31372616300DFB46D /* b2Body.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913309A1372616300DFB46D /* b2Body.h */; };
+ 491330E41372616300DFB46D /* b2ContactManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913309B1372616300DFB46D /* b2ContactManager.cpp */; };
+ 491330E51372616300DFB46D /* b2ContactManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913309C1372616300DFB46D /* b2ContactManager.h */; };
+ 491330E61372616300DFB46D /* b2Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913309D1372616300DFB46D /* b2Fixture.cpp */; };
+ 491330E71372616300DFB46D /* b2Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913309E1372616300DFB46D /* b2Fixture.h */; };
+ 491330E81372616300DFB46D /* b2Island.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4913309F1372616300DFB46D /* b2Island.cpp */; };
+ 491330E91372616300DFB46D /* b2Island.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330A01372616300DFB46D /* b2Island.h */; };
+ 491330EA1372616300DFB46D /* b2TimeStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330A11372616300DFB46D /* b2TimeStep.h */; };
+ 491330EB1372616300DFB46D /* b2World.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330A21372616300DFB46D /* b2World.cpp */; };
+ 491330EC1372616300DFB46D /* b2World.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330A31372616300DFB46D /* b2World.h */; };
+ 491330ED1372616300DFB46D /* b2WorldCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330A41372616300DFB46D /* b2WorldCallbacks.cpp */; };
+ 491330EE1372616300DFB46D /* b2WorldCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330A51372616300DFB46D /* b2WorldCallbacks.h */; };
+ 491330EF1372616300DFB46D /* b2CircleContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330A71372616300DFB46D /* b2CircleContact.cpp */; };
+ 491330F01372616300DFB46D /* b2CircleContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330A81372616300DFB46D /* b2CircleContact.h */; };
+ 491330F11372616300DFB46D /* b2Contact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330A91372616300DFB46D /* b2Contact.cpp */; };
+ 491330F21372616300DFB46D /* b2Contact.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330AA1372616300DFB46D /* b2Contact.h */; };
+ 491330F31372616300DFB46D /* b2ContactSolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330AB1372616300DFB46D /* b2ContactSolver.cpp */; };
+ 491330F41372616300DFB46D /* b2ContactSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330AC1372616300DFB46D /* b2ContactSolver.h */; };
+ 491330F51372616300DFB46D /* b2PolygonAndCircleContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330AD1372616300DFB46D /* b2PolygonAndCircleContact.cpp */; };
+ 491330F61372616300DFB46D /* b2PolygonAndCircleContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330AE1372616300DFB46D /* b2PolygonAndCircleContact.h */; };
+ 491330F71372616300DFB46D /* b2PolygonContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330AF1372616300DFB46D /* b2PolygonContact.cpp */; };
+ 491330F81372616300DFB46D /* b2PolygonContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330B01372616300DFB46D /* b2PolygonContact.h */; };
+ 491330F91372616300DFB46D /* b2TOISolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330B11372616300DFB46D /* b2TOISolver.cpp */; };
+ 491330FA1372616300DFB46D /* b2TOISolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330B21372616300DFB46D /* b2TOISolver.h */; };
+ 491330FB1372616300DFB46D /* b2DistanceJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330B41372616300DFB46D /* b2DistanceJoint.cpp */; };
+ 491330FC1372616300DFB46D /* b2DistanceJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330B51372616300DFB46D /* b2DistanceJoint.h */; };
+ 491330FD1372616300DFB46D /* b2FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330B61372616300DFB46D /* b2FrictionJoint.cpp */; };
+ 491330FE1372616300DFB46D /* b2FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330B71372616300DFB46D /* b2FrictionJoint.h */; };
+ 491330FF1372616300DFB46D /* b2GearJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330B81372616300DFB46D /* b2GearJoint.cpp */; };
+ 491331001372616300DFB46D /* b2GearJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330B91372616300DFB46D /* b2GearJoint.h */; };
+ 491331011372616300DFB46D /* b2Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330BA1372616300DFB46D /* b2Joint.cpp */; };
+ 491331021372616300DFB46D /* b2Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330BB1372616300DFB46D /* b2Joint.h */; };
+ 491331031372616300DFB46D /* b2LineJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330BC1372616300DFB46D /* b2LineJoint.cpp */; };
+ 491331041372616300DFB46D /* b2LineJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330BD1372616300DFB46D /* b2LineJoint.h */; };
+ 491331051372616300DFB46D /* b2MouseJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330BE1372616300DFB46D /* b2MouseJoint.cpp */; };
+ 491331061372616300DFB46D /* b2MouseJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330BF1372616300DFB46D /* b2MouseJoint.h */; };
+ 491331071372616300DFB46D /* b2PrismaticJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330C01372616300DFB46D /* b2PrismaticJoint.cpp */; };
+ 491331081372616300DFB46D /* b2PrismaticJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330C11372616300DFB46D /* b2PrismaticJoint.h */; };
+ 491331091372616300DFB46D /* b2PulleyJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330C21372616300DFB46D /* b2PulleyJoint.cpp */; };
+ 4913310A1372616300DFB46D /* b2PulleyJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330C31372616300DFB46D /* b2PulleyJoint.h */; };
+ 4913310B1372616300DFB46D /* b2RevoluteJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330C41372616300DFB46D /* b2RevoluteJoint.cpp */; };
+ 4913310C1372616300DFB46D /* b2RevoluteJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330C51372616300DFB46D /* b2RevoluteJoint.h */; };
+ 4913310D1372616300DFB46D /* b2WeldJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491330C61372616300DFB46D /* b2WeldJoint.cpp */; };
+ 4913310E1372616300DFB46D /* b2WeldJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 491330C71372616300DFB46D /* b2WeldJoint.h */; };
+ 49133123137262F200DFB46D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49133122137262F200DFB46D /* Foundation.framework */; };
+ 491331281372630700DFB46D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 491331271372630700DFB46D /* UIKit.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 4913305F1372610400DFB46D /* libBox2D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBox2D.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4913307B1372616300DFB46D /* Box2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2D.h; sourceTree = "<group>"; };
+ 4913307D1372616300DFB46D /* b2BroadPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2BroadPhase.cpp; sourceTree = "<group>"; };
+ 4913307E1372616300DFB46D /* b2BroadPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2BroadPhase.h; sourceTree = "<group>"; };
+ 4913307F1372616300DFB46D /* b2CollideCircle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollideCircle.cpp; sourceTree = "<group>"; };
+ 491330801372616300DFB46D /* b2CollidePolygon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollidePolygon.cpp; sourceTree = "<group>"; };
+ 491330811372616300DFB46D /* b2Collision.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Collision.cpp; sourceTree = "<group>"; };
+ 491330821372616300DFB46D /* b2Collision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Collision.h; sourceTree = "<group>"; };
+ 491330831372616300DFB46D /* b2Distance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Distance.cpp; sourceTree = "<group>"; };
+ 491330841372616300DFB46D /* b2Distance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Distance.h; sourceTree = "<group>"; };
+ 491330851372616300DFB46D /* b2DynamicTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2DynamicTree.cpp; sourceTree = "<group>"; };
+ 491330861372616300DFB46D /* b2DynamicTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2DynamicTree.h; sourceTree = "<group>"; };
+ 491330871372616300DFB46D /* b2TimeOfImpact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2TimeOfImpact.cpp; sourceTree = "<group>"; };
+ 491330881372616300DFB46D /* b2TimeOfImpact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TimeOfImpact.h; sourceTree = "<group>"; };
+ 4913308A1372616300DFB46D /* b2CircleShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CircleShape.cpp; sourceTree = "<group>"; };
+ 4913308B1372616300DFB46D /* b2CircleShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2CircleShape.h; sourceTree = "<group>"; };
+ 4913308C1372616300DFB46D /* b2PolygonShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonShape.cpp; sourceTree = "<group>"; };
+ 4913308D1372616300DFB46D /* b2PolygonShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonShape.h; sourceTree = "<group>"; };
+ 4913308E1372616300DFB46D /* b2Shape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Shape.h; sourceTree = "<group>"; };
+ 491330901372616300DFB46D /* b2BlockAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2BlockAllocator.cpp; sourceTree = "<group>"; };
+ 491330911372616300DFB46D /* b2BlockAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2BlockAllocator.h; sourceTree = "<group>"; };
+ 491330921372616300DFB46D /* b2Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Math.cpp; sourceTree = "<group>"; };
+ 491330931372616300DFB46D /* b2Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Math.h; sourceTree = "<group>"; };
+ 491330941372616300DFB46D /* b2Settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Settings.cpp; sourceTree = "<group>"; };
+ 491330951372616300DFB46D /* b2Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Settings.h; sourceTree = "<group>"; };
+ 491330961372616300DFB46D /* b2StackAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2StackAllocator.cpp; sourceTree = "<group>"; };
+ 491330971372616300DFB46D /* b2StackAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2StackAllocator.h; sourceTree = "<group>"; };
+ 491330991372616300DFB46D /* b2Body.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Body.cpp; sourceTree = "<group>"; };
+ 4913309A1372616300DFB46D /* b2Body.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Body.h; sourceTree = "<group>"; };
+ 4913309B1372616300DFB46D /* b2ContactManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2ContactManager.cpp; sourceTree = "<group>"; };
+ 4913309C1372616300DFB46D /* b2ContactManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2ContactManager.h; sourceTree = "<group>"; };
+ 4913309D1372616300DFB46D /* b2Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Fixture.cpp; sourceTree = "<group>"; };
+ 4913309E1372616300DFB46D /* b2Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Fixture.h; sourceTree = "<group>"; };
+ 4913309F1372616300DFB46D /* b2Island.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Island.cpp; sourceTree = "<group>"; };
+ 491330A01372616300DFB46D /* b2Island.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Island.h; sourceTree = "<group>"; };
+ 491330A11372616300DFB46D /* b2TimeStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TimeStep.h; sourceTree = "<group>"; };
+ 491330A21372616300DFB46D /* b2World.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2World.cpp; sourceTree = "<group>"; };
+ 491330A31372616300DFB46D /* b2World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2World.h; sourceTree = "<group>"; };
+ 491330A41372616300DFB46D /* b2WorldCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2WorldCallbacks.cpp; sourceTree = "<group>"; };
+ 491330A51372616300DFB46D /* b2WorldCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2WorldCallbacks.h; sourceTree = "<group>"; };
+ 491330A71372616300DFB46D /* b2CircleContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CircleContact.cpp; sourceTree = "<group>"; };
+ 491330A81372616300DFB46D /* b2CircleContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2CircleContact.h; sourceTree = "<group>"; };
+ 491330A91372616300DFB46D /* b2Contact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Contact.cpp; sourceTree = "<group>"; };
+ 491330AA1372616300DFB46D /* b2Contact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Contact.h; sourceTree = "<group>"; };
+ 491330AB1372616300DFB46D /* b2ContactSolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2ContactSolver.cpp; sourceTree = "<group>"; };
+ 491330AC1372616300DFB46D /* b2ContactSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2ContactSolver.h; sourceTree = "<group>"; };
+ 491330AD1372616300DFB46D /* b2PolygonAndCircleContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonAndCircleContact.cpp; sourceTree = "<group>"; };
+ 491330AE1372616300DFB46D /* b2PolygonAndCircleContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonAndCircleContact.h; sourceTree = "<group>"; };
+ 491330AF1372616300DFB46D /* b2PolygonContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonContact.cpp; sourceTree = "<group>"; };
+ 491330B01372616300DFB46D /* b2PolygonContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonContact.h; sourceTree = "<group>"; };
+ 491330B11372616300DFB46D /* b2TOISolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2TOISolver.cpp; sourceTree = "<group>"; };
+ 491330B21372616300DFB46D /* b2TOISolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TOISolver.h; sourceTree = "<group>"; };
+ 491330B41372616300DFB46D /* b2DistanceJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2DistanceJoint.cpp; sourceTree = "<group>"; };
+ 491330B51372616300DFB46D /* b2DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2DistanceJoint.h; sourceTree = "<group>"; };
+ 491330B61372616300DFB46D /* b2FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2FrictionJoint.cpp; sourceTree = "<group>"; };
+ 491330B71372616300DFB46D /* b2FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2FrictionJoint.h; sourceTree = "<group>"; };
+ 491330B81372616300DFB46D /* b2GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2GearJoint.cpp; sourceTree = "<group>"; };
+ 491330B91372616300DFB46D /* b2GearJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2GearJoint.h; sourceTree = "<group>"; };
+ 491330BA1372616300DFB46D /* b2Joint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Joint.cpp; sourceTree = "<group>"; };
+ 491330BB1372616300DFB46D /* b2Joint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Joint.h; sourceTree = "<group>"; };
+ 491330BC1372616300DFB46D /* b2LineJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2LineJoint.cpp; sourceTree = "<group>"; };
+ 491330BD1372616300DFB46D /* b2LineJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2LineJoint.h; sourceTree = "<group>"; };
+ 491330BE1372616300DFB46D /* b2MouseJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2MouseJoint.cpp; sourceTree = "<group>"; };
+ 491330BF1372616300DFB46D /* b2MouseJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2MouseJoint.h; sourceTree = "<group>"; };
+ 491330C01372616300DFB46D /* b2PrismaticJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PrismaticJoint.cpp; sourceTree = "<group>"; };
+ 491330C11372616300DFB46D /* b2PrismaticJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PrismaticJoint.h; sourceTree = "<group>"; };
+ 491330C21372616300DFB46D /* b2PulleyJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PulleyJoint.cpp; sourceTree = "<group>"; };
+ 491330C31372616300DFB46D /* b2PulleyJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PulleyJoint.h; sourceTree = "<group>"; };
+ 491330C41372616300DFB46D /* b2RevoluteJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2RevoluteJoint.cpp; sourceTree = "<group>"; };
+ 491330C51372616300DFB46D /* b2RevoluteJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2RevoluteJoint.h; sourceTree = "<group>"; };
+ 491330C61372616300DFB46D /* b2WeldJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2WeldJoint.cpp; sourceTree = "<group>"; };
+ 491330C71372616300DFB46D /* b2WeldJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2WeldJoint.h; sourceTree = "<group>"; };
+ 49133122137262F200DFB46D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 491331271372630700DFB46D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4913305C1372610400DFB46D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 491331281372630700DFB46D /* UIKit.framework in Frameworks */,
+ 49133123137262F200DFB46D /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 491330541372610400DFB46D = {
+ isa = PBXGroup;
+ children = (
+ 4913307A1372616300DFB46D /* Box2D */,
+ 491331291372630F00DFB46D /* Frameworks */,
+ 491330601372610400DFB46D /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 491330601372610400DFB46D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4913305F1372610400DFB46D /* libBox2D.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4913307A1372616300DFB46D /* Box2D */ = {
+ isa = PBXGroup;
+ children = (
+ 4913307B1372616300DFB46D /* Box2D.h */,
+ 4913307C1372616300DFB46D /* Collision */,
+ 4913308F1372616300DFB46D /* Common */,
+ 491330981372616300DFB46D /* Dynamics */,
+ );
+ name = Box2D;
+ path = src/Box2D;
+ sourceTree = "<group>";
+ };
+ 4913307C1372616300DFB46D /* Collision */ = {
+ isa = PBXGroup;
+ children = (
+ 4913307D1372616300DFB46D /* b2BroadPhase.cpp */,
+ 4913307E1372616300DFB46D /* b2BroadPhase.h */,
+ 4913307F1372616300DFB46D /* b2CollideCircle.cpp */,
+ 491330801372616300DFB46D /* b2CollidePolygon.cpp */,
+ 491330811372616300DFB46D /* b2Collision.cpp */,
+ 491330821372616300DFB46D /* b2Collision.h */,
+ 491330831372616300DFB46D /* b2Distance.cpp */,
+ 491330841372616300DFB46D /* b2Distance.h */,
+ 491330851372616300DFB46D /* b2DynamicTree.cpp */,
+ 491330861372616300DFB46D /* b2DynamicTree.h */,
+ 491330871372616300DFB46D /* b2TimeOfImpact.cpp */,
+ 491330881372616300DFB46D /* b2TimeOfImpact.h */,
+ 491330891372616300DFB46D /* Shapes */,
+ );
+ path = Collision;
+ sourceTree = "<group>";
+ };
+ 491330891372616300DFB46D /* Shapes */ = {
+ isa = PBXGroup;
+ children = (
+ 4913308A1372616300DFB46D /* b2CircleShape.cpp */,
+ 4913308B1372616300DFB46D /* b2CircleShape.h */,
+ 4913308C1372616300DFB46D /* b2PolygonShape.cpp */,
+ 4913308D1372616300DFB46D /* b2PolygonShape.h */,
+ 4913308E1372616300DFB46D /* b2Shape.h */,
+ );
+ path = Shapes;
+ sourceTree = "<group>";
+ };
+ 4913308F1372616300DFB46D /* Common */ = {
+ isa = PBXGroup;
+ children = (
+ 491330901372616300DFB46D /* b2BlockAllocator.cpp */,
+ 491330911372616300DFB46D /* b2BlockAllocator.h */,
+ 491330921372616300DFB46D /* b2Math.cpp */,
+ 491330931372616300DFB46D /* b2Math.h */,
+ 491330941372616300DFB46D /* b2Settings.cpp */,
+ 491330951372616300DFB46D /* b2Settings.h */,
+ 491330961372616300DFB46D /* b2StackAllocator.cpp */,
+ 491330971372616300DFB46D /* b2StackAllocator.h */,
+ );
+ path = Common;
+ sourceTree = "<group>";
+ };
+ 491330981372616300DFB46D /* Dynamics */ = {
+ isa = PBXGroup;
+ children = (
+ 491330991372616300DFB46D /* b2Body.cpp */,
+ 4913309A1372616300DFB46D /* b2Body.h */,
+ 4913309B1372616300DFB46D /* b2ContactManager.cpp */,
+ 4913309C1372616300DFB46D /* b2ContactManager.h */,
+ 4913309D1372616300DFB46D /* b2Fixture.cpp */,
+ 4913309E1372616300DFB46D /* b2Fixture.h */,
+ 4913309F1372616300DFB46D /* b2Island.cpp */,
+ 491330A01372616300DFB46D /* b2Island.h */,
+ 491330A11372616300DFB46D /* b2TimeStep.h */,
+ 491330A21372616300DFB46D /* b2World.cpp */,
+ 491330A31372616300DFB46D /* b2World.h */,
+ 491330A41372616300DFB46D /* b2WorldCallbacks.cpp */,
+ 491330A51372616300DFB46D /* b2WorldCallbacks.h */,
+ 491330A61372616300DFB46D /* Contacts */,
+ 491330B31372616300DFB46D /* Joints */,
+ );
+ path = Dynamics;
+ sourceTree = "<group>";
+ };
+ 491330A61372616300DFB46D /* Contacts */ = {
+ isa = PBXGroup;
+ children = (
+ 491330A71372616300DFB46D /* b2CircleContact.cpp */,
+ 491330A81372616300DFB46D /* b2CircleContact.h */,
+ 491330A91372616300DFB46D /* b2Contact.cpp */,
+ 491330AA1372616300DFB46D /* b2Contact.h */,
+ 491330AB1372616300DFB46D /* b2ContactSolver.cpp */,
+ 491330AC1372616300DFB46D /* b2ContactSolver.h */,
+ 491330AD1372616300DFB46D /* b2PolygonAndCircleContact.cpp */,
+ 491330AE1372616300DFB46D /* b2PolygonAndCircleContact.h */,
+ 491330AF1372616300DFB46D /* b2PolygonContact.cpp */,
+ 491330B01372616300DFB46D /* b2PolygonContact.h */,
+ 491330B11372616300DFB46D /* b2TOISolver.cpp */,
+ 491330B21372616300DFB46D /* b2TOISolver.h */,
+ );
+ path = Contacts;
+ sourceTree = "<group>";
+ };
+ 491330B31372616300DFB46D /* Joints */ = {
+ isa = PBXGroup;
+ children = (
+ 491330B41372616300DFB46D /* b2DistanceJoint.cpp */,
+ 491330B51372616300DFB46D /* b2DistanceJoint.h */,
+ 491330B61372616300DFB46D /* b2FrictionJoint.cpp */,
+ 491330B71372616300DFB46D /* b2FrictionJoint.h */,
+ 491330B81372616300DFB46D /* b2GearJoint.cpp */,
+ 491330B91372616300DFB46D /* b2GearJoint.h */,
+ 491330BA1372616300DFB46D /* b2Joint.cpp */,
+ 491330BB1372616300DFB46D /* b2Joint.h */,
+ 491330BC1372616300DFB46D /* b2LineJoint.cpp */,
+ 491330BD1372616300DFB46D /* b2LineJoint.h */,
+ 491330BE1372616300DFB46D /* b2MouseJoint.cpp */,
+ 491330BF1372616300DFB46D /* b2MouseJoint.h */,
+ 491330C01372616300DFB46D /* b2PrismaticJoint.cpp */,
+ 491330C11372616300DFB46D /* b2PrismaticJoint.h */,
+ 491330C21372616300DFB46D /* b2PulleyJoint.cpp */,
+ 491330C31372616300DFB46D /* b2PulleyJoint.h */,
+ 491330C41372616300DFB46D /* b2RevoluteJoint.cpp */,
+ 491330C51372616300DFB46D /* b2RevoluteJoint.h */,
+ 491330C61372616300DFB46D /* b2WeldJoint.cpp */,
+ 491330C71372616300DFB46D /* b2WeldJoint.h */,
+ );
+ path = Joints;
+ sourceTree = "<group>";
+ };
+ 491331291372630F00DFB46D /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 491331271372630700DFB46D /* UIKit.framework */,
+ 49133122137262F200DFB46D /* Foundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 4913305D1372610400DFB46D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 491330C81372616300DFB46D /* Box2D.h in Headers */,
+ 491330CA1372616300DFB46D /* b2BroadPhase.h in Headers */,
+ 491330CE1372616300DFB46D /* b2Collision.h in Headers */,
+ 491330D01372616300DFB46D /* b2Distance.h in Headers */,
+ 491330D21372616300DFB46D /* b2DynamicTree.h in Headers */,
+ 491330D41372616300DFB46D /* b2TimeOfImpact.h in Headers */,
+ 491330D61372616300DFB46D /* b2CircleShape.h in Headers */,
+ 491330D81372616300DFB46D /* b2PolygonShape.h in Headers */,
+ 491330D91372616300DFB46D /* b2Shape.h in Headers */,
+ 491330DB1372616300DFB46D /* b2BlockAllocator.h in Headers */,
+ 491330DD1372616300DFB46D /* b2Math.h in Headers */,
+ 491330DF1372616300DFB46D /* b2Settings.h in Headers */,
+ 491330E11372616300DFB46D /* b2StackAllocator.h in Headers */,
+ 491330E31372616300DFB46D /* b2Body.h in Headers */,
+ 491330E51372616300DFB46D /* b2ContactManager.h in Headers */,
+ 491330E71372616300DFB46D /* b2Fixture.h in Headers */,
+ 491330E91372616300DFB46D /* b2Island.h in Headers */,
+ 491330EA1372616300DFB46D /* b2TimeStep.h in Headers */,
+ 491330EC1372616300DFB46D /* b2World.h in Headers */,
+ 491330EE1372616300DFB46D /* b2WorldCallbacks.h in Headers */,
+ 491330F01372616300DFB46D /* b2CircleContact.h in Headers */,
+ 491330F21372616300DFB46D /* b2Contact.h in Headers */,
+ 491330F41372616300DFB46D /* b2ContactSolver.h in Headers */,
+ 491330F61372616300DFB46D /* b2PolygonAndCircleContact.h in Headers */,
+ 491330F81372616300DFB46D /* b2PolygonContact.h in Headers */,
+ 491330FA1372616300DFB46D /* b2TOISolver.h in Headers */,
+ 491330FC1372616300DFB46D /* b2DistanceJoint.h in Headers */,
+ 491330FE1372616300DFB46D /* b2FrictionJoint.h in Headers */,
+ 491331001372616300DFB46D /* b2GearJoint.h in Headers */,
+ 491331021372616300DFB46D /* b2Joint.h in Headers */,
+ 491331041372616300DFB46D /* b2LineJoint.h in Headers */,
+ 491331061372616300DFB46D /* b2MouseJoint.h in Headers */,
+ 491331081372616300DFB46D /* b2PrismaticJoint.h in Headers */,
+ 4913310A1372616300DFB46D /* b2PulleyJoint.h in Headers */,
+ 4913310C1372616300DFB46D /* b2RevoluteJoint.h in Headers */,
+ 4913310E1372616300DFB46D /* b2WeldJoint.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 4913305E1372610400DFB46D /* Box2D */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 491330691372610400DFB46D /* Build configuration list for PBXNativeTarget "Box2D" */;
+ buildPhases = (
+ 4913305B1372610400DFB46D /* Sources */,
+ 4913305C1372610400DFB46D /* Frameworks */,
+ 4913305D1372610400DFB46D /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Box2D;
+ productName = Box2D;
+ productReference = 4913305F1372610400DFB46D /* libBox2D.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 491330561372610400DFB46D /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 491330591372610400DFB46D /* Build configuration list for PBXProject "box2d-ios" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 491330541372610400DFB46D;
+ productRefGroup = 491330601372610400DFB46D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4913305E1372610400DFB46D /* Box2D */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4913305B1372610400DFB46D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 491330C91372616300DFB46D /* b2BroadPhase.cpp in Sources */,
+ 491330CB1372616300DFB46D /* b2CollideCircle.cpp in Sources */,
+ 491330CC1372616300DFB46D /* b2CollidePolygon.cpp in Sources */,
+ 491330CD1372616300DFB46D /* b2Collision.cpp in Sources */,
+ 491330CF1372616300DFB46D /* b2Distance.cpp in Sources */,
+ 491330D11372616300DFB46D /* b2DynamicTree.cpp in Sources */,
+ 491330D31372616300DFB46D /* b2TimeOfImpact.cpp in Sources */,
+ 491330D51372616300DFB46D /* b2CircleShape.cpp in Sources */,
+ 491330D71372616300DFB46D /* b2PolygonShape.cpp in Sources */,
+ 491330DA1372616300DFB46D /* b2BlockAllocator.cpp in Sources */,
+ 491330DC1372616300DFB46D /* b2Math.cpp in Sources */,
+ 491330DE1372616300DFB46D /* b2Settings.cpp in Sources */,
+ 491330E01372616300DFB46D /* b2StackAllocator.cpp in Sources */,
+ 491330E21372616300DFB46D /* b2Body.cpp in Sources */,
+ 491330E41372616300DFB46D /* b2ContactManager.cpp in Sources */,
+ 491330E61372616300DFB46D /* b2Fixture.cpp in Sources */,
+ 491330E81372616300DFB46D /* b2Island.cpp in Sources */,
+ 491330EB1372616300DFB46D /* b2World.cpp in Sources */,
+ 491330ED1372616300DFB46D /* b2WorldCallbacks.cpp in Sources */,
+ 491330EF1372616300DFB46D /* b2CircleContact.cpp in Sources */,
+ 491330F11372616300DFB46D /* b2Contact.cpp in Sources */,
+ 491330F31372616300DFB46D /* b2ContactSolver.cpp in Sources */,
+ 491330F51372616300DFB46D /* b2PolygonAndCircleContact.cpp in Sources */,
+ 491330F71372616300DFB46D /* b2PolygonContact.cpp in Sources */,
+ 491330F91372616300DFB46D /* b2TOISolver.cpp in Sources */,
+ 491330FB1372616300DFB46D /* b2DistanceJoint.cpp in Sources */,
+ 491330FD1372616300DFB46D /* b2FrictionJoint.cpp in Sources */,
+ 491330FF1372616300DFB46D /* b2GearJoint.cpp in Sources */,
+ 491331011372616300DFB46D /* b2Joint.cpp in Sources */,
+ 491331031372616300DFB46D /* b2LineJoint.cpp in Sources */,
+ 491331051372616300DFB46D /* b2MouseJoint.cpp in Sources */,
+ 491331071372616300DFB46D /* b2PrismaticJoint.cpp in Sources */,
+ 491331091372616300DFB46D /* b2PulleyJoint.cpp in Sources */,
+ 4913310B1372616300DFB46D /* b2RevoluteJoint.cpp in Sources */,
+ 4913310D1372616300DFB46D /* b2WeldJoint.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 491330671372610400DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = 4.2;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 491330681372610400DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = 4.2;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+ 4913306A1372610400DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ DSTROOT = /tmp/Box2D.dst;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Box2D/Box2D-Prefix.pch";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ };
+ name = Debug;
+ };
+ 4913306B1372610400DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ DSTROOT = /tmp/Box2D.dst;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Box2D/Box2D-Prefix.pch";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 491330591372610400DFB46D /* Build configuration list for PBXProject "box2d-ios" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 491330671372610400DFB46D /* Debug */,
+ 491330681372610400DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 491330691372610400DFB46D /* Build configuration list for PBXNativeTarget "Box2D" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4913306A1372610400DFB46D /* Debug */,
+ 4913306B1372610400DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 491330561372610400DFB46D /* Project object */;
+}
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 4913316E1372645C00DFB46D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4913316D1372645C00DFB46D /* UIKit.framework */; };
+ 491331701372645C00DFB46D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4913316F1372645C00DFB46D /* Foundation.framework */; };
+ 491331721372645C00DFB46D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 491331711372645C00DFB46D /* CoreGraphics.framework */; };
+ 491331A91372653600DFB46D /* Box2DAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4913319A1372653600DFB46D /* Box2DAppDelegate.mm */; };
+ 491331AA1372653600DFB46D /* Box2DView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4913319C1372653600DFB46D /* Box2DView.mm */; };
+ 491331AB1372653600DFB46D /* GLES-Render.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4913319F1372653600DFB46D /* GLES-Render.mm */; };
+ 491331AC1372653600DFB46D /* iPhoneTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 491331A11372653600DFB46D /* iPhoneTest.mm */; };
+ 491331AD1372653600DFB46D /* iPhoneTestEntries.mm in Sources */ = {isa = PBXBuildFile; fileRef = 491331A21372653600DFB46D /* iPhoneTestEntries.mm */; };
+ 491331AE1372653600DFB46D /* TestEntriesViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 491331A41372653600DFB46D /* TestEntriesViewController.mm */; };
+ 491331AF1372653600DFB46D /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 491331A51372653600DFB46D /* Icon.png */; };
+ 491331B01372653600DFB46D /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 491331A61372653600DFB46D /* Info.plist */; };
+ 491331B11372653600DFB46D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 491331A71372653600DFB46D /* main.m */; };
+ 491331B21372653600DFB46D /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 491331A81372653600DFB46D /* MainWindow.xib */; };
+ 491331C11372663200DFB46D /* libBox2D.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 491331C01372663200DFB46D /* libBox2D.a */; };
+ 4913323813726B1F00DFB46D /* ApplyForce.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913320D13726B1F00DFB46D /* ApplyForce.h */; };
+ 4913323913726B1F00DFB46D /* BodyTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913320E13726B1F00DFB46D /* BodyTypes.h */; };
+ 4913323A13726B1F00DFB46D /* Breakable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913320F13726B1F00DFB46D /* Breakable.h */; };
+ 4913323B13726B1F00DFB46D /* Bridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321013726B1F00DFB46D /* Bridge.h */; };
+ 4913323C13726B1F00DFB46D /* BulletTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321113726B1F00DFB46D /* BulletTest.h */; };
+ 4913323D13726B1F00DFB46D /* Cantilever.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321213726B1F00DFB46D /* Cantilever.h */; };
+ 4913323E13726B1F00DFB46D /* Car.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321313726B1F00DFB46D /* Car.h */; };
+ 4913323F13726B1F00DFB46D /* Chain.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321413726B1F00DFB46D /* Chain.h */; };
+ 4913324013726B1F00DFB46D /* CharacterCollision.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321513726B1F00DFB46D /* CharacterCollision.h */; };
+ 4913324113726B1F00DFB46D /* CollisionFiltering.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321613726B1F00DFB46D /* CollisionFiltering.h */; };
+ 4913324213726B1F00DFB46D /* CollisionProcessing.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321713726B1F00DFB46D /* CollisionProcessing.h */; };
+ 4913324313726B1F00DFB46D /* CompoundShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321813726B1F00DFB46D /* CompoundShapes.h */; };
+ 4913324413726B1F00DFB46D /* Confined.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321913726B1F00DFB46D /* Confined.h */; };
+ 4913324513726B1F00DFB46D /* ContinuousTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321A13726B1F00DFB46D /* ContinuousTest.h */; };
+ 4913324613726B1F00DFB46D /* DistanceTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321B13726B1F00DFB46D /* DistanceTest.h */; };
+ 4913324713726B1F00DFB46D /* Dominos.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321C13726B1F00DFB46D /* Dominos.h */; };
+ 4913324813726B1F00DFB46D /* DynamicTreeTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321D13726B1F00DFB46D /* DynamicTreeTest.h */; };
+ 4913324913726B1F00DFB46D /* EdgeShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321E13726B1F00DFB46D /* EdgeShapes.h */; };
+ 4913324A13726B1F00DFB46D /* EdgeTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913321F13726B1F00DFB46D /* EdgeTest.h */; };
+ 4913324B13726B1F00DFB46D /* Gears.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322013726B1F00DFB46D /* Gears.h */; };
+ 4913324C13726B1F00DFB46D /* LineJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322113726B1F00DFB46D /* LineJoint.h */; };
+ 4913324D13726B1F00DFB46D /* OneSidedPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322213726B1F00DFB46D /* OneSidedPlatform.h */; };
+ 4913324E13726B1F00DFB46D /* Pinball.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322313726B1F00DFB46D /* Pinball.h */; };
+ 4913324F13726B1F00DFB46D /* PolyCollision.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322413726B1F00DFB46D /* PolyCollision.h */; };
+ 4913325013726B1F00DFB46D /* PolyShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322513726B1F00DFB46D /* PolyShapes.h */; };
+ 4913325113726B1F00DFB46D /* Prismatic.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322613726B1F00DFB46D /* Prismatic.h */; };
+ 4913325213726B1F00DFB46D /* Pulleys.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322713726B1F00DFB46D /* Pulleys.h */; };
+ 4913325313726B1F00DFB46D /* Pyramid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322813726B1F00DFB46D /* Pyramid.h */; };
+ 4913325413726B1F00DFB46D /* RayCast.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322913726B1F00DFB46D /* RayCast.h */; };
+ 4913325513726B1F00DFB46D /* Revolute.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322A13726B1F00DFB46D /* Revolute.h */; };
+ 4913325613726B1F00DFB46D /* Rope.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322B13726B1F00DFB46D /* Rope.h */; };
+ 4913325713726B1F00DFB46D /* RopeJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322C13726B1F00DFB46D /* RopeJoint.h */; };
+ 4913325813726B1F00DFB46D /* SensorTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322D13726B1F00DFB46D /* SensorTest.h */; };
+ 4913325913726B1F00DFB46D /* ShapeEditing.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322E13726B1F00DFB46D /* ShapeEditing.h */; };
+ 4913325A13726B1F00DFB46D /* SliderCrank.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913322F13726B1F00DFB46D /* SliderCrank.h */; };
+ 4913325B13726B1F00DFB46D /* SphereStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323013726B1F00DFB46D /* SphereStack.h */; };
+ 4913325C13726B1F00DFB46D /* TheoJansen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323113726B1F00DFB46D /* TheoJansen.h */; };
+ 4913325D13726B1F00DFB46D /* Tiles.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323213726B1F00DFB46D /* Tiles.h */; };
+ 4913325E13726B1F00DFB46D /* TimeOfImpact.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323313726B1F00DFB46D /* TimeOfImpact.h */; };
+ 4913325F13726B1F00DFB46D /* VaryingFriction.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323413726B1F00DFB46D /* VaryingFriction.h */; };
+ 4913326013726B1F00DFB46D /* VaryingRestitution.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323513726B1F00DFB46D /* VaryingRestitution.h */; };
+ 4913326113726B1F00DFB46D /* VerticalStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323613726B1F00DFB46D /* VerticalStack.h */; };
+ 4913326213726B1F00DFB46D /* Web.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913323713726B1F00DFB46D /* Web.h */; };
+ 4913326413726B5D00DFB46D /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4913326313726B5D00DFB46D /* OpenGLES.framework */; };
+ 4913326E13726BC800DFB46D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4913326D13726BC800DFB46D /* QuartzCore.framework */; };
+ 4913326F13726D2F00DFB46D /* Box2DAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 491331991372653600DFB46D /* Box2DAppDelegate.h */; };
+ 4913327013726D2F00DFB46D /* Box2DView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913319B1372653600DFB46D /* Box2DView.h */; };
+ 4913327113726D2F00DFB46D /* Delegates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913319D1372653600DFB46D /* Delegates.h */; };
+ 4913327213726D2F00DFB46D /* GLES-Render.h in Headers */ = {isa = PBXBuildFile; fileRef = 4913319E1372653600DFB46D /* GLES-Render.h */; };
+ 4913327313726D2F00DFB46D /* iPhoneTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 491331A01372653600DFB46D /* iPhoneTest.h */; };
+ 4913327413726D2F00DFB46D /* TestEntriesViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 491331A31372653600DFB46D /* TestEntriesViewController.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 491331BB1372661700DFB46D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 491331B41372661600DFB46D /* box2d-ios.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 4913305F1372610400DFB46D;
+ remoteInfo = Box2D;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 491331691372645C00DFB46D /* box2d-iphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "box2d-iphone.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4913316D1372645C00DFB46D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 4913316F1372645C00DFB46D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 491331711372645C00DFB46D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 491331971372653600DFB46D /* Box2D_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2D_Prefix.pch; sourceTree = "<group>"; };
+ 491331991372653600DFB46D /* Box2DAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2DAppDelegate.h; sourceTree = "<group>"; };
+ 4913319A1372653600DFB46D /* Box2DAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Box2DAppDelegate.mm; sourceTree = "<group>"; };
+ 4913319B1372653600DFB46D /* Box2DView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2DView.h; sourceTree = "<group>"; };
+ 4913319C1372653600DFB46D /* Box2DView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Box2DView.mm; sourceTree = "<group>"; };
+ 4913319D1372653600DFB46D /* Delegates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Delegates.h; sourceTree = "<group>"; };
+ 4913319E1372653600DFB46D /* GLES-Render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLES-Render.h"; sourceTree = "<group>"; };
+ 4913319F1372653600DFB46D /* GLES-Render.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "GLES-Render.mm"; sourceTree = "<group>"; };
+ 491331A01372653600DFB46D /* iPhoneTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneTest.h; sourceTree = "<group>"; };
+ 491331A11372653600DFB46D /* iPhoneTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iPhoneTest.mm; sourceTree = "<group>"; };
+ 491331A21372653600DFB46D /* iPhoneTestEntries.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iPhoneTestEntries.mm; sourceTree = "<group>"; };
+ 491331A31372653600DFB46D /* TestEntriesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestEntriesViewController.h; sourceTree = "<group>"; };
+ 491331A41372653600DFB46D /* TestEntriesViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestEntriesViewController.mm; sourceTree = "<group>"; };
+ 491331A51372653600DFB46D /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
+ 491331A61372653600DFB46D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 491331A71372653600DFB46D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 491331A81372653600DFB46D /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
+ 491331B41372661600DFB46D /* box2d-ios.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = "box2d-ios.xcodeproj"; sourceTree = SOURCE_ROOT; };
+ 491331C01372663200DFB46D /* libBox2D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libBox2D.a; sourceTree = SOURCE_ROOT; };
+ 4913320D13726B1F00DFB46D /* ApplyForce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplyForce.h; sourceTree = "<group>"; };
+ 4913320E13726B1F00DFB46D /* BodyTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BodyTypes.h; sourceTree = "<group>"; };
+ 4913320F13726B1F00DFB46D /* Breakable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakable.h; sourceTree = "<group>"; };
+ 4913321013726B1F00DFB46D /* Bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bridge.h; sourceTree = "<group>"; };
+ 4913321113726B1F00DFB46D /* BulletTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BulletTest.h; sourceTree = "<group>"; };
+ 4913321213726B1F00DFB46D /* Cantilever.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Cantilever.h; sourceTree = "<group>"; };
+ 4913321313726B1F00DFB46D /* Car.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Car.h; sourceTree = "<group>"; };
+ 4913321413726B1F00DFB46D /* Chain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Chain.h; sourceTree = "<group>"; };
+ 4913321513726B1F00DFB46D /* CharacterCollision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterCollision.h; sourceTree = "<group>"; };
+ 4913321613726B1F00DFB46D /* CollisionFiltering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollisionFiltering.h; sourceTree = "<group>"; };
+ 4913321713726B1F00DFB46D /* CollisionProcessing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollisionProcessing.h; sourceTree = "<group>"; };
+ 4913321813726B1F00DFB46D /* CompoundShapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompoundShapes.h; sourceTree = "<group>"; };
+ 4913321913726B1F00DFB46D /* Confined.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Confined.h; sourceTree = "<group>"; };
+ 4913321A13726B1F00DFB46D /* ContinuousTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContinuousTest.h; sourceTree = "<group>"; };
+ 4913321B13726B1F00DFB46D /* DistanceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DistanceTest.h; sourceTree = "<group>"; };
+ 4913321C13726B1F00DFB46D /* Dominos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dominos.h; sourceTree = "<group>"; };
+ 4913321D13726B1F00DFB46D /* DynamicTreeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicTreeTest.h; sourceTree = "<group>"; };
+ 4913321E13726B1F00DFB46D /* EdgeShapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdgeShapes.h; sourceTree = "<group>"; };
+ 4913321F13726B1F00DFB46D /* EdgeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdgeTest.h; sourceTree = "<group>"; };
+ 4913322013726B1F00DFB46D /* Gears.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gears.h; sourceTree = "<group>"; };
+ 4913322113726B1F00DFB46D /* LineJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineJoint.h; sourceTree = "<group>"; };
+ 4913322213726B1F00DFB46D /* OneSidedPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OneSidedPlatform.h; sourceTree = "<group>"; };
+ 4913322313726B1F00DFB46D /* Pinball.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pinball.h; sourceTree = "<group>"; };
+ 4913322413726B1F00DFB46D /* PolyCollision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolyCollision.h; sourceTree = "<group>"; };
+ 4913322513726B1F00DFB46D /* PolyShapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolyShapes.h; sourceTree = "<group>"; };
+ 4913322613726B1F00DFB46D /* Prismatic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prismatic.h; sourceTree = "<group>"; };
+ 4913322713726B1F00DFB46D /* Pulleys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pulleys.h; sourceTree = "<group>"; };
+ 4913322813726B1F00DFB46D /* Pyramid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pyramid.h; sourceTree = "<group>"; };
+ 4913322913726B1F00DFB46D /* RayCast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RayCast.h; sourceTree = "<group>"; };
+ 4913322A13726B1F00DFB46D /* Revolute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Revolute.h; sourceTree = "<group>"; };
+ 4913322B13726B1F00DFB46D /* Rope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Rope.h; sourceTree = "<group>"; };
+ 4913322C13726B1F00DFB46D /* RopeJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RopeJoint.h; sourceTree = "<group>"; };
+ 4913322D13726B1F00DFB46D /* SensorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SensorTest.h; sourceTree = "<group>"; };
+ 4913322E13726B1F00DFB46D /* ShapeEditing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShapeEditing.h; sourceTree = "<group>"; };
+ 4913322F13726B1F00DFB46D /* SliderCrank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SliderCrank.h; sourceTree = "<group>"; };
+ 4913323013726B1F00DFB46D /* SphereStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SphereStack.h; sourceTree = "<group>"; };
+ 4913323113726B1F00DFB46D /* TheoJansen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TheoJansen.h; sourceTree = "<group>"; };
+ 4913323213726B1F00DFB46D /* Tiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tiles.h; sourceTree = "<group>"; };
+ 4913323313726B1F00DFB46D /* TimeOfImpact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeOfImpact.h; sourceTree = "<group>"; };
+ 4913323413726B1F00DFB46D /* VaryingFriction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VaryingFriction.h; sourceTree = "<group>"; };
+ 4913323513726B1F00DFB46D /* VaryingRestitution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VaryingRestitution.h; sourceTree = "<group>"; };
+ 4913323613726B1F00DFB46D /* VerticalStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VerticalStack.h; sourceTree = "<group>"; };
+ 4913323713726B1F00DFB46D /* Web.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Web.h; sourceTree = "<group>"; };
+ 4913326313726B5D00DFB46D /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ 4913326D13726BC800DFB46D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 491331661372645C00DFB46D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4913326E13726BC800DFB46D /* QuartzCore.framework in Frameworks */,
+ 4913326413726B5D00DFB46D /* OpenGLES.framework in Frameworks */,
+ 4913316E1372645C00DFB46D /* UIKit.framework in Frameworks */,
+ 491331701372645C00DFB46D /* Foundation.framework in Frameworks */,
+ 491331721372645C00DFB46D /* CoreGraphics.framework in Frameworks */,
+ 491331C11372663200DFB46D /* libBox2D.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4913315E1372645C00DFB46D = {
+ isa = PBXGroup;
+ children = (
+ 491331B41372661600DFB46D /* box2d-ios.xcodeproj */,
+ 491331961372653600DFB46D /* iPhone */,
+ 4913320C13726B1F00DFB46D /* Tests */,
+ 491331B31372654900DFB46D /* Resources */,
+ 4913316C1372645C00DFB46D /* Frameworks */,
+ 4913316A1372645C00DFB46D /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 4913316A1372645C00DFB46D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 491331691372645C00DFB46D /* box2d-iphone.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4913316C1372645C00DFB46D /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 4913326D13726BC800DFB46D /* QuartzCore.framework */,
+ 4913326313726B5D00DFB46D /* OpenGLES.framework */,
+ 491331C01372663200DFB46D /* libBox2D.a */,
+ 4913316D1372645C00DFB46D /* UIKit.framework */,
+ 4913316F1372645C00DFB46D /* Foundation.framework */,
+ 491331711372645C00DFB46D /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 491331961372653600DFB46D /* iPhone */ = {
+ isa = PBXGroup;
+ children = (
+ 491331971372653600DFB46D /* Box2D_Prefix.pch */,
+ 491331981372653600DFB46D /* Classes */,
+ 491331A71372653600DFB46D /* main.m */,
+ 491331A81372653600DFB46D /* MainWindow.xib */,
+ );
+ path = iPhone;
+ sourceTree = "<group>";
+ };
+ 491331981372653600DFB46D /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 491331991372653600DFB46D /* Box2DAppDelegate.h */,
+ 4913319A1372653600DFB46D /* Box2DAppDelegate.mm */,
+ 4913319B1372653600DFB46D /* Box2DView.h */,
+ 4913319C1372653600DFB46D /* Box2DView.mm */,
+ 4913319D1372653600DFB46D /* Delegates.h */,
+ 4913319E1372653600DFB46D /* GLES-Render.h */,
+ 4913319F1372653600DFB46D /* GLES-Render.mm */,
+ 491331A01372653600DFB46D /* iPhoneTest.h */,
+ 491331A11372653600DFB46D /* iPhoneTest.mm */,
+ 491331A21372653600DFB46D /* iPhoneTestEntries.mm */,
+ 491331A31372653600DFB46D /* TestEntriesViewController.h */,
+ 491331A41372653600DFB46D /* TestEntriesViewController.mm */,
+ );
+ path = Classes;
+ sourceTree = "<group>";
+ };
+ 491331B31372654900DFB46D /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 491331A51372653600DFB46D /* Icon.png */,
+ 491331A61372653600DFB46D /* Info.plist */,
+ );
+ name = Resources;
+ path = iPhone;
+ sourceTree = "<group>";
+ };
+ 491331B51372661600DFB46D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 491331BC1372661700DFB46D /* libBox2D.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4913320C13726B1F00DFB46D /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+ 4913320D13726B1F00DFB46D /* ApplyForce.h */,
+ 4913320E13726B1F00DFB46D /* BodyTypes.h */,
+ 4913320F13726B1F00DFB46D /* Breakable.h */,
+ 4913321013726B1F00DFB46D /* Bridge.h */,
+ 4913321113726B1F00DFB46D /* BulletTest.h */,
+ 4913321213726B1F00DFB46D /* Cantilever.h */,
+ 4913321313726B1F00DFB46D /* Car.h */,
+ 4913321413726B1F00DFB46D /* Chain.h */,
+ 4913321513726B1F00DFB46D /* CharacterCollision.h */,
+ 4913321613726B1F00DFB46D /* CollisionFiltering.h */,
+ 4913321713726B1F00DFB46D /* CollisionProcessing.h */,
+ 4913321813726B1F00DFB46D /* CompoundShapes.h */,
+ 4913321913726B1F00DFB46D /* Confined.h */,
+ 4913321A13726B1F00DFB46D /* ContinuousTest.h */,
+ 4913321B13726B1F00DFB46D /* DistanceTest.h */,
+ 4913321C13726B1F00DFB46D /* Dominos.h */,
+ 4913321D13726B1F00DFB46D /* DynamicTreeTest.h */,
+ 4913321E13726B1F00DFB46D /* EdgeShapes.h */,
+ 4913321F13726B1F00DFB46D /* EdgeTest.h */,
+ 4913322013726B1F00DFB46D /* Gears.h */,
+ 4913322113726B1F00DFB46D /* LineJoint.h */,
+ 4913322213726B1F00DFB46D /* OneSidedPlatform.h */,
+ 4913322313726B1F00DFB46D /* Pinball.h */,
+ 4913322413726B1F00DFB46D /* PolyCollision.h */,
+ 4913322513726B1F00DFB46D /* PolyShapes.h */,
+ 4913322613726B1F00DFB46D /* Prismatic.h */,
+ 4913322713726B1F00DFB46D /* Pulleys.h */,
+ 4913322813726B1F00DFB46D /* Pyramid.h */,
+ 4913322913726B1F00DFB46D /* RayCast.h */,
+ 4913322A13726B1F00DFB46D /* Revolute.h */,
+ 4913322B13726B1F00DFB46D /* Rope.h */,
+ 4913322C13726B1F00DFB46D /* RopeJoint.h */,
+ 4913322D13726B1F00DFB46D /* SensorTest.h */,
+ 4913322E13726B1F00DFB46D /* ShapeEditing.h */,
+ 4913322F13726B1F00DFB46D /* SliderCrank.h */,
+ 4913323013726B1F00DFB46D /* SphereStack.h */,
+ 4913323113726B1F00DFB46D /* TheoJansen.h */,
+ 4913323213726B1F00DFB46D /* Tiles.h */,
+ 4913323313726B1F00DFB46D /* TimeOfImpact.h */,
+ 4913323413726B1F00DFB46D /* VaryingFriction.h */,
+ 4913323513726B1F00DFB46D /* VaryingRestitution.h */,
+ 4913323613726B1F00DFB46D /* VerticalStack.h */,
+ 4913323713726B1F00DFB46D /* Web.h */,
+ );
+ name = Tests;
+ path = src/Tests;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 491331E71372682200DFB46D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4913326F13726D2F00DFB46D /* Box2DAppDelegate.h in Headers */,
+ 4913327013726D2F00DFB46D /* Box2DView.h in Headers */,
+ 4913327113726D2F00DFB46D /* Delegates.h in Headers */,
+ 4913327213726D2F00DFB46D /* GLES-Render.h in Headers */,
+ 4913327313726D2F00DFB46D /* iPhoneTest.h in Headers */,
+ 4913327413726D2F00DFB46D /* TestEntriesViewController.h in Headers */,
+ 4913323813726B1F00DFB46D /* ApplyForce.h in Headers */,
+ 4913323913726B1F00DFB46D /* BodyTypes.h in Headers */,
+ 4913323A13726B1F00DFB46D /* Breakable.h in Headers */,
+ 4913323B13726B1F00DFB46D /* Bridge.h in Headers */,
+ 4913323C13726B1F00DFB46D /* BulletTest.h in Headers */,
+ 4913323D13726B1F00DFB46D /* Cantilever.h in Headers */,
+ 4913323E13726B1F00DFB46D /* Car.h in Headers */,
+ 4913323F13726B1F00DFB46D /* Chain.h in Headers */,
+ 4913324013726B1F00DFB46D /* CharacterCollision.h in Headers */,
+ 4913324113726B1F00DFB46D /* CollisionFiltering.h in Headers */,
+ 4913324213726B1F00DFB46D /* CollisionProcessing.h in Headers */,
+ 4913324313726B1F00DFB46D /* CompoundShapes.h in Headers */,
+ 4913324413726B1F00DFB46D /* Confined.h in Headers */,
+ 4913324513726B1F00DFB46D /* ContinuousTest.h in Headers */,
+ 4913324613726B1F00DFB46D /* DistanceTest.h in Headers */,
+ 4913324713726B1F00DFB46D /* Dominos.h in Headers */,
+ 4913324813726B1F00DFB46D /* DynamicTreeTest.h in Headers */,
+ 4913324913726B1F00DFB46D /* EdgeShapes.h in Headers */,
+ 4913324A13726B1F00DFB46D /* EdgeTest.h in Headers */,
+ 4913324B13726B1F00DFB46D /* Gears.h in Headers */,
+ 4913324C13726B1F00DFB46D /* LineJoint.h in Headers */,
+ 4913324D13726B1F00DFB46D /* OneSidedPlatform.h in Headers */,
+ 4913324E13726B1F00DFB46D /* Pinball.h in Headers */,
+ 4913324F13726B1F00DFB46D /* PolyCollision.h in Headers */,
+ 4913325013726B1F00DFB46D /* PolyShapes.h in Headers */,
+ 4913325113726B1F00DFB46D /* Prismatic.h in Headers */,
+ 4913325213726B1F00DFB46D /* Pulleys.h in Headers */,
+ 4913325313726B1F00DFB46D /* Pyramid.h in Headers */,
+ 4913325413726B1F00DFB46D /* RayCast.h in Headers */,
+ 4913325513726B1F00DFB46D /* Revolute.h in Headers */,
+ 4913325613726B1F00DFB46D /* Rope.h in Headers */,
+ 4913325713726B1F00DFB46D /* RopeJoint.h in Headers */,
+ 4913325813726B1F00DFB46D /* SensorTest.h in Headers */,
+ 4913325913726B1F00DFB46D /* ShapeEditing.h in Headers */,
+ 4913325A13726B1F00DFB46D /* SliderCrank.h in Headers */,
+ 4913325B13726B1F00DFB46D /* SphereStack.h in Headers */,
+ 4913325C13726B1F00DFB46D /* TheoJansen.h in Headers */,
+ 4913325D13726B1F00DFB46D /* Tiles.h in Headers */,
+ 4913325E13726B1F00DFB46D /* TimeOfImpact.h in Headers */,
+ 4913325F13726B1F00DFB46D /* VaryingFriction.h in Headers */,
+ 4913326013726B1F00DFB46D /* VaryingRestitution.h in Headers */,
+ 4913326113726B1F00DFB46D /* VerticalStack.h in Headers */,
+ 4913326213726B1F00DFB46D /* Web.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 491331681372645C00DFB46D /* box2d-iphone */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 491331841372645C00DFB46D /* Build configuration list for PBXNativeTarget "box2d-iphone" */;
+ buildPhases = (
+ 491331651372645C00DFB46D /* Sources */,
+ 491331661372645C00DFB46D /* Frameworks */,
+ 491331671372645C00DFB46D /* Resources */,
+ 491331E71372682200DFB46D /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "box2d-iphone";
+ productName = "box2d-iphone";
+ productReference = 491331691372645C00DFB46D /* box2d-iphone.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 491331601372645C00DFB46D /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 491331631372645C00DFB46D /* Build configuration list for PBXProject "box2d-iphone" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 4913315E1372645C00DFB46D;
+ productRefGroup = 4913316A1372645C00DFB46D /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 491331B51372661600DFB46D /* Products */;
+ ProjectRef = 491331B41372661600DFB46D /* box2d-ios.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 491331681372645C00DFB46D /* box2d-iphone */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 491331BC1372661700DFB46D /* libBox2D.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libBox2D.a;
+ remoteRef = 491331BB1372661700DFB46D /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 491331671372645C00DFB46D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 491331AF1372653600DFB46D /* Icon.png in Resources */,
+ 491331B01372653600DFB46D /* Info.plist in Resources */,
+ 491331B21372653600DFB46D /* MainWindow.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 491331651372645C00DFB46D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 491331A91372653600DFB46D /* Box2DAppDelegate.mm in Sources */,
+ 491331AA1372653600DFB46D /* Box2DView.mm in Sources */,
+ 491331AB1372653600DFB46D /* GLES-Render.mm in Sources */,
+ 491331AC1372653600DFB46D /* iPhoneTest.mm in Sources */,
+ 491331AD1372653600DFB46D /* iPhoneTestEntries.mm in Sources */,
+ 491331AE1372653600DFB46D /* TestEntriesViewController.mm in Sources */,
+ 491331B11372653600DFB46D /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 491331821372645C00DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 491331831372645C00DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+ 491331851372645C00DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "box2d-iphone/box2d-iphone-Prefix.pch";
+ GCC_VERSION = 4.2;
+ HEADER_SEARCH_PATHS = "./src/**";
+ INFOPLIST_FILE = "box2d-iphone/box2d-iphone-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)\"",
+ );
+ OTHER_LDFLAGS = "-Wl,-search_paths_first";
+ PREBINDING = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ USE_HEADERMAP = NO;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 491331861372645C00DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ COPY_PHASE_STRIP = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "box2d-iphone/box2d-iphone-Prefix.pch";
+ GCC_VERSION = 4.2;
+ HEADER_SEARCH_PATHS = "./src/**";
+ INFOPLIST_FILE = "box2d-iphone/box2d-iphone-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)\"",
+ );
+ OTHER_LDFLAGS = "-Wl,-search_paths_first";
+ PREBINDING = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ USE_HEADERMAP = NO;
+ VALIDATE_PRODUCT = YES;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 491331631372645C00DFB46D /* Build configuration list for PBXProject "box2d-iphone" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 491331821372645C00DFB46D /* Debug */,
+ 491331831372645C00DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 491331841372645C00DFB46D /* Build configuration list for PBXNativeTarget "box2d-iphone" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 491331851372645C00DFB46D /* Debug */,
+ 491331861372645C00DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 491331601372645C00DFB46D /* Project object */;
+}
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 49132FCD13725D1000DFB46D /* Box2D.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8013725D1000DFB46D /* Box2D.h */; };
+ 49132FCE13725D1000DFB46D /* b2BroadPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8213725D1000DFB46D /* b2BroadPhase.cpp */; };
+ 49132FCF13725D1000DFB46D /* b2BroadPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8313725D1000DFB46D /* b2BroadPhase.h */; };
+ 49132FD013725D1000DFB46D /* b2CollideCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8413725D1000DFB46D /* b2CollideCircle.cpp */; };
+ 49132FD113725D1000DFB46D /* b2CollidePolygon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8513725D1000DFB46D /* b2CollidePolygon.cpp */; };
+ 49132FD213725D1000DFB46D /* b2Collision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8613725D1000DFB46D /* b2Collision.cpp */; };
+ 49132FD313725D1000DFB46D /* b2Collision.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8713725D1000DFB46D /* b2Collision.h */; };
+ 49132FD413725D1000DFB46D /* b2Distance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8813725D1000DFB46D /* b2Distance.cpp */; };
+ 49132FD513725D1000DFB46D /* b2Distance.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8913725D1000DFB46D /* b2Distance.h */; };
+ 49132FD613725D1000DFB46D /* b2DynamicTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8A13725D1000DFB46D /* b2DynamicTree.cpp */; };
+ 49132FD713725D1000DFB46D /* b2DynamicTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8B13725D1000DFB46D /* b2DynamicTree.h */; };
+ 49132FD813725D1000DFB46D /* b2TimeOfImpact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8C13725D1000DFB46D /* b2TimeOfImpact.cpp */; };
+ 49132FD913725D1000DFB46D /* b2TimeOfImpact.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F8D13725D1000DFB46D /* b2TimeOfImpact.h */; };
+ 49132FDA13725D1000DFB46D /* b2CircleShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F8F13725D1000DFB46D /* b2CircleShape.cpp */; };
+ 49132FDB13725D1000DFB46D /* b2CircleShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9013725D1000DFB46D /* b2CircleShape.h */; };
+ 49132FDC13725D1000DFB46D /* b2PolygonShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9113725D1000DFB46D /* b2PolygonShape.cpp */; };
+ 49132FDD13725D1000DFB46D /* b2PolygonShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9213725D1000DFB46D /* b2PolygonShape.h */; };
+ 49132FDE13725D1000DFB46D /* b2Shape.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9313725D1000DFB46D /* b2Shape.h */; };
+ 49132FDF13725D1000DFB46D /* b2BlockAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9513725D1000DFB46D /* b2BlockAllocator.cpp */; };
+ 49132FE013725D1000DFB46D /* b2BlockAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9613725D1000DFB46D /* b2BlockAllocator.h */; };
+ 49132FE113725D1000DFB46D /* b2Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9713725D1000DFB46D /* b2Math.cpp */; };
+ 49132FE213725D1000DFB46D /* b2Math.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9813725D1000DFB46D /* b2Math.h */; };
+ 49132FE313725D1000DFB46D /* b2Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9913725D1000DFB46D /* b2Settings.cpp */; };
+ 49132FE413725D1000DFB46D /* b2Settings.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9A13725D1000DFB46D /* b2Settings.h */; };
+ 49132FE513725D1000DFB46D /* b2StackAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9B13725D1000DFB46D /* b2StackAllocator.cpp */; };
+ 49132FE613725D1000DFB46D /* b2StackAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9C13725D1000DFB46D /* b2StackAllocator.h */; };
+ 49132FE713725D1000DFB46D /* b2Body.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132F9E13725D1000DFB46D /* b2Body.cpp */; };
+ 49132FE813725D1000DFB46D /* b2Body.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132F9F13725D1000DFB46D /* b2Body.h */; };
+ 49132FE913725D1000DFB46D /* b2ContactManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FA013725D1000DFB46D /* b2ContactManager.cpp */; };
+ 49132FEA13725D1000DFB46D /* b2ContactManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FA113725D1000DFB46D /* b2ContactManager.h */; };
+ 49132FEB13725D1000DFB46D /* b2Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FA213725D1000DFB46D /* b2Fixture.cpp */; };
+ 49132FEC13725D1000DFB46D /* b2Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FA313725D1000DFB46D /* b2Fixture.h */; };
+ 49132FED13725D1000DFB46D /* b2Island.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FA413725D1000DFB46D /* b2Island.cpp */; };
+ 49132FEE13725D1000DFB46D /* b2Island.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FA513725D1000DFB46D /* b2Island.h */; };
+ 49132FEF13725D1000DFB46D /* b2TimeStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FA613725D1000DFB46D /* b2TimeStep.h */; };
+ 49132FF013725D1000DFB46D /* b2World.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FA713725D1000DFB46D /* b2World.cpp */; };
+ 49132FF113725D1000DFB46D /* b2World.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FA813725D1000DFB46D /* b2World.h */; };
+ 49132FF213725D1000DFB46D /* b2WorldCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FA913725D1000DFB46D /* b2WorldCallbacks.cpp */; };
+ 49132FF313725D1000DFB46D /* b2WorldCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FAA13725D1000DFB46D /* b2WorldCallbacks.h */; };
+ 49132FF413725D1000DFB46D /* b2CircleContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FAC13725D1000DFB46D /* b2CircleContact.cpp */; };
+ 49132FF513725D1000DFB46D /* b2CircleContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FAD13725D1000DFB46D /* b2CircleContact.h */; };
+ 49132FF613725D1000DFB46D /* b2Contact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FAE13725D1000DFB46D /* b2Contact.cpp */; };
+ 49132FF713725D1000DFB46D /* b2Contact.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FAF13725D1000DFB46D /* b2Contact.h */; };
+ 49132FF813725D1000DFB46D /* b2ContactSolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FB013725D1000DFB46D /* b2ContactSolver.cpp */; };
+ 49132FF913725D1000DFB46D /* b2ContactSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FB113725D1000DFB46D /* b2ContactSolver.h */; };
+ 49132FFA13725D1000DFB46D /* b2PolygonAndCircleContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FB213725D1000DFB46D /* b2PolygonAndCircleContact.cpp */; };
+ 49132FFB13725D1000DFB46D /* b2PolygonAndCircleContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FB313725D1000DFB46D /* b2PolygonAndCircleContact.h */; };
+ 49132FFC13725D1000DFB46D /* b2PolygonContact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FB413725D1000DFB46D /* b2PolygonContact.cpp */; };
+ 49132FFD13725D1000DFB46D /* b2PolygonContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FB513725D1000DFB46D /* b2PolygonContact.h */; };
+ 49132FFE13725D1000DFB46D /* b2TOISolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FB613725D1000DFB46D /* b2TOISolver.cpp */; };
+ 49132FFF13725D1000DFB46D /* b2TOISolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FB713725D1000DFB46D /* b2TOISolver.h */; };
+ 4913300013725D1000DFB46D /* b2DistanceJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FB913725D1000DFB46D /* b2DistanceJoint.cpp */; };
+ 4913300113725D1000DFB46D /* b2DistanceJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FBA13725D1000DFB46D /* b2DistanceJoint.h */; };
+ 4913300213725D1000DFB46D /* b2FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FBB13725D1000DFB46D /* b2FrictionJoint.cpp */; };
+ 4913300313725D1000DFB46D /* b2FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FBC13725D1000DFB46D /* b2FrictionJoint.h */; };
+ 4913300413725D1000DFB46D /* b2GearJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FBD13725D1000DFB46D /* b2GearJoint.cpp */; };
+ 4913300513725D1000DFB46D /* b2GearJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FBE13725D1000DFB46D /* b2GearJoint.h */; };
+ 4913300613725D1000DFB46D /* b2Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FBF13725D1000DFB46D /* b2Joint.cpp */; };
+ 4913300713725D1000DFB46D /* b2Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FC013725D1000DFB46D /* b2Joint.h */; };
+ 4913300813725D1000DFB46D /* b2LineJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FC113725D1000DFB46D /* b2LineJoint.cpp */; };
+ 4913300913725D1000DFB46D /* b2LineJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FC213725D1000DFB46D /* b2LineJoint.h */; };
+ 4913300A13725D1000DFB46D /* b2MouseJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FC313725D1000DFB46D /* b2MouseJoint.cpp */; };
+ 4913300B13725D1000DFB46D /* b2MouseJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FC413725D1000DFB46D /* b2MouseJoint.h */; };
+ 4913300C13725D1000DFB46D /* b2PrismaticJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FC513725D1000DFB46D /* b2PrismaticJoint.cpp */; };
+ 4913300D13725D1000DFB46D /* b2PrismaticJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FC613725D1000DFB46D /* b2PrismaticJoint.h */; };
+ 4913300E13725D1000DFB46D /* b2PulleyJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FC713725D1000DFB46D /* b2PulleyJoint.cpp */; };
+ 4913300F13725D1000DFB46D /* b2PulleyJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FC813725D1000DFB46D /* b2PulleyJoint.h */; };
+ 4913301013725D1000DFB46D /* b2RevoluteJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FC913725D1000DFB46D /* b2RevoluteJoint.cpp */; };
+ 4913301113725D1000DFB46D /* b2RevoluteJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FCA13725D1000DFB46D /* b2RevoluteJoint.h */; };
+ 4913301213725D1000DFB46D /* b2WeldJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49132FCB13725D1000DFB46D /* b2WeldJoint.cpp */; };
+ 4913301313725D1000DFB46D /* b2WeldJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 49132FCC13725D1000DFB46D /* b2WeldJoint.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 49132F7113725CDD00DFB46D /* Box2D.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = Box2D.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+ 49132F7413725CDD00DFB46D /* Box2D-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Box2D-Prefix.pch"; sourceTree = "<group>"; };
+ 49132F7513725CDD00DFB46D /* Box2DProj.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Box2DProj.xcconfig; sourceTree = "<group>"; };
+ 49132F7613725CDD00DFB46D /* Box2DTarget.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Box2DTarget.xcconfig; sourceTree = "<group>"; };
+ 49132F8013725D1000DFB46D /* Box2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2D.h; sourceTree = "<group>"; };
+ 49132F8213725D1000DFB46D /* b2BroadPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2BroadPhase.cpp; sourceTree = "<group>"; };
+ 49132F8313725D1000DFB46D /* b2BroadPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2BroadPhase.h; sourceTree = "<group>"; };
+ 49132F8413725D1000DFB46D /* b2CollideCircle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollideCircle.cpp; sourceTree = "<group>"; };
+ 49132F8513725D1000DFB46D /* b2CollidePolygon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollidePolygon.cpp; sourceTree = "<group>"; };
+ 49132F8613725D1000DFB46D /* b2Collision.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Collision.cpp; sourceTree = "<group>"; };
+ 49132F8713725D1000DFB46D /* b2Collision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Collision.h; sourceTree = "<group>"; };
+ 49132F8813725D1000DFB46D /* b2Distance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Distance.cpp; sourceTree = "<group>"; };
+ 49132F8913725D1000DFB46D /* b2Distance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Distance.h; sourceTree = "<group>"; };
+ 49132F8A13725D1000DFB46D /* b2DynamicTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2DynamicTree.cpp; sourceTree = "<group>"; };
+ 49132F8B13725D1000DFB46D /* b2DynamicTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2DynamicTree.h; sourceTree = "<group>"; };
+ 49132F8C13725D1000DFB46D /* b2TimeOfImpact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2TimeOfImpact.cpp; sourceTree = "<group>"; };
+ 49132F8D13725D1000DFB46D /* b2TimeOfImpact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TimeOfImpact.h; sourceTree = "<group>"; };
+ 49132F8F13725D1000DFB46D /* b2CircleShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CircleShape.cpp; sourceTree = "<group>"; };
+ 49132F9013725D1000DFB46D /* b2CircleShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2CircleShape.h; sourceTree = "<group>"; };
+ 49132F9113725D1000DFB46D /* b2PolygonShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonShape.cpp; sourceTree = "<group>"; };
+ 49132F9213725D1000DFB46D /* b2PolygonShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonShape.h; sourceTree = "<group>"; };
+ 49132F9313725D1000DFB46D /* b2Shape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Shape.h; sourceTree = "<group>"; };
+ 49132F9513725D1000DFB46D /* b2BlockAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2BlockAllocator.cpp; sourceTree = "<group>"; };
+ 49132F9613725D1000DFB46D /* b2BlockAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2BlockAllocator.h; sourceTree = "<group>"; };
+ 49132F9713725D1000DFB46D /* b2Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Math.cpp; sourceTree = "<group>"; };
+ 49132F9813725D1000DFB46D /* b2Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Math.h; sourceTree = "<group>"; };
+ 49132F9913725D1000DFB46D /* b2Settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Settings.cpp; sourceTree = "<group>"; };
+ 49132F9A13725D1000DFB46D /* b2Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Settings.h; sourceTree = "<group>"; };
+ 49132F9B13725D1000DFB46D /* b2StackAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2StackAllocator.cpp; sourceTree = "<group>"; };
+ 49132F9C13725D1000DFB46D /* b2StackAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2StackAllocator.h; sourceTree = "<group>"; };
+ 49132F9E13725D1000DFB46D /* b2Body.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Body.cpp; sourceTree = "<group>"; };
+ 49132F9F13725D1000DFB46D /* b2Body.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Body.h; sourceTree = "<group>"; };
+ 49132FA013725D1000DFB46D /* b2ContactManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2ContactManager.cpp; sourceTree = "<group>"; };
+ 49132FA113725D1000DFB46D /* b2ContactManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2ContactManager.h; sourceTree = "<group>"; };
+ 49132FA213725D1000DFB46D /* b2Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Fixture.cpp; sourceTree = "<group>"; };
+ 49132FA313725D1000DFB46D /* b2Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Fixture.h; sourceTree = "<group>"; };
+ 49132FA413725D1000DFB46D /* b2Island.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Island.cpp; sourceTree = "<group>"; };
+ 49132FA513725D1000DFB46D /* b2Island.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Island.h; sourceTree = "<group>"; };
+ 49132FA613725D1000DFB46D /* b2TimeStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TimeStep.h; sourceTree = "<group>"; };
+ 49132FA713725D1000DFB46D /* b2World.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2World.cpp; sourceTree = "<group>"; };
+ 49132FA813725D1000DFB46D /* b2World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2World.h; sourceTree = "<group>"; };
+ 49132FA913725D1000DFB46D /* b2WorldCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2WorldCallbacks.cpp; sourceTree = "<group>"; };
+ 49132FAA13725D1000DFB46D /* b2WorldCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2WorldCallbacks.h; sourceTree = "<group>"; };
+ 49132FAC13725D1000DFB46D /* b2CircleContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2CircleContact.cpp; sourceTree = "<group>"; };
+ 49132FAD13725D1000DFB46D /* b2CircleContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2CircleContact.h; sourceTree = "<group>"; };
+ 49132FAE13725D1000DFB46D /* b2Contact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Contact.cpp; sourceTree = "<group>"; };
+ 49132FAF13725D1000DFB46D /* b2Contact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Contact.h; sourceTree = "<group>"; };
+ 49132FB013725D1000DFB46D /* b2ContactSolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2ContactSolver.cpp; sourceTree = "<group>"; };
+ 49132FB113725D1000DFB46D /* b2ContactSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2ContactSolver.h; sourceTree = "<group>"; };
+ 49132FB213725D1000DFB46D /* b2PolygonAndCircleContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonAndCircleContact.cpp; sourceTree = "<group>"; };
+ 49132FB313725D1000DFB46D /* b2PolygonAndCircleContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonAndCircleContact.h; sourceTree = "<group>"; };
+ 49132FB413725D1000DFB46D /* b2PolygonContact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PolygonContact.cpp; sourceTree = "<group>"; };
+ 49132FB513725D1000DFB46D /* b2PolygonContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PolygonContact.h; sourceTree = "<group>"; };
+ 49132FB613725D1000DFB46D /* b2TOISolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2TOISolver.cpp; sourceTree = "<group>"; };
+ 49132FB713725D1000DFB46D /* b2TOISolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2TOISolver.h; sourceTree = "<group>"; };
+ 49132FB913725D1000DFB46D /* b2DistanceJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2DistanceJoint.cpp; sourceTree = "<group>"; };
+ 49132FBA13725D1000DFB46D /* b2DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2DistanceJoint.h; sourceTree = "<group>"; };
+ 49132FBB13725D1000DFB46D /* b2FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2FrictionJoint.cpp; sourceTree = "<group>"; };
+ 49132FBC13725D1000DFB46D /* b2FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2FrictionJoint.h; sourceTree = "<group>"; };
+ 49132FBD13725D1000DFB46D /* b2GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2GearJoint.cpp; sourceTree = "<group>"; };
+ 49132FBE13725D1000DFB46D /* b2GearJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2GearJoint.h; sourceTree = "<group>"; };
+ 49132FBF13725D1000DFB46D /* b2Joint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2Joint.cpp; sourceTree = "<group>"; };
+ 49132FC013725D1000DFB46D /* b2Joint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2Joint.h; sourceTree = "<group>"; };
+ 49132FC113725D1000DFB46D /* b2LineJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2LineJoint.cpp; sourceTree = "<group>"; };
+ 49132FC213725D1000DFB46D /* b2LineJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2LineJoint.h; sourceTree = "<group>"; };
+ 49132FC313725D1000DFB46D /* b2MouseJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2MouseJoint.cpp; sourceTree = "<group>"; };
+ 49132FC413725D1000DFB46D /* b2MouseJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2MouseJoint.h; sourceTree = "<group>"; };
+ 49132FC513725D1000DFB46D /* b2PrismaticJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PrismaticJoint.cpp; sourceTree = "<group>"; };
+ 49132FC613725D1000DFB46D /* b2PrismaticJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PrismaticJoint.h; sourceTree = "<group>"; };
+ 49132FC713725D1000DFB46D /* b2PulleyJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2PulleyJoint.cpp; sourceTree = "<group>"; };
+ 49132FC813725D1000DFB46D /* b2PulleyJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2PulleyJoint.h; sourceTree = "<group>"; };
+ 49132FC913725D1000DFB46D /* b2RevoluteJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2RevoluteJoint.cpp; sourceTree = "<group>"; };
+ 49132FCA13725D1000DFB46D /* b2RevoluteJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2RevoluteJoint.h; sourceTree = "<group>"; };
+ 49132FCB13725D1000DFB46D /* b2WeldJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2WeldJoint.cpp; sourceTree = "<group>"; };
+ 49132FCC13725D1000DFB46D /* b2WeldJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2WeldJoint.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 49132F6E13725CDD00DFB46D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 49132EDD13725A9600DFB46D = {
+ isa = PBXGroup;
+ children = (
+ 49132F7F13725D1000DFB46D /* Box2D */,
+ 49132F7113725CDD00DFB46D /* Box2D.dylib */,
+ 49132F7213725CDD00DFB46D /* Box2D */,
+ );
+ sourceTree = "<group>";
+ };
+ 49132F7213725CDD00DFB46D /* Box2D */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F7513725CDD00DFB46D /* Box2DProj.xcconfig */,
+ 49132F7613725CDD00DFB46D /* Box2DTarget.xcconfig */,
+ 49132F7313725CDD00DFB46D /* Supporting Files */,
+ );
+ path = Box2D;
+ sourceTree = "<group>";
+ };
+ 49132F7313725CDD00DFB46D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F7413725CDD00DFB46D /* Box2D-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 49132F7F13725D1000DFB46D /* Box2D */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F8013725D1000DFB46D /* Box2D.h */,
+ 49132F8113725D1000DFB46D /* Collision */,
+ 49132F9413725D1000DFB46D /* Common */,
+ 49132F9D13725D1000DFB46D /* Dynamics */,
+ );
+ name = Box2D;
+ path = src/Box2D;
+ sourceTree = "<group>";
+ };
+ 49132F8113725D1000DFB46D /* Collision */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F8213725D1000DFB46D /* b2BroadPhase.cpp */,
+ 49132F8313725D1000DFB46D /* b2BroadPhase.h */,
+ 49132F8413725D1000DFB46D /* b2CollideCircle.cpp */,
+ 49132F8513725D1000DFB46D /* b2CollidePolygon.cpp */,
+ 49132F8613725D1000DFB46D /* b2Collision.cpp */,
+ 49132F8713725D1000DFB46D /* b2Collision.h */,
+ 49132F8813725D1000DFB46D /* b2Distance.cpp */,
+ 49132F8913725D1000DFB46D /* b2Distance.h */,
+ 49132F8A13725D1000DFB46D /* b2DynamicTree.cpp */,
+ 49132F8B13725D1000DFB46D /* b2DynamicTree.h */,
+ 49132F8C13725D1000DFB46D /* b2TimeOfImpact.cpp */,
+ 49132F8D13725D1000DFB46D /* b2TimeOfImpact.h */,
+ 49132F8E13725D1000DFB46D /* Shapes */,
+ );
+ path = Collision;
+ sourceTree = "<group>";
+ };
+ 49132F8E13725D1000DFB46D /* Shapes */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F8F13725D1000DFB46D /* b2CircleShape.cpp */,
+ 49132F9013725D1000DFB46D /* b2CircleShape.h */,
+ 49132F9113725D1000DFB46D /* b2PolygonShape.cpp */,
+ 49132F9213725D1000DFB46D /* b2PolygonShape.h */,
+ 49132F9313725D1000DFB46D /* b2Shape.h */,
+ );
+ path = Shapes;
+ sourceTree = "<group>";
+ };
+ 49132F9413725D1000DFB46D /* Common */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F9513725D1000DFB46D /* b2BlockAllocator.cpp */,
+ 49132F9613725D1000DFB46D /* b2BlockAllocator.h */,
+ 49132F9713725D1000DFB46D /* b2Math.cpp */,
+ 49132F9813725D1000DFB46D /* b2Math.h */,
+ 49132F9913725D1000DFB46D /* b2Settings.cpp */,
+ 49132F9A13725D1000DFB46D /* b2Settings.h */,
+ 49132F9B13725D1000DFB46D /* b2StackAllocator.cpp */,
+ 49132F9C13725D1000DFB46D /* b2StackAllocator.h */,
+ );
+ path = Common;
+ sourceTree = "<group>";
+ };
+ 49132F9D13725D1000DFB46D /* Dynamics */ = {
+ isa = PBXGroup;
+ children = (
+ 49132F9E13725D1000DFB46D /* b2Body.cpp */,
+ 49132F9F13725D1000DFB46D /* b2Body.h */,
+ 49132FA013725D1000DFB46D /* b2ContactManager.cpp */,
+ 49132FA113725D1000DFB46D /* b2ContactManager.h */,
+ 49132FA213725D1000DFB46D /* b2Fixture.cpp */,
+ 49132FA313725D1000DFB46D /* b2Fixture.h */,
+ 49132FA413725D1000DFB46D /* b2Island.cpp */,
+ 49132FA513725D1000DFB46D /* b2Island.h */,
+ 49132FA613725D1000DFB46D /* b2TimeStep.h */,
+ 49132FA713725D1000DFB46D /* b2World.cpp */,
+ 49132FA813725D1000DFB46D /* b2World.h */,
+ 49132FA913725D1000DFB46D /* b2WorldCallbacks.cpp */,
+ 49132FAA13725D1000DFB46D /* b2WorldCallbacks.h */,
+ 49132FAB13725D1000DFB46D /* Contacts */,
+ 49132FB813725D1000DFB46D /* Joints */,
+ );
+ path = Dynamics;
+ sourceTree = "<group>";
+ };
+ 49132FAB13725D1000DFB46D /* Contacts */ = {
+ isa = PBXGroup;
+ children = (
+ 49132FAC13725D1000DFB46D /* b2CircleContact.cpp */,
+ 49132FAD13725D1000DFB46D /* b2CircleContact.h */,
+ 49132FAE13725D1000DFB46D /* b2Contact.cpp */,
+ 49132FAF13725D1000DFB46D /* b2Contact.h */,
+ 49132FB013725D1000DFB46D /* b2ContactSolver.cpp */,
+ 49132FB113725D1000DFB46D /* b2ContactSolver.h */,
+ 49132FB213725D1000DFB46D /* b2PolygonAndCircleContact.cpp */,
+ 49132FB313725D1000DFB46D /* b2PolygonAndCircleContact.h */,
+ 49132FB413725D1000DFB46D /* b2PolygonContact.cpp */,
+ 49132FB513725D1000DFB46D /* b2PolygonContact.h */,
+ 49132FB613725D1000DFB46D /* b2TOISolver.cpp */,
+ 49132FB713725D1000DFB46D /* b2TOISolver.h */,
+ );
+ path = Contacts;
+ sourceTree = "<group>";
+ };
+ 49132FB813725D1000DFB46D /* Joints */ = {
+ isa = PBXGroup;
+ children = (
+ 49132FB913725D1000DFB46D /* b2DistanceJoint.cpp */,
+ 49132FBA13725D1000DFB46D /* b2DistanceJoint.h */,
+ 49132FBB13725D1000DFB46D /* b2FrictionJoint.cpp */,
+ 49132FBC13725D1000DFB46D /* b2FrictionJoint.h */,
+ 49132FBD13725D1000DFB46D /* b2GearJoint.cpp */,
+ 49132FBE13725D1000DFB46D /* b2GearJoint.h */,
+ 49132FBF13725D1000DFB46D /* b2Joint.cpp */,
+ 49132FC013725D1000DFB46D /* b2Joint.h */,
+ 49132FC113725D1000DFB46D /* b2LineJoint.cpp */,
+ 49132FC213725D1000DFB46D /* b2LineJoint.h */,
+ 49132FC313725D1000DFB46D /* b2MouseJoint.cpp */,
+ 49132FC413725D1000DFB46D /* b2MouseJoint.h */,
+ 49132FC513725D1000DFB46D /* b2PrismaticJoint.cpp */,
+ 49132FC613725D1000DFB46D /* b2PrismaticJoint.h */,
+ 49132FC713725D1000DFB46D /* b2PulleyJoint.cpp */,
+ 49132FC813725D1000DFB46D /* b2PulleyJoint.h */,
+ 49132FC913725D1000DFB46D /* b2RevoluteJoint.cpp */,
+ 49132FCA13725D1000DFB46D /* b2RevoluteJoint.h */,
+ 49132FCB13725D1000DFB46D /* b2WeldJoint.cpp */,
+ 49132FCC13725D1000DFB46D /* b2WeldJoint.h */,
+ );
+ path = Joints;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 49132F6F13725CDD00DFB46D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 49132FCD13725D1000DFB46D /* Box2D.h in Headers */,
+ 49132FCF13725D1000DFB46D /* b2BroadPhase.h in Headers */,
+ 49132FD313725D1000DFB46D /* b2Collision.h in Headers */,
+ 49132FD513725D1000DFB46D /* b2Distance.h in Headers */,
+ 49132FD713725D1000DFB46D /* b2DynamicTree.h in Headers */,
+ 49132FD913725D1000DFB46D /* b2TimeOfImpact.h in Headers */,
+ 49132FDB13725D1000DFB46D /* b2CircleShape.h in Headers */,
+ 49132FDD13725D1000DFB46D /* b2PolygonShape.h in Headers */,
+ 49132FDE13725D1000DFB46D /* b2Shape.h in Headers */,
+ 49132FE013725D1000DFB46D /* b2BlockAllocator.h in Headers */,
+ 49132FE213725D1000DFB46D /* b2Math.h in Headers */,
+ 49132FE413725D1000DFB46D /* b2Settings.h in Headers */,
+ 49132FE613725D1000DFB46D /* b2StackAllocator.h in Headers */,
+ 49132FE813725D1000DFB46D /* b2Body.h in Headers */,
+ 49132FEA13725D1000DFB46D /* b2ContactManager.h in Headers */,
+ 49132FEC13725D1000DFB46D /* b2Fixture.h in Headers */,
+ 49132FEE13725D1000DFB46D /* b2Island.h in Headers */,
+ 49132FEF13725D1000DFB46D /* b2TimeStep.h in Headers */,
+ 49132FF113725D1000DFB46D /* b2World.h in Headers */,
+ 49132FF313725D1000DFB46D /* b2WorldCallbacks.h in Headers */,
+ 49132FF513725D1000DFB46D /* b2CircleContact.h in Headers */,
+ 49132FF713725D1000DFB46D /* b2Contact.h in Headers */,
+ 49132FF913725D1000DFB46D /* b2ContactSolver.h in Headers */,
+ 49132FFB13725D1000DFB46D /* b2PolygonAndCircleContact.h in Headers */,
+ 49132FFD13725D1000DFB46D /* b2PolygonContact.h in Headers */,
+ 49132FFF13725D1000DFB46D /* b2TOISolver.h in Headers */,
+ 4913300113725D1000DFB46D /* b2DistanceJoint.h in Headers */,
+ 4913300313725D1000DFB46D /* b2FrictionJoint.h in Headers */,
+ 4913300513725D1000DFB46D /* b2GearJoint.h in Headers */,
+ 4913300713725D1000DFB46D /* b2Joint.h in Headers */,
+ 4913300913725D1000DFB46D /* b2LineJoint.h in Headers */,
+ 4913300B13725D1000DFB46D /* b2MouseJoint.h in Headers */,
+ 4913300D13725D1000DFB46D /* b2PrismaticJoint.h in Headers */,
+ 4913300F13725D1000DFB46D /* b2PulleyJoint.h in Headers */,
+ 4913301113725D1000DFB46D /* b2RevoluteJoint.h in Headers */,
+ 4913301313725D1000DFB46D /* b2WeldJoint.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 49132F7013725CDD00DFB46D /* Box2D */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 49132F7C13725CDD00DFB46D /* Build configuration list for PBXNativeTarget "Box2D" */;
+ buildPhases = (
+ 49132F6D13725CDD00DFB46D /* Sources */,
+ 49132F6E13725CDD00DFB46D /* Frameworks */,
+ 49132F6F13725CDD00DFB46D /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Box2D;
+ productName = Box2D;
+ productReference = 49132F7113725CDD00DFB46D /* Box2D.dylib */;
+ productType = "com.apple.product-type.library.dynamic";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 49132EDF13725A9600DFB46D /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 49132EE213725A9600DFB46D /* Build configuration list for PBXProject "box2d" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 49132EDD13725A9600DFB46D;
+ productRefGroup = 49132EDD13725A9600DFB46D;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 49132F7013725CDD00DFB46D /* Box2D */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 49132F6D13725CDD00DFB46D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 49132FCE13725D1000DFB46D /* b2BroadPhase.cpp in Sources */,
+ 49132FD013725D1000DFB46D /* b2CollideCircle.cpp in Sources */,
+ 49132FD113725D1000DFB46D /* b2CollidePolygon.cpp in Sources */,
+ 49132FD213725D1000DFB46D /* b2Collision.cpp in Sources */,
+ 49132FD413725D1000DFB46D /* b2Distance.cpp in Sources */,
+ 49132FD613725D1000DFB46D /* b2DynamicTree.cpp in Sources */,
+ 49132FD813725D1000DFB46D /* b2TimeOfImpact.cpp in Sources */,
+ 49132FDA13725D1000DFB46D /* b2CircleShape.cpp in Sources */,
+ 49132FDC13725D1000DFB46D /* b2PolygonShape.cpp in Sources */,
+ 49132FDF13725D1000DFB46D /* b2BlockAllocator.cpp in Sources */,
+ 49132FE113725D1000DFB46D /* b2Math.cpp in Sources */,
+ 49132FE313725D1000DFB46D /* b2Settings.cpp in Sources */,
+ 49132FE513725D1000DFB46D /* b2StackAllocator.cpp in Sources */,
+ 49132FE713725D1000DFB46D /* b2Body.cpp in Sources */,
+ 49132FE913725D1000DFB46D /* b2ContactManager.cpp in Sources */,
+ 49132FEB13725D1000DFB46D /* b2Fixture.cpp in Sources */,
+ 49132FED13725D1000DFB46D /* b2Island.cpp in Sources */,
+ 49132FF013725D1000DFB46D /* b2World.cpp in Sources */,
+ 49132FF213725D1000DFB46D /* b2WorldCallbacks.cpp in Sources */,
+ 49132FF413725D1000DFB46D /* b2CircleContact.cpp in Sources */,
+ 49132FF613725D1000DFB46D /* b2Contact.cpp in Sources */,
+ 49132FF813725D1000DFB46D /* b2ContactSolver.cpp in Sources */,
+ 49132FFA13725D1000DFB46D /* b2PolygonAndCircleContact.cpp in Sources */,
+ 49132FFC13725D1000DFB46D /* b2PolygonContact.cpp in Sources */,
+ 49132FFE13725D1000DFB46D /* b2TOISolver.cpp in Sources */,
+ 4913300013725D1000DFB46D /* b2DistanceJoint.cpp in Sources */,
+ 4913300213725D1000DFB46D /* b2FrictionJoint.cpp in Sources */,
+ 4913300413725D1000DFB46D /* b2GearJoint.cpp in Sources */,
+ 4913300613725D1000DFB46D /* b2Joint.cpp in Sources */,
+ 4913300813725D1000DFB46D /* b2LineJoint.cpp in Sources */,
+ 4913300A13725D1000DFB46D /* b2MouseJoint.cpp in Sources */,
+ 4913300C13725D1000DFB46D /* b2PrismaticJoint.cpp in Sources */,
+ 4913300E13725D1000DFB46D /* b2PulleyJoint.cpp in Sources */,
+ 4913301013725D1000DFB46D /* b2RevoluteJoint.cpp in Sources */,
+ 4913301213725D1000DFB46D /* b2WeldJoint.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 49132EE413725A9600DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 49132EE513725A9600DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ 49132F7D13725CDD00DFB46D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = 4.2;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ };
+ name = Debug;
+ };
+ 49132F7E13725CDD00DFB46D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_VERSION = 4.2;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ USER_HEADER_SEARCH_PATHS = "./src/**";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 49132EE213725A9600DFB46D /* Build configuration list for PBXProject "box2d" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 49132EE413725A9600DFB46D /* Debug */,
+ 49132EE513725A9600DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 49132F7C13725CDD00DFB46D /* Build configuration list for PBXNativeTarget "Box2D" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 49132F7D13725CDD00DFB46D /* Debug */,
+ 49132F7E13725CDD00DFB46D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 49132EDF13725A9600DFB46D /* Project object */;
+}
--- /dev/null
+//
+// Prefix header for all source files of the 'Box2D' target in the 'Box2D' project
+//
+
+#ifdef __OBJC__
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#endif
--- /dev/null
+//
+// Box2DAppDelegate.h
+// Box2D
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+#import <UIKit/UIKit.h>
+#import "TestEntriesViewController.h"
+#import "Delegates.h"
+
+@class Box2DView;
+
+@interface Box2DAppDelegate : NSObject <UIApplicationDelegate,TestSelectDelegate> {
+ UIWindow *window;
+ Box2DView *glView;
+ TestEntriesViewController *testEntriesView;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) IBOutlet Box2DView *glView;
+
+@end
+
--- /dev/null
+//
+// Box2DAppDelegate.m
+// Box2D
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+#import <UIKit/UIKit.h>
+#import "Box2DAppDelegate.h"
+#import "Box2DView.h"
+
+@implementation Box2DAppDelegate
+
+@synthesize window;
+@synthesize glView;
+
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+ [application setStatusBarHidden:true];
+
+ [glView removeFromSuperview];
+
+ glView.animationInterval = 1.0 / 60.0;
+
+ testEntriesView=[[TestEntriesViewController alloc] initWithStyle:UITableViewStylePlain];
+ [testEntriesView setDelegate:self];
+ [glView setDelegate:self];
+
+ [window addSubview:[testEntriesView view]];
+}
+
+-(void) selectTest:(int) testIndex
+{
+ [[testEntriesView view] removeFromSuperview];
+ [window addSubview:glView];
+ [glView startAnimation];
+ [glView selectTestEntry:testIndex];
+}
+
+-(void) leaveTest
+{
+ [glView stopAnimation];
+ [glView removeFromSuperview];
+ [window addSubview:[testEntriesView view]];
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ glView.animationInterval = 1.0 / 5.0;
+}
+
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ glView.animationInterval = 1.0 / 60.0;
+}
+
+
+- (void)dealloc {
+ [window release];
+ [glView release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+//
+// Box2DView.h
+// Box2D OpenGL View
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#import "iPhoneTest.h"
+#import "Delegates.h"
+
+/*
+This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
+The view content is basically an EAGL surface you render your OpenGL scene into.
+Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
+*/
+@interface Box2DView : UIView <UIAccelerometerDelegate> {
+
+@private
+ /* The pixel dimensions of the backbuffer */
+ GLint backingWidth;
+ GLint backingHeight;
+
+ EAGLContext *context;
+
+ /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
+ GLuint viewRenderbuffer, viewFramebuffer;
+
+ /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
+ GLuint depthRenderbuffer;
+
+ NSTimer *animationTimer;
+ NSTimeInterval animationInterval;
+
+ TestEntry* entry;
+ Test* test;
+
+ // Position offset and scale
+ float sceneScale;
+ CGPoint positionOffset;
+ CGPoint lastWorldTouch;
+ CGPoint lastScreenTouch;
+
+ bool panning;
+ int doubleClickValidCountdown;
+
+ id<TestSelectDelegate> _delegate;
+
+}
+@property(assign) id<TestSelectDelegate> delegate;
+@property NSTimeInterval animationInterval;
+
+- (void)startAnimation;
+- (void)stopAnimation;
+- (void)drawView;
+-(void) selectTestEntry:(int) testIndex;
+
+@end
--- /dev/null
+//
+// Box2DView.mm
+// Box2D OpenGL View
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGLES/EAGLDrawable.h>
+
+#import "Box2DView.h"
+
+#define USE_DEPTH_BUFFER 0
+#define kAccelerometerFrequency 30
+#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10
+
+Settings settings;
+
+// A class extension to declare private methods
+@interface Box2DView ()
+
+@property (nonatomic, retain) EAGLContext *context;
+@property (nonatomic, assign) NSTimer *animationTimer;
+
+- (BOOL) createFramebuffer;
+- (void) destroyFramebuffer;
+
+@end
+
+
+@implementation Box2DView
+
+@synthesize context;
+@synthesize animationTimer;
+@synthesize animationInterval;
+@synthesize delegate=_delegate;
+
+// You must implement this method
++ (Class)layerClass {
+ return [CAEAGLLayer class];
+}
+
+
+//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
+- (id)initWithCoder:(NSCoder*)coder {
+
+ if ((self = [super initWithCoder:coder])) {
+ // Get the layer
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+
+ eaglLayer.opaque = YES;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+
+ context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+
+ if (!context || ![EAGLContext setCurrentContext:context]) {
+ [self release];
+ return nil;
+ }
+
+ animationInterval = 1.0 / 60.0;
+ sceneScale=10.0f;
+ positionOffset=CGPointMake(0, 0);
+ lastWorldTouch=CGPointMake(0, 0);
+
+ [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
+ [[UIAccelerometer sharedAccelerometer] setDelegate:self];
+
+ //[self setMultipleTouchEnabled:YES];
+ }
+
+
+ return self;
+}
+
+-(void) selectTestEntry:(int) testIndex
+{
+ // Destroy existing scene
+ delete test;
+
+ entry = g_testEntries + testIndex;
+ test = entry->createFcn();
+
+ doubleClickValidCountdown=0;
+
+ sceneScale=10.0f;
+ positionOffset=CGPointMake(0, 0);
+ lastWorldTouch=CGPointMake(0, 0);
+}
+
+
+
+- (void)drawView {
+
+
+
+ if (doubleClickValidCountdown>0) doubleClickValidCountdown--;
+
+ [EAGLContext setCurrentContext:context];
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+ glViewport(0, 0, backingWidth, backingHeight);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glOrthof(-sceneScale, sceneScale, -sceneScale*1.5f, sceneScale*1.5f, -1.0f, 1.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(positionOffset.x, positionOffset.y,0);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ test->Step(&settings);
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+ [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+}
+
+
+- (void)layoutSubviews {
+ [EAGLContext setCurrentContext:context];
+ [self destroyFramebuffer];
+ [self createFramebuffer];
+ [self drawView];
+}
+
+
+- (BOOL)createFramebuffer {
+
+ glGenFramebuffersOES(1, &viewFramebuffer);
+ glGenRenderbuffersOES(1, &viewRenderbuffer);
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+ [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
+
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
+
+ if (USE_DEPTH_BUFFER) {
+ glGenRenderbuffersOES(1, &depthRenderbuffer);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
+ glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
+ }
+
+ if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+ NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ return NO;
+ }
+
+ return YES;
+}
+
+
+- (void)destroyFramebuffer {
+
+ glDeleteFramebuffersOES(1, &viewFramebuffer);
+ viewFramebuffer = 0;
+ glDeleteRenderbuffersOES(1, &viewRenderbuffer);
+ viewRenderbuffer = 0;
+
+ if(depthRenderbuffer) {
+ glDeleteRenderbuffersOES(1, &depthRenderbuffer);
+ depthRenderbuffer = 0;
+ }
+}
+
+
+- (void)startAnimation {
+ self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
+}
+
+
+- (void)stopAnimation {
+ self.animationTimer = nil;
+}
+
+
+- (void)setAnimationTimer:(NSTimer *)newTimer {
+ [animationTimer invalidate];
+ animationTimer = newTimer;
+}
+
+
+- (void)setAnimationInterval:(NSTimeInterval)interval {
+
+ animationInterval = interval;
+ if (animationTimer) {
+ [self stopAnimation];
+ [self startAnimation];
+ }
+}
+
+
+- (void)dealloc {
+
+ [self stopAnimation];
+
+ if ([EAGLContext currentContext] == context) {
+ [EAGLContext setCurrentContext:nil];
+ }
+
+ [context release];
+ [super dealloc];
+}
+
+-(CGPoint) screenSpaceToWorldSpace:(CGPoint) screenLocation
+{
+ screenLocation.x-=160;
+ screenLocation.y-=240;
+ screenLocation.x/=160;
+ screenLocation.y/=160;
+ screenLocation.x*=sceneScale;
+ screenLocation.y*=-sceneScale;
+
+ screenLocation.x-=positionOffset.x;
+ screenLocation.y-=positionOffset.y;
+ return screenLocation;
+}
+
+- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
+{
+
+ if (doubleClickValidCountdown>0)
+ {
+ [_delegate leaveTest];
+ return;
+ }
+
+ doubleClickValidCountdown=FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK;
+
+
+ panning=false;
+ for (UITouch *touch in touches)
+ {
+ CGPoint touchLocation=[touch locationInView:self];
+ CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
+ //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+ lastScreenTouch=touchLocation;
+ lastWorldTouch=worldPosition;
+ b2Vec2 p = b2Vec2(lastWorldTouch.x,lastWorldTouch.y);
+ test->MouseDown(p);
+ //test->ShiftMouseDown(p);
+
+ if (!test->m_mouseJoint) panning=true;
+ }
+}
+
+- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
+{
+ for (UITouch *touch in touches)
+ {
+ CGPoint touchLocation=[touch locationInView:self];
+ CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
+ //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+
+
+ CGPoint screenDistanceMoved=CGPointMake(touchLocation.x-lastScreenTouch.x,touchLocation.y-lastScreenTouch.y);
+ if (panning)
+ {
+ screenDistanceMoved.x/=160;
+ screenDistanceMoved.y/=160;
+ screenDistanceMoved.x*=sceneScale;
+ screenDistanceMoved.y*=-sceneScale;
+ positionOffset.x+=screenDistanceMoved.x;
+ positionOffset.y+=screenDistanceMoved.y;
+ }
+
+ lastScreenTouch=touchLocation;
+ lastWorldTouch=worldPosition;
+ test->MouseMove(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+
+ }
+}
+- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
+{
+ test->MouseUp(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+}
+
+- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
+{
+ // Only run for valid values
+ if (acceleration.y!=0 && acceleration.x!=0)
+ {
+ if (test) test->SetGravity(acceleration.x,acceleration.y);
+ }
+}
+
+@end
--- /dev/null
+/*
+ * Delegates.h
+ * Box2D
+ *
+ * Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+ *
+ *
+ */
+
+@protocol TestSelectDelegate <NSObject>
+ -(void) selectTest:(int) testIndex;
+ -(void) leaveTest;
+
+@end
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+*
+* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef RENDER_H
+#define RENDER_H
+
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#include <Box2D/Box2D.h>
+
+struct b2AABB;
+
+// This class implements debug drawing callbacks that are invoked
+// inside b2World::Step.
+class GLESDebugDraw : public b2Draw
+{
+public:
+ void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
+
+ void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
+
+ void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
+
+ void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
+
+ void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
+
+ void DrawTransform(const b2Transform& xf);
+
+ void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
+
+ void DrawString(int x, int y, const char* string, ...);
+
+ void DrawAABB(b2AABB* aabb, const b2Color& color);
+};
+
+
+#endif
--- /dev/null
+/*
+* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+*
+* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "GLES-Render.h"
+
+
+#include <cstdio>
+#include <cstdarg>
+
+#include <cstring>
+
+void GLESDebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ glColor4f(color.r, color.g, color.b,1);
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
+}
+
+void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ glColor4f(color.r, color.g, color.b,0.5f);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
+
+ glColor4f(color.r, color.g, color.b,1);
+ glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
+}
+
+void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
+{
+ const float32 k_segments = 16.0f;
+ int vertexCount=16;
+ const float32 k_increment = 2.0f * b2_pi / k_segments;
+ float32 theta = 0.0f;
+
+ GLfloat glVertices[vertexCount*2];
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertices[i*2]=v.x;
+ glVertices[i*2+1]=v.y;
+ theta += k_increment;
+ }
+
+ glColor4f(color.r, color.g, color.b,1);
+ glVertexPointer(2, GL_FLOAT, 0, glVertices);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
+}
+
+void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
+{
+ const float32 k_segments = 16.0f;
+ int vertexCount=16;
+ const float32 k_increment = 2.0f * b2_pi / k_segments;
+ float32 theta = 0.0f;
+
+ GLfloat glVertices[vertexCount*2];
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertices[i*2]=v.x;
+ glVertices[i*2+1]=v.y;
+ theta += k_increment;
+ }
+
+ glColor4f(color.r, color.g, color.b,0.5f);
+ glVertexPointer(2, GL_FLOAT, 0, glVertices);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
+ glColor4f(color.r, color.g, color.b,1);
+ glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
+
+ // Draw the axis line
+ DrawSegment(center,center+radius*axis,color);
+}
+
+void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
+{
+ glColor4f(color.r, color.g, color.b,1);
+ GLfloat glVertices[] = {
+ p1.x,p1.y,p2.x,p2.y
+ };
+ glVertexPointer(2, GL_FLOAT, 0, glVertices);
+ glDrawArrays(GL_LINES, 0, 2);
+}
+
+void GLESDebugDraw::DrawTransform(const b2Transform& xf)
+{
+ b2Vec2 p1 = xf.position, p2;
+ const float32 k_axisScale = 0.4f;
+
+ p2 = p1 + k_axisScale * xf.R.col1;
+ DrawSegment(p1,p2,b2Color(1,0,0));
+
+ p2 = p1 + k_axisScale * xf.R.col2;
+ DrawSegment(p1,p2,b2Color(0,1,0));
+}
+
+void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
+{
+ glColor4f(color.r, color.g, color.b,1);
+ glPointSize(size);
+ GLfloat glVertices[] = {
+ p.x,p.y
+ };
+ glVertexPointer(2, GL_FLOAT, 0, glVertices);
+ glDrawArrays(GL_POINTS, 0, 1);
+ glPointSize(1.0f);
+}
+
+void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
+{
+
+ /* Unsupported as yet. Could replace with bitmap font renderer at a later date */
+}
+
+void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
+{
+
+ glColor4f(c.r, c.g, c.b,1);
+
+ GLfloat glVertices[] = {
+ aabb->lowerBound.x, aabb->lowerBound.y,
+ aabb->upperBound.x, aabb->lowerBound.y,
+ aabb->upperBound.x, aabb->upperBound.y,
+ aabb->lowerBound.x, aabb->upperBound.y
+ };
+ glVertexPointer(2, GL_FLOAT, 0, glVertices);
+ glDrawArrays(GL_LINE_LOOP, 0, 8);
+
+}
--- /dev/null
+//
+// TestEntriesViewController.h
+// Box2D
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+#import <UIKit/UIKit.h>
+#import "iPhoneTest.h"
+#import "Delegates.h"
+
+@interface TestEntriesViewController : UITableViewController {
+ int32 testCount;
+ id<TestSelectDelegate> _delegate;
+}
+
+@property(assign) id<TestSelectDelegate> delegate;
+
+@end
--- /dev/null
+//
+// TestEntriesViewController.m
+// Box2D
+//
+// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+//
+
+#import "TestEntriesViewController.h"
+
+
+@implementation TestEntriesViewController
+
+@synthesize delegate=_delegate;
+
+- (id)initWithStyle:(UITableViewStyle)style {
+ if (self = [super initWithStyle:style]) {
+ testCount = 0;
+ TestEntry* e = g_testEntries;
+ while (e->createFcn)
+ {
+ ++testCount;
+ ++e;
+ }
+ }
+ return self;
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
+ // Release anything that's not essential, such as cached data
+}
+
+#pragma mark Table view methods
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return 1;
+}
+
+
+// Customize the number of rows in the table view.
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return testCount;
+}
+
+
+// Customize the appearance of table view cells.
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+
+ static NSString *CellIdentifier = @"Cell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
+ }
+
+ // Set up the cell...
+ TestEntry* e = g_testEntries;
+ e+=indexPath.row;
+
+ cell.textLabel.text = [NSString stringWithUTF8String:e->name];
+ return cell;
+}
+
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ [_delegate selectTest:indexPath.row];
+}
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
+
--- /dev/null
+/*
+* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+*
+* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef TEST_H
+#define TEST_H
+
+#import <UIKit/UIKit.h>
+#include <Box2D/Box2D.h>
+#include "GLES-Render.h"
+
+#include <cstdlib>
+
+class Test;
+struct Settings;
+
+typedef Test* TestCreateFcn();
+
+#define RAND_LIMIT 32767
+
+/// Random number in range [-1,1]
+inline float32 RandomFloat()
+{
+ float32 r = (float32)(rand() & (RAND_LIMIT));
+ r /= RAND_LIMIT;
+ r = 2.0f * r - 1.0f;
+ return r;
+}
+
+/// Random floating point number in range [lo, hi]
+inline float32 RandomFloat(float32 lo, float32 hi)
+{
+ float32 r = (float32)(rand() & (RAND_LIMIT));
+ r /= RAND_LIMIT;
+ r = (hi - lo) * r + lo;
+ return r;
+}
+
+/// Test settings. Some can be controlled in the GUI.
+struct Settings
+{
+ Settings() :
+ viewCenter(0.0f, 20.0f),
+ hz(60.0f),
+ velocityIterations(8),
+ positionIterations(3),
+ drawShapes(1),
+ drawJoints(1),
+ drawAABBs(0),
+ drawPairs(0),
+ drawContactPoints(0),
+ drawContactNormals(0),
+ drawContactForces(0),
+ drawFrictionForces(0),
+ drawCOMs(0),
+ drawStats(0),
+ enableWarmStarting(1),
+ enableContinuous(1),
+ enableSubStepping(0),
+ pause(0),
+ singleStep(0)
+ {}
+
+ b2Vec2 viewCenter;
+ float32 hz;
+ int32 velocityIterations;
+ int32 positionIterations;
+ int32 drawShapes;
+ int32 drawJoints;
+ int32 drawAABBs;
+ int32 drawPairs;
+ int32 drawContactPoints;
+ int32 drawContactNormals;
+ int32 drawContactForces;
+ int32 drawFrictionForces;
+ int32 drawCOMs;
+ int32 drawStats;
+ int32 enableWarmStarting;
+ int32 enableContinuous;
+ int32 enableSubStepping;
+ int32 pause;
+ int32 singleStep;
+};
+
+struct TestEntry
+{
+ const char *name;
+ TestCreateFcn *createFcn;
+};
+
+extern TestEntry g_testEntries[];
+// This is called when a joint in the world is implicitly destroyed
+// because an attached body is destroyed. This gives us a chance to
+// nullify the mouse joint.
+class DestructionListener : public b2DestructionListener
+ {
+ public:
+ void SayGoodbye(b2Fixture* fixture) { B2_NOT_USED(fixture); }
+ void SayGoodbye(b2Joint* joint);
+
+ Test* test;
+ };
+
+const int32 k_maxContactPoints = 2048;
+
+struct ContactPoint
+{
+ b2Fixture* fixtureA;
+ b2Fixture* fixtureB;
+ b2Vec2 normal;
+ b2Vec2 position;
+ b2PointState state;
+};
+
+class Test : public b2ContactListener
+ {
+ public:
+
+ Test();
+ virtual ~Test();
+
+ void SetGravity(float x,float y);
+ void SetTextLine(int32 line) { m_textLine = line; }
+ void DrawTitle(int x, int y, const char *string);
+ virtual void Step(Settings* settings);
+ virtual void Keyboard(unsigned char key) { B2_NOT_USED(key); }
+ void ShiftMouseDown(const b2Vec2& p);
+ virtual void MouseDown(const b2Vec2& p);
+ virtual void MouseUp(const b2Vec2& p);
+ void MouseMove(const b2Vec2& p);
+ void LaunchBomb();
+ void LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);
+
+ void SpawnBomb(const b2Vec2& worldPt);
+ void CompleteBombSpawn(const b2Vec2& p);
+
+ // Let derived tests know that a joint was destroyed.
+ virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }
+
+ // Callbacks for derived classes.
+ virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
+ virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
+ virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
+ virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
+ {
+ B2_NOT_USED(contact);
+ B2_NOT_USED(impulse);
+ }
+
+ protected:
+ friend class DestructionListener;
+ friend class BoundaryListener;
+ friend class ContactListener;
+
+ b2Body* m_groundBody;
+ b2AABB m_worldAABB;
+ ContactPoint m_points[k_maxContactPoints];
+ int32 m_pointCount;
+ DestructionListener m_destructionListener;
+ GLESDebugDraw m_debugDraw;
+ int32 m_textLine;
+ b2World* m_world;
+ b2Body* m_bomb;
+ b2MouseJoint* m_mouseJoint;
+ b2Vec2 m_bombSpawnPoint;
+ bool m_bombSpawning;
+ b2Vec2 m_mouseWorld;
+ int32 m_stepCount;
+ };
+
+#endif
--- /dev/null
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "iPhoneTest.h"
+#include "GLES-Render.h"
+
+#include <cstdio>
+
+void DestructionListener::SayGoodbye(b2Joint* joint)
+{
+ if (test->m_mouseJoint == joint)
+ {
+ test->m_mouseJoint = NULL;
+ }
+ else
+ {
+ test->JointDestroyed(joint);
+ }
+}
+
+Test::Test()
+: m_debugDraw()
+{
+ b2Vec2 gravity;
+ gravity.Set(0.0f, -10.0f);
+ bool doSleep = true;
+ m_world = new b2World(gravity, doSleep);
+ m_bomb = NULL;
+ m_textLine = 30;
+ m_mouseJoint = NULL;
+ m_pointCount = 0;
+
+ m_destructionListener.test = this;
+ m_world->SetDestructionListener(&m_destructionListener);
+ m_world->SetContactListener(this);
+ m_world->SetDebugDraw(&m_debugDraw);
+
+ m_bombSpawning = false;
+
+ m_stepCount = 0;
+
+ b2BodyDef bodyDef;
+ m_groundBody = m_world->CreateBody(&bodyDef);
+}
+
+Test::~Test()
+{
+ // By deleting the world, we delete the bomb, mouse joint, etc.
+ delete m_world;
+ m_world = NULL;
+
+}
+
+void Test::SetGravity( float x, float y)
+{
+ float tVectorLength=sqrt(x*x+y*y);
+ float newGravityX=9.81f*x/tVectorLength;
+ float newGravityY=9.81f*y/tVectorLength;
+ m_world->SetGravity(b2Vec2(newGravityX,newGravityY));
+}
+
+void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{
+ const b2Manifold* manifold = contact->GetManifold();
+
+ if (manifold->pointCount == 0)
+ {
+ return;
+ }
+
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
+ b2GetPointStates(state1, state2, oldManifold, manifold);
+
+ b2WorldManifold worldManifold;
+ contact->GetWorldManifold(&worldManifold);
+
+ for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
+ {
+ ContactPoint* cp = m_points + m_pointCount;
+ cp->fixtureA = fixtureA;
+ cp->fixtureB = fixtureB;
+ cp->position = worldManifold.points[i];
+ cp->normal = worldManifold.normal;
+ cp->state = state2[i];
+ ++m_pointCount;
+ }
+}
+
+void Test::DrawTitle(int x, int y, const char *string)
+{
+ m_debugDraw.DrawString(x, y, string);
+}
+
+class QueryCallback : public b2QueryCallback
+{
+public:
+ QueryCallback(const b2Vec2& point)
+ {
+ m_point = point;
+ m_fixture = NULL;
+ }
+
+ bool ReportFixture(b2Fixture* fixture)
+ {
+ b2Body* body = fixture->GetBody();
+ if (body->GetType() == b2_dynamicBody)
+ {
+ bool inside = fixture->TestPoint(m_point);
+ if (inside)
+ {
+ m_fixture = fixture;
+
+ // We are done, terminate the query.
+ return false;
+ }
+ }
+
+ // Continue the query.
+ return true;
+ }
+
+ b2Vec2 m_point;
+ b2Fixture* m_fixture;
+};
+
+void Test::MouseDown(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint != NULL)
+ {
+ return;
+ }
+
+ // Make a small box.
+ b2AABB aabb;
+ b2Vec2 d;
+ d.Set(0.001f, 0.001f);
+ aabb.lowerBound = p - d;
+ aabb.upperBound = p + d;
+
+ // Query the world for overlapping shapes.
+ QueryCallback callback(p);
+ m_world->QueryAABB(&callback, aabb);
+
+ if (callback.m_fixture)
+ {
+ b2Body* body = callback.m_fixture->GetBody();
+ b2MouseJointDef md;
+ md.bodyA = m_groundBody;
+ md.bodyB = body;
+ md.target = p;
+#ifdef TARGET_FLOAT32_IS_FIXED
+ md.maxForce = (body->GetMass() < 16.0)?
+ (1000.0f * body->GetMass()) : float32(16000.0);
+#else
+ md.maxForce = 1000.0f * body->GetMass();
+#endif
+ m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
+ body->SetAwake(true);
+ }
+}
+
+void Test::SpawnBomb(const b2Vec2& worldPt)
+{
+ m_bombSpawnPoint = worldPt;
+ m_bombSpawning = true;
+}
+
+void Test::CompleteBombSpawn(const b2Vec2& p)
+{
+ if (m_bombSpawning == false)
+ {
+ return;
+ }
+
+ const float multiplier = 30.0f;
+ b2Vec2 vel = m_bombSpawnPoint - p;
+ vel *= multiplier;
+ LaunchBomb(m_bombSpawnPoint,vel);
+ m_bombSpawning = false;
+}
+
+void Test::ShiftMouseDown(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint != NULL)
+ {
+ return;
+ }
+
+ SpawnBomb(p);
+}
+
+void Test::MouseUp(const b2Vec2& p)
+{
+ if (m_mouseJoint)
+ {
+ m_world->DestroyJoint(m_mouseJoint);
+ m_mouseJoint = NULL;
+ }
+
+ if (m_bombSpawning)
+ {
+ CompleteBombSpawn(p);
+ }
+}
+
+void Test::MouseMove(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint)
+ {
+ m_mouseJoint->SetTarget(p);
+ }
+}
+
+void Test::LaunchBomb()
+{
+ b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
+ b2Vec2 v = -5.0f * p;
+ LaunchBomb(p, v);
+}
+
+void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
+{
+ if (m_bomb)
+ {
+ m_world->DestroyBody(m_bomb);
+ m_bomb = NULL;
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = position;
+ bd.bullet = true;
+ m_bomb = m_world->CreateBody(&bd);
+ m_bomb->SetLinearVelocity(velocity);
+
+ b2CircleShape circle;
+ circle.m_radius = 0.3f;
+
+ b2FixtureDef fd;
+ fd.shape = &circle;
+ fd.density = 20.0f;
+ fd.restitution = 0.0f;
+
+ b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
+ b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);
+
+ b2AABB aabb;
+ aabb.lowerBound = minV;
+ aabb.upperBound = maxV;
+
+ m_bomb->CreateFixture(&fd);
+}
+
+void Test::Step(Settings* settings)
+{
+ float32 timeStep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);
+
+ if (settings->pause)
+ {
+ if (settings->singleStep)
+ {
+ settings->singleStep = 0;
+ }
+ else
+ {
+ timeStep = 0.0f;
+ }
+
+ m_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
+ m_textLine += 15;
+ }
+
+ uint32 flags = 0;
+ flags += settings->drawShapes * b2Draw::e_shapeBit;
+ flags += settings->drawJoints * b2Draw::e_jointBit;
+ flags += settings->drawAABBs * b2Draw::e_aabbBit;
+ flags += settings->drawPairs * b2Draw::e_pairBit;
+ flags += settings->drawCOMs * b2Draw::e_centerOfMassBit;
+ m_debugDraw.SetFlags(flags);
+
+ m_world->SetWarmStarting(settings->enableWarmStarting > 0);
+ m_world->SetContinuousPhysics(settings->enableContinuous > 0);
+ m_world->SetSubStepping(settings->enableSubStepping > 0);
+
+ m_pointCount = 0;
+
+ m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);
+
+ m_world->DrawDebugData();
+
+ if (timeStep > 0.0f)
+ {
+ ++m_stepCount;
+ }
+
+ if (settings->drawStats)
+ {
+ m_debugDraw.DrawString(5, m_textLine, "bodies/contacts/joints/proxies = %d/%d/%d",
+ m_world->GetBodyCount(), m_world->GetContactCount(), m_world->GetJointCount(), m_world->GetProxyCount());
+ m_textLine += 15;
+ }
+
+ if (m_mouseJoint)
+ {
+ b2Vec2 p1 = m_mouseJoint->GetAnchorB();
+ b2Vec2 p2 = m_mouseJoint->GetTarget();
+
+ glPointSize(4.0f);
+ glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+ GLbyte verts1[2 * 3] = {
+ p1.x, p1.y, 0.0f,
+ p2.x, p2.y, 0.0f
+ };
+ glVertexPointer(3, GL_BYTE, 0, verts1);
+ glDrawArrays(GL_POINTS, 0, 2);
+ glPointSize(1.0f);
+
+ glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
+ GLbyte verts2[2 * 3] = {
+ p1.x, p1.y, 0.0f,
+ p2.x, p2.y, 0.0f
+ };
+ glVertexPointer(3, GL_BYTE, 0, verts2);
+ glDrawArrays(GL_LINES, 0, 2);
+ }
+
+ if (m_bombSpawning)
+ {
+ glPointSize(4.0f);
+ glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
+ glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
+ GLbyte verts1[1 * 3] = {
+ m_bombSpawnPoint.x, m_bombSpawnPoint.y, 0.0f
+ };
+ glVertexPointer(3, GL_BYTE, 0, verts1);
+ glDrawArrays(GL_POINTS, 0, 1);
+
+ glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
+ GLbyte verts2[2 * 3] = {
+ m_mouseWorld.x, m_mouseWorld.y, 0.0f,
+ m_bombSpawnPoint.x, m_bombSpawnPoint.y, 0.0f
+ };
+ glVertexPointer(3, GL_BYTE, 0, verts2);
+ glDrawArrays(GL_LINES, 0, 2);
+ }
+
+ if (settings->drawContactPoints)
+ {
+ //const float32 k_impulseScale = 0.1f;
+ const float32 k_axisScale = 0.3f;
+
+ for (int32 i = 0; i < m_pointCount; ++i)
+ {
+ ContactPoint* point = m_points + i;
+
+ if (point->state == b2_addState)
+ {
+ // Add
+ m_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
+ }
+ else if (point->state == b2_persistState)
+ {
+ // Persist
+ m_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
+ }
+
+ if (settings->drawContactNormals == 1)
+ {
+ b2Vec2 p1 = point->position;
+ b2Vec2 p2 = p1 + k_axisScale * point->normal;
+ m_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f));
+ }
+ else if (settings->drawContactForces == 1)
+ {
+ //b2Vec2 p1 = point->position;
+ //b2Vec2 p2 = p1 + k_forceScale * point->normalForce * point->normal;
+ //DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
+ }
+
+ if (settings->drawFrictionForces == 1)
+ {
+ //b2Vec2 tangent = b2Cross(point->normal, 1.0f);
+ //b2Vec2 p1 = point->position;
+ //b2Vec2 p2 = p1 + k_forceScale * point->tangentForce * tangent;
+ //DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
+ }
+ }
+ }
+}
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include "iPhoneTest.h"\r
+#include <cstring>\r
+using namespace std;\r
+\r
+#include "ApplyForce.h"\r
+#include "BodyTypes.h"\r
+#include "Breakable.h"\r
+#include "Bridge.h"\r
+#include "BulletTest.h"\r
+#include "Cantilever.h"\r
+#include "Car.h"\r
+#include "ContinuousTest.h"\r
+#include "Chain.h"\r
+#include "CharacterCollision.h"\r
+#include "CollisionFiltering.h"\r
+#include "CollisionProcessing.h"\r
+#include "CompoundShapes.h"\r
+#include "Confined.h"\r
+#include "DistanceTest.h"\r
+#include "Dominos.h"\r
+#include "DynamicTreeTest.h"\r
+#include "EdgeShapes.h"\r
+#include "EdgeTest.h"\r
+#include "Gears.h"\r
+#include "OneSidedPlatform.h"\r
+#include "Pinball.h"\r
+#include "PolyCollision.h"\r
+#include "PolyShapes.h"\r
+#include "Prismatic.h"\r
+#include "Pulleys.h"\r
+#include "Pyramid.h"\r
+#include "RayCast.h"\r
+#include "Revolute.h"\r
+#include "Rope.h"\r
+#include "RopeJoint.h"\r
+#include "SensorTest.h"\r
+#include "ShapeEditing.h"\r
+#include "SliderCrank.h"\r
+#include "SphereStack.h"\r
+#include "TheoJansen.h"\r
+#include "Tiles.h"\r
+#include "TimeOfImpact.h"\r
+#include "VaryingFriction.h"\r
+#include "VaryingRestitution.h"\r
+#include "VerticalStack.h"\r
+#include "Web.h"\r
+\r
+TestEntry g_testEntries[] =\r
+{\r
+ {"Pulleys", Pulleys::Create},\r
+ {"SphereStack", SphereStack::Create},\r
+ {"Tiles", Tiles::Create},\r
+ {"Polygon Shapes", PolyShapes::Create},\r
+ {"Rope", Rope::Create},\r
+ {"Web", Web::Create},\r
+ {"Car", Car::Create},\r
+ {"Vertical Stack", VerticalStack::Create},\r
+ {"RopeJoint", RopeJoint::Create},\r
+ {"Character Collision", CharacterCollision::Create},\r
+ {"Edge Test", EdgeTest::Create},\r
+ {"One-Sided Platform", OneSidedPlatform::Create},\r
+ {"Pinball", Pinball::Create},\r
+ {"Bullet Test", BulletTest::Create},\r
+ {"Continuous Test", ContinuousTest::Create},\r
+ {"Time of Impact", TimeOfImpact::Create},\r
+ {"Ray-Cast", RayCast::Create},\r
+ {"Confined", Confined::Create},\r
+ {"Pyramid", Pyramid::Create},\r
+ {"Varying Restitution", VaryingRestitution::Create},\r
+ {"Theo Jansen's Walker", TheoJansen::Create},\r
+ {"Body Types", BodyTypes::Create},\r
+ {"Prismatic", Prismatic::Create},\r
+ {"Edge Shapes", EdgeShapes::Create},\r
+ {"PolyCollision", PolyCollision::Create},\r
+ {"Apply Force", ApplyForce::Create},\r
+ {"Cantilever", Cantilever::Create},\r
+ {"Bridge", Bridge::Create},\r
+ {"Breakable", Breakable::Create},\r
+ {"Chain", Chain::Create},\r
+ {"Collision Filtering", CollisionFiltering::Create},\r
+ {"Collision Processing", CollisionProcessing::Create},\r
+ {"Compound Shapes", CompoundShapes::Create},\r
+ {"Distance Test", DistanceTest::Create},\r
+ {"Dominos", Dominos::Create},\r
+ {"Dynamic Tree", DynamicTreeTest::Create},\r
+ {"Gears", Gears::Create},\r
+ {"Revolute", Revolute::Create},\r
+ {"Sensor Test", SensorTest::Create},\r
+ {"Shape Editing", ShapeEditing::Create},\r
+ {"Slider Crank", SliderCrank::Create},\r
+ {"Varying Friction", VaryingFriction::Create},\r
+ {NULL, NULL}\r
+};\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainWindow</string>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">528</int>
+ <string key="IBDocument.SystemVersion">9G55</string>
+ <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.AppKitVersion">949.43</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="8"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="191355593">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUICustomObject" id="664661524"/>
+ <object class="IBUIWindow" id="380026005">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">1316</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIView" id="773737154">
+ <reference key="NSNextResponder" ref="380026005"/>
+ <int key="NSvFlags">1298</int>
+ <string key="NSFrameSize">{320, 480}</string>
+ <reference key="NSSuperview" ref="380026005"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ </object>
+ </object>
+ <object class="NSPSMatrix" key="NSFrameMatrix"/>
+ <string key="NSFrameSize">{320, 480}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <bool key="IBUIVisibleAtLaunch">YES</bool>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="841351856"/>
+ <reference key="destination" ref="664661524"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="380026005"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">glView</string>
+ <reference key="source" ref="664661524"/>
+ <reference key="destination" ref="773737154"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="957960031">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="380026005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="773737154"/>
+ </object>
+ <reference key="parent" ref="957960031"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="957960031"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="664661524"/>
+ <reference key="parent" ref="957960031"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">8</int>
+ <reference key="object" ref="773737154"/>
+ <reference key="parent" ref="380026005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="191355593"/>
+ <reference key="parent" ref="957960031"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>2.IBAttributePlaceholdersKey</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ <string>8.CustomClassName</string>
+ <string>8.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIApplication</string>
+ <string>UIResponder</string>
+ <object class="NSMutableDictionary">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <string>{{500, 343}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>Box2DAppDelegate</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>Box2DView</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">9</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">Box2DAppDelegate</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>glView</string>
+ <string>window</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>Box2DView</string>
+ <string>UIWindow</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/Box2DAppDelegate.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">Box2DView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Classes/Box2DView.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">Box2D.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
--- /dev/null
+//
+// main.m
+// Box2D
+//
+// Created by Simon Oliver on 14/01/2009.
+// Copyright HandCircus 2009. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, nil);
+ [pool release];
+ return retVal;
+}
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef BOX2D_H\r
+#define BOX2D_H\r
+\r
+/**\r
+\mainpage Box2D API Documentation\r
+\r
+\section intro_sec Getting Started\r
+\r
+For documentation please see http://box2d.org/documentation.html\r
+\r
+For discussion please visit http://box2d.org/forum\r
+*/\r
+\r
+// These include files constitute the main Box2D API\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+\r
+#include <Box2D/Collision/Shapes/b2CircleShape.h>\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+\r
+#include <Box2D/Collision/b2BroadPhase.h>\r
+#include <Box2D/Collision/b2Distance.h>\r
+#include <Box2D/Collision/b2DynamicTree.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2WorldCallbacks.h>\r
+#include <Box2D/Dynamics/b2TimeStep.h>\r
+#include <Box2D/Dynamics/b2World.h>\r
+\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+\r
+#include <Box2D/Dynamics/Joints/b2DistanceJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2FrictionJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2GearJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2LineJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2MouseJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2PrismaticJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2PulleyJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2RevoluteJoint.h>\r
+#include <Box2D/Dynamics/Joints/b2WeldJoint.h>\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/Shapes/b2CircleShape.h>\r
+#include <new>\r
+\r
+b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const\r
+{\r
+ void* mem = allocator->Allocate(sizeof(b2CircleShape));\r
+ b2CircleShape* clone = new (mem) b2CircleShape;\r
+ *clone = *this;\r
+ return clone;\r
+}\r
+\r
+bool b2CircleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const\r
+{\r
+ b2Vec2 center = transform.position + b2Mul(transform.R, m_p);\r
+ b2Vec2 d = p - center;\r
+ return b2Dot(d, d) <= m_radius * m_radius;\r
+}\r
+\r
+// Collision Detection in Interactive 3D Environments by Gino van den Bergen\r
+// From Section 3.1.2\r
+// x = s + a * r\r
+// norm(x) = radius\r
+bool b2CircleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const\r
+{\r
+ b2Vec2 position = transform.position + b2Mul(transform.R, m_p);\r
+ b2Vec2 s = input.p1 - position;\r
+ float32 b = b2Dot(s, s) - m_radius * m_radius;\r
+\r
+ // Solve quadratic equation.\r
+ b2Vec2 r = input.p2 - input.p1;\r
+ float32 c = b2Dot(s, r);\r
+ float32 rr = b2Dot(r, r);\r
+ float32 sigma = c * c - rr * b;\r
+\r
+ // Check for negative discriminant and short segment.\r
+ if (sigma < 0.0f || rr < b2_epsilon)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Find the point of intersection of the line with the circle.\r
+ float32 a = -(c + b2Sqrt(sigma));\r
+\r
+ // Is the intersection point on the segment?\r
+ if (0.0f <= a && a <= input.maxFraction * rr)\r
+ {\r
+ a /= rr;\r
+ output->fraction = a;\r
+ output->normal = s + a * r;\r
+ output->normal.Normalize();\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+void b2CircleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform) const\r
+{\r
+ b2Vec2 p = transform.position + b2Mul(transform.R, m_p);\r
+ aabb->lowerBound.Set(p.x - m_radius, p.y - m_radius);\r
+ aabb->upperBound.Set(p.x + m_radius, p.y + m_radius);\r
+}\r
+\r
+void b2CircleShape::ComputeMass(b2MassData* massData, float32 density) const\r
+{\r
+ massData->mass = density * b2_pi * m_radius * m_radius;\r
+ massData->center = m_p;\r
+\r
+ // inertia about the local origin\r
+ massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_p, m_p));\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_CIRCLE_SHAPE_H\r
+#define B2_CIRCLE_SHAPE_H\r
+\r
+#include <Box2D/Collision/Shapes/b2Shape.h>\r
+\r
+/// A circle shape.\r
+class b2CircleShape : public b2Shape\r
+{\r
+public:\r
+ b2CircleShape();\r
+\r
+ /// Implement b2Shape.\r
+ b2Shape* Clone(b2BlockAllocator* allocator) const;\r
+\r
+ /// Implement b2Shape.\r
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;\r
+\r
+ /// Implement b2Shape.\r
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const;\r
+\r
+ /// @see b2Shape::ComputeAABB\r
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform) const;\r
+\r
+ /// @see b2Shape::ComputeMass\r
+ void ComputeMass(b2MassData* massData, float32 density) const;\r
+\r
+ /// Get the supporting vertex index in the given direction.\r
+ int32 GetSupport(const b2Vec2& d) const;\r
+\r
+ /// Get the supporting vertex in the given direction.\r
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;\r
+\r
+ /// Get the vertex count.\r
+ int32 GetVertexCount() const { return 1; }\r
+\r
+ /// Get a vertex by index. Used by b2Distance.\r
+ const b2Vec2& GetVertex(int32 index) const;\r
+\r
+ /// Position\r
+ b2Vec2 m_p;\r
+};\r
+\r
+inline b2CircleShape::b2CircleShape()\r
+{\r
+ m_type = e_circle;\r
+ m_radius = 0.0f;\r
+ m_p.SetZero();\r
+}\r
+\r
+inline int32 b2CircleShape::GetSupport(const b2Vec2 &d) const\r
+{\r
+ B2_NOT_USED(d);\r
+ return 0;\r
+}\r
+\r
+inline const b2Vec2& b2CircleShape::GetSupportVertex(const b2Vec2 &d) const\r
+{\r
+ B2_NOT_USED(d);\r
+ return m_p;\r
+}\r
+\r
+inline const b2Vec2& b2CircleShape::GetVertex(int32 index) const\r
+{\r
+ B2_NOT_USED(index);\r
+ b2Assert(index == 0);\r
+ return m_p;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+#include <new>\r
+\r
+b2Shape* b2PolygonShape::Clone(b2BlockAllocator* allocator) const\r
+{\r
+ void* mem = allocator->Allocate(sizeof(b2PolygonShape));\r
+ b2PolygonShape* clone = new (mem) b2PolygonShape;\r
+ *clone = *this;\r
+ return clone;\r
+}\r
+\r
+void b2PolygonShape::SetAsBox(float32 hx, float32 hy)\r
+{\r
+ m_vertexCount = 4;\r
+ m_vertices[0].Set(-hx, -hy);\r
+ m_vertices[1].Set( hx, -hy);\r
+ m_vertices[2].Set( hx, hy);\r
+ m_vertices[3].Set(-hx, hy);\r
+ m_normals[0].Set(0.0f, -1.0f);\r
+ m_normals[1].Set(1.0f, 0.0f);\r
+ m_normals[2].Set(0.0f, 1.0f);\r
+ m_normals[3].Set(-1.0f, 0.0f);\r
+ m_centroid.SetZero();\r
+}\r
+\r
+void b2PolygonShape::SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle)\r
+{\r
+ m_vertexCount = 4;\r
+ m_vertices[0].Set(-hx, -hy);\r
+ m_vertices[1].Set( hx, -hy);\r
+ m_vertices[2].Set( hx, hy);\r
+ m_vertices[3].Set(-hx, hy);\r
+ m_normals[0].Set(0.0f, -1.0f);\r
+ m_normals[1].Set(1.0f, 0.0f);\r
+ m_normals[2].Set(0.0f, 1.0f);\r
+ m_normals[3].Set(-1.0f, 0.0f);\r
+ m_centroid = center;\r
+\r
+ b2Transform xf;\r
+ xf.position = center;\r
+ xf.R.Set(angle);\r
+\r
+ // Transform vertices and normals.\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ m_vertices[i] = b2Mul(xf, m_vertices[i]);\r
+ m_normals[i] = b2Mul(xf.R, m_normals[i]);\r
+ }\r
+}\r
+\r
+void b2PolygonShape::SetAsEdge(const b2Vec2& v1, const b2Vec2& v2)\r
+{\r
+ m_vertexCount = 2;\r
+ m_vertices[0] = v1;\r
+ m_vertices[1] = v2;\r
+ m_centroid = 0.5f * (v1 + v2);\r
+ m_normals[0] = b2Cross(v2 - v1, 1.0f);\r
+ m_normals[0].Normalize();\r
+ m_normals[1] = -m_normals[0];\r
+}\r
+\r
+static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)\r
+{\r
+ b2Assert(count >= 2);\r
+\r
+ b2Vec2 c; c.Set(0.0f, 0.0f);\r
+ float32 area = 0.0f;\r
+\r
+ if (count == 2)\r
+ {\r
+ c = 0.5f * (vs[0] + vs[1]);\r
+ return c;\r
+ }\r
+\r
+ // pRef is the reference point for forming triangles.\r
+ // It's location doesn't change the result (except for rounding error).\r
+ b2Vec2 pRef(0.0f, 0.0f);\r
+#if 0\r
+ // This code would put the reference point inside the polygon.\r
+ for (int32 i = 0; i < count; ++i)\r
+ {\r
+ pRef += vs[i];\r
+ }\r
+ pRef *= 1.0f / count;\r
+#endif\r
+\r
+ const float32 inv3 = 1.0f / 3.0f;\r
+\r
+ for (int32 i = 0; i < count; ++i)\r
+ {\r
+ // Triangle vertices.\r
+ b2Vec2 p1 = pRef;\r
+ b2Vec2 p2 = vs[i];\r
+ b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];\r
+\r
+ b2Vec2 e1 = p2 - p1;\r
+ b2Vec2 e2 = p3 - p1;\r
+\r
+ float32 D = b2Cross(e1, e2);\r
+\r
+ float32 triangleArea = 0.5f * D;\r
+ area += triangleArea;\r
+\r
+ // Area weighted centroid\r
+ c += triangleArea * inv3 * (p1 + p2 + p3);\r
+ }\r
+\r
+ // Centroid\r
+ b2Assert(area > b2_epsilon);\r
+ c *= 1.0f / area;\r
+ return c;\r
+}\r
+\r
+void b2PolygonShape::Set(const b2Vec2* vertices, int32 count)\r
+{\r
+ b2Assert(2 <= count && count <= b2_maxPolygonVertices);\r
+ m_vertexCount = count;\r
+\r
+ // Copy vertices.\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ m_vertices[i] = vertices[i];\r
+ }\r
+\r
+ // Compute normals. Ensure the edges have non-zero length.\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ int32 i1 = i;\r
+ int32 i2 = i + 1 < m_vertexCount ? i + 1 : 0;\r
+ b2Vec2 edge = m_vertices[i2] - m_vertices[i1];\r
+ b2Assert(edge.LengthSquared() > b2_epsilon * b2_epsilon);\r
+ m_normals[i] = b2Cross(edge, 1.0f);\r
+ m_normals[i].Normalize();\r
+ }\r
+\r
+#ifdef _DEBUG\r
+ // Ensure the polygon is convex and the interior\r
+ // is to the left of each edge.\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ int32 i1 = i;\r
+ int32 i2 = i + 1 < m_vertexCount ? i + 1 : 0;\r
+ b2Vec2 edge = m_vertices[i2] - m_vertices[i1];\r
+\r
+ for (int32 j = 0; j < m_vertexCount; ++j)\r
+ {\r
+ // Don't check vertices on the current edge.\r
+ if (j == i1 || j == i2)\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ b2Vec2 r = m_vertices[j] - m_vertices[i1];\r
+\r
+ // Your polygon is non-convex (it has an indentation) or\r
+ // has colinear edges.\r
+ float32 s = b2Cross(edge, r);\r
+ b2Assert(s > 0.0f);\r
+ }\r
+ }\r
+#endif\r
+\r
+ // Compute the polygon centroid.\r
+ m_centroid = ComputeCentroid(m_vertices, m_vertexCount);\r
+}\r
+\r
+bool b2PolygonShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const\r
+{\r
+ b2Vec2 pLocal = b2MulT(xf.R, p - xf.position);\r
+\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ float32 dot = b2Dot(m_normals[i], pLocal - m_vertices[i]);\r
+ if (dot > 0.0f)\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+bool b2PolygonShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& xf) const\r
+{\r
+ // Put the ray into the polygon's frame of reference.\r
+ b2Vec2 p1 = b2MulT(xf.R, input.p1 - xf.position);\r
+ b2Vec2 p2 = b2MulT(xf.R, input.p2 - xf.position);\r
+ b2Vec2 d = p2 - p1;\r
+\r
+ if (m_vertexCount == 2)\r
+ {\r
+ b2Vec2 v1 = m_vertices[0];\r
+ b2Vec2 v2 = m_vertices[1];\r
+ b2Vec2 normal = m_normals[0];\r
+\r
+ // q = p1 + t * d\r
+ // dot(normal, q - v1) = 0\r
+ // dot(normal, p1 - v1) + t * dot(normal, d) = 0\r
+ float32 numerator = b2Dot(normal, v1 - p1);\r
+ float32 denominator = b2Dot(normal, d);\r
+\r
+ if (denominator == 0.0f)\r
+ {\r
+ return false;\r
+ }\r
+ \r
+ float32 t = numerator / denominator;\r
+ if (t < 0.0f || 1.0f < t)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ b2Vec2 q = p1 + t * d;\r
+\r
+ // q = v1 + s * r\r
+ // s = dot(q - v1, r) / dot(r, r)\r
+ b2Vec2 r = v2 - v1;\r
+ float32 rr = b2Dot(r, r);\r
+ if (rr == 0.0f)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ float32 s = b2Dot(q - v1, r) / rr;\r
+ if (s < 0.0f || 1.0f < s)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ output->fraction = t;\r
+ if (numerator > 0.0f)\r
+ {\r
+ output->normal = -normal;\r
+ }\r
+ else\r
+ {\r
+ output->normal = normal;\r
+ }\r
+ return true;\r
+ }\r
+ else\r
+ {\r
+ float32 lower = 0.0f, upper = input.maxFraction;\r
+\r
+ int32 index = -1;\r
+\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ // p = p1 + a * d\r
+ // dot(normal, p - v) = 0\r
+ // dot(normal, p1 - v) + a * dot(normal, d) = 0\r
+ float32 numerator = b2Dot(m_normals[i], m_vertices[i] - p1);\r
+ float32 denominator = b2Dot(m_normals[i], d);\r
+\r
+ if (denominator == 0.0f)\r
+ { \r
+ if (numerator < 0.0f)\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Note: we want this predicate without division:\r
+ // lower < numerator / denominator, where denominator < 0\r
+ // Since denominator < 0, we have to flip the inequality:\r
+ // lower < numerator / denominator <==> denominator * lower > numerator.\r
+ if (denominator < 0.0f && numerator < lower * denominator)\r
+ {\r
+ // Increase lower.\r
+ // The segment enters this half-space.\r
+ lower = numerator / denominator;\r
+ index = i;\r
+ }\r
+ else if (denominator > 0.0f && numerator < upper * denominator)\r
+ {\r
+ // Decrease upper.\r
+ // The segment exits this half-space.\r
+ upper = numerator / denominator;\r
+ }\r
+ }\r
+\r
+ // The use of epsilon here causes the assert on lower to trip\r
+ // in some cases. Apparently the use of epsilon was to make edge\r
+ // shapes work, but now those are handled separately.\r
+ //if (upper < lower - b2_epsilon)\r
+ if (upper < lower)\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ b2Assert(0.0f <= lower && lower <= input.maxFraction);\r
+\r
+ if (index >= 0)\r
+ {\r
+ output->fraction = lower;\r
+ output->normal = b2Mul(xf.R, m_normals[index]);\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+void b2PolygonShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf) const\r
+{\r
+ b2Vec2 lower = b2Mul(xf, m_vertices[0]);\r
+ b2Vec2 upper = lower;\r
+\r
+ for (int32 i = 1; i < m_vertexCount; ++i)\r
+ {\r
+ b2Vec2 v = b2Mul(xf, m_vertices[i]);\r
+ lower = b2Min(lower, v);\r
+ upper = b2Max(upper, v);\r
+ }\r
+\r
+ b2Vec2 r(m_radius, m_radius);\r
+ aabb->lowerBound = lower - r;\r
+ aabb->upperBound = upper + r;\r
+}\r
+\r
+void b2PolygonShape::ComputeMass(b2MassData* massData, float32 density) const\r
+{\r
+ // Polygon mass, centroid, and inertia.\r
+ // Let rho be the polygon density in mass per unit area.\r
+ // Then:\r
+ // mass = rho * int(dA)\r
+ // centroid.x = (1/mass) * rho * int(x * dA)\r
+ // centroid.y = (1/mass) * rho * int(y * dA)\r
+ // I = rho * int((x*x + y*y) * dA)\r
+ //\r
+ // We can compute these integrals by summing all the integrals\r
+ // for each triangle of the polygon. To evaluate the integral\r
+ // for a single triangle, we make a change of variables to\r
+ // the (u,v) coordinates of the triangle:\r
+ // x = x0 + e1x * u + e2x * v\r
+ // y = y0 + e1y * u + e2y * v\r
+ // where 0 <= u && 0 <= v && u + v <= 1.\r
+ //\r
+ // We integrate u from [0,1-v] and then v from [0,1].\r
+ // We also need to use the Jacobian of the transformation:\r
+ // D = cross(e1, e2)\r
+ //\r
+ // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)\r
+ //\r
+ // The rest of the derivation is handled by computer algebra.\r
+\r
+ b2Assert(m_vertexCount >= 2);\r
+\r
+ // A line segment has zero mass.\r
+ if (m_vertexCount == 2)\r
+ {\r
+ massData->center = 0.5f * (m_vertices[0] + m_vertices[1]);\r
+ massData->mass = 0.0f;\r
+ massData->I = 0.0f;\r
+ return;\r
+ }\r
+\r
+ b2Vec2 center; center.Set(0.0f, 0.0f);\r
+ float32 area = 0.0f;\r
+ float32 I = 0.0f;\r
+\r
+ // pRef is the reference point for forming triangles.\r
+ // It's location doesn't change the result (except for rounding error).\r
+ b2Vec2 pRef(0.0f, 0.0f);\r
+#if 0\r
+ // This code would put the reference point inside the polygon.\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ pRef += m_vertices[i];\r
+ }\r
+ pRef *= 1.0f / count;\r
+#endif\r
+\r
+ const float32 k_inv3 = 1.0f / 3.0f;\r
+\r
+ for (int32 i = 0; i < m_vertexCount; ++i)\r
+ {\r
+ // Triangle vertices.\r
+ b2Vec2 p1 = pRef;\r
+ b2Vec2 p2 = m_vertices[i];\r
+ b2Vec2 p3 = i + 1 < m_vertexCount ? m_vertices[i+1] : m_vertices[0];\r
+\r
+ b2Vec2 e1 = p2 - p1;\r
+ b2Vec2 e2 = p3 - p1;\r
+\r
+ float32 D = b2Cross(e1, e2);\r
+\r
+ float32 triangleArea = 0.5f * D;\r
+ area += triangleArea;\r
+\r
+ // Area weighted centroid\r
+ center += triangleArea * k_inv3 * (p1 + p2 + p3);\r
+\r
+ float32 px = p1.x, py = p1.y;\r
+ float32 ex1 = e1.x, ey1 = e1.y;\r
+ float32 ex2 = e2.x, ey2 = e2.y;\r
+\r
+ float32 intx2 = k_inv3 * (0.25f * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5f*px*px;\r
+ float32 inty2 = k_inv3 * (0.25f * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5f*py*py;\r
+\r
+ I += D * (intx2 + inty2);\r
+ }\r
+\r
+ // Total mass\r
+ massData->mass = density * area;\r
+\r
+ // Center of mass\r
+ b2Assert(area > b2_epsilon);\r
+ center *= 1.0f / area;\r
+ massData->center = center;\r
+\r
+ // Inertia tensor relative to the local origin.\r
+ massData->I = density * I;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_POLYGON_SHAPE_H\r
+#define B2_POLYGON_SHAPE_H\r
+\r
+#include <Box2D/Collision/Shapes/b2Shape.h>\r
+\r
+/// A convex polygon. It is assumed that the interior of the polygon is to\r
+/// the left of each edge.\r
+class b2PolygonShape : public b2Shape\r
+{\r
+public:\r
+ b2PolygonShape();\r
+\r
+ /// Implement b2Shape.\r
+ b2Shape* Clone(b2BlockAllocator* allocator) const;\r
+\r
+ /// Copy vertices. This assumes the vertices define a convex polygon.\r
+ /// It is assumed that the exterior is the the right of each edge.\r
+ void Set(const b2Vec2* vertices, int32 vertexCount);\r
+\r
+ /// Build vertices to represent an axis-aligned box.\r
+ /// @param hx the half-width.\r
+ /// @param hy the half-height.\r
+ void SetAsBox(float32 hx, float32 hy);\r
+\r
+ /// Build vertices to represent an oriented box.\r
+ /// @param hx the half-width.\r
+ /// @param hy the half-height.\r
+ /// @param center the center of the box in local coordinates.\r
+ /// @param angle the rotation of the box in local coordinates.\r
+ void SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle);\r
+\r
+ /// Set this as a single edge.\r
+ void SetAsEdge(const b2Vec2& v1, const b2Vec2& v2);\r
+\r
+ /// @see b2Shape::TestPoint\r
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;\r
+\r
+ /// Implement b2Shape.\r
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const;\r
+\r
+ /// @see b2Shape::ComputeAABB\r
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform) const;\r
+\r
+ /// @see b2Shape::ComputeMass\r
+ void ComputeMass(b2MassData* massData, float32 density) const;\r
+\r
+ /// Get the supporting vertex index in the given direction.\r
+ int32 GetSupport(const b2Vec2& d) const;\r
+\r
+ /// Get the supporting vertex in the given direction.\r
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;\r
+\r
+ /// Get the vertex count.\r
+ int32 GetVertexCount() const { return m_vertexCount; }\r
+\r
+ /// Get a vertex by index.\r
+ const b2Vec2& GetVertex(int32 index) const;\r
+\r
+ b2Vec2 m_centroid;\r
+ b2Vec2 m_vertices[b2_maxPolygonVertices];\r
+ b2Vec2 m_normals[b2_maxPolygonVertices];\r
+ int32 m_vertexCount;\r
+};\r
+\r
+inline b2PolygonShape::b2PolygonShape()\r
+{\r
+ m_type = e_polygon;\r
+ m_radius = b2_polygonRadius;\r
+ m_vertexCount = 0;\r
+ m_centroid.SetZero();\r
+}\r
+\r
+inline int32 b2PolygonShape::GetSupport(const b2Vec2& d) const\r
+{\r
+ int32 bestIndex = 0;\r
+ float32 bestValue = b2Dot(m_vertices[0], d);\r
+ for (int32 i = 1; i < m_vertexCount; ++i)\r
+ {\r
+ float32 value = b2Dot(m_vertices[i], d);\r
+ if (value > bestValue)\r
+ {\r
+ bestIndex = i;\r
+ bestValue = value;\r
+ }\r
+ }\r
+\r
+ return bestIndex;\r
+}\r
+\r
+inline const b2Vec2& b2PolygonShape::GetSupportVertex(const b2Vec2& d) const\r
+{\r
+ int32 bestIndex = 0;\r
+ float32 bestValue = b2Dot(m_vertices[0], d);\r
+ for (int32 i = 1; i < m_vertexCount; ++i)\r
+ {\r
+ float32 value = b2Dot(m_vertices[i], d);\r
+ if (value > bestValue)\r
+ {\r
+ bestIndex = i;\r
+ bestValue = value;\r
+ }\r
+ }\r
+\r
+ return m_vertices[bestIndex];\r
+}\r
+\r
+inline const b2Vec2& b2PolygonShape::GetVertex(int32 index) const\r
+{\r
+ b2Assert(0 <= index && index < m_vertexCount);\r
+ return m_vertices[index];\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_SHAPE_H\r
+#define B2_SHAPE_H\r
+\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <Box2D/Common/b2Math.h>\r
+#include <Box2D/Collision/b2Collision.h>\r
+\r
+/// This holds the mass data computed for a shape.\r
+struct b2MassData\r
+{\r
+ /// The mass of the shape, usually in kilograms.\r
+ float32 mass;\r
+\r
+ /// The position of the shape's centroid relative to the shape's origin.\r
+ b2Vec2 center;\r
+\r
+ /// The rotational inertia of the shape about the local origin.\r
+ float32 I;\r
+};\r
+\r
+/// A shape is used for collision detection. You can create a shape however you like.\r
+/// Shapes used for simulation in b2World are created automatically when a b2Fixture\r
+/// is created.\r
+class b2Shape\r
+{\r
+public:\r
+ \r
+ enum Type\r
+ {\r
+ e_unknown= -1,\r
+ e_circle = 0,\r
+ e_polygon = 1,\r
+ e_typeCount = 2,\r
+ };\r
+\r
+ b2Shape() { m_type = e_unknown; }\r
+ virtual ~b2Shape() {}\r
+\r
+ /// Clone the concrete shape using the provided allocator.\r
+ virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0;\r
+\r
+ /// Get the type of this shape. You can use this to down cast to the concrete shape.\r
+ /// @return the shape type.\r
+ Type GetType() const;\r
+\r
+ /// Test a point for containment in this shape. This only works for convex shapes.\r
+ /// @param xf the shape world transform.\r
+ /// @param p a point in world coordinates.\r
+ virtual bool TestPoint(const b2Transform& xf, const b2Vec2& p) const = 0;\r
+\r
+ /// Cast a ray against this shape.\r
+ /// @param output the ray-cast results.\r
+ /// @param input the ray-cast input parameters.\r
+ /// @param transform the transform to be applied to the shape.\r
+ virtual bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const = 0;\r
+\r
+ /// Given a transform, compute the associated axis aligned bounding box for this shape.\r
+ /// @param aabb returns the axis aligned box.\r
+ /// @param xf the world transform of the shape.\r
+ virtual void ComputeAABB(b2AABB* aabb, const b2Transform& xf) const = 0;\r
+\r
+ /// Compute the mass properties of this shape using its dimensions and density.\r
+ /// The inertia tensor is computed about the local origin.\r
+ /// @param massData returns the mass data for this shape.\r
+ /// @param density the density in kilograms per meter squared.\r
+ virtual void ComputeMass(b2MassData* massData, float32 density) const = 0;\r
+\r
+ Type m_type;\r
+ float32 m_radius;\r
+};\r
+\r
+inline b2Shape::Type b2Shape::GetType() const\r
+{\r
+ return m_type;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2BroadPhase.h>\r
+#include <cstring>\r
+\r
+b2BroadPhase::b2BroadPhase()\r
+{\r
+ m_proxyCount = 0;\r
+\r
+ m_pairCapacity = 16;\r
+ m_pairCount = 0;\r
+ m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair));\r
+\r
+ m_moveCapacity = 16;\r
+ m_moveCount = 0;\r
+ m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32));\r
+}\r
+\r
+b2BroadPhase::~b2BroadPhase()\r
+{\r
+ b2Free(m_moveBuffer);\r
+ b2Free(m_pairBuffer);\r
+}\r
+\r
+int32 b2BroadPhase::CreateProxy(const b2AABB& aabb, void* userData)\r
+{\r
+ int32 proxyId = m_tree.CreateProxy(aabb, userData);\r
+ ++m_proxyCount;\r
+ BufferMove(proxyId);\r
+ return proxyId;\r
+}\r
+\r
+void b2BroadPhase::DestroyProxy(int32 proxyId)\r
+{\r
+ UnBufferMove(proxyId);\r
+ --m_proxyCount;\r
+ m_tree.DestroyProxy(proxyId);\r
+}\r
+\r
+void b2BroadPhase::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement)\r
+{\r
+ bool buffer = m_tree.MoveProxy(proxyId, aabb, displacement);\r
+ if (buffer)\r
+ {\r
+ BufferMove(proxyId);\r
+ }\r
+}\r
+\r
+void b2BroadPhase::BufferMove(int32 proxyId)\r
+{\r
+ if (m_moveCount == m_moveCapacity)\r
+ {\r
+ int32* oldBuffer = m_moveBuffer;\r
+ m_moveCapacity *= 2;\r
+ m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32));\r
+ memcpy(m_moveBuffer, oldBuffer, m_moveCount * sizeof(int32));\r
+ b2Free(oldBuffer);\r
+ }\r
+\r
+ m_moveBuffer[m_moveCount] = proxyId;\r
+ ++m_moveCount;\r
+}\r
+\r
+void b2BroadPhase::UnBufferMove(int32 proxyId)\r
+{\r
+ for (int32 i = 0; i < m_moveCount; ++i)\r
+ {\r
+ if (m_moveBuffer[i] == proxyId)\r
+ {\r
+ m_moveBuffer[i] = e_nullProxy;\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+// This is called from b2DynamicTree::Query when we are gathering pairs.\r
+bool b2BroadPhase::QueryCallback(int32 proxyId)\r
+{\r
+ // A proxy cannot form a pair with itself.\r
+ if (proxyId == m_queryProxyId)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ // Grow the pair buffer as needed.\r
+ if (m_pairCount == m_pairCapacity)\r
+ {\r
+ b2Pair* oldBuffer = m_pairBuffer;\r
+ m_pairCapacity *= 2;\r
+ m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair));\r
+ memcpy(m_pairBuffer, oldBuffer, m_pairCount * sizeof(b2Pair));\r
+ b2Free(oldBuffer);\r
+ }\r
+\r
+ m_pairBuffer[m_pairCount].proxyIdA = b2Min(proxyId, m_queryProxyId);\r
+ m_pairBuffer[m_pairCount].proxyIdB = b2Max(proxyId, m_queryProxyId);\r
+ ++m_pairCount;\r
+\r
+ return true;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_BROAD_PHASE_H\r
+#define B2_BROAD_PHASE_H\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/b2DynamicTree.h>\r
+#include <algorithm>\r
+\r
+struct b2Pair\r
+{\r
+ int32 proxyIdA;\r
+ int32 proxyIdB;\r
+ int32 next;\r
+};\r
+\r
+/// The broad-phase is used for computing pairs and performing volume queries and ray casts.\r
+/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs.\r
+/// It is up to the client to consume the new pairs and to track subsequent overlap.\r
+class b2BroadPhase\r
+{\r
+public:\r
+\r
+ enum\r
+ {\r
+ e_nullProxy = -1,\r
+ };\r
+\r
+ b2BroadPhase();\r
+ ~b2BroadPhase();\r
+\r
+ /// Create a proxy with an initial AABB. Pairs are not reported until\r
+ /// UpdatePairs is called.\r
+ int32 CreateProxy(const b2AABB& aabb, void* userData);\r
+\r
+ /// Destroy a proxy. It is up to the client to remove any pairs.\r
+ void DestroyProxy(int32 proxyId);\r
+\r
+ /// Call MoveProxy as many times as you like, then when you are done\r
+ /// call UpdatePairs to finalized the proxy pairs (for your time step).\r
+ void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement);\r
+\r
+ /// Get the fat AABB for a proxy.\r
+ const b2AABB& GetFatAABB(int32 proxyId) const;\r
+\r
+ /// Get user data from a proxy. Returns NULL if the id is invalid.\r
+ void* GetUserData(int32 proxyId) const;\r
+\r
+ /// Test overlap of fat AABBs.\r
+ bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const;\r
+\r
+ /// Get the number of proxies.\r
+ int32 GetProxyCount() const;\r
+\r
+ /// Update the pairs. This results in pair callbacks. This can only add pairs.\r
+ template <typename T>\r
+ void UpdatePairs(T* callback);\r
+\r
+ /// Query an AABB for overlapping proxies. The callback class\r
+ /// is called for each proxy that overlaps the supplied AABB.\r
+ template <typename T>\r
+ void Query(T* callback, const b2AABB& aabb) const;\r
+\r
+ /// Ray-cast against the proxies in the tree. This relies on the callback\r
+ /// to perform a exact ray-cast in the case were the proxy contains a shape.\r
+ /// The callback also performs the any collision filtering. This has performance\r
+ /// roughly equal to k * log(n), where k is the number of collisions and n is the\r
+ /// number of proxies in the tree.\r
+ /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).\r
+ /// @param callback a callback class that is called for each proxy that is hit by the ray.\r
+ template <typename T>\r
+ void RayCast(T* callback, const b2RayCastInput& input) const;\r
+\r
+ /// Compute the height of the embedded tree.\r
+ int32 ComputeHeight() const;\r
+\r
+private:\r
+\r
+ friend class b2DynamicTree;\r
+\r
+ void BufferMove(int32 proxyId);\r
+ void UnBufferMove(int32 proxyId);\r
+\r
+ bool QueryCallback(int32 proxyId);\r
+\r
+ b2DynamicTree m_tree;\r
+\r
+ int32 m_proxyCount;\r
+\r
+ int32* m_moveBuffer;\r
+ int32 m_moveCapacity;\r
+ int32 m_moveCount;\r
+\r
+ b2Pair* m_pairBuffer;\r
+ int32 m_pairCapacity;\r
+ int32 m_pairCount;\r
+\r
+ int32 m_queryProxyId;\r
+};\r
+\r
+/// This is used to sort pairs.\r
+inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2)\r
+{\r
+ if (pair1.proxyIdA < pair2.proxyIdA)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ if (pair1.proxyIdA == pair2.proxyIdA)\r
+ {\r
+ return pair1.proxyIdB < pair2.proxyIdB;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+inline void* b2BroadPhase::GetUserData(int32 proxyId) const\r
+{\r
+ return m_tree.GetUserData(proxyId);\r
+}\r
+\r
+inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const\r
+{\r
+ const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);\r
+ const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);\r
+ return b2TestOverlap(aabbA, aabbB);\r
+}\r
+\r
+inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const\r
+{\r
+ return m_tree.GetFatAABB(proxyId);\r
+}\r
+\r
+inline int32 b2BroadPhase::GetProxyCount() const\r
+{\r
+ return m_proxyCount;\r
+}\r
+\r
+inline int32 b2BroadPhase::ComputeHeight() const\r
+{\r
+ return m_tree.ComputeHeight();\r
+}\r
+\r
+template <typename T>\r
+void b2BroadPhase::UpdatePairs(T* callback)\r
+{\r
+ // Reset pair buffer\r
+ m_pairCount = 0;\r
+\r
+ // Perform tree queries for all moving proxies.\r
+ for (int32 i = 0; i < m_moveCount; ++i)\r
+ {\r
+ m_queryProxyId = m_moveBuffer[i];\r
+ if (m_queryProxyId == e_nullProxy)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // We have to query the tree with the fat AABB so that\r
+ // we don't fail to create a pair that may touch later.\r
+ const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);\r
+\r
+ // Query tree, create pairs and add them pair buffer.\r
+ m_tree.Query(this, fatAABB);\r
+ }\r
+\r
+ // Reset move buffer\r
+ m_moveCount = 0;\r
+\r
+ // Sort the pair buffer to expose duplicates.\r
+ std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan);\r
+\r
+ // Send the pairs back to the client.\r
+ int32 i = 0;\r
+ while (i < m_pairCount)\r
+ {\r
+ b2Pair* primaryPair = m_pairBuffer + i;\r
+ void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);\r
+ void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);\r
+\r
+ callback->AddPair(userDataA, userDataB);\r
+ ++i;\r
+\r
+ // Skip any duplicate pairs.\r
+ while (i < m_pairCount)\r
+ {\r
+ b2Pair* pair = m_pairBuffer + i;\r
+ if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB)\r
+ {\r
+ break;\r
+ }\r
+ ++i;\r
+ }\r
+ }\r
+\r
+ // Try to keep the tree balanced.\r
+ m_tree.Rebalance(4);\r
+}\r
+\r
+template <typename T>\r
+inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const\r
+{\r
+ m_tree.Query(callback, aabb);\r
+}\r
+\r
+template <typename T>\r
+inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const\r
+{\r
+ m_tree.RayCast(callback, input);\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2007-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/Shapes/b2CircleShape.h>\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+\r
+void b2CollideCircles(\r
+ b2Manifold* manifold,\r
+ const b2CircleShape* circleA, const b2Transform& xfA,\r
+ const b2CircleShape* circleB, const b2Transform& xfB)\r
+{\r
+ manifold->pointCount = 0;\r
+\r
+ b2Vec2 pA = b2Mul(xfA, circleA->m_p);\r
+ b2Vec2 pB = b2Mul(xfB, circleB->m_p);\r
+\r
+ b2Vec2 d = pB - pA;\r
+ float32 distSqr = b2Dot(d, d);\r
+ float32 rA = circleA->m_radius, rB = circleB->m_radius;\r
+ float32 radius = rA + rB;\r
+ if (distSqr > radius * radius)\r
+ {\r
+ return;\r
+ }\r
+\r
+ manifold->type = b2Manifold::e_circles;\r
+ manifold->localPoint = circleA->m_p;\r
+ manifold->localNormal.SetZero();\r
+ manifold->pointCount = 1;\r
+\r
+ manifold->points[0].localPoint = circleB->m_p;\r
+ manifold->points[0].id.key = 0;\r
+}\r
+\r
+void b2CollidePolygonAndCircle(\r
+ b2Manifold* manifold,\r
+ const b2PolygonShape* polygonA, const b2Transform& xfA,\r
+ const b2CircleShape* circleB, const b2Transform& xfB)\r
+{\r
+ manifold->pointCount = 0;\r
+\r
+ // Compute circle position in the frame of the polygon.\r
+ b2Vec2 c = b2Mul(xfB, circleB->m_p);\r
+ b2Vec2 cLocal = b2MulT(xfA, c);\r
+\r
+ // Find the min separating edge.\r
+ int32 normalIndex = 0;\r
+ float32 separation = -b2_maxFloat;\r
+ float32 radius = polygonA->m_radius + circleB->m_radius;\r
+ int32 vertexCount = polygonA->m_vertexCount;\r
+ const b2Vec2* vertices = polygonA->m_vertices;\r
+ const b2Vec2* normals = polygonA->m_normals;\r
+\r
+ for (int32 i = 0; i < vertexCount; ++i)\r
+ {\r
+ float32 s = b2Dot(normals[i], cLocal - vertices[i]);\r
+\r
+ if (s > radius)\r
+ {\r
+ // Early out.\r
+ return;\r
+ }\r
+\r
+ if (s > separation)\r
+ {\r
+ separation = s;\r
+ normalIndex = i;\r
+ }\r
+ }\r
+\r
+ // Vertices that subtend the incident face.\r
+ int32 vertIndex1 = normalIndex;\r
+ int32 vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;\r
+ b2Vec2 v1 = vertices[vertIndex1];\r
+ b2Vec2 v2 = vertices[vertIndex2];\r
+\r
+ // If the center is inside the polygon ...\r
+ if (separation < b2_epsilon)\r
+ {\r
+ manifold->pointCount = 1;\r
+ manifold->type = b2Manifold::e_faceA;\r
+ manifold->localNormal = normals[normalIndex];\r
+ manifold->localPoint = 0.5f * (v1 + v2);\r
+ manifold->points[0].localPoint = circleB->m_p;\r
+ manifold->points[0].id.key = 0;\r
+ return;\r
+ }\r
+\r
+ // Compute barycentric coordinates\r
+ float32 u1 = b2Dot(cLocal - v1, v2 - v1);\r
+ float32 u2 = b2Dot(cLocal - v2, v1 - v2);\r
+ if (u1 <= 0.0f)\r
+ {\r
+ if (b2DistanceSquared(cLocal, v1) > radius * radius)\r
+ {\r
+ return;\r
+ }\r
+\r
+ manifold->pointCount = 1;\r
+ manifold->type = b2Manifold::e_faceA;\r
+ manifold->localNormal = cLocal - v1;\r
+ manifold->localNormal.Normalize();\r
+ manifold->localPoint = v1;\r
+ manifold->points[0].localPoint = circleB->m_p;\r
+ manifold->points[0].id.key = 0;\r
+ }\r
+ else if (u2 <= 0.0f)\r
+ {\r
+ if (b2DistanceSquared(cLocal, v2) > radius * radius)\r
+ {\r
+ return;\r
+ }\r
+\r
+ manifold->pointCount = 1;\r
+ manifold->type = b2Manifold::e_faceA;\r
+ manifold->localNormal = cLocal - v2;\r
+ manifold->localNormal.Normalize();\r
+ manifold->localPoint = v2;\r
+ manifold->points[0].localPoint = circleB->m_p;\r
+ manifold->points[0].id.key = 0;\r
+ }\r
+ else\r
+ {\r
+ b2Vec2 faceCenter = 0.5f * (v1 + v2);\r
+ float32 separation = b2Dot(cLocal - faceCenter, normals[vertIndex1]);\r
+ if (separation > radius)\r
+ {\r
+ return;\r
+ }\r
+\r
+ manifold->pointCount = 1;\r
+ manifold->type = b2Manifold::e_faceA;\r
+ manifold->localNormal = normals[vertIndex1];\r
+ manifold->localPoint = faceCenter;\r
+ manifold->points[0].localPoint = circleB->m_p;\r
+ manifold->points[0].id.key = 0;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+\r
+// Find the separation between poly1 and poly2 for a give edge normal on poly1.\r
+static float32 b2EdgeSeparation(const b2PolygonShape* poly1, const b2Transform& xf1, int32 edge1,\r
+ const b2PolygonShape* poly2, const b2Transform& xf2)\r
+{\r
+ int32 count1 = poly1->m_vertexCount;\r
+ const b2Vec2* vertices1 = poly1->m_vertices;\r
+ const b2Vec2* normals1 = poly1->m_normals;\r
+\r
+ int32 count2 = poly2->m_vertexCount;\r
+ const b2Vec2* vertices2 = poly2->m_vertices;\r
+\r
+ b2Assert(0 <= edge1 && edge1 < count1);\r
+\r
+ // Convert normal from poly1's frame into poly2's frame.\r
+ b2Vec2 normal1World = b2Mul(xf1.R, normals1[edge1]);\r
+ b2Vec2 normal1 = b2MulT(xf2.R, normal1World);\r
+\r
+ // Find support vertex on poly2 for -normal.\r
+ int32 index = 0;\r
+ float32 minDot = b2_maxFloat;\r
+\r
+ for (int32 i = 0; i < count2; ++i)\r
+ {\r
+ float32 dot = b2Dot(vertices2[i], normal1);\r
+ if (dot < minDot)\r
+ {\r
+ minDot = dot;\r
+ index = i;\r
+ }\r
+ }\r
+\r
+ b2Vec2 v1 = b2Mul(xf1, vertices1[edge1]);\r
+ b2Vec2 v2 = b2Mul(xf2, vertices2[index]);\r
+ float32 separation = b2Dot(v2 - v1, normal1World);\r
+ return separation;\r
+}\r
+\r
+// Find the max separation between poly1 and poly2 using edge normals from poly1.\r
+static float32 b2FindMaxSeparation(int32* edgeIndex,\r
+ const b2PolygonShape* poly1, const b2Transform& xf1,\r
+ const b2PolygonShape* poly2, const b2Transform& xf2)\r
+{\r
+ int32 count1 = poly1->m_vertexCount;\r
+ const b2Vec2* normals1 = poly1->m_normals;\r
+\r
+ // Vector pointing from the centroid of poly1 to the centroid of poly2.\r
+ b2Vec2 d = b2Mul(xf2, poly2->m_centroid) - b2Mul(xf1, poly1->m_centroid);\r
+ b2Vec2 dLocal1 = b2MulT(xf1.R, d);\r
+\r
+ // Find edge normal on poly1 that has the largest projection onto d.\r
+ int32 edge = 0;\r
+ float32 maxDot = -b2_maxFloat;\r
+ for (int32 i = 0; i < count1; ++i)\r
+ {\r
+ float32 dot = b2Dot(normals1[i], dLocal1);\r
+ if (dot > maxDot)\r
+ {\r
+ maxDot = dot;\r
+ edge = i;\r
+ }\r
+ }\r
+\r
+ // Get the separation for the edge normal.\r
+ float32 s = b2EdgeSeparation(poly1, xf1, edge, poly2, xf2);\r
+\r
+ // Check the separation for the previous edge normal.\r
+ int32 prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;\r
+ float32 sPrev = b2EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);\r
+\r
+ // Check the separation for the next edge normal.\r
+ int32 nextEdge = edge + 1 < count1 ? edge + 1 : 0;\r
+ float32 sNext = b2EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);\r
+\r
+ // Find the best edge and the search direction.\r
+ int32 bestEdge;\r
+ float32 bestSeparation;\r
+ int32 increment;\r
+ if (sPrev > s && sPrev > sNext)\r
+ {\r
+ increment = -1;\r
+ bestEdge = prevEdge;\r
+ bestSeparation = sPrev;\r
+ }\r
+ else if (sNext > s)\r
+ {\r
+ increment = 1;\r
+ bestEdge = nextEdge;\r
+ bestSeparation = sNext;\r
+ }\r
+ else\r
+ {\r
+ *edgeIndex = edge;\r
+ return s;\r
+ }\r
+\r
+ // Perform a local search for the best edge normal.\r
+ for ( ; ; )\r
+ {\r
+ if (increment == -1)\r
+ edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;\r
+ else\r
+ edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;\r
+\r
+ s = b2EdgeSeparation(poly1, xf1, edge, poly2, xf2);\r
+\r
+ if (s > bestSeparation)\r
+ {\r
+ bestEdge = edge;\r
+ bestSeparation = s;\r
+ }\r
+ else\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ *edgeIndex = bestEdge;\r
+ return bestSeparation;\r
+}\r
+\r
+static void b2FindIncidentEdge(b2ClipVertex c[2],\r
+ const b2PolygonShape* poly1, const b2Transform& xf1, int32 edge1,\r
+ const b2PolygonShape* poly2, const b2Transform& xf2)\r
+{\r
+ int32 count1 = poly1->m_vertexCount;\r
+ const b2Vec2* normals1 = poly1->m_normals;\r
+\r
+ int32 count2 = poly2->m_vertexCount;\r
+ const b2Vec2* vertices2 = poly2->m_vertices;\r
+ const b2Vec2* normals2 = poly2->m_normals;\r
+\r
+ b2Assert(0 <= edge1 && edge1 < count1);\r
+\r
+ // Get the normal of the reference edge in poly2's frame.\r
+ b2Vec2 normal1 = b2MulT(xf2.R, b2Mul(xf1.R, normals1[edge1]));\r
+\r
+ // Find the incident edge on poly2.\r
+ int32 index = 0;\r
+ float32 minDot = b2_maxFloat;\r
+ for (int32 i = 0; i < count2; ++i)\r
+ {\r
+ float32 dot = b2Dot(normal1, normals2[i]);\r
+ if (dot < minDot)\r
+ {\r
+ minDot = dot;\r
+ index = i;\r
+ }\r
+ }\r
+\r
+ // Build the clip vertices for the incident edge.\r
+ int32 i1 = index;\r
+ int32 i2 = i1 + 1 < count2 ? i1 + 1 : 0;\r
+\r
+ c[0].v = b2Mul(xf2, vertices2[i1]);\r
+ c[0].id.features.referenceEdge = (uint8)edge1;\r
+ c[0].id.features.incidentEdge = (uint8)i1;\r
+ c[0].id.features.incidentVertex = 0;\r
+\r
+ c[1].v = b2Mul(xf2, vertices2[i2]);\r
+ c[1].id.features.referenceEdge = (uint8)edge1;\r
+ c[1].id.features.incidentEdge = (uint8)i2;\r
+ c[1].id.features.incidentVertex = 1;\r
+}\r
+\r
+// Find edge normal of max separation on A - return if separating axis is found\r
+// Find edge normal of max separation on B - return if separation axis is found\r
+// Choose reference edge as min(minA, minB)\r
+// Find incident edge\r
+// Clip\r
+\r
+// The normal points from 1 to 2\r
+void b2CollidePolygons(b2Manifold* manifold,\r
+ const b2PolygonShape* polyA, const b2Transform& xfA,\r
+ const b2PolygonShape* polyB, const b2Transform& xfB)\r
+{\r
+ manifold->pointCount = 0;\r
+ float32 totalRadius = polyA->m_radius + polyB->m_radius;\r
+\r
+ int32 edgeA = 0;\r
+ float32 separationA = b2FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);\r
+ if (separationA > totalRadius)\r
+ return;\r
+\r
+ int32 edgeB = 0;\r
+ float32 separationB = b2FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);\r
+ if (separationB > totalRadius)\r
+ return;\r
+\r
+ const b2PolygonShape* poly1; // reference polygon\r
+ const b2PolygonShape* poly2; // incident polygon\r
+ b2Transform xf1, xf2;\r
+ int32 edge1; // reference edge\r
+ uint8 flip;\r
+ const float32 k_relativeTol = 0.98f;\r
+ const float32 k_absoluteTol = 0.001f;\r
+\r
+ if (separationB > k_relativeTol * separationA + k_absoluteTol)\r
+ {\r
+ poly1 = polyB;\r
+ poly2 = polyA;\r
+ xf1 = xfB;\r
+ xf2 = xfA;\r
+ edge1 = edgeB;\r
+ manifold->type = b2Manifold::e_faceB;\r
+ flip = 1;\r
+ }\r
+ else\r
+ {\r
+ poly1 = polyA;\r
+ poly2 = polyB;\r
+ xf1 = xfA;\r
+ xf2 = xfB;\r
+ edge1 = edgeA;\r
+ manifold->type = b2Manifold::e_faceA;\r
+ flip = 0;\r
+ }\r
+\r
+ b2ClipVertex incidentEdge[2];\r
+ b2FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);\r
+\r
+ int32 count1 = poly1->m_vertexCount;\r
+ const b2Vec2* vertices1 = poly1->m_vertices;\r
+\r
+ b2Vec2 v11 = vertices1[edge1];\r
+ b2Vec2 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];\r
+\r
+ b2Vec2 localTangent = v12 - v11;\r
+ localTangent.Normalize();\r
+ \r
+ b2Vec2 localNormal = b2Cross(localTangent, 1.0f);\r
+ b2Vec2 planePoint = 0.5f * (v11 + v12);\r
+\r
+ b2Vec2 tangent = b2Mul(xf1.R, localTangent);\r
+ b2Vec2 normal = b2Cross(tangent, 1.0f);\r
+ \r
+ v11 = b2Mul(xf1, v11);\r
+ v12 = b2Mul(xf1, v12);\r
+\r
+ // Face offset.\r
+ float32 frontOffset = b2Dot(normal, v11);\r
+\r
+ // Side offsets, extended by polytope skin thickness.\r
+ float32 sideOffset1 = -b2Dot(tangent, v11) + totalRadius;\r
+ float32 sideOffset2 = b2Dot(tangent, v12) + totalRadius;\r
+\r
+ // Clip incident edge against extruded edge1 side edges.\r
+ b2ClipVertex clipPoints1[2];\r
+ b2ClipVertex clipPoints2[2];\r
+ int np;\r
+\r
+ // Clip to box side 1\r
+ np = b2ClipSegmentToLine(clipPoints1, incidentEdge, -tangent, sideOffset1);\r
+\r
+ if (np < 2)\r
+ return;\r
+\r
+ // Clip to negative box side 1\r
+ np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2);\r
+\r
+ if (np < 2)\r
+ {\r
+ return;\r
+ }\r
+\r
+ // Now clipPoints2 contains the clipped points.\r
+ manifold->localNormal = localNormal;\r
+ manifold->localPoint = planePoint;\r
+\r
+ int32 pointCount = 0;\r
+ for (int32 i = 0; i < b2_maxManifoldPoints; ++i)\r
+ {\r
+ float32 separation = b2Dot(normal, clipPoints2[i].v) - frontOffset;\r
+\r
+ if (separation <= totalRadius)\r
+ {\r
+ b2ManifoldPoint* cp = manifold->points + pointCount;\r
+ cp->localPoint = b2MulT(xf2, clipPoints2[i].v);\r
+ cp->id = clipPoints2[i].id;\r
+ cp->id.features.flip = flip;\r
+ ++pointCount;\r
+ }\r
+ }\r
+\r
+ manifold->pointCount = pointCount;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2007-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/b2Distance.h>\r
+\r
+void b2WorldManifold::Initialize(const b2Manifold* manifold,\r
+ const b2Transform& xfA, float32 radiusA,\r
+ const b2Transform& xfB, float32 radiusB)\r
+{\r
+ if (manifold->pointCount == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ switch (manifold->type)\r
+ {\r
+ case b2Manifold::e_circles:\r
+ {\r
+ normal.Set(1.0f, 0.0f);\r
+ b2Vec2 pointA = b2Mul(xfA, manifold->localPoint);\r
+ b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint);\r
+ if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)\r
+ {\r
+ normal = pointB - pointA;\r
+ normal.Normalize();\r
+ }\r
+\r
+ b2Vec2 cA = pointA + radiusA * normal;\r
+ b2Vec2 cB = pointB - radiusB * normal;\r
+ points[0] = 0.5f * (cA + cB);\r
+ }\r
+ break;\r
+\r
+ case b2Manifold::e_faceA:\r
+ {\r
+ normal = b2Mul(xfA.R, manifold->localNormal);\r
+ b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint);\r
+ \r
+ for (int32 i = 0; i < manifold->pointCount; ++i)\r
+ {\r
+ b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint);\r
+ b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal;\r
+ b2Vec2 cB = clipPoint - radiusB * normal;\r
+ points[i] = 0.5f * (cA + cB);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case b2Manifold::e_faceB:\r
+ {\r
+ normal = b2Mul(xfB.R, manifold->localNormal);\r
+ b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint);\r
+\r
+ for (int32 i = 0; i < manifold->pointCount; ++i)\r
+ {\r
+ b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint);\r
+ b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal;\r
+ b2Vec2 cA = clipPoint - radiusA * normal;\r
+ points[i] = 0.5f * (cA + cB);\r
+ }\r
+\r
+ // Ensure normal points from A to B.\r
+ normal = -normal;\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],\r
+ const b2Manifold* manifold1, const b2Manifold* manifold2)\r
+{\r
+ for (int32 i = 0; i < b2_maxManifoldPoints; ++i)\r
+ {\r
+ state1[i] = b2_nullState;\r
+ state2[i] = b2_nullState;\r
+ }\r
+\r
+ // Detect persists and removes.\r
+ for (int32 i = 0; i < manifold1->pointCount; ++i)\r
+ {\r
+ b2ContactID id = manifold1->points[i].id;\r
+\r
+ state1[i] = b2_removeState;\r
+\r
+ for (int32 j = 0; j < manifold2->pointCount; ++j)\r
+ {\r
+ if (manifold2->points[j].id.key == id.key)\r
+ {\r
+ state1[i] = b2_persistState;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Detect persists and adds.\r
+ for (int32 i = 0; i < manifold2->pointCount; ++i)\r
+ {\r
+ b2ContactID id = manifold2->points[i].id;\r
+\r
+ state2[i] = b2_addState;\r
+\r
+ for (int32 j = 0; j < manifold1->pointCount; ++j)\r
+ {\r
+ if (manifold1->points[j].id.key == id.key)\r
+ {\r
+ state2[i] = b2_persistState;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+// From Real-time Collision Detection, p179.\r
+bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const\r
+{\r
+ float32 tmin = -b2_maxFloat;\r
+ float32 tmax = b2_maxFloat;\r
+\r
+ b2Vec2 p = input.p1;\r
+ b2Vec2 d = input.p2 - input.p1;\r
+ b2Vec2 absD = b2Abs(d);\r
+\r
+ b2Vec2 normal;\r
+\r
+ for (int32 i = 0; i < 2; ++i)\r
+ {\r
+ if (absD(i) < b2_epsilon)\r
+ {\r
+ // Parallel.\r
+ if (p(i) < lowerBound(i) || upperBound(i) < p(i))\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ float32 inv_d = 1.0f / d(i);\r
+ float32 t1 = (lowerBound(i) - p(i)) * inv_d;\r
+ float32 t2 = (upperBound(i) - p(i)) * inv_d;\r
+\r
+ // Sign of the normal vector.\r
+ float32 s = -1.0f;\r
+\r
+ if (t1 > t2)\r
+ {\r
+ b2Swap(t1, t2);\r
+ s = 1.0f;\r
+ }\r
+\r
+ // Push the min up\r
+ if (t1 > tmin)\r
+ {\r
+ normal.SetZero();\r
+ normal(i) = s;\r
+ tmin = t1;\r
+ }\r
+\r
+ // Pull the max down\r
+ tmax = b2Min(tmax, t2);\r
+\r
+ if (tmin > tmax)\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Does the ray start inside the box?\r
+ // Does the ray intersect beyond the max fraction?\r
+ if (tmin < 0.0f || input.maxFraction < tmin)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // Intersection.\r
+ output->fraction = tmin;\r
+ output->normal = normal;\r
+ return true;\r
+}\r
+\r
+// Sutherland-Hodgman clipping.\r
+int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],\r
+ const b2Vec2& normal, float32 offset)\r
+{\r
+ // Start with no output points\r
+ int32 numOut = 0;\r
+\r
+ // Calculate the distance of end points to the line\r
+ float32 distance0 = b2Dot(normal, vIn[0].v) - offset;\r
+ float32 distance1 = b2Dot(normal, vIn[1].v) - offset;\r
+\r
+ // If the points are behind the plane\r
+ if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];\r
+ if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];\r
+\r
+ // If the points are on different sides of the plane\r
+ if (distance0 * distance1 < 0.0f)\r
+ {\r
+ // Find intersection point of edge and plane\r
+ float32 interp = distance0 / (distance0 - distance1);\r
+ vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);\r
+ if (distance0 > 0.0f)\r
+ {\r
+ vOut[numOut].id = vIn[0].id;\r
+ }\r
+ else\r
+ {\r
+ vOut[numOut].id = vIn[1].id;\r
+ }\r
+ ++numOut;\r
+ }\r
+\r
+ return numOut;\r
+}\r
+\r
+bool b2TestOverlap(const b2Shape* shapeA, const b2Shape* shapeB,\r
+ const b2Transform& xfA, const b2Transform& xfB)\r
+{\r
+ b2DistanceInput input;\r
+ input.proxyA.Set(shapeA);\r
+ input.proxyB.Set(shapeB);\r
+ input.transformA = xfA;\r
+ input.transformB = xfB;\r
+ input.useRadii = true;\r
+\r
+ b2SimplexCache cache;\r
+ cache.count = 0;\r
+\r
+ b2DistanceOutput output;\r
+\r
+ b2Distance(&output, &cache, &input);\r
+\r
+ return output.distance < 10.0f * b2_epsilon;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_COLLISION_H\r
+#define B2_COLLISION_H\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+#include <climits>\r
+\r
+/// @file\r
+/// Structures and functions used for computing contact points, distance\r
+/// queries, and TOI queries.\r
+\r
+class b2Shape;\r
+class b2CircleShape;\r
+class b2PolygonShape;\r
+\r
+const uint8 b2_nullFeature = UCHAR_MAX;\r
+\r
+/// Contact ids to facilitate warm starting.\r
+union b2ContactID\r
+{\r
+ /// The features that intersect to form the contact point\r
+ struct Features\r
+ {\r
+ uint8 referenceEdge; ///< The edge that defines the outward contact normal.\r
+ uint8 incidentEdge; ///< The edge most anti-parallel to the reference edge.\r
+ uint8 incidentVertex; ///< The vertex (0 or 1) on the incident edge that was clipped.\r
+ uint8 flip; ///< A value of 1 indicates that the reference edge is on shape2.\r
+ } features;\r
+ uint32 key; ///< Used to quickly compare contact ids.\r
+};\r
+\r
+/// A manifold point is a contact point belonging to a contact\r
+/// manifold. It holds details related to the geometry and dynamics\r
+/// of the contact points.\r
+/// The local point usage depends on the manifold type:\r
+/// -e_circles: the local center of circleB\r
+/// -e_faceA: the local center of cirlceB or the clip point of polygonB\r
+/// -e_faceB: the clip point of polygonA\r
+/// This structure is stored across time steps, so we keep it small.\r
+/// Note: the impulses are used for internal caching and may not\r
+/// provide reliable contact forces, especially for high speed collisions.\r
+struct b2ManifoldPoint\r
+{\r
+ b2Vec2 localPoint; ///< usage depends on manifold type\r
+ float32 normalImpulse; ///< the non-penetration impulse\r
+ float32 tangentImpulse; ///< the friction impulse\r
+ b2ContactID id; ///< uniquely identifies a contact point between two shapes\r
+};\r
+\r
+/// A manifold for two touching convex shapes.\r
+/// Box2D supports multiple types of contact:\r
+/// - clip point versus plane with radius\r
+/// - point versus point with radius (circles)\r
+/// The local point usage depends on the manifold type:\r
+/// -e_circles: the local center of circleA\r
+/// -e_faceA: the center of faceA\r
+/// -e_faceB: the center of faceB\r
+/// Similarly the local normal usage:\r
+/// -e_circles: not used\r
+/// -e_faceA: the normal on polygonA\r
+/// -e_faceB: the normal on polygonB\r
+/// We store contacts in this way so that position correction can\r
+/// account for movement, which is critical for continuous physics.\r
+/// All contact scenarios must be expressed in one of these types.\r
+/// This structure is stored across time steps, so we keep it small.\r
+struct b2Manifold\r
+{\r
+ enum Type\r
+ {\r
+ e_circles,\r
+ e_faceA,\r
+ e_faceB\r
+ };\r
+\r
+ b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact\r
+ b2Vec2 localNormal; ///< not use for Type::e_points\r
+ b2Vec2 localPoint; ///< usage depends on manifold type\r
+ Type type;\r
+ int32 pointCount; ///< the number of manifold points\r
+};\r
+\r
+/// This is used to compute the current state of a contact manifold.\r
+struct b2WorldManifold\r
+{\r
+ /// Evaluate the manifold with supplied transforms. This assumes\r
+ /// modest motion from the original state. This does not change the\r
+ /// point count, impulses, etc. The radii must come from the shapes\r
+ /// that generated the manifold.\r
+ void Initialize(const b2Manifold* manifold,\r
+ const b2Transform& xfA, float32 radiusA,\r
+ const b2Transform& xfB, float32 radiusB);\r
+\r
+ b2Vec2 normal; ///< world vector pointing from A to B\r
+ b2Vec2 points[b2_maxManifoldPoints]; ///< world contact point (point of intersection)\r
+};\r
+\r
+/// This is used for determining the state of contact points.\r
+enum b2PointState\r
+{\r
+ b2_nullState, ///< point does not exist\r
+ b2_addState, ///< point was added in the update\r
+ b2_persistState, ///< point persisted across the update\r
+ b2_removeState ///< point was removed in the update\r
+};\r
+\r
+/// Compute the point states given two manifolds. The states pertain to the transition from manifold1\r
+/// to manifold2. So state1 is either persist or remove while state2 is either add or persist.\r
+void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],\r
+ const b2Manifold* manifold1, const b2Manifold* manifold2);\r
+\r
+/// Used for computing contact manifolds.\r
+struct b2ClipVertex\r
+{\r
+ b2Vec2 v;\r
+ b2ContactID id;\r
+};\r
+\r
+/// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).\r
+struct b2RayCastInput\r
+{\r
+ b2Vec2 p1, p2;\r
+ float32 maxFraction;\r
+};\r
+\r
+/// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2\r
+/// come from b2RayCastInput.\r
+struct b2RayCastOutput\r
+{\r
+ b2Vec2 normal;\r
+ float32 fraction;\r
+};\r
+\r
+/// An axis aligned bounding box.\r
+struct b2AABB\r
+{\r
+ /// Verify that the bounds are sorted.\r
+ bool IsValid() const;\r
+\r
+ /// Get the center of the AABB.\r
+ b2Vec2 GetCenter() const\r
+ {\r
+ return 0.5f * (lowerBound + upperBound);\r
+ }\r
+\r
+ /// Get the extents of the AABB (half-widths).\r
+ b2Vec2 GetExtents() const\r
+ {\r
+ return 0.5f * (upperBound - lowerBound);\r
+ }\r
+\r
+ /// Combine two AABBs into this one.\r
+ void Combine(const b2AABB& aabb1, const b2AABB& aabb2)\r
+ {\r
+ lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound);\r
+ upperBound = b2Max(aabb1.upperBound, aabb2.upperBound);\r
+ }\r
+\r
+ /// Does this aabb contain the provided AABB.\r
+ bool Contains(const b2AABB& aabb) const\r
+ {\r
+ bool result = true;\r
+ result = result && lowerBound.x <= aabb.lowerBound.x;\r
+ result = result && lowerBound.y <= aabb.lowerBound.y;\r
+ result = result && aabb.upperBound.x <= upperBound.x;\r
+ result = result && aabb.upperBound.y <= upperBound.y;\r
+ return result;\r
+ }\r
+\r
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const;\r
+\r
+ b2Vec2 lowerBound; ///< the lower vertex\r
+ b2Vec2 upperBound; ///< the upper vertex\r
+};\r
+\r
+/// Compute the collision manifold between two circles.\r
+void b2CollideCircles(b2Manifold* manifold,\r
+ const b2CircleShape* circle1, const b2Transform& xf1,\r
+ const b2CircleShape* circle2, const b2Transform& xf2);\r
+\r
+/// Compute the collision manifold between a polygon and a circle.\r
+void b2CollidePolygonAndCircle(b2Manifold* manifold,\r
+ const b2PolygonShape* polygon, const b2Transform& xf1,\r
+ const b2CircleShape* circle, const b2Transform& xf2);\r
+\r
+/// Compute the collision manifold between two polygons.\r
+void b2CollidePolygons(b2Manifold* manifold,\r
+ const b2PolygonShape* polygon1, const b2Transform& xf1,\r
+ const b2PolygonShape* polygon2, const b2Transform& xf2);\r
+\r
+/// Clipping for contact manifolds.\r
+int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],\r
+ const b2Vec2& normal, float32 offset);\r
+\r
+/// Determine if two generic shapes overlap.\r
+bool b2TestOverlap(const b2Shape* shapeA, const b2Shape* shapeB,\r
+ const b2Transform& xfA, const b2Transform& xfB);\r
+\r
+// ---------------- Inline Functions ------------------------------------------\r
+\r
+inline bool b2AABB::IsValid() const\r
+{\r
+ b2Vec2 d = upperBound - lowerBound;\r
+ bool valid = d.x >= 0.0f && d.y >= 0.0f;\r
+ valid = valid && lowerBound.IsValid() && upperBound.IsValid();\r
+ return valid;\r
+}\r
+\r
+inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b)\r
+{\r
+ b2Vec2 d1, d2;\r
+ d1 = b.lowerBound - a.upperBound;\r
+ d2 = a.lowerBound - b.upperBound;\r
+\r
+ if (d1.x > 0.0f || d1.y > 0.0f)\r
+ return false;\r
+\r
+ if (d2.x > 0.0f || d2.y > 0.0f)\r
+ return false;\r
+\r
+ return true;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2007-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2Distance.h>\r
+#include <Box2D/Collision/Shapes/b2CircleShape.h>\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+\r
+// GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.\r
+int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;\r
+\r
+void b2DistanceProxy::Set(const b2Shape* shape)\r
+{\r
+ switch (shape->GetType())\r
+ {\r
+ case b2Shape::e_circle:\r
+ {\r
+ const b2CircleShape* circle = (b2CircleShape*)shape;\r
+ m_vertices = &circle->m_p;\r
+ m_count = 1;\r
+ m_radius = circle->m_radius;\r
+ }\r
+ break;\r
+\r
+ case b2Shape::e_polygon:\r
+ {\r
+ const b2PolygonShape* polygon = (b2PolygonShape*)shape;\r
+ m_vertices = polygon->m_vertices;\r
+ m_count = polygon->m_vertexCount;\r
+ m_radius = polygon->m_radius;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ b2Assert(false);\r
+ }\r
+}\r
+\r
+\r
+struct b2SimplexVertex\r
+{\r
+ b2Vec2 wA; // support point in proxyA\r
+ b2Vec2 wB; // support point in proxyB\r
+ b2Vec2 w; // wB - wA\r
+ float32 a; // barycentric coordinate for closest point\r
+ int32 indexA; // wA index\r
+ int32 indexB; // wB index\r
+};\r
+\r
+struct b2Simplex\r
+{\r
+ void ReadCache( const b2SimplexCache* cache,\r
+ const b2DistanceProxy* proxyA, const b2Transform& transformA,\r
+ const b2DistanceProxy* proxyB, const b2Transform& transformB)\r
+ {\r
+ b2Assert(cache->count <= 3);\r
+ \r
+ // Copy data from cache.\r
+ m_count = cache->count;\r
+ b2SimplexVertex* vertices = &m_v1;\r
+ for (int32 i = 0; i < m_count; ++i)\r
+ {\r
+ b2SimplexVertex* v = vertices + i;\r
+ v->indexA = cache->indexA[i];\r
+ v->indexB = cache->indexB[i];\r
+ b2Vec2 wALocal = proxyA->GetVertex(v->indexA);\r
+ b2Vec2 wBLocal = proxyB->GetVertex(v->indexB);\r
+ v->wA = b2Mul(transformA, wALocal);\r
+ v->wB = b2Mul(transformB, wBLocal);\r
+ v->w = v->wB - v->wA;\r
+ v->a = 0.0f;\r
+ }\r
+\r
+ // Compute the new simplex metric, if it is substantially different than\r
+ // old metric then flush the simplex.\r
+ if (m_count > 1)\r
+ {\r
+ float32 metric1 = cache->metric;\r
+ float32 metric2 = GetMetric();\r
+ if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon)\r
+ {\r
+ // Reset the simplex.\r
+ m_count = 0;\r
+ }\r
+ }\r
+\r
+ // If the cache is empty or invalid ...\r
+ if (m_count == 0)\r
+ {\r
+ b2SimplexVertex* v = vertices + 0;\r
+ v->indexA = 0;\r
+ v->indexB = 0;\r
+ b2Vec2 wALocal = proxyA->GetVertex(0);\r
+ b2Vec2 wBLocal = proxyB->GetVertex(0);\r
+ v->wA = b2Mul(transformA, wALocal);\r
+ v->wB = b2Mul(transformB, wBLocal);\r
+ v->w = v->wB - v->wA;\r
+ m_count = 1;\r
+ }\r
+ }\r
+\r
+ void WriteCache(b2SimplexCache* cache) const\r
+ {\r
+ cache->metric = GetMetric();\r
+ cache->count = uint16(m_count);\r
+ const b2SimplexVertex* vertices = &m_v1;\r
+ for (int32 i = 0; i < m_count; ++i)\r
+ {\r
+ cache->indexA[i] = uint8(vertices[i].indexA);\r
+ cache->indexB[i] = uint8(vertices[i].indexB);\r
+ }\r
+ }\r
+\r
+ b2Vec2 GetSearchDirection() const\r
+ {\r
+ switch (m_count)\r
+ {\r
+ case 1:\r
+ return -m_v1.w;\r
+\r
+ case 2:\r
+ {\r
+ b2Vec2 e12 = m_v2.w - m_v1.w;\r
+ float32 sgn = b2Cross(e12, -m_v1.w);\r
+ if (sgn > 0.0f)\r
+ {\r
+ // Origin is left of e12.\r
+ return b2Cross(1.0f, e12);\r
+ }\r
+ else\r
+ {\r
+ // Origin is right of e12.\r
+ return b2Cross(e12, 1.0f);\r
+ }\r
+ }\r
+\r
+ default:\r
+ b2Assert(false);\r
+ return b2Vec2_zero;\r
+ }\r
+ }\r
+\r
+ b2Vec2 GetClosestPoint() const\r
+ {\r
+ switch (m_count)\r
+ {\r
+ case 0:\r
+ b2Assert(false);\r
+ return b2Vec2_zero;\r
+\r
+ case 1:\r
+ return m_v1.w;\r
+\r
+ case 2:\r
+ return m_v1.a * m_v1.w + m_v2.a * m_v2.w;\r
+\r
+ case 3:\r
+ return b2Vec2_zero;\r
+\r
+ default:\r
+ b2Assert(false);\r
+ return b2Vec2_zero;\r
+ }\r
+ }\r
+\r
+ void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const\r
+ {\r
+ switch (m_count)\r
+ {\r
+ case 0:\r
+ b2Assert(false);\r
+ break;\r
+\r
+ case 1:\r
+ *pA = m_v1.wA;\r
+ *pB = m_v1.wB;\r
+ break;\r
+\r
+ case 2:\r
+ *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA;\r
+ *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB;\r
+ break;\r
+\r
+ case 3:\r
+ *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA;\r
+ *pB = *pA;\r
+ break;\r
+\r
+ default:\r
+ b2Assert(false);\r
+ break;\r
+ }\r
+ }\r
+\r
+ float32 GetMetric() const\r
+ {\r
+ switch (m_count)\r
+ {\r
+ case 0:\r
+ b2Assert(false);\r
+ return 0.0;\r
+\r
+ case 1:\r
+ return 0.0f;\r
+\r
+ case 2:\r
+ return b2Distance(m_v1.w, m_v2.w);\r
+\r
+ case 3:\r
+ return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);\r
+\r
+ default:\r
+ b2Assert(false);\r
+ return 0.0f;\r
+ }\r
+ }\r
+\r
+ void Solve2();\r
+ void Solve3();\r
+\r
+ b2SimplexVertex m_v1, m_v2, m_v3;\r
+ int32 m_count;\r
+};\r
+\r
+\r
+// Solve a line segment using barycentric coordinates.\r
+//\r
+// p = a1 * w1 + a2 * w2\r
+// a1 + a2 = 1\r
+//\r
+// The vector from the origin to the closest point on the line is\r
+// perpendicular to the line.\r
+// e12 = w2 - w1\r
+// dot(p, e) = 0\r
+// a1 * dot(w1, e) + a2 * dot(w2, e) = 0\r
+//\r
+// 2-by-2 linear system\r
+// [1 1 ][a1] = [1]\r
+// [w1.e12 w2.e12][a2] = [0]\r
+//\r
+// Define\r
+// d12_1 = dot(w2, e12)\r
+// d12_2 = -dot(w1, e12)\r
+// d12 = d12_1 + d12_2\r
+//\r
+// Solution\r
+// a1 = d12_1 / d12\r
+// a2 = d12_2 / d12\r
+void b2Simplex::Solve2()\r
+{\r
+ b2Vec2 w1 = m_v1.w;\r
+ b2Vec2 w2 = m_v2.w;\r
+ b2Vec2 e12 = w2 - w1;\r
+\r
+ // w1 region\r
+ float32 d12_2 = -b2Dot(w1, e12);\r
+ if (d12_2 <= 0.0f)\r
+ {\r
+ // a2 <= 0, so we clamp it to 0\r
+ m_v1.a = 1.0f;\r
+ m_count = 1;\r
+ return;\r
+ }\r
+\r
+ // w2 region\r
+ float32 d12_1 = b2Dot(w2, e12);\r
+ if (d12_1 <= 0.0f)\r
+ {\r
+ // a1 <= 0, so we clamp it to 0\r
+ m_v2.a = 1.0f;\r
+ m_count = 1;\r
+ m_v1 = m_v2;\r
+ return;\r
+ }\r
+\r
+ // Must be in e12 region.\r
+ float32 inv_d12 = 1.0f / (d12_1 + d12_2);\r
+ m_v1.a = d12_1 * inv_d12;\r
+ m_v2.a = d12_2 * inv_d12;\r
+ m_count = 2;\r
+}\r
+\r
+// Possible regions:\r
+// - points[2]\r
+// - edge points[0]-points[2]\r
+// - edge points[1]-points[2]\r
+// - inside the triangle\r
+void b2Simplex::Solve3()\r
+{\r
+ b2Vec2 w1 = m_v1.w;\r
+ b2Vec2 w2 = m_v2.w;\r
+ b2Vec2 w3 = m_v3.w;\r
+\r
+ // Edge12\r
+ // [1 1 ][a1] = [1]\r
+ // [w1.e12 w2.e12][a2] = [0]\r
+ // a3 = 0\r
+ b2Vec2 e12 = w2 - w1;\r
+ float32 w1e12 = b2Dot(w1, e12);\r
+ float32 w2e12 = b2Dot(w2, e12);\r
+ float32 d12_1 = w2e12;\r
+ float32 d12_2 = -w1e12;\r
+\r
+ // Edge13\r
+ // [1 1 ][a1] = [1]\r
+ // [w1.e13 w3.e13][a3] = [0]\r
+ // a2 = 0\r
+ b2Vec2 e13 = w3 - w1;\r
+ float32 w1e13 = b2Dot(w1, e13);\r
+ float32 w3e13 = b2Dot(w3, e13);\r
+ float32 d13_1 = w3e13;\r
+ float32 d13_2 = -w1e13;\r
+\r
+ // Edge23\r
+ // [1 1 ][a2] = [1]\r
+ // [w2.e23 w3.e23][a3] = [0]\r
+ // a1 = 0\r
+ b2Vec2 e23 = w3 - w2;\r
+ float32 w2e23 = b2Dot(w2, e23);\r
+ float32 w3e23 = b2Dot(w3, e23);\r
+ float32 d23_1 = w3e23;\r
+ float32 d23_2 = -w2e23;\r
+ \r
+ // Triangle123\r
+ float32 n123 = b2Cross(e12, e13);\r
+\r
+ float32 d123_1 = n123 * b2Cross(w2, w3);\r
+ float32 d123_2 = n123 * b2Cross(w3, w1);\r
+ float32 d123_3 = n123 * b2Cross(w1, w2);\r
+\r
+ // w1 region\r
+ if (d12_2 <= 0.0f && d13_2 <= 0.0f)\r
+ {\r
+ m_v1.a = 1.0f;\r
+ m_count = 1;\r
+ return;\r
+ }\r
+\r
+ // e12\r
+ if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)\r
+ {\r
+ float32 inv_d12 = 1.0f / (d12_1 + d12_2);\r
+ m_v1.a = d12_1 * inv_d12;\r
+ m_v2.a = d12_2 * inv_d12;\r
+ m_count = 2;\r
+ return;\r
+ }\r
+\r
+ // e13\r
+ if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)\r
+ {\r
+ float32 inv_d13 = 1.0f / (d13_1 + d13_2);\r
+ m_v1.a = d13_1 * inv_d13;\r
+ m_v3.a = d13_2 * inv_d13;\r
+ m_count = 2;\r
+ m_v2 = m_v3;\r
+ return;\r
+ }\r
+\r
+ // w2 region\r
+ if (d12_1 <= 0.0f && d23_2 <= 0.0f)\r
+ {\r
+ m_v2.a = 1.0f;\r
+ m_count = 1;\r
+ m_v1 = m_v2;\r
+ return;\r
+ }\r
+\r
+ // w3 region\r
+ if (d13_1 <= 0.0f && d23_1 <= 0.0f)\r
+ {\r
+ m_v3.a = 1.0f;\r
+ m_count = 1;\r
+ m_v1 = m_v3;\r
+ return;\r
+ }\r
+\r
+ // e23\r
+ if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)\r
+ {\r
+ float32 inv_d23 = 1.0f / (d23_1 + d23_2);\r
+ m_v2.a = d23_1 * inv_d23;\r
+ m_v3.a = d23_2 * inv_d23;\r
+ m_count = 2;\r
+ m_v1 = m_v3;\r
+ return;\r
+ }\r
+\r
+ // Must be in triangle123\r
+ float32 inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);\r
+ m_v1.a = d123_1 * inv_d123;\r
+ m_v2.a = d123_2 * inv_d123;\r
+ m_v3.a = d123_3 * inv_d123;\r
+ m_count = 3;\r
+}\r
+\r
+void b2Distance(b2DistanceOutput* output,\r
+ b2SimplexCache* cache,\r
+ const b2DistanceInput* input)\r
+{\r
+ ++b2_gjkCalls;\r
+\r
+ const b2DistanceProxy* proxyA = &input->proxyA;\r
+ const b2DistanceProxy* proxyB = &input->proxyB;\r
+\r
+ b2Transform transformA = input->transformA;\r
+ b2Transform transformB = input->transformB;\r
+\r
+ // Initialize the simplex.\r
+ b2Simplex simplex;\r
+ simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);\r
+\r
+ // Get simplex vertices as an array.\r
+ b2SimplexVertex* vertices = &simplex.m_v1;\r
+ const int32 k_maxIters = 20;\r
+\r
+ // These store the vertices of the last simplex so that we\r
+ // can check for duplicates and prevent cycling.\r
+ int32 saveA[3], saveB[3];\r
+ int32 saveCount = 0;\r
+\r
+ b2Vec2 closestPoint = simplex.GetClosestPoint();\r
+ float32 distanceSqr1 = closestPoint.LengthSquared();\r
+ float32 distanceSqr2 = distanceSqr1;\r
+\r
+ // Main iteration loop.\r
+ int32 iter = 0;\r
+ while (iter < k_maxIters)\r
+ {\r
+ // Copy simplex so we can identify duplicates.\r
+ saveCount = simplex.m_count;\r
+ for (int32 i = 0; i < saveCount; ++i)\r
+ {\r
+ saveA[i] = vertices[i].indexA;\r
+ saveB[i] = vertices[i].indexB;\r
+ }\r
+\r
+ switch (simplex.m_count)\r
+ {\r
+ case 1:\r
+ break;\r
+\r
+ case 2:\r
+ simplex.Solve2();\r
+ break;\r
+\r
+ case 3:\r
+ simplex.Solve3();\r
+ break;\r
+\r
+ default:\r
+ b2Assert(false);\r
+ }\r
+\r
+ // If we have 3 points, then the origin is in the corresponding triangle.\r
+ if (simplex.m_count == 3)\r
+ {\r
+ break;\r
+ }\r
+\r
+ // Compute closest point.\r
+ b2Vec2 p = simplex.GetClosestPoint();\r
+ distanceSqr2 = p.LengthSquared();\r
+\r
+ // Ensure progress\r
+ if (distanceSqr2 >= distanceSqr1)\r
+ {\r
+ //break;\r
+ }\r
+ distanceSqr1 = distanceSqr2;\r
+\r
+ // Get search direction.\r
+ b2Vec2 d = simplex.GetSearchDirection();\r
+\r
+ // Ensure the search direction is numerically fit.\r
+ if (d.LengthSquared() < b2_epsilon * b2_epsilon)\r
+ {\r
+ // The origin is probably contained by a line segment\r
+ // or triangle. Thus the shapes are overlapped.\r
+\r
+ // We can't return zero here even though there may be overlap.\r
+ // In case the simplex is a point, segment, or triangle it is difficult\r
+ // to determine if the origin is contained in the CSO or very close to it.\r
+ break;\r
+ }\r
+\r
+ // Compute a tentative new simplex vertex using support points.\r
+ b2SimplexVertex* vertex = vertices + simplex.m_count;\r
+ vertex->indexA = proxyA->GetSupport(b2MulT(transformA.R, -d));\r
+ vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));\r
+ b2Vec2 wBLocal;\r
+ vertex->indexB = proxyB->GetSupport(b2MulT(transformB.R, d));\r
+ vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));\r
+ vertex->w = vertex->wB - vertex->wA;\r
+\r
+ // Iteration count is equated to the number of support point calls.\r
+ ++iter;\r
+ ++b2_gjkIters;\r
+\r
+ // Check for duplicate support points. This is the main termination criteria.\r
+ bool duplicate = false;\r
+ for (int32 i = 0; i < saveCount; ++i)\r
+ {\r
+ if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i])\r
+ {\r
+ duplicate = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ // If we found a duplicate support point we must exit to avoid cycling.\r
+ if (duplicate)\r
+ {\r
+ break;\r
+ }\r
+\r
+ // New vertex is ok and needed.\r
+ ++simplex.m_count;\r
+ }\r
+\r
+ b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter);\r
+\r
+ // Prepare output.\r
+ simplex.GetWitnessPoints(&output->pointA, &output->pointB);\r
+ output->distance = b2Distance(output->pointA, output->pointB);\r
+ output->iterations = iter;\r
+\r
+ // Cache the simplex.\r
+ simplex.WriteCache(cache);\r
+\r
+ // Apply radii if requested.\r
+ if (input->useRadii)\r
+ {\r
+ float32 rA = proxyA->m_radius;\r
+ float32 rB = proxyB->m_radius;\r
+\r
+ if (output->distance > rA + rB && output->distance > b2_epsilon)\r
+ {\r
+ // Shapes are still no overlapped.\r
+ // Move the witness points to the outer surface.\r
+ output->distance -= rA + rB;\r
+ b2Vec2 normal = output->pointB - output->pointA;\r
+ normal.Normalize();\r
+ output->pointA += rA * normal;\r
+ output->pointB -= rB * normal;\r
+ }\r
+ else\r
+ {\r
+ // Shapes are overlapped when radii are considered.\r
+ // Move the witness points to the middle.\r
+ b2Vec2 p = 0.5f * (output->pointA + output->pointB);\r
+ output->pointA = p;\r
+ output->pointB = p;\r
+ output->distance = 0.0f;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+\r
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_DISTANCE_H\r
+#define B2_DISTANCE_H\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+#include <climits>\r
+\r
+class b2Shape;\r
+\r
+/// A distance proxy is used by the GJK algorithm.\r
+/// It encapsulates any shape.\r
+struct b2DistanceProxy\r
+{\r
+ b2DistanceProxy() : m_vertices(NULL), m_count(0), m_radius(0.0f) {}\r
+\r
+ /// Initialize the proxy using the given shape. The shape\r
+ /// must remain in scope while the proxy is in use.\r
+ void Set(const b2Shape* shape);\r
+\r
+ /// Get the supporting vertex index in the given direction.\r
+ int32 GetSupport(const b2Vec2& d) const;\r
+\r
+ /// Get the supporting vertex in the given direction.\r
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;\r
+\r
+ /// Get the vertex count.\r
+ int32 GetVertexCount() const;\r
+\r
+ /// Get a vertex by index. Used by b2Distance.\r
+ const b2Vec2& GetVertex(int32 index) const;\r
+\r
+ const b2Vec2* m_vertices;\r
+ int32 m_count;\r
+ float32 m_radius;\r
+};\r
+\r
+/// Used to warm start b2Distance.\r
+/// Set count to zero on first call.\r
+struct b2SimplexCache\r
+{\r
+ float32 metric; ///< length or area\r
+ uint16 count;\r
+ uint8 indexA[3]; ///< vertices on shape A\r
+ uint8 indexB[3]; ///< vertices on shape B\r
+};\r
+\r
+/// Input for b2Distance.\r
+/// You have to option to use the shape radii\r
+/// in the computation. Even \r
+struct b2DistanceInput\r
+{\r
+ b2DistanceProxy proxyA;\r
+ b2DistanceProxy proxyB;\r
+ b2Transform transformA;\r
+ b2Transform transformB;\r
+ bool useRadii;\r
+};\r
+\r
+/// Output for b2Distance.\r
+struct b2DistanceOutput\r
+{\r
+ b2Vec2 pointA; ///< closest point on shapeA\r
+ b2Vec2 pointB; ///< closest point on shapeB\r
+ float32 distance;\r
+ int32 iterations; ///< number of GJK iterations used\r
+};\r
+\r
+/// Compute the closest points between two shapes. Supports any combination of:\r
+/// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output.\r
+/// On the first call set b2SimplexCache.count to zero.\r
+void b2Distance(b2DistanceOutput* output,\r
+ b2SimplexCache* cache, \r
+ const b2DistanceInput* input);\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
+inline int32 b2DistanceProxy::GetVertexCount() const\r
+{\r
+ return m_count;\r
+}\r
+\r
+inline const b2Vec2& b2DistanceProxy::GetVertex(int32 index) const\r
+{\r
+ b2Assert(0 <= index && index < m_count);\r
+ return m_vertices[index];\r
+}\r
+\r
+inline int32 b2DistanceProxy::GetSupport(const b2Vec2& d) const\r
+{\r
+ int32 bestIndex = 0;\r
+ float32 bestValue = b2Dot(m_vertices[0], d);\r
+ for (int32 i = 1; i < m_count; ++i)\r
+ {\r
+ float32 value = b2Dot(m_vertices[i], d);\r
+ if (value > bestValue)\r
+ {\r
+ bestIndex = i;\r
+ bestValue = value;\r
+ }\r
+ }\r
+\r
+ return bestIndex;\r
+}\r
+\r
+inline const b2Vec2& b2DistanceProxy::GetSupportVertex(const b2Vec2& d) const\r
+{\r
+ int32 bestIndex = 0;\r
+ float32 bestValue = b2Dot(m_vertices[0], d);\r
+ for (int32 i = 1; i < m_count; ++i)\r
+ {\r
+ float32 value = b2Dot(m_vertices[i], d);\r
+ if (value > bestValue)\r
+ {\r
+ bestIndex = i;\r
+ bestValue = value;\r
+ }\r
+ }\r
+\r
+ return m_vertices[bestIndex];\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2DynamicTree.h>\r
+#include <cstring>\r
+#include <cfloat>\r
+\r
+b2DynamicTree::b2DynamicTree()\r
+{\r
+ m_root = b2_nullNode;\r
+\r
+ m_nodeCapacity = 16;\r
+ m_nodeCount = 0;\r
+ m_nodes = (b2DynamicTreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2DynamicTreeNode));\r
+ memset(m_nodes, 0, m_nodeCapacity * sizeof(b2DynamicTreeNode));\r
+\r
+ // Build a linked list for the free list.\r
+ for (int32 i = 0; i < m_nodeCapacity - 1; ++i)\r
+ {\r
+ m_nodes[i].next = i + 1;\r
+ }\r
+ m_nodes[m_nodeCapacity-1].next = b2_nullNode;\r
+ m_freeList = 0;\r
+\r
+ m_path = 0;\r
+\r
+ m_insertionCount = 0;\r
+}\r
+\r
+b2DynamicTree::~b2DynamicTree()\r
+{\r
+ // This frees the entire tree in one shot.\r
+ b2Free(m_nodes);\r
+}\r
+\r
+// Allocate a node from the pool. Grow the pool if necessary.\r
+int32 b2DynamicTree::AllocateNode()\r
+{\r
+ // Expand the node pool as needed.\r
+ if (m_freeList == b2_nullNode)\r
+ {\r
+ b2Assert(m_nodeCount == m_nodeCapacity);\r
+\r
+ // The free list is empty. Rebuild a bigger pool.\r
+ b2DynamicTreeNode* oldNodes = m_nodes;\r
+ m_nodeCapacity *= 2;\r
+ m_nodes = (b2DynamicTreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2DynamicTreeNode));\r
+ memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2DynamicTreeNode));\r
+ b2Free(oldNodes);\r
+\r
+ // Build a linked list for the free list. The parent\r
+ // pointer becomes the "next" pointer.\r
+ for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i)\r
+ {\r
+ m_nodes[i].next = i + 1;\r
+ }\r
+ m_nodes[m_nodeCapacity-1].next = b2_nullNode;\r
+ m_freeList = m_nodeCount;\r
+ }\r
+\r
+ // Peel a node off the free list.\r
+ int32 nodeId = m_freeList;\r
+ m_freeList = m_nodes[nodeId].next;\r
+ m_nodes[nodeId].parent = b2_nullNode;\r
+ m_nodes[nodeId].child1 = b2_nullNode;\r
+ m_nodes[nodeId].child2 = b2_nullNode;\r
+ ++m_nodeCount;\r
+ return nodeId;\r
+}\r
+\r
+// Return a node to the pool.\r
+void b2DynamicTree::FreeNode(int32 nodeId)\r
+{\r
+ b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);\r
+ b2Assert(0 < m_nodeCount);\r
+ m_nodes[nodeId].next = m_freeList;\r
+ m_freeList = nodeId;\r
+ --m_nodeCount;\r
+}\r
+\r
+// Create a proxy in the tree as a leaf node. We return the index\r
+// of the node instead of a pointer so that we can grow\r
+// the node pool.\r
+int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData)\r
+{\r
+ int32 proxyId = AllocateNode();\r
+\r
+ // Fatten the aabb.\r
+ b2Vec2 r(b2_aabbExtension, b2_aabbExtension);\r
+ m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r;\r
+ m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r;\r
+ m_nodes[proxyId].userData = userData;\r
+\r
+ InsertLeaf(proxyId);\r
+\r
+ // Rebalance if necessary.\r
+ int32 iterationCount = m_nodeCount >> 4;\r
+ int32 tryCount = 0;\r
+ int32 height = ComputeHeight();\r
+ while (height > 64 && tryCount < 10)\r
+ {\r
+ Rebalance(iterationCount);\r
+ height = ComputeHeight();\r
+ ++tryCount;\r
+ }\r
+\r
+ return proxyId;\r
+}\r
+\r
+void b2DynamicTree::DestroyProxy(int32 proxyId)\r
+{\r
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);\r
+ b2Assert(m_nodes[proxyId].IsLeaf());\r
+\r
+ RemoveLeaf(proxyId);\r
+ FreeNode(proxyId);\r
+}\r
+\r
+bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement)\r
+{\r
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);\r
+\r
+ b2Assert(m_nodes[proxyId].IsLeaf());\r
+\r
+ if (m_nodes[proxyId].aabb.Contains(aabb))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ RemoveLeaf(proxyId);\r
+\r
+ // Extend AABB.\r
+ b2AABB b = aabb;\r
+ b2Vec2 r(b2_aabbExtension, b2_aabbExtension);\r
+ b.lowerBound = b.lowerBound - r;\r
+ b.upperBound = b.upperBound + r;\r
+\r
+ // Predict AABB displacement.\r
+ b2Vec2 d = b2_aabbMultiplier * displacement;\r
+\r
+ if (d.x < 0.0f)\r
+ {\r
+ b.lowerBound.x += d.x;\r
+ }\r
+ else\r
+ {\r
+ b.upperBound.x += d.x;\r
+ }\r
+\r
+ if (d.y < 0.0f)\r
+ {\r
+ b.lowerBound.y += d.y;\r
+ }\r
+ else\r
+ {\r
+ b.upperBound.y += d.y;\r
+ }\r
+\r
+ m_nodes[proxyId].aabb = b;\r
+\r
+ InsertLeaf(proxyId);\r
+ return true;\r
+}\r
+\r
+void b2DynamicTree::InsertLeaf(int32 leaf)\r
+{\r
+ ++m_insertionCount;\r
+\r
+ if (m_root == b2_nullNode)\r
+ {\r
+ m_root = leaf;\r
+ m_nodes[m_root].parent = b2_nullNode;\r
+ return;\r
+ }\r
+\r
+ // Find the best sibling for this node.\r
+ b2Vec2 center = m_nodes[leaf].aabb.GetCenter();\r
+ int32 sibling = m_root;\r
+ if (m_nodes[sibling].IsLeaf() == false)\r
+ {\r
+ do \r
+ {\r
+ int32 child1 = m_nodes[sibling].child1;\r
+ int32 child2 = m_nodes[sibling].child2;\r
+\r
+ b2Vec2 delta1 = b2Abs(m_nodes[child1].aabb.GetCenter() - center);\r
+ b2Vec2 delta2 = b2Abs(m_nodes[child2].aabb.GetCenter() - center);\r
+\r
+ float32 norm1 = delta1.x + delta1.y;\r
+ float32 norm2 = delta2.x + delta2.y;\r
+\r
+ if (norm1 < norm2)\r
+ {\r
+ sibling = child1;\r
+ }\r
+ else\r
+ {\r
+ sibling = child2;\r
+ }\r
+\r
+ }\r
+ while(m_nodes[sibling].IsLeaf() == false);\r
+ }\r
+\r
+ // Create a parent for the siblings.\r
+ int32 node1 = m_nodes[sibling].parent;\r
+ int32 node2 = AllocateNode();\r
+ m_nodes[node2].parent = node1;\r
+ m_nodes[node2].userData = NULL;\r
+ m_nodes[node2].aabb.Combine(m_nodes[leaf].aabb, m_nodes[sibling].aabb);\r
+\r
+ if (node1 != b2_nullNode)\r
+ {\r
+ if (m_nodes[m_nodes[sibling].parent].child1 == sibling)\r
+ {\r
+ m_nodes[node1].child1 = node2;\r
+ }\r
+ else\r
+ {\r
+ m_nodes[node1].child2 = node2;\r
+ }\r
+\r
+ m_nodes[node2].child1 = sibling;\r
+ m_nodes[node2].child2 = leaf;\r
+ m_nodes[sibling].parent = node2;\r
+ m_nodes[leaf].parent = node2;\r
+\r
+ do \r
+ {\r
+ if (m_nodes[node1].aabb.Contains(m_nodes[node2].aabb))\r
+ {\r
+ break;\r
+ }\r
+\r
+ m_nodes[node1].aabb.Combine(m_nodes[m_nodes[node1].child1].aabb, m_nodes[m_nodes[node1].child2].aabb);\r
+ node2 = node1;\r
+ node1 = m_nodes[node1].parent;\r
+ }\r
+ while(node1 != b2_nullNode);\r
+ }\r
+ else\r
+ {\r
+ m_nodes[node2].child1 = sibling;\r
+ m_nodes[node2].child2 = leaf;\r
+ m_nodes[sibling].parent = node2;\r
+ m_nodes[leaf].parent = node2;\r
+ m_root = node2;\r
+ }\r
+}\r
+\r
+void b2DynamicTree::RemoveLeaf(int32 leaf)\r
+{\r
+ if (leaf == m_root)\r
+ {\r
+ m_root = b2_nullNode;\r
+ return;\r
+ }\r
+\r
+ int32 node2 = m_nodes[leaf].parent;\r
+ int32 node1 = m_nodes[node2].parent;\r
+ int32 sibling;\r
+ if (m_nodes[node2].child1 == leaf)\r
+ {\r
+ sibling = m_nodes[node2].child2;\r
+ }\r
+ else\r
+ {\r
+ sibling = m_nodes[node2].child1;\r
+ }\r
+\r
+ if (node1 != b2_nullNode)\r
+ {\r
+ // Destroy node2 and connect node1 to sibling.\r
+ if (m_nodes[node1].child1 == node2)\r
+ {\r
+ m_nodes[node1].child1 = sibling;\r
+ }\r
+ else\r
+ {\r
+ m_nodes[node1].child2 = sibling;\r
+ }\r
+ m_nodes[sibling].parent = node1;\r
+ FreeNode(node2);\r
+\r
+ // Adjust ancestor bounds.\r
+ while (node1 != b2_nullNode)\r
+ {\r
+ b2AABB oldAABB = m_nodes[node1].aabb;\r
+ m_nodes[node1].aabb.Combine(m_nodes[m_nodes[node1].child1].aabb, m_nodes[m_nodes[node1].child2].aabb);\r
+\r
+ if (oldAABB.Contains(m_nodes[node1].aabb))\r
+ {\r
+ break;\r
+ }\r
+\r
+ node1 = m_nodes[node1].parent;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ m_root = sibling;\r
+ m_nodes[sibling].parent = b2_nullNode;\r
+ FreeNode(node2);\r
+ }\r
+}\r
+\r
+void b2DynamicTree::Rebalance(int32 iterations)\r
+{\r
+ if (m_root == b2_nullNode)\r
+ {\r
+ return;\r
+ }\r
+\r
+ for (int32 i = 0; i < iterations; ++i)\r
+ {\r
+ int32 node = m_root;\r
+\r
+ uint32 bit = 0;\r
+ while (m_nodes[node].IsLeaf() == false)\r
+ {\r
+ int32* children = &m_nodes[node].child1;\r
+ node = children[(m_path >> bit) & 1];\r
+ bit = (bit + 1) & (8* sizeof(uint32) - 1);\r
+ }\r
+ ++m_path;\r
+\r
+ RemoveLeaf(node);\r
+ InsertLeaf(node);\r
+ }\r
+}\r
+\r
+// Compute the height of a sub-tree.\r
+int32 b2DynamicTree::ComputeHeight(int32 nodeId) const\r
+{\r
+ if (nodeId == b2_nullNode)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);\r
+ b2DynamicTreeNode* node = m_nodes + nodeId;\r
+ int32 height1 = ComputeHeight(node->child1);\r
+ int32 height2 = ComputeHeight(node->child2);\r
+ return 1 + b2Max(height1, height2);\r
+}\r
+\r
+int32 b2DynamicTree::ComputeHeight() const\r
+{\r
+ return ComputeHeight(m_root);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_DYNAMIC_TREE_H\r
+#define B2_DYNAMIC_TREE_H\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+\r
+/// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.\r
+\r
+#define b2_nullNode (-1)\r
+\r
+/// A node in the dynamic tree. The client does not interact with this directly.\r
+struct b2DynamicTreeNode\r
+{\r
+ bool IsLeaf() const\r
+ {\r
+ return child1 == b2_nullNode;\r
+ }\r
+\r
+ /// This is the fattened AABB.\r
+ b2AABB aabb;\r
+\r
+ //int32 userData;\r
+ void* userData;\r
+\r
+ union\r
+ {\r
+ int32 parent;\r
+ int32 next;\r
+ };\r
+\r
+ int32 child1;\r
+ int32 child2;\r
+};\r
+\r
+/// A dynamic tree arranges data in a binary tree to accelerate\r
+/// queries such as volume queries and ray casts. Leafs are proxies\r
+/// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor\r
+/// so that the proxy AABB is bigger than the client object. This allows the client\r
+/// object to move by small amounts without triggering a tree update.\r
+///\r
+/// Nodes are pooled and relocatable, so we use node indices rather than pointers.\r
+class b2DynamicTree\r
+{\r
+public:\r
+\r
+ /// Constructing the tree initializes the node pool.\r
+ b2DynamicTree();\r
+\r
+ /// Destroy the tree, freeing the node pool.\r
+ ~b2DynamicTree();\r
+\r
+ /// Create a proxy. Provide a tight fitting AABB and a userData pointer.\r
+ int32 CreateProxy(const b2AABB& aabb, void* userData);\r
+\r
+ /// Destroy a proxy. This asserts if the id is invalid.\r
+ void DestroyProxy(int32 proxyId);\r
+\r
+ /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,\r
+ /// then the proxy is removed from the tree and re-inserted. Otherwise\r
+ /// the function returns immediately.\r
+ /// @return true if the proxy was re-inserted.\r
+ bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);\r
+\r
+ /// Perform some iterations to re-balance the tree.\r
+ void Rebalance(int32 iterations);\r
+\r
+ /// Get proxy user data.\r
+ /// @return the proxy user data or 0 if the id is invalid.\r
+ void* GetUserData(int32 proxyId) const;\r
+\r
+ /// Get the fat AABB for a proxy.\r
+ const b2AABB& GetFatAABB(int32 proxyId) const;\r
+\r
+ /// Compute the height of the tree.\r
+ int32 ComputeHeight() const;\r
+\r
+ /// Query an AABB for overlapping proxies. The callback class\r
+ /// is called for each proxy that overlaps the supplied AABB.\r
+ template <typename T>\r
+ void Query(T* callback, const b2AABB& aabb) const;\r
+\r
+ /// Ray-cast against the proxies in the tree. This relies on the callback\r
+ /// to perform a exact ray-cast in the case were the proxy contains a shape.\r
+ /// The callback also performs the any collision filtering. This has performance\r
+ /// roughly equal to k * log(n), where k is the number of collisions and n is the\r
+ /// number of proxies in the tree.\r
+ /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).\r
+ /// @param callback a callback class that is called for each proxy that is hit by the ray.\r
+ template <typename T>\r
+ void RayCast(T* callback, const b2RayCastInput& input) const;\r
+\r
+private:\r
+\r
+ int32 AllocateNode();\r
+ void FreeNode(int32 node);\r
+\r
+ void InsertLeaf(int32 node);\r
+ void RemoveLeaf(int32 node);\r
+\r
+ int32 ComputeHeight(int32 nodeId) const;\r
+\r
+ int32 m_root;\r
+\r
+ b2DynamicTreeNode* m_nodes;\r
+ int32 m_nodeCount;\r
+ int32 m_nodeCapacity;\r
+\r
+ int32 m_freeList;\r
+\r
+ /// This is used incrementally traverse the tree for re-balancing.\r
+ uint32 m_path;\r
+\r
+ int32 m_insertionCount;\r
+};\r
+\r
+inline void* b2DynamicTree::GetUserData(int32 proxyId) const\r
+{\r
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);\r
+ return m_nodes[proxyId].userData;\r
+}\r
+\r
+inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const\r
+{\r
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);\r
+ return m_nodes[proxyId].aabb;\r
+}\r
+\r
+template <typename T>\r
+inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const\r
+{\r
+ const int32 k_stackSize = 128;\r
+ int32 stack[k_stackSize];\r
+\r
+ int32 count = 0;\r
+ stack[count++] = m_root;\r
+\r
+ while (count > 0)\r
+ {\r
+ int32 nodeId = stack[--count];\r
+ if (nodeId == b2_nullNode)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ const b2DynamicTreeNode* node = m_nodes + nodeId;\r
+\r
+ if (b2TestOverlap(node->aabb, aabb))\r
+ {\r
+ if (node->IsLeaf())\r
+ {\r
+ bool proceed = callback->QueryCallback(nodeId);\r
+ if (proceed == false)\r
+ {\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (count < k_stackSize)\r
+ {\r
+ stack[count++] = node->child1;\r
+ }\r
+\r
+ if (count < k_stackSize)\r
+ {\r
+ stack[count++] = node->child2;\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+template <typename T>\r
+inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const\r
+{\r
+ b2Vec2 p1 = input.p1;\r
+ b2Vec2 p2 = input.p2;\r
+ b2Vec2 r = p2 - p1;\r
+ b2Assert(r.LengthSquared() > 0.0f);\r
+ r.Normalize();\r
+\r
+ // v is perpendicular to the segment.\r
+ b2Vec2 v = b2Cross(1.0f, r);\r
+ b2Vec2 abs_v = b2Abs(v);\r
+\r
+ // Separating axis for segment (Gino, p80).\r
+ // |dot(v, p1 - c)| > dot(|v|, h)\r
+\r
+ float32 maxFraction = input.maxFraction;\r
+\r
+ // Build a bounding box for the segment.\r
+ b2AABB segmentAABB;\r
+ {\r
+ b2Vec2 t = p1 + maxFraction * (p2 - p1);\r
+ segmentAABB.lowerBound = b2Min(p1, t);\r
+ segmentAABB.upperBound = b2Max(p1, t);\r
+ }\r
+\r
+ const int32 k_stackSize = 128;\r
+ int32 stack[k_stackSize];\r
+\r
+ int32 count = 0;\r
+ stack[count++] = m_root;\r
+\r
+ while (count > 0)\r
+ {\r
+ int32 nodeId = stack[--count];\r
+ if (nodeId == b2_nullNode)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ const b2DynamicTreeNode* node = m_nodes + nodeId;\r
+\r
+ if (b2TestOverlap(node->aabb, segmentAABB) == false)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ // Separating axis for segment (Gino, p80).\r
+ // |dot(v, p1 - c)| > dot(|v|, h)\r
+ b2Vec2 c = node->aabb.GetCenter();\r
+ b2Vec2 h = node->aabb.GetExtents();\r
+ float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);\r
+ if (separation > 0.0f)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ if (node->IsLeaf())\r
+ {\r
+ b2RayCastInput subInput;\r
+ subInput.p1 = input.p1;\r
+ subInput.p2 = input.p2;\r
+ subInput.maxFraction = maxFraction;\r
+\r
+ float32 value = callback->RayCastCallback(subInput, nodeId);\r
+\r
+ if (value == 0.0f)\r
+ {\r
+ // The client has terminated the ray cast.\r
+ return;\r
+ }\r
+\r
+ if (value > 0.0f)\r
+ {\r
+ // Update segment bounding box.\r
+ maxFraction = value;\r
+ b2Vec2 t = p1 + maxFraction * (p2 - p1);\r
+ segmentAABB.lowerBound = b2Min(p1, t);\r
+ segmentAABB.upperBound = b2Max(p1, t);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (count < k_stackSize)\r
+ {\r
+ stack[count++] = node->child1;\r
+ }\r
+\r
+ if (count < k_stackSize)\r
+ {\r
+ stack[count++] = node->child2;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2007-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/b2Distance.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+#include <Box2D/Collision/Shapes/b2CircleShape.h>\r
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>\r
+\r
+#include <cstdio>\r
+\r
+int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters;\r
+int32 b2_toiRootIters, b2_toiMaxRootIters;\r
+\r
+int32 b2_toiMaxOptIters;\r
+\r
+struct b2SeparationFunction\r
+{\r
+ enum Type\r
+ {\r
+ e_points,\r
+ e_faceA,\r
+ e_faceB\r
+ };\r
+\r
+ // TODO_ERIN might not need to return the separation\r
+\r
+ float32 Initialize(const b2SimplexCache* cache,\r
+ const b2DistanceProxy* proxyA, const b2Sweep& sweepA,\r
+ const b2DistanceProxy* proxyB, const b2Sweep& sweepB)\r
+ {\r
+ m_proxyA = proxyA;\r
+ m_proxyB = proxyB;\r
+ int32 count = cache->count;\r
+ b2Assert(0 < count && count < 3);\r
+\r
+ m_sweepA = sweepA;\r
+ m_sweepB = sweepB;\r
+\r
+ b2Transform xfA, xfB;\r
+ m_sweepA.GetTransform(&xfA, 0.0f);\r
+ m_sweepB.GetTransform(&xfB, 0.0f);\r
+\r
+ if (count == 1)\r
+ {\r
+ m_type = e_points;\r
+ b2Vec2 localPointA = m_proxyA->GetVertex(cache->indexA[0]);\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]);\r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+ m_axis = pointB - pointA;\r
+ float32 s = m_axis.Normalize();\r
+ return s;\r
+ }\r
+ else if (cache->indexA[0] == cache->indexA[1])\r
+ {\r
+ // Two points on B and one on A.\r
+ m_type = e_faceB;\r
+ b2Vec2 localPointB1 = proxyB->GetVertex(cache->indexB[0]);\r
+ b2Vec2 localPointB2 = proxyB->GetVertex(cache->indexB[1]);\r
+\r
+ m_axis = b2Cross(localPointB2 - localPointB1, 1.0f);\r
+ m_axis.Normalize();\r
+ b2Vec2 normal = b2Mul(xfB.R, m_axis);\r
+\r
+ m_localPoint = 0.5f * (localPointB1 + localPointB2);\r
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);\r
+\r
+ b2Vec2 localPointA = proxyA->GetVertex(cache->indexA[0]);\r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+\r
+ float32 s = b2Dot(pointA - pointB, normal);\r
+ if (s < 0.0f)\r
+ {\r
+ m_axis = -m_axis;\r
+ s = -s;\r
+ }\r
+ return s;\r
+ }\r
+ else\r
+ {\r
+ // Two points on A and one or two points on B.\r
+ m_type = e_faceA;\r
+ b2Vec2 localPointA1 = m_proxyA->GetVertex(cache->indexA[0]);\r
+ b2Vec2 localPointA2 = m_proxyA->GetVertex(cache->indexA[1]);\r
+ \r
+ m_axis = b2Cross(localPointA2 - localPointA1, 1.0f);\r
+ m_axis.Normalize();\r
+ b2Vec2 normal = b2Mul(xfA.R, m_axis);\r
+\r
+ m_localPoint = 0.5f * (localPointA1 + localPointA2);\r
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);\r
+\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+\r
+ float32 s = b2Dot(pointB - pointA, normal);\r
+ if (s < 0.0f)\r
+ {\r
+ m_axis = -m_axis;\r
+ s = -s;\r
+ }\r
+ return s;\r
+ }\r
+ }\r
+\r
+ float32 FindMinSeparation(int32* indexA, int32* indexB, float32 t) const\r
+ {\r
+ b2Transform xfA, xfB;\r
+ m_sweepA.GetTransform(&xfA, t);\r
+ m_sweepB.GetTransform(&xfB, t);\r
+\r
+ switch (m_type)\r
+ {\r
+ case e_points:\r
+ {\r
+ b2Vec2 axisA = b2MulT(xfA.R, m_axis);\r
+ b2Vec2 axisB = b2MulT(xfB.R, -m_axis);\r
+\r
+ *indexA = m_proxyA->GetSupport(axisA);\r
+ *indexB = m_proxyB->GetSupport(axisB);\r
+\r
+ b2Vec2 localPointA = m_proxyA->GetVertex(*indexA);\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(*indexB);\r
+ \r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+\r
+ float32 separation = b2Dot(pointB - pointA, m_axis);\r
+ return separation;\r
+ }\r
+\r
+ case e_faceA:\r
+ {\r
+ b2Vec2 normal = b2Mul(xfA.R, m_axis);\r
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);\r
+\r
+ b2Vec2 axisB = b2MulT(xfB.R, -normal);\r
+ \r
+ *indexA = -1;\r
+ *indexB = m_proxyB->GetSupport(axisB);\r
+\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(*indexB);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+\r
+ float32 separation = b2Dot(pointB - pointA, normal);\r
+ return separation;\r
+ }\r
+\r
+ case e_faceB:\r
+ {\r
+ b2Vec2 normal = b2Mul(xfB.R, m_axis);\r
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);\r
+\r
+ b2Vec2 axisA = b2MulT(xfA.R, -normal);\r
+\r
+ *indexB = -1;\r
+ *indexA = m_proxyA->GetSupport(axisA);\r
+\r
+ b2Vec2 localPointA = m_proxyA->GetVertex(*indexA);\r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+\r
+ float32 separation = b2Dot(pointA - pointB, normal);\r
+ return separation;\r
+ }\r
+\r
+ default:\r
+ b2Assert(false);\r
+ *indexA = -1;\r
+ *indexB = -1;\r
+ return 0.0f;\r
+ }\r
+ }\r
+\r
+ float32 Evaluate(int32 indexA, int32 indexB, float32 t) const\r
+ {\r
+ b2Transform xfA, xfB;\r
+ m_sweepA.GetTransform(&xfA, t);\r
+ m_sweepB.GetTransform(&xfB, t);\r
+\r
+ switch (m_type)\r
+ {\r
+ case e_points:\r
+ {\r
+ b2Vec2 axisA = b2MulT(xfA.R, m_axis);\r
+ b2Vec2 axisB = b2MulT(xfB.R, -m_axis);\r
+\r
+ b2Vec2 localPointA = m_proxyA->GetVertex(indexA);\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(indexB);\r
+\r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+ float32 separation = b2Dot(pointB - pointA, m_axis);\r
+\r
+ return separation;\r
+ }\r
+\r
+ case e_faceA:\r
+ {\r
+ b2Vec2 normal = b2Mul(xfA.R, m_axis);\r
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);\r
+\r
+ b2Vec2 axisB = b2MulT(xfB.R, -normal);\r
+\r
+ b2Vec2 localPointB = m_proxyB->GetVertex(indexB);\r
+ b2Vec2 pointB = b2Mul(xfB, localPointB);\r
+\r
+ float32 separation = b2Dot(pointB - pointA, normal);\r
+ return separation;\r
+ }\r
+\r
+ case e_faceB:\r
+ {\r
+ b2Vec2 normal = b2Mul(xfB.R, m_axis);\r
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);\r
+\r
+ b2Vec2 axisA = b2MulT(xfA.R, -normal);\r
+\r
+ b2Vec2 localPointA = m_proxyA->GetVertex(indexA);\r
+ b2Vec2 pointA = b2Mul(xfA, localPointA);\r
+\r
+ float32 separation = b2Dot(pointA - pointB, normal);\r
+ return separation;\r
+ }\r
+\r
+ default:\r
+ b2Assert(false);\r
+ return 0.0f;\r
+ }\r
+ }\r
+\r
+ const b2DistanceProxy* m_proxyA;\r
+ const b2DistanceProxy* m_proxyB;\r
+ b2Sweep m_sweepA, m_sweepB;\r
+ Type m_type;\r
+ b2Vec2 m_localPoint;\r
+ b2Vec2 m_axis;\r
+};\r
+\r
+// CCD via the local separating axis method. This seeks progression\r
+// by computing the largest time at which separation is maintained.\r
+void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input)\r
+{\r
+ ++b2_toiCalls;\r
+\r
+ output->state = b2TOIOutput::e_unknown;\r
+ output->t = input->tMax;\r
+\r
+ const b2DistanceProxy* proxyA = &input->proxyA;\r
+ const b2DistanceProxy* proxyB = &input->proxyB;\r
+\r
+ b2Sweep sweepA = input->sweepA;\r
+ b2Sweep sweepB = input->sweepB;\r
+\r
+ // Large rotations can make the root finder fail, so we normalize the\r
+ // sweep angles.\r
+ sweepA.Normalize();\r
+ sweepB.Normalize();\r
+\r
+ float32 tMax = input->tMax;\r
+\r
+ float32 totalRadius = proxyA->m_radius + proxyB->m_radius;\r
+ float32 target = b2Max(b2_linearSlop, totalRadius - 3.0f * b2_linearSlop);\r
+ float32 tolerance = 0.25f * b2_linearSlop;\r
+ b2Assert(target > tolerance);\r
+\r
+ float32 t1 = 0.0f;\r
+ const int32 k_maxIterations = 20; // TODO_ERIN b2Settings\r
+ int32 iter = 0;\r
+\r
+ // Prepare input for distance query.\r
+ b2SimplexCache cache;\r
+ cache.count = 0;\r
+ b2DistanceInput distanceInput;\r
+ distanceInput.proxyA = input->proxyA;\r
+ distanceInput.proxyB = input->proxyB;\r
+ distanceInput.useRadii = false;\r
+\r
+ // The outer loop progressively attempts to compute new separating axes.\r
+ // This loop terminates when an axis is repeated (no progress is made).\r
+ for(;;)\r
+ {\r
+ b2Transform xfA, xfB;\r
+ sweepA.GetTransform(&xfA, t1);\r
+ sweepB.GetTransform(&xfB, t1);\r
+\r
+ // Get the distance between shapes. We can also use the results\r
+ // to get a separating axis.\r
+ distanceInput.transformA = xfA;\r
+ distanceInput.transformB = xfB;\r
+ b2DistanceOutput distanceOutput;\r
+ b2Distance(&distanceOutput, &cache, &distanceInput);\r
+\r
+ // If the shapes are overlapped, we give up on continuous collision.\r
+ if (distanceOutput.distance <= 0.0f)\r
+ {\r
+ // Failure!\r
+ output->state = b2TOIOutput::e_overlapped;\r
+ output->t = 0.0f;\r
+ break;\r
+ }\r
+\r
+ if (distanceOutput.distance < target + tolerance)\r
+ {\r
+ // Victory!\r
+ output->state = b2TOIOutput::e_touching;\r
+ output->t = t1;\r
+ break;\r
+ }\r
+\r
+ // Initialize the separating axis.\r
+ b2SeparationFunction fcn;\r
+ fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB);\r
+#if 0\r
+ // Dump the curve seen by the root finder\r
+ {\r
+ const int32 N = 100;\r
+ float32 dx = 1.0f / N;\r
+ float32 xs[N+1];\r
+ float32 fs[N+1];\r
+\r
+ float32 x = 0.0f;\r
+\r
+ for (int32 i = 0; i <= N; ++i)\r
+ {\r
+ sweepA.GetTransform(&xfA, x);\r
+ sweepB.GetTransform(&xfB, x);\r
+ float32 f = fcn.Evaluate(xfA, xfB) - target;\r
+\r
+ printf("%g %g\n", x, f);\r
+\r
+ xs[i] = x;\r
+ fs[i] = f;\r
+\r
+ x += dx;\r
+ }\r
+ }\r
+#endif\r
+\r
+ // Compute the TOI on the separating axis. We do this by successively\r
+ // resolving the deepest point. This loop is bounded by the number of vertices.\r
+ bool done = false;\r
+ float32 t2 = tMax;\r
+ int32 pushBackIter = 0;\r
+ for (;;)\r
+ {\r
+ // Find the deepest point at t2. Store the witness point indices.\r
+ int32 indexA, indexB;\r
+ float32 s2 = fcn.FindMinSeparation(&indexA, &indexB, t2);\r
+\r
+ // Is the final configuration separated?\r
+ if (s2 > target + tolerance)\r
+ {\r
+ // Victory!\r
+ output->state = b2TOIOutput::e_separated;\r
+ output->t = tMax;\r
+ done = true;\r
+ break;\r
+ }\r
+\r
+ // Has the separation reached tolerance?\r
+ if (s2 > target - tolerance)\r
+ {\r
+ // Advance the sweeps\r
+ t1 = t2;\r
+ break;\r
+ }\r
+\r
+ // Compute the initial separation of the witness points.\r
+ float32 s1 = fcn.Evaluate(indexA, indexB, t1);\r
+\r
+ // Check for initial overlap. This might happen if the root finder\r
+ // runs out of iterations.\r
+ if (s1 < target - tolerance)\r
+ {\r
+ output->state = b2TOIOutput::e_failed;\r
+ output->t = t1;\r
+ done = true;\r
+ break;\r
+ }\r
+\r
+ // Check for touching\r
+ if (s1 <= target + tolerance)\r
+ {\r
+ // Victory! t1 should hold the TOI (could be 0.0).\r
+ output->state = b2TOIOutput::e_touching;\r
+ output->t = t1;\r
+ done = true;\r
+ break;\r
+ }\r
+\r
+ // Compute 1D root of: f(x) - target = 0\r
+ int32 rootIterCount = 0;\r
+ float32 a1 = t1, a2 = t2;\r
+ for (;;)\r
+ {\r
+ // Use a mix of the secant rule and bisection.\r
+ float32 t;\r
+ if (rootIterCount & 1)\r
+ {\r
+ // Secant rule to improve convergence.\r
+ t = a1 + (target - s1) * (a2 - a1) / (s2 - s1);\r
+ }\r
+ else\r
+ {\r
+ // Bisection to guarantee progress.\r
+ t = 0.5f * (a1 + a2);\r
+ }\r
+\r
+ float32 s = fcn.Evaluate(indexA, indexB, t);\r
+\r
+ if (b2Abs(s - target) < tolerance)\r
+ {\r
+ // t2 holds a tentative value for t1\r
+ t2 = t;\r
+ break;\r
+ }\r
+\r
+ // Ensure we continue to bracket the root.\r
+ if (s > target)\r
+ {\r
+ a1 = t;\r
+ s1 = s;\r
+ }\r
+ else\r
+ {\r
+ a2 = t;\r
+ s2 = s;\r
+ }\r
+\r
+ ++rootIterCount;\r
+ ++b2_toiRootIters;\r
+\r
+ if (rootIterCount == 50)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ b2_toiMaxRootIters = b2Max(b2_toiMaxRootIters, rootIterCount);\r
+\r
+ ++pushBackIter;\r
+\r
+ if (pushBackIter == b2_maxPolygonVertices)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ ++iter;\r
+ ++b2_toiIters;\r
+\r
+ if (done)\r
+ {\r
+ break;\r
+ }\r
+\r
+ if (iter == k_maxIterations)\r
+ {\r
+ // Root finder got stuck. Semi-victory.\r
+ output->state = b2TOIOutput::e_failed;\r
+ output->t = t1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ b2_toiMaxIters = b2Max(b2_toiMaxIters, iter);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_TIME_OF_IMPACT_H\r
+#define B2_TIME_OF_IMPACT_H\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+#include <Box2D/Collision/b2Distance.h>\r
+#include <climits>\r
+\r
+/// Input parameters for b2TimeOfImpact\r
+struct b2TOIInput\r
+{\r
+ b2DistanceProxy proxyA;\r
+ b2DistanceProxy proxyB;\r
+ b2Sweep sweepA;\r
+ b2Sweep sweepB;\r
+ float32 tMax; // defines sweep interval [0, tMax]\r
+};\r
+\r
+// Output parameters for b2TimeOfImpact.\r
+struct b2TOIOutput\r
+{\r
+ enum State\r
+ {\r
+ e_unknown,\r
+ e_failed,\r
+ e_overlapped,\r
+ e_touching,\r
+ e_separated\r
+ };\r
+\r
+ State state;\r
+ float32 t;\r
+};\r
+\r
+/// Compute the upper bound on time before two shapes penetrate. Time is represented as\r
+/// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate,\r
+/// non-tunneling collision. If you change the time interval, you should call this function\r
+/// again.\r
+/// Note: use b2Distance to compute the contact point and normal at the time of impact.\r
+void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <cstdlib>\r
+#include <climits>\r
+#include <cstring>\r
+#include <memory>\r
+\r
+int32 b2BlockAllocator::s_blockSizes[b2_blockSizes] = \r
+{\r
+ 16, // 0\r
+ 32, // 1\r
+ 64, // 2\r
+ 96, // 3\r
+ 128, // 4\r
+ 160, // 5\r
+ 192, // 6\r
+ 224, // 7\r
+ 256, // 8\r
+ 320, // 9\r
+ 384, // 10\r
+ 448, // 11\r
+ 512, // 12\r
+ 640, // 13\r
+};\r
+uint8 b2BlockAllocator::s_blockSizeLookup[b2_maxBlockSize + 1];\r
+bool b2BlockAllocator::s_blockSizeLookupInitialized;\r
+\r
+struct b2Chunk\r
+{\r
+ int32 blockSize;\r
+ b2Block* blocks;\r
+};\r
+\r
+struct b2Block\r
+{\r
+ b2Block* next;\r
+};\r
+\r
+b2BlockAllocator::b2BlockAllocator()\r
+{\r
+ b2Assert(b2_blockSizes < UCHAR_MAX);\r
+\r
+ m_chunkSpace = b2_chunkArrayIncrement;\r
+ m_chunkCount = 0;\r
+ m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));\r
+ \r
+ memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));\r
+ memset(m_freeLists, 0, sizeof(m_freeLists));\r
+\r
+ if (s_blockSizeLookupInitialized == false)\r
+ {\r
+ int32 j = 0;\r
+ for (int32 i = 1; i <= b2_maxBlockSize; ++i)\r
+ {\r
+ b2Assert(j < b2_blockSizes);\r
+ if (i <= s_blockSizes[j])\r
+ {\r
+ s_blockSizeLookup[i] = (uint8)j;\r
+ }\r
+ else\r
+ {\r
+ ++j;\r
+ s_blockSizeLookup[i] = (uint8)j;\r
+ }\r
+ }\r
+\r
+ s_blockSizeLookupInitialized = true;\r
+ }\r
+}\r
+\r
+b2BlockAllocator::~b2BlockAllocator()\r
+{\r
+ for (int32 i = 0; i < m_chunkCount; ++i)\r
+ {\r
+ b2Free(m_chunks[i].blocks);\r
+ }\r
+\r
+ b2Free(m_chunks);\r
+}\r
+\r
+void* b2BlockAllocator::Allocate(int32 size)\r
+{\r
+ if (size == 0)\r
+ return NULL;\r
+\r
+ b2Assert(0 < size && size <= b2_maxBlockSize);\r
+\r
+ int32 index = s_blockSizeLookup[size];\r
+ b2Assert(0 <= index && index < b2_blockSizes);\r
+\r
+ if (m_freeLists[index])\r
+ {\r
+ b2Block* block = m_freeLists[index];\r
+ m_freeLists[index] = block->next;\r
+ return block;\r
+ }\r
+ else\r
+ {\r
+ if (m_chunkCount == m_chunkSpace)\r
+ {\r
+ b2Chunk* oldChunks = m_chunks;\r
+ m_chunkSpace += b2_chunkArrayIncrement;\r
+ m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));\r
+ memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk));\r
+ memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk));\r
+ b2Free(oldChunks);\r
+ }\r
+\r
+ b2Chunk* chunk = m_chunks + m_chunkCount;\r
+ chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize);\r
+#if defined(_DEBUG)\r
+ memset(chunk->blocks, 0xcd, b2_chunkSize);\r
+#endif\r
+ int32 blockSize = s_blockSizes[index];\r
+ chunk->blockSize = blockSize;\r
+ int32 blockCount = b2_chunkSize / blockSize;\r
+ b2Assert(blockCount * blockSize <= b2_chunkSize);\r
+ for (int32 i = 0; i < blockCount - 1; ++i)\r
+ {\r
+ b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i);\r
+ b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1));\r
+ block->next = next;\r
+ }\r
+ b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1));\r
+ last->next = NULL;\r
+\r
+ m_freeLists[index] = chunk->blocks->next;\r
+ ++m_chunkCount;\r
+\r
+ return chunk->blocks;\r
+ }\r
+}\r
+\r
+void b2BlockAllocator::Free(void* p, int32 size)\r
+{\r
+ if (size == 0)\r
+ {\r
+ return;\r
+ }\r
+\r
+ b2Assert(0 < size && size <= b2_maxBlockSize);\r
+\r
+ int32 index = s_blockSizeLookup[size];\r
+ b2Assert(0 <= index && index < b2_blockSizes);\r
+\r
+#ifdef _DEBUG\r
+ // Verify the memory address and size is valid.\r
+ int32 blockSize = s_blockSizes[index];\r
+ bool found = false;\r
+ for (int32 i = 0; i < m_chunkCount; ++i)\r
+ {\r
+ b2Chunk* chunk = m_chunks + i;\r
+ if (chunk->blockSize != blockSize)\r
+ {\r
+ b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks ||\r
+ (int8*)chunk->blocks + b2_chunkSize <= (int8*)p);\r
+ }\r
+ else\r
+ {\r
+ if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize)\r
+ {\r
+ found = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ b2Assert(found);\r
+\r
+ memset(p, 0xfd, blockSize);\r
+#endif\r
+\r
+ b2Block* block = (b2Block*)p;\r
+ block->next = m_freeLists[index];\r
+ m_freeLists[index] = block;\r
+}\r
+\r
+void b2BlockAllocator::Clear()\r
+{\r
+ for (int32 i = 0; i < m_chunkCount; ++i)\r
+ {\r
+ b2Free(m_chunks[i].blocks);\r
+ }\r
+\r
+ m_chunkCount = 0;\r
+ memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));\r
+\r
+ memset(m_freeLists, 0, sizeof(m_freeLists));\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_BLOCK_ALLOCATOR_H\r
+#define B2_BLOCK_ALLOCATOR_H\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+\r
+const int32 b2_chunkSize = 4096;\r
+const int32 b2_maxBlockSize = 640;\r
+const int32 b2_blockSizes = 14;\r
+const int32 b2_chunkArrayIncrement = 128;\r
+\r
+struct b2Block;\r
+struct b2Chunk;\r
+\r
+// This is a small object allocator used for allocating small\r
+// objects that persist for more than one time step.\r
+// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp\r
+class b2BlockAllocator\r
+{\r
+public:\r
+ b2BlockAllocator();\r
+ ~b2BlockAllocator();\r
+\r
+ void* Allocate(int32 size);\r
+ void Free(void* p, int32 size);\r
+\r
+ void Clear();\r
+\r
+private:\r
+\r
+ b2Chunk* m_chunks;\r
+ int32 m_chunkCount;\r
+ int32 m_chunkSpace;\r
+\r
+ b2Block* m_freeLists[b2_blockSizes];\r
+\r
+ static int32 s_blockSizes[b2_blockSizes];\r
+ static uint8 s_blockSizeLookup[b2_maxBlockSize + 1];\r
+ static bool s_blockSizeLookupInitialized;\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2007-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+\r
+const b2Vec2 b2Vec2_zero(0.0f, 0.0f);\r
+const b2Mat22 b2Mat22_identity(1.0f, 0.0f, 0.0f, 1.0f);\r
+const b2Transform b2Transform_identity(b2Vec2_zero, b2Mat22_identity);\r
+\r
+/// Solve A * x = b, where b is a column vector. This is more efficient\r
+/// than computing the inverse in one-shot cases.\r
+b2Vec3 b2Mat33::Solve33(const b2Vec3& b) const\r
+{\r
+ float32 det = b2Dot(col1, b2Cross(col2, col3));\r
+ if (det != 0.0f)\r
+ {\r
+ det = 1.0f / det;\r
+ }\r
+ b2Vec3 x;\r
+ x.x = det * b2Dot(b, b2Cross(col2, col3));\r
+ x.y = det * b2Dot(col1, b2Cross(b, col3));\r
+ x.z = det * b2Dot(col1, b2Cross(col2, b));\r
+ return x;\r
+}\r
+\r
+/// Solve A * x = b, where b is a column vector. This is more efficient\r
+/// than computing the inverse in one-shot cases.\r
+b2Vec2 b2Mat33::Solve22(const b2Vec2& b) const\r
+{\r
+ float32 a11 = col1.x, a12 = col2.x, a21 = col1.y, a22 = col2.y;\r
+ float32 det = a11 * a22 - a12 * a21;\r
+ if (det != 0.0f)\r
+ {\r
+ det = 1.0f / det;\r
+ }\r
+ b2Vec2 x;\r
+ x.x = det * (a22 * b.x - a12 * b.y);\r
+ x.y = det * (a11 * b.y - a21 * b.x);\r
+ return x;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_MATH_H\r
+#define B2_MATH_H\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+\r
+#include <cmath>\r
+#include <cfloat>\r
+#include <cstddef>\r
+#include <limits>\r
+\r
+/// This function is used to ensure that a floating point number is\r
+/// not a NaN or infinity.\r
+inline bool b2IsValid(float32 x)\r
+{\r
+ if (x != x)\r
+ {\r
+ // NaN.\r
+ return false;\r
+ }\r
+\r
+ float32 infinity = std::numeric_limits<float32>::infinity();\r
+ return -infinity < x && x < infinity;\r
+}\r
+\r
+/// This is a approximate yet fast inverse square-root.\r
+inline float32 b2InvSqrt(float32 x)\r
+{\r
+ union\r
+ {\r
+ float32 x;\r
+ int32 i;\r
+ } convert;\r
+\r
+ convert.x = x;\r
+ float32 xhalf = 0.5f * x;\r
+ convert.i = 0x5f3759df - (convert.i >> 1);\r
+ x = convert.x;\r
+ x = x * (1.5f - xhalf * x * x);\r
+ return x;\r
+}\r
+\r
+#define b2Sqrt(x) sqrtf(x)\r
+#define b2Atan2(y, x) atan2f(y, x)\r
+\r
+inline float32 b2Abs(float32 a)\r
+{\r
+ return a > 0.0f ? a : -a;\r
+}\r
+\r
+/// A 2D column vector.\r
+struct b2Vec2\r
+{\r
+ /// Default constructor does nothing (for performance).\r
+ b2Vec2() {}\r
+\r
+ /// Construct using coordinates.\r
+ b2Vec2(float32 x, float32 y) : x(x), y(y) {}\r
+\r
+ /// Set this vector to all zeros.\r
+ void SetZero() { x = 0.0f; y = 0.0f; }\r
+\r
+ /// Set this vector to some specified coordinates.\r
+ void Set(float32 x_, float32 y_) { x = x_; y = y_; }\r
+\r
+ /// Negate this vector.\r
+ b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; }\r
+ \r
+ /// Read from and indexed element.\r
+ float32 operator () (int32 i) const\r
+ {\r
+ return (&x)[i];\r
+ }\r
+\r
+ /// Write to an indexed element.\r
+ float32& operator () (int32 i)\r
+ {\r
+ return (&x)[i];\r
+ }\r
+\r
+ /// Add a vector to this vector.\r
+ void operator += (const b2Vec2& v)\r
+ {\r
+ x += v.x; y += v.y;\r
+ }\r
+ \r
+ /// Subtract a vector from this vector.\r
+ void operator -= (const b2Vec2& v)\r
+ {\r
+ x -= v.x; y -= v.y;\r
+ }\r
+\r
+ /// Multiply this vector by a scalar.\r
+ void operator *= (float32 a)\r
+ {\r
+ x *= a; y *= a;\r
+ }\r
+\r
+ /// Get the length of this vector (the norm).\r
+ float32 Length() const\r
+ {\r
+ return b2Sqrt(x * x + y * y);\r
+ }\r
+\r
+ /// Get the length squared. For performance, use this instead of\r
+ /// b2Vec2::Length (if possible).\r
+ float32 LengthSquared() const\r
+ {\r
+ return x * x + y * y;\r
+ }\r
+\r
+ /// Convert this vector into a unit vector. Returns the length.\r
+ float32 Normalize()\r
+ {\r
+ float32 length = Length();\r
+ if (length < b2_epsilon)\r
+ {\r
+ return 0.0f;\r
+ }\r
+ float32 invLength = 1.0f / length;\r
+ x *= invLength;\r
+ y *= invLength;\r
+\r
+ return length;\r
+ }\r
+\r
+ /// Does this vector contain finite coordinates?\r
+ bool IsValid() const\r
+ {\r
+ return b2IsValid(x) && b2IsValid(y);\r
+ }\r
+\r
+ float32 x, y;\r
+};\r
+\r
+/// A 2D column vector with 3 elements.\r
+struct b2Vec3\r
+{\r
+ /// Default constructor does nothing (for performance).\r
+ b2Vec3() {}\r
+\r
+ /// Construct using coordinates.\r
+ b2Vec3(float32 x, float32 y, float32 z) : x(x), y(y), z(z) {}\r
+\r
+ /// Set this vector to all zeros.\r
+ void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; }\r
+\r
+ /// Set this vector to some specified coordinates.\r
+ void Set(float32 x_, float32 y_, float32 z_) { x = x_; y = y_; z = z_; }\r
+\r
+ /// Negate this vector.\r
+ b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; }\r
+\r
+ /// Add a vector to this vector.\r
+ void operator += (const b2Vec3& v)\r
+ {\r
+ x += v.x; y += v.y; z += v.z;\r
+ }\r
+\r
+ /// Subtract a vector from this vector.\r
+ void operator -= (const b2Vec3& v)\r
+ {\r
+ x -= v.x; y -= v.y; z -= v.z;\r
+ }\r
+\r
+ /// Multiply this vector by a scalar.\r
+ void operator *= (float32 s)\r
+ {\r
+ x *= s; y *= s; z *= s;\r
+ }\r
+\r
+ float32 x, y, z;\r
+};\r
+\r
+/// A 2-by-2 matrix. Stored in column-major order.\r
+struct b2Mat22\r
+{\r
+ /// The default constructor does nothing (for performance).\r
+ b2Mat22() {}\r
+\r
+ /// Construct this matrix using columns.\r
+ b2Mat22(const b2Vec2& c1, const b2Vec2& c2)\r
+ {\r
+ col1 = c1;\r
+ col2 = c2;\r
+ }\r
+\r
+ /// Construct this matrix using scalars.\r
+ b2Mat22(float32 a11, float32 a12, float32 a21, float32 a22)\r
+ {\r
+ col1.x = a11; col1.y = a21;\r
+ col2.x = a12; col2.y = a22;\r
+ }\r
+\r
+ /// Construct this matrix using an angle. This matrix becomes\r
+ /// an orthonormal rotation matrix.\r
+ explicit b2Mat22(float32 angle)\r
+ {\r
+ // TODO_ERIN compute sin+cos together.\r
+ float32 c = cosf(angle), s = sinf(angle);\r
+ col1.x = c; col2.x = -s;\r
+ col1.y = s; col2.y = c;\r
+ }\r
+\r
+ /// Initialize this matrix using columns.\r
+ void Set(const b2Vec2& c1, const b2Vec2& c2)\r
+ {\r
+ col1 = c1;\r
+ col2 = c2;\r
+ }\r
+\r
+ /// Initialize this matrix using an angle. This matrix becomes\r
+ /// an orthonormal rotation matrix.\r
+ void Set(float32 angle)\r
+ {\r
+ float32 c = cosf(angle), s = sinf(angle);\r
+ col1.x = c; col2.x = -s;\r
+ col1.y = s; col2.y = c;\r
+ }\r
+\r
+ /// Set this to the identity matrix.\r
+ void SetIdentity()\r
+ {\r
+ col1.x = 1.0f; col2.x = 0.0f;\r
+ col1.y = 0.0f; col2.y = 1.0f;\r
+ }\r
+\r
+ /// Set this matrix to all zeros.\r
+ void SetZero()\r
+ {\r
+ col1.x = 0.0f; col2.x = 0.0f;\r
+ col1.y = 0.0f; col2.y = 0.0f;\r
+ }\r
+\r
+ /// Extract the angle from this matrix (assumed to be\r
+ /// a rotation matrix).\r
+ float32 GetAngle() const\r
+ {\r
+ return b2Atan2(col1.y, col1.x);\r
+ }\r
+\r
+ b2Mat22 GetInverse() const\r
+ {\r
+ float32 a = col1.x, b = col2.x, c = col1.y, d = col2.y;\r
+ b2Mat22 B;\r
+ float32 det = a * d - b * c;\r
+ if (det != 0.0f)\r
+ {\r
+ det = 1.0f / det;\r
+ }\r
+ B.col1.x = det * d; B.col2.x = -det * b;\r
+ B.col1.y = -det * c; B.col2.y = det * a;\r
+ return B;\r
+ }\r
+\r
+ /// Solve A * x = b, where b is a column vector. This is more efficient\r
+ /// than computing the inverse in one-shot cases.\r
+ b2Vec2 Solve(const b2Vec2& b) const\r
+ {\r
+ float32 a11 = col1.x, a12 = col2.x, a21 = col1.y, a22 = col2.y;\r
+ float32 det = a11 * a22 - a12 * a21;\r
+ if (det != 0.0f)\r
+ {\r
+ det = 1.0f / det;\r
+ }\r
+ b2Vec2 x;\r
+ x.x = det * (a22 * b.x - a12 * b.y);\r
+ x.y = det * (a11 * b.y - a21 * b.x);\r
+ return x;\r
+ }\r
+\r
+ b2Vec2 col1, col2;\r
+};\r
+\r
+/// A 3-by-3 matrix. Stored in column-major order.\r
+struct b2Mat33\r
+{\r
+ /// The default constructor does nothing (for performance).\r
+ b2Mat33() {}\r
+\r
+ /// Construct this matrix using columns.\r
+ b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3)\r
+ {\r
+ col1 = c1;\r
+ col2 = c2;\r
+ col3 = c3;\r
+ }\r
+\r
+ /// Set this matrix to all zeros.\r
+ void SetZero()\r
+ {\r
+ col1.SetZero();\r
+ col2.SetZero();\r
+ col3.SetZero();\r
+ }\r
+\r
+ /// Solve A * x = b, where b is a column vector. This is more efficient\r
+ /// than computing the inverse in one-shot cases.\r
+ b2Vec3 Solve33(const b2Vec3& b) const;\r
+\r
+ /// Solve A * x = b, where b is a column vector. This is more efficient\r
+ /// than computing the inverse in one-shot cases. Solve only the upper\r
+ /// 2-by-2 matrix equation.\r
+ b2Vec2 Solve22(const b2Vec2& b) const;\r
+\r
+ b2Vec3 col1, col2, col3;\r
+};\r
+\r
+/// A transform contains translation and rotation. It is used to represent\r
+/// the position and orientation of rigid frames.\r
+struct b2Transform\r
+{\r
+ /// The default constructor does nothing (for performance).\r
+ b2Transform() {}\r
+\r
+ /// Initialize using a position vector and a rotation matrix.\r
+ b2Transform(const b2Vec2& position, const b2Mat22& R) : position(position), R(R) {}\r
+\r
+ /// Set this to the identity transform.\r
+ void SetIdentity()\r
+ {\r
+ position.SetZero();\r
+ R.SetIdentity();\r
+ }\r
+\r
+ /// Set this based on the position and angle.\r
+ void Set(const b2Vec2& p, float32 angle)\r
+ {\r
+ position = p;\r
+ R.Set(angle);\r
+ }\r
+\r
+ /// Calculate the angle that the rotation matrix represents.\r
+ float32 GetAngle() const\r
+ {\r
+ return b2Atan2(R.col1.y, R.col1.x);\r
+ }\r
+\r
+ b2Vec2 position;\r
+ b2Mat22 R;\r
+};\r
+\r
+/// This describes the motion of a body/shape for TOI computation.\r
+/// Shapes are defined with respect to the body origin, which may\r
+/// no coincide with the center of mass. However, to support dynamics\r
+/// we must interpolate the center of mass position.\r
+struct b2Sweep\r
+{\r
+ /// Get the interpolated transform at a specific time.\r
+ /// @param alpha is a factor in [0,1], where 0 indicates t0.\r
+ void GetTransform(b2Transform* xf, float32 alpha) const;\r
+\r
+ /// Advance the sweep forward, yielding a new initial state.\r
+ /// @param t the new initial time.\r
+ void Advance(float32 t);\r
+\r
+ /// Normalize the angles.\r
+ void Normalize();\r
+\r
+ b2Vec2 localCenter; ///< local center of mass position\r
+ b2Vec2 c0, c; ///< center world positions\r
+ float32 a0, a; ///< world angles\r
+};\r
+\r
+\r
+extern const b2Vec2 b2Vec2_zero;\r
+extern const b2Mat22 b2Mat22_identity;\r
+extern const b2Transform b2Transform_identity;\r
+\r
+/// Perform the dot product on two vectors.\r
+inline float32 b2Dot(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return a.x * b.x + a.y * b.y;\r
+}\r
+\r
+/// Perform the cross product on two vectors. In 2D this produces a scalar.\r
+inline float32 b2Cross(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return a.x * b.y - a.y * b.x;\r
+}\r
+\r
+/// Perform the cross product on a vector and a scalar. In 2D this produces\r
+/// a vector.\r
+inline b2Vec2 b2Cross(const b2Vec2& a, float32 s)\r
+{\r
+ return b2Vec2(s * a.y, -s * a.x);\r
+}\r
+\r
+/// Perform the cross product on a scalar and a vector. In 2D this produces\r
+/// a vector.\r
+inline b2Vec2 b2Cross(float32 s, const b2Vec2& a)\r
+{\r
+ return b2Vec2(-s * a.y, s * a.x);\r
+}\r
+\r
+/// Multiply a matrix times a vector. If a rotation matrix is provided,\r
+/// then this transforms the vector from one frame to another.\r
+inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v)\r
+{\r
+ return b2Vec2(A.col1.x * v.x + A.col2.x * v.y, A.col1.y * v.x + A.col2.y * v.y);\r
+}\r
+\r
+/// Multiply a matrix transpose times a vector. If a rotation matrix is provided,\r
+/// then this transforms the vector from one frame to another (inverse transform).\r
+inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v)\r
+{\r
+ return b2Vec2(b2Dot(v, A.col1), b2Dot(v, A.col2));\r
+}\r
+\r
+/// Add two vectors component-wise.\r
+inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return b2Vec2(a.x + b.x, a.y + b.y);\r
+}\r
+\r
+/// Subtract two vectors component-wise.\r
+inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return b2Vec2(a.x - b.x, a.y - b.y);\r
+}\r
+\r
+inline b2Vec2 operator * (float32 s, const b2Vec2& a)\r
+{\r
+ return b2Vec2(s * a.x, s * a.y);\r
+}\r
+\r
+inline bool operator == (const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return a.x == b.x && a.y == b.y;\r
+}\r
+\r
+inline float32 b2Distance(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ b2Vec2 c = a - b;\r
+ return c.Length();\r
+}\r
+\r
+inline float32 b2DistanceSquared(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ b2Vec2 c = a - b;\r
+ return b2Dot(c, c);\r
+}\r
+\r
+inline b2Vec3 operator * (float32 s, const b2Vec3& a)\r
+{\r
+ return b2Vec3(s * a.x, s * a.y, s * a.z);\r
+}\r
+\r
+/// Add two vectors component-wise.\r
+inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b)\r
+{\r
+ return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z);\r
+}\r
+\r
+/// Subtract two vectors component-wise.\r
+inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b)\r
+{\r
+ return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z);\r
+}\r
+\r
+/// Perform the dot product on two vectors.\r
+inline float32 b2Dot(const b2Vec3& a, const b2Vec3& b)\r
+{\r
+ return a.x * b.x + a.y * b.y + a.z * b.z;\r
+}\r
+\r
+/// Perform the cross product on two vectors.\r
+inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b)\r
+{\r
+ return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);\r
+}\r
+\r
+inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B)\r
+{\r
+ return b2Mat22(A.col1 + B.col1, A.col2 + B.col2);\r
+}\r
+\r
+// A * B\r
+inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B)\r
+{\r
+ return b2Mat22(b2Mul(A, B.col1), b2Mul(A, B.col2));\r
+}\r
+\r
+// A^T * B\r
+inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B)\r
+{\r
+ b2Vec2 c1(b2Dot(A.col1, B.col1), b2Dot(A.col2, B.col1));\r
+ b2Vec2 c2(b2Dot(A.col1, B.col2), b2Dot(A.col2, B.col2));\r
+ return b2Mat22(c1, c2);\r
+}\r
+\r
+/// Multiply a matrix times a vector.\r
+inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v)\r
+{\r
+ return v.x * A.col1 + v.y * A.col2 + v.z * A.col3;\r
+}\r
+\r
+inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v)\r
+{\r
+ float32 x = T.position.x + T.R.col1.x * v.x + T.R.col2.x * v.y;\r
+ float32 y = T.position.y + T.R.col1.y * v.x + T.R.col2.y * v.y;\r
+\r
+ return b2Vec2(x, y);\r
+}\r
+\r
+inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v)\r
+{\r
+ return b2MulT(T.R, v - T.position);\r
+}\r
+\r
+inline b2Vec2 b2Abs(const b2Vec2& a)\r
+{\r
+ return b2Vec2(b2Abs(a.x), b2Abs(a.y));\r
+}\r
+\r
+inline b2Mat22 b2Abs(const b2Mat22& A)\r
+{\r
+ return b2Mat22(b2Abs(A.col1), b2Abs(A.col2));\r
+}\r
+\r
+template <typename T>\r
+inline T b2Min(T a, T b)\r
+{\r
+ return a < b ? a : b;\r
+}\r
+\r
+inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y));\r
+}\r
+\r
+template <typename T>\r
+inline T b2Max(T a, T b)\r
+{\r
+ return a > b ? a : b;\r
+}\r
+\r
+inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b)\r
+{\r
+ return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y));\r
+}\r
+\r
+template <typename T>\r
+inline T b2Clamp(T a, T low, T high)\r
+{\r
+ return b2Max(low, b2Min(a, high));\r
+}\r
+\r
+inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high)\r
+{\r
+ return b2Max(low, b2Min(a, high));\r
+}\r
+\r
+template<typename T> inline void b2Swap(T& a, T& b)\r
+{\r
+ T tmp = a;\r
+ a = b;\r
+ b = tmp;\r
+}\r
+\r
+/// "Next Largest Power of 2\r
+/// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm\r
+/// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with\r
+/// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next\r
+/// largest power of 2. For a 32-bit value:"\r
+inline uint32 b2NextPowerOfTwo(uint32 x)\r
+{\r
+ x |= (x >> 1);\r
+ x |= (x >> 2);\r
+ x |= (x >> 4);\r
+ x |= (x >> 8);\r
+ x |= (x >> 16);\r
+ return x + 1;\r
+}\r
+\r
+inline bool b2IsPowerOfTwo(uint32 x)\r
+{\r
+ bool result = x > 0 && (x & (x - 1)) == 0;\r
+ return result;\r
+}\r
+\r
+inline void b2Sweep::GetTransform(b2Transform* xf, float32 alpha) const\r
+{\r
+ xf->position = (1.0f - alpha) * c0 + alpha * c;\r
+ float32 angle = (1.0f - alpha) * a0 + alpha * a;\r
+ xf->R.Set(angle);\r
+\r
+ // Shift to origin\r
+ xf->position -= b2Mul(xf->R, localCenter);\r
+}\r
+\r
+inline void b2Sweep::Advance(float32 t)\r
+{\r
+ c0 = (1.0f - t) * c0 + t * c;\r
+ a0 = (1.0f - t) * a0 + t * a;\r
+}\r
+\r
+/// Normalize an angle in radians to be between -pi and pi\r
+inline void b2Sweep::Normalize()\r
+{\r
+ float32 twoPi = 2.0f * b2_pi;\r
+ float32 d = twoPi * floorf(a0 / twoPi);\r
+ a0 -= d;\r
+ a -= d;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+#include <cstdlib>\r
+\r
+b2Version b2_version = {2, 1, 2};\r
+\r
+// Memory allocators. Modify these to use your own allocator.\r
+void* b2Alloc(int32 size)\r
+{\r
+ return malloc(size);\r
+}\r
+\r
+void b2Free(void* mem)\r
+{\r
+ free(mem);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_SETTINGS_H\r
+#define B2_SETTINGS_H\r
+\r
+#include <cassert>\r
+#include <cmath>\r
+\r
+#define B2_NOT_USED(x) ((void)(x))\r
+#define b2Assert(A) assert(A)\r
+\r
+typedef signed char int8;\r
+typedef signed short int16;\r
+typedef signed int int32;\r
+typedef unsigned char uint8;\r
+typedef unsigned short uint16;\r
+typedef unsigned int uint32;\r
+typedef float float32;\r
+\r
+#define b2_maxFloat FLT_MAX\r
+#define b2_epsilon FLT_EPSILON\r
+#define b2_pi 3.14159265359f\r
+\r
+/// @file\r
+/// Global tuning constants based on meters-kilograms-seconds (MKS) units.\r
+///\r
+\r
+// Collision\r
+\r
+/// The maximum number of contact points between two convex shapes.\r
+#define b2_maxManifoldPoints 2\r
+\r
+/// The maximum number of vertices on a convex polygon.\r
+#define b2_maxPolygonVertices 8\r
+\r
+/// This is used to fatten AABBs in the dynamic tree. This allows proxies\r
+/// to move by a small amount without triggering a tree adjustment.\r
+/// This is in meters.\r
+#define b2_aabbExtension 0.1f\r
+\r
+/// This is used to fatten AABBs in the dynamic tree. This is used to predict\r
+/// the future position based on the current displacement.\r
+/// This is a dimensionless multiplier.\r
+#define b2_aabbMultiplier 2.0f\r
+\r
+/// A small length used as a collision and constraint tolerance. Usually it is\r
+/// chosen to be numerically significant, but visually insignificant.\r
+#define b2_linearSlop 0.005f\r
+\r
+/// A small angle used as a collision and constraint tolerance. Usually it is\r
+/// chosen to be numerically significant, but visually insignificant.\r
+#define b2_angularSlop (2.0f / 180.0f * b2_pi)\r
+\r
+/// The radius of the polygon/edge shape skin. This should not be modified. Making\r
+/// this smaller means polygons will have an insufficient buffer for continuous collision.\r
+/// Making it larger may create artifacts for vertex collision.\r
+#define b2_polygonRadius (2.0f * b2_linearSlop)\r
+\r
+\r
+// Dynamics\r
+\r
+/// Maximum number of contacts to be handled to solve a TOI impact.\r
+#define b2_maxTOIContacts 32\r
+\r
+/// A velocity threshold for elastic collisions. Any collision with a relative linear\r
+/// velocity below this threshold will be treated as inelastic.\r
+#define b2_velocityThreshold 1.0f\r
+\r
+/// The maximum linear position correction used when solving constraints. This helps to\r
+/// prevent overshoot.\r
+#define b2_maxLinearCorrection 0.2f\r
+\r
+/// The maximum angular position correction used when solving constraints. This helps to\r
+/// prevent overshoot.\r
+#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi)\r
+\r
+/// The maximum linear velocity of a body. This limit is very large and is used\r
+/// to prevent numerical problems. You shouldn't need to adjust this.\r
+#define b2_maxTranslation 2.0f\r
+#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation)\r
+\r
+/// The maximum angular velocity of a body. This limit is very large and is used\r
+/// to prevent numerical problems. You shouldn't need to adjust this.\r
+#define b2_maxRotation (0.5f * b2_pi)\r
+#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation)\r
+\r
+/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so\r
+/// that overlap is removed in one time step. However using values close to 1 often lead\r
+/// to overshoot.\r
+#define b2_contactBaumgarte 0.2f\r
+\r
+// Sleep\r
+\r
+/// The time that a body must be still before it will go to sleep.\r
+#define b2_timeToSleep 0.5f\r
+\r
+/// A body cannot sleep if its linear velocity is above this tolerance.\r
+#define b2_linearSleepTolerance 0.01f\r
+\r
+/// A body cannot sleep if its angular velocity is above this tolerance.\r
+#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi)\r
+\r
+// Memory Allocation\r
+\r
+/// Implement this function to use your own memory allocator.\r
+void* b2Alloc(int32 size);\r
+\r
+/// If you implement b2Alloc, you should also implement this function.\r
+void b2Free(void* mem);\r
+\r
+/// Version numbering scheme.\r
+/// See http://en.wikipedia.org/wiki/Software_versioning\r
+struct b2Version\r
+{\r
+ int32 major; ///< significant changes\r
+ int32 minor; ///< incremental changes\r
+ int32 revision; ///< bug fixes\r
+};\r
+\r
+/// Current version.\r
+extern b2Version b2_version;\r
+\r
+/// Friction mixing law. Feel free to customize this.\r
+inline float32 b2MixFriction(float32 friction1, float32 friction2)\r
+{\r
+ return sqrtf(friction1 * friction2);\r
+}\r
+\r
+/// Restitution mixing law. Feel free to customize this.\r
+inline float32 b2MixRestitution(float32 restitution1, float32 restitution2)\r
+{\r
+ return restitution1 > restitution2 ? restitution1 : restitution2;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Common/b2StackAllocator.h>\r
+#include <Box2D/Common/b2Math.h>\r
+\r
+b2StackAllocator::b2StackAllocator()\r
+{\r
+ m_index = 0;\r
+ m_allocation = 0;\r
+ m_maxAllocation = 0;\r
+ m_entryCount = 0;\r
+}\r
+\r
+b2StackAllocator::~b2StackAllocator()\r
+{\r
+ b2Assert(m_index == 0);\r
+ b2Assert(m_entryCount == 0);\r
+}\r
+\r
+void* b2StackAllocator::Allocate(int32 size)\r
+{\r
+ b2Assert(m_entryCount < b2_maxStackEntries);\r
+\r
+ b2StackEntry* entry = m_entries + m_entryCount;\r
+ entry->size = size;\r
+ if (m_index + size > b2_stackSize)\r
+ {\r
+ entry->data = (char*)b2Alloc(size);\r
+ entry->usedMalloc = true;\r
+ }\r
+ else\r
+ {\r
+ entry->data = m_data + m_index;\r
+ entry->usedMalloc = false;\r
+ m_index += size;\r
+ }\r
+\r
+ m_allocation += size;\r
+ m_maxAllocation = b2Max(m_maxAllocation, m_allocation);\r
+ ++m_entryCount;\r
+\r
+ return entry->data;\r
+}\r
+\r
+void b2StackAllocator::Free(void* p)\r
+{\r
+ b2Assert(m_entryCount > 0);\r
+ b2StackEntry* entry = m_entries + m_entryCount - 1;\r
+ b2Assert(p == entry->data);\r
+ if (entry->usedMalloc)\r
+ {\r
+ b2Free(p);\r
+ }\r
+ else\r
+ {\r
+ m_index -= entry->size;\r
+ }\r
+ m_allocation -= entry->size;\r
+ --m_entryCount;\r
+\r
+ p = NULL;\r
+}\r
+\r
+int32 b2StackAllocator::GetMaxAllocation() const\r
+{\r
+ return m_maxAllocation;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_STACK_ALLOCATOR_H\r
+#define B2_STACK_ALLOCATOR_H\r
+\r
+#include <Box2D/Common/b2Settings.h>\r
+\r
+const int32 b2_stackSize = 100 * 1024; // 100k\r
+const int32 b2_maxStackEntries = 32;\r
+\r
+struct b2StackEntry\r
+{\r
+ char* data;\r
+ int32 size;\r
+ bool usedMalloc;\r
+};\r
+\r
+// This is a stack allocator used for fast per step allocations.\r
+// You must nest allocate/free pairs. The code will assert\r
+// if you try to interleave multiple allocate/free pairs.\r
+class b2StackAllocator\r
+{\r
+public:\r
+ b2StackAllocator();\r
+ ~b2StackAllocator();\r
+\r
+ void* Allocate(int32 size);\r
+ void Free(void* p);\r
+\r
+ int32 GetMaxAllocation() const;\r
+\r
+private:\r
+\r
+ char m_data[b2_stackSize];\r
+ int32 m_index;\r
+\r
+ int32 m_allocation;\r
+ int32 m_maxAllocation;\r
+\r
+ b2StackEntry m_entries[b2_maxStackEntries];\r
+ int32 m_entryCount;\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2CircleContact.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2WorldCallbacks.h>\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+\r
+#include <new>\r
+\r
+b2Contact* b2CircleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)\r
+{\r
+ void* mem = allocator->Allocate(sizeof(b2CircleContact));\r
+ return new (mem) b2CircleContact(fixtureA, fixtureB);\r
+}\r
+\r
+void b2CircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)\r
+{\r
+ ((b2CircleContact*)contact)->~b2CircleContact();\r
+ allocator->Free(contact, sizeof(b2CircleContact));\r
+}\r
+\r
+b2CircleContact::b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)\r
+ : b2Contact(fixtureA, fixtureB)\r
+{\r
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_circle);\r
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);\r
+}\r
+\r
+void b2CircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)\r
+{\r
+ b2CollideCircles(manifold,\r
+ (b2CircleShape*)m_fixtureA->GetShape(), xfA,\r
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_CIRCLE_CONTACT_H\r
+#define B2_CIRCLE_CONTACT_H\r
+\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+\r
+class b2BlockAllocator;\r
+\r
+class b2CircleContact : public b2Contact\r
+{\r
+public:\r
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);\r
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);\r
+\r
+ b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);\r
+ ~b2CircleContact() {}\r
+\r
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+#include <Box2D/Dynamics/Contacts/b2CircleContact.h>\r
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h>\r
+#include <Box2D/Dynamics/Contacts/b2PolygonContact.h>\r
+#include <Box2D/Dynamics/Contacts/b2ContactSolver.h>\r
+\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+#include <Box2D/Collision/Shapes/b2Shape.h>\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2World.h>\r
+\r
+b2ContactRegister b2Contact::s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];\r
+bool b2Contact::s_initialized = false;\r
+\r
+void b2Contact::InitializeRegisters()\r
+{\r
+ AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle);\r
+ AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle);\r
+ AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon);\r
+}\r
+\r
+void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn,\r
+ b2Shape::Type type1, b2Shape::Type type2)\r
+{\r
+ b2Assert(b2Shape::e_unknown < type1 && type1 < b2Shape::e_typeCount);\r
+ b2Assert(b2Shape::e_unknown < type2 && type2 < b2Shape::e_typeCount);\r
+ \r
+ s_registers[type1][type2].createFcn = createFcn;\r
+ s_registers[type1][type2].destroyFcn = destoryFcn;\r
+ s_registers[type1][type2].primary = true;\r
+\r
+ if (type1 != type2)\r
+ {\r
+ s_registers[type2][type1].createFcn = createFcn;\r
+ s_registers[type2][type1].destroyFcn = destoryFcn;\r
+ s_registers[type2][type1].primary = false;\r
+ }\r
+}\r
+\r
+b2Contact* b2Contact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)\r
+{\r
+ if (s_initialized == false)\r
+ {\r
+ InitializeRegisters();\r
+ s_initialized = true;\r
+ }\r
+\r
+ b2Shape::Type type1 = fixtureA->GetType();\r
+ b2Shape::Type type2 = fixtureB->GetType();\r
+\r
+ b2Assert(b2Shape::e_unknown < type1 && type1 < b2Shape::e_typeCount);\r
+ b2Assert(b2Shape::e_unknown < type2 && type2 < b2Shape::e_typeCount);\r
+ \r
+ b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn;\r
+ if (createFcn)\r
+ {\r
+ if (s_registers[type1][type2].primary)\r
+ {\r
+ return createFcn(fixtureA, fixtureB, allocator);\r
+ }\r
+ else\r
+ {\r
+ return createFcn(fixtureB, fixtureA, allocator);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+void b2Contact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)\r
+{\r
+ b2Assert(s_initialized == true);\r
+\r
+ if (contact->m_manifold.pointCount > 0)\r
+ {\r
+ contact->GetFixtureA()->GetBody()->SetAwake(true);\r
+ contact->GetFixtureB()->GetBody()->SetAwake(true);\r
+ }\r
+\r
+ b2Shape::Type typeA = contact->GetFixtureA()->GetType();\r
+ b2Shape::Type typeB = contact->GetFixtureB()->GetType();\r
+\r
+ b2Assert(b2Shape::e_unknown < typeA && typeB < b2Shape::e_typeCount);\r
+ b2Assert(b2Shape::e_unknown < typeA && typeB < b2Shape::e_typeCount);\r
+\r
+ b2ContactDestroyFcn* destroyFcn = s_registers[typeA][typeB].destroyFcn;\r
+ destroyFcn(contact, allocator);\r
+}\r
+\r
+b2Contact::b2Contact(b2Fixture* fA, b2Fixture* fB)\r
+{\r
+ m_flags = e_enabledFlag;\r
+\r
+ m_fixtureA = fA;\r
+ m_fixtureB = fB;\r
+\r
+ m_manifold.pointCount = 0;\r
+\r
+ m_prev = NULL;\r
+ m_next = NULL;\r
+\r
+ m_nodeA.contact = NULL;\r
+ m_nodeA.prev = NULL;\r
+ m_nodeA.next = NULL;\r
+ m_nodeA.other = NULL;\r
+\r
+ m_nodeB.contact = NULL;\r
+ m_nodeB.prev = NULL;\r
+ m_nodeB.next = NULL;\r
+ m_nodeB.other = NULL;\r
+\r
+ m_toiCount = 0;\r
+}\r
+\r
+// Update the contact manifold and touching status.\r
+// Note: do not assume the fixture AABBs are overlapping or are valid.\r
+void b2Contact::Update(b2ContactListener* listener)\r
+{\r
+ b2Manifold oldManifold = m_manifold;\r
+\r
+ // Re-enable this contact.\r
+ m_flags |= e_enabledFlag;\r
+\r
+ bool touching = false;\r
+ bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag;\r
+\r
+ bool sensorA = m_fixtureA->IsSensor();\r
+ bool sensorB = m_fixtureB->IsSensor();\r
+ bool sensor = sensorA || sensorB;\r
+\r
+ b2Body* bodyA = m_fixtureA->GetBody();\r
+ b2Body* bodyB = m_fixtureB->GetBody();\r
+ const b2Transform& xfA = bodyA->GetTransform();\r
+ const b2Transform& xfB = bodyB->GetTransform();\r
+\r
+ // Is this contact a sensor?\r
+ if (sensor)\r
+ {\r
+ const b2Shape* shapeA = m_fixtureA->GetShape();\r
+ const b2Shape* shapeB = m_fixtureB->GetShape();\r
+ touching = b2TestOverlap(shapeA, shapeB, xfA, xfB);\r
+\r
+ // Sensors don't generate manifolds.\r
+ m_manifold.pointCount = 0;\r
+ }\r
+ else\r
+ {\r
+ Evaluate(&m_manifold, xfA, xfB);\r
+ touching = m_manifold.pointCount > 0;\r
+\r
+ // Match old contact ids to new contact ids and copy the\r
+ // stored impulses to warm start the solver.\r
+ for (int32 i = 0; i < m_manifold.pointCount; ++i)\r
+ {\r
+ b2ManifoldPoint* mp2 = m_manifold.points + i;\r
+ mp2->normalImpulse = 0.0f;\r
+ mp2->tangentImpulse = 0.0f;\r
+ b2ContactID id2 = mp2->id;\r
+\r
+ for (int32 j = 0; j < oldManifold.pointCount; ++j)\r
+ {\r
+ b2ManifoldPoint* mp1 = oldManifold.points + j;\r
+\r
+ if (mp1->id.key == id2.key)\r
+ {\r
+ mp2->normalImpulse = mp1->normalImpulse;\r
+ mp2->tangentImpulse = mp1->tangentImpulse;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (touching != wasTouching)\r
+ {\r
+ bodyA->SetAwake(true);\r
+ bodyB->SetAwake(true);\r
+ }\r
+ }\r
+\r
+ if (touching)\r
+ {\r
+ m_flags |= e_touchingFlag;\r
+ }\r
+ else\r
+ {\r
+ m_flags &= ~e_touchingFlag;\r
+ }\r
+\r
+ if (wasTouching == false && touching == true && listener)\r
+ {\r
+ listener->BeginContact(this);\r
+ }\r
+\r
+ if (wasTouching == true && touching == false && listener)\r
+ {\r
+ listener->EndContact(this);\r
+ }\r
+\r
+ if (sensor == false && touching && listener)\r
+ {\r
+ listener->PreSolve(this, &oldManifold);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_CONTACT_H\r
+#define B2_CONTACT_H\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Collision/Shapes/b2Shape.h>\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+\r
+class b2Body;\r
+class b2Contact;\r
+class b2Fixture;\r
+class b2World;\r
+class b2BlockAllocator;\r
+class b2StackAllocator;\r
+class b2ContactListener;\r
+\r
+typedef b2Contact* b2ContactCreateFcn(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);\r
+typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);\r
+\r
+struct b2ContactRegister\r
+{\r
+ b2ContactCreateFcn* createFcn;\r
+ b2ContactDestroyFcn* destroyFcn;\r
+ bool primary;\r
+};\r
+\r
+/// A contact edge is used to connect bodies and contacts together\r
+/// in a contact graph where each body is a node and each contact\r
+/// is an edge. A contact edge belongs to a doubly linked list\r
+/// maintained in each attached body. Each contact has two contact\r
+/// nodes, one for each attached body.\r
+struct b2ContactEdge\r
+{\r
+ b2Body* other; ///< provides quick access to the other body attached.\r
+ b2Contact* contact; ///< the contact\r
+ b2ContactEdge* prev; ///< the previous contact edge in the body's contact list\r
+ b2ContactEdge* next; ///< the next contact edge in the body's contact list\r
+};\r
+\r
+/// The class manages contact between two shapes. A contact exists for each overlapping\r
+/// AABB in the broad-phase (except if filtered). Therefore a contact object may exist\r
+/// that has no contact points.\r
+class b2Contact\r
+{\r
+public:\r
+\r
+ /// Get the contact manifold. Do not modify the manifold unless you understand the\r
+ /// internals of Box2D.\r
+ b2Manifold* GetManifold();\r
+ const b2Manifold* GetManifold() const;\r
+\r
+ /// Get the world manifold.\r
+ void GetWorldManifold(b2WorldManifold* worldManifold) const;\r
+\r
+ /// Is this contact touching?\r
+ bool IsTouching() const;\r
+\r
+ /// Enable/disable this contact. This can be used inside the pre-solve\r
+ /// contact listener. The contact is only disabled for the current\r
+ /// time step (or sub-step in continuous collisions).\r
+ void SetEnabled(bool flag);\r
+\r
+ /// Has this contact been disabled?\r
+ bool IsEnabled() const;\r
+\r
+ /// Get the next contact in the world's contact list.\r
+ b2Contact* GetNext();\r
+ const b2Contact* GetNext() const;\r
+\r
+ /// Get the first fixture in this contact.\r
+ b2Fixture* GetFixtureA();\r
+ const b2Fixture* GetFixtureA() const;\r
+\r
+ /// Get the second fixture in this contact.\r
+ b2Fixture* GetFixtureB();\r
+ const b2Fixture* GetFixtureB() const;\r
+\r
+ /// Evaluate this contact with your own manifold and transforms.\r
+ virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;\r
+\r
+protected:\r
+ friend class b2ContactManager;\r
+ friend class b2World;\r
+ friend class b2ContactSolver;\r
+ friend class b2Body;\r
+ friend class b2Fixture;\r
+\r
+ // Flags stored in m_flags\r
+ enum\r
+ {\r
+ // Used when crawling contact graph when forming islands.\r
+ e_islandFlag = 0x0001,\r
+\r
+ // Set when the shapes are touching.\r
+ e_touchingFlag = 0x0002,\r
+\r
+ // This contact can be disabled (by user)\r
+ e_enabledFlag = 0x0004,\r
+\r
+ // This contact needs filtering because a fixture filter was changed.\r
+ e_filterFlag = 0x0008,\r
+\r
+ // This bullet contact had a TOI event\r
+ e_bulletHitFlag = 0x0010,\r
+\r
+ };\r
+\r
+ /// Flag this contact for filtering. Filtering will occur the next time step.\r
+ void FlagForFiltering();\r
+\r
+ static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,\r
+ b2Shape::Type typeA, b2Shape::Type typeB);\r
+ static void InitializeRegisters();\r
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);\r
+ static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);\r
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);\r
+\r
+ b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {}\r
+ b2Contact(b2Fixture* fixtureA, b2Fixture* fixtureB);\r
+ virtual ~b2Contact() {}\r
+\r
+ void Update(b2ContactListener* listener);\r
+\r
+ static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];\r
+ static bool s_initialized;\r
+\r
+ uint32 m_flags;\r
+\r
+ // World pool and list pointers.\r
+ b2Contact* m_prev;\r
+ b2Contact* m_next;\r
+\r
+ // Nodes for connecting bodies.\r
+ b2ContactEdge m_nodeA;\r
+ b2ContactEdge m_nodeB;\r
+\r
+ b2Fixture* m_fixtureA;\r
+ b2Fixture* m_fixtureB;\r
+\r
+ b2Manifold m_manifold;\r
+\r
+ int32 m_toiCount;\r
+// float32 m_toi;\r
+};\r
+\r
+inline b2Manifold* b2Contact::GetManifold()\r
+{\r
+ return &m_manifold;\r
+}\r
+\r
+inline const b2Manifold* b2Contact::GetManifold() const\r
+{\r
+ return &m_manifold;\r
+}\r
+\r
+inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const\r
+{\r
+ const b2Body* bodyA = m_fixtureA->GetBody();\r
+ const b2Body* bodyB = m_fixtureB->GetBody();\r
+ const b2Shape* shapeA = m_fixtureA->GetShape();\r
+ const b2Shape* shapeB = m_fixtureB->GetShape();\r
+\r
+ worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);\r
+}\r
+\r
+inline void b2Contact::SetEnabled(bool flag)\r
+{\r
+ if (flag)\r
+ {\r
+ m_flags |= e_enabledFlag;\r
+ }\r
+ else\r
+ {\r
+ m_flags &= ~e_enabledFlag;\r
+ }\r
+}\r
+\r
+inline bool b2Contact::IsEnabled() const\r
+{\r
+ return (m_flags & e_enabledFlag) == e_enabledFlag;\r
+}\r
+\r
+inline bool b2Contact::IsTouching() const\r
+{\r
+ return (m_flags & e_touchingFlag) == e_touchingFlag;\r
+}\r
+\r
+inline b2Contact* b2Contact::GetNext()\r
+{\r
+ return m_next;\r
+}\r
+\r
+inline const b2Contact* b2Contact::GetNext() const\r
+{\r
+ return m_next;\r
+}\r
+\r
+inline b2Fixture* b2Contact::GetFixtureA()\r
+{\r
+ return m_fixtureA;\r
+}\r
+\r
+inline const b2Fixture* b2Contact::GetFixtureA() const\r
+{\r
+ return m_fixtureA;\r
+}\r
+\r
+inline b2Fixture* b2Contact::GetFixtureB()\r
+{\r
+ return m_fixtureB;\r
+}\r
+\r
+inline const b2Fixture* b2Contact::GetFixtureB() const\r
+{\r
+ return m_fixtureB;\r
+}\r
+\r
+inline void b2Contact::FlagForFiltering()\r
+{\r
+ m_flags |= e_filterFlag;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2ContactSolver.h>\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2World.h>\r
+#include <Box2D/Common/b2StackAllocator.h>\r
+\r
+#define B2_DEBUG_SOLVER 0\r
+\r
+b2ContactSolver::b2ContactSolver(b2Contact** contacts, int32 contactCount,\r
+ b2StackAllocator* allocator, float32 impulseRatio)\r
+{\r
+ m_allocator = allocator;\r
+\r
+ m_constraintCount = contactCount;\r
+ m_constraints = (b2ContactConstraint*)m_allocator->Allocate(m_constraintCount * sizeof(b2ContactConstraint));\r
+\r
+ for (int32 i = 0; i < m_constraintCount; ++i)\r
+ {\r
+ b2Contact* contact = contacts[i];\r
+\r
+ b2Fixture* fixtureA = contact->m_fixtureA;\r
+ b2Fixture* fixtureB = contact->m_fixtureB;\r
+ b2Shape* shapeA = fixtureA->GetShape();\r
+ b2Shape* shapeB = fixtureB->GetShape();\r
+ float32 radiusA = shapeA->m_radius;\r
+ float32 radiusB = shapeB->m_radius;\r
+ b2Body* bodyA = fixtureA->GetBody();\r
+ b2Body* bodyB = fixtureB->GetBody();\r
+ b2Manifold* manifold = contact->GetManifold();\r
+\r
+ float32 friction = b2MixFriction(fixtureA->GetFriction(), fixtureB->GetFriction());\r
+ float32 restitution = b2MixRestitution(fixtureA->GetRestitution(), fixtureB->GetRestitution());\r
+\r
+ b2Vec2 vA = bodyA->m_linearVelocity;\r
+ b2Vec2 vB = bodyB->m_linearVelocity;\r
+ float32 wA = bodyA->m_angularVelocity;\r
+ float32 wB = bodyB->m_angularVelocity;\r
+\r
+ b2Assert(manifold->pointCount > 0);\r
+\r
+ b2WorldManifold worldManifold;\r
+ worldManifold.Initialize(manifold, bodyA->m_xf, radiusA, bodyB->m_xf, radiusB);\r
+\r
+ b2ContactConstraint* cc = m_constraints + i;\r
+ cc->bodyA = bodyA;\r
+ cc->bodyB = bodyB;\r
+ cc->manifold = manifold;\r
+ cc->normal = worldManifold.normal;\r
+ cc->pointCount = manifold->pointCount;\r
+ cc->friction = friction;\r
+\r
+ cc->localNormal = manifold->localNormal;\r
+ cc->localPoint = manifold->localPoint;\r
+ cc->radius = radiusA + radiusB;\r
+ cc->type = manifold->type;\r
+\r
+ for (int32 j = 0; j < cc->pointCount; ++j)\r
+ {\r
+ b2ManifoldPoint* cp = manifold->points + j;\r
+ b2ContactConstraintPoint* ccp = cc->points + j;\r
+\r
+ ccp->normalImpulse = impulseRatio * cp->normalImpulse;\r
+ ccp->tangentImpulse = impulseRatio * cp->tangentImpulse;\r
+\r
+ ccp->localPoint = cp->localPoint;\r
+\r
+ ccp->rA = worldManifold.points[j] - bodyA->m_sweep.c;\r
+ ccp->rB = worldManifold.points[j] - bodyB->m_sweep.c;\r
+\r
+ float32 rnA = b2Cross(ccp->rA, cc->normal);\r
+ float32 rnB = b2Cross(ccp->rB, cc->normal);\r
+ rnA *= rnA;\r
+ rnB *= rnB;\r
+\r
+ float32 kNormal = bodyA->m_invMass + bodyB->m_invMass + bodyA->m_invI * rnA + bodyB->m_invI * rnB;\r
+\r
+ b2Assert(kNormal > b2_epsilon);\r
+ ccp->normalMass = 1.0f / kNormal;\r
+\r
+ b2Vec2 tangent = b2Cross(cc->normal, 1.0f);\r
+\r
+ float32 rtA = b2Cross(ccp->rA, tangent);\r
+ float32 rtB = b2Cross(ccp->rB, tangent);\r
+ rtA *= rtA;\r
+ rtB *= rtB;\r
+\r
+ float32 kTangent = bodyA->m_invMass + bodyB->m_invMass + bodyA->m_invI * rtA + bodyB->m_invI * rtB;\r
+\r
+ b2Assert(kTangent > b2_epsilon);\r
+ ccp->tangentMass = 1.0f / kTangent;\r
+\r
+ // Setup a velocity bias for restitution.\r
+ ccp->velocityBias = 0.0f;\r
+ float32 vRel = b2Dot(cc->normal, vB + b2Cross(wB, ccp->rB) - vA - b2Cross(wA, ccp->rA));\r
+ if (vRel < -b2_velocityThreshold)\r
+ {\r
+ ccp->velocityBias = -restitution * vRel;\r
+ }\r
+ }\r
+\r
+ // If we have two points, then prepare the block solver.\r
+ if (cc->pointCount == 2)\r
+ {\r
+ b2ContactConstraintPoint* ccp1 = cc->points + 0;\r
+ b2ContactConstraintPoint* ccp2 = cc->points + 1;\r
+ \r
+ float32 invMassA = bodyA->m_invMass;\r
+ float32 invIA = bodyA->m_invI;\r
+ float32 invMassB = bodyB->m_invMass;\r
+ float32 invIB = bodyB->m_invI;\r
+\r
+ float32 rn1A = b2Cross(ccp1->rA, cc->normal);\r
+ float32 rn1B = b2Cross(ccp1->rB, cc->normal);\r
+ float32 rn2A = b2Cross(ccp2->rA, cc->normal);\r
+ float32 rn2B = b2Cross(ccp2->rB, cc->normal);\r
+\r
+ float32 k11 = invMassA + invMassB + invIA * rn1A * rn1A + invIB * rn1B * rn1B;\r
+ float32 k22 = invMassA + invMassB + invIA * rn2A * rn2A + invIB * rn2B * rn2B;\r
+ float32 k12 = invMassA + invMassB + invIA * rn1A * rn2A + invIB * rn1B * rn2B;\r
+\r
+ // Ensure a reasonable condition number.\r
+ const float32 k_maxConditionNumber = 100.0f;\r
+ if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))\r
+ {\r
+ // K is safe to invert.\r
+ cc->K.col1.Set(k11, k12);\r
+ cc->K.col2.Set(k12, k22);\r
+ cc->normalMass = cc->K.GetInverse();\r
+ }\r
+ else\r
+ {\r
+ // The constraints are redundant, just use one.\r
+ // TODO_ERIN use deepest?\r
+ cc->pointCount = 1;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+b2ContactSolver::~b2ContactSolver()\r
+{\r
+ m_allocator->Free(m_constraints);\r
+}\r
+\r
+void b2ContactSolver::WarmStart()\r
+{\r
+ // Warm start.\r
+ for (int32 i = 0; i < m_constraintCount; ++i)\r
+ {\r
+ b2ContactConstraint* c = m_constraints + i;\r
+\r
+ b2Body* bodyA = c->bodyA;\r
+ b2Body* bodyB = c->bodyB;\r
+ float32 invMassA = bodyA->m_invMass;\r
+ float32 invIA = bodyA->m_invI;\r
+ float32 invMassB = bodyB->m_invMass;\r
+ float32 invIB = bodyB->m_invI;\r
+ b2Vec2 normal = c->normal;\r
+ b2Vec2 tangent = b2Cross(normal, 1.0f);\r
+\r
+ for (int32 j = 0; j < c->pointCount; ++j)\r
+ {\r
+ b2ContactConstraintPoint* ccp = c->points + j;\r
+ b2Vec2 P = ccp->normalImpulse * normal + ccp->tangentImpulse * tangent;\r
+ bodyA->m_angularVelocity -= invIA * b2Cross(ccp->rA, P);\r
+ bodyA->m_linearVelocity -= invMassA * P;\r
+ bodyB->m_angularVelocity += invIB * b2Cross(ccp->rB, P);\r
+ bodyB->m_linearVelocity += invMassB * P;\r
+ }\r
+ }\r
+}\r
+\r
+void b2ContactSolver::SolveVelocityConstraints()\r
+{\r
+ for (int32 i = 0; i < m_constraintCount; ++i)\r
+ {\r
+ b2ContactConstraint* c = m_constraints + i;\r
+ b2Body* bodyA = c->bodyA;\r
+ b2Body* bodyB = c->bodyB;\r
+ float32 wA = bodyA->m_angularVelocity;\r
+ float32 wB = bodyB->m_angularVelocity;\r
+ b2Vec2 vA = bodyA->m_linearVelocity;\r
+ b2Vec2 vB = bodyB->m_linearVelocity;\r
+ float32 invMassA = bodyA->m_invMass;\r
+ float32 invIA = bodyA->m_invI;\r
+ float32 invMassB = bodyB->m_invMass;\r
+ float32 invIB = bodyB->m_invI;\r
+ b2Vec2 normal = c->normal;\r
+ b2Vec2 tangent = b2Cross(normal, 1.0f);\r
+ float32 friction = c->friction;\r
+\r
+ b2Assert(c->pointCount == 1 || c->pointCount == 2);\r
+\r
+ // Solve tangent constraints\r
+ for (int32 j = 0; j < c->pointCount; ++j)\r
+ {\r
+ b2ContactConstraintPoint* ccp = c->points + j;\r
+\r
+ // Relative velocity at contact\r
+ b2Vec2 dv = vB + b2Cross(wB, ccp->rB) - vA - b2Cross(wA, ccp->rA);\r
+\r
+ // Compute tangent force\r
+ float32 vt = b2Dot(dv, tangent);\r
+ float32 lambda = ccp->tangentMass * (-vt);\r
+\r
+ // b2Clamp the accumulated force\r
+ float32 maxFriction = friction * ccp->normalImpulse;\r
+ float32 newImpulse = b2Clamp(ccp->tangentImpulse + lambda, -maxFriction, maxFriction);\r
+ lambda = newImpulse - ccp->tangentImpulse;\r
+\r
+ // Apply contact impulse\r
+ b2Vec2 P = lambda * tangent;\r
+\r
+ vA -= invMassA * P;\r
+ wA -= invIA * b2Cross(ccp->rA, P);\r
+\r
+ vB += invMassB * P;\r
+ wB += invIB * b2Cross(ccp->rB, P);\r
+\r
+ ccp->tangentImpulse = newImpulse;\r
+ }\r
+\r
+ // Solve normal constraints\r
+ if (c->pointCount == 1)\r
+ {\r
+ b2ContactConstraintPoint* ccp = c->points + 0;\r
+\r
+ // Relative velocity at contact\r
+ b2Vec2 dv = vB + b2Cross(wB, ccp->rB) - vA - b2Cross(wA, ccp->rA);\r
+\r
+ // Compute normal impulse\r
+ float32 vn = b2Dot(dv, normal);\r
+ float32 lambda = -ccp->normalMass * (vn - ccp->velocityBias);\r
+\r
+ // b2Clamp the accumulated impulse\r
+ float32 newImpulse = b2Max(ccp->normalImpulse + lambda, 0.0f);\r
+ lambda = newImpulse - ccp->normalImpulse;\r
+\r
+ // Apply contact impulse\r
+ b2Vec2 P = lambda * normal;\r
+ vA -= invMassA * P;\r
+ wA -= invIA * b2Cross(ccp->rA, P);\r
+\r
+ vB += invMassB * P;\r
+ wB += invIB * b2Cross(ccp->rB, P);\r
+ ccp->normalImpulse = newImpulse;\r
+ }\r
+ else\r
+ {\r
+ // Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on Box2D_Lite).\r
+ // Build the mini LCP for this contact patch\r
+ //\r
+ // vn = A * x + b, vn >= 0, , vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2\r
+ //\r
+ // A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n )\r
+ // b = vn_0 - velocityBias\r
+ //\r
+ // The system is solved using the "Total enumeration method" (s. Murty). The complementary constraint vn_i * x_i\r
+ // implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D contact problem the cases\r
+ // vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be tested. The first valid\r
+ // solution that satisfies the problem is chosen.\r
+ // \r
+ // In order to account of the accumulated impulse 'a' (because of the iterative nature of the solver which only requires\r
+ // that the accumulated impulse is clamped and not the incremental impulse) we change the impulse variable (x_i).\r
+ //\r
+ // Substitute:\r
+ // \r
+ // x = x' - a\r
+ // \r
+ // Plug into above equation:\r
+ //\r
+ // vn = A * x + b\r
+ // = A * (x' - a) + b\r
+ // = A * x' + b - A * a\r
+ // = A * x' + b'\r
+ // b' = b - A * a;\r
+\r
+ b2ContactConstraintPoint* cp1 = c->points + 0;\r
+ b2ContactConstraintPoint* cp2 = c->points + 1;\r
+\r
+ b2Vec2 a(cp1->normalImpulse, cp2->normalImpulse);\r
+ b2Assert(a.x >= 0.0f && a.y >= 0.0f);\r
+\r
+ // Relative velocity at contact\r
+ b2Vec2 dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);\r
+ b2Vec2 dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);\r
+\r
+ // Compute normal velocity\r
+ float32 vn1 = b2Dot(dv1, normal);\r
+ float32 vn2 = b2Dot(dv2, normal);\r
+\r
+ b2Vec2 b;\r
+ b.x = vn1 - cp1->velocityBias;\r
+ b.y = vn2 - cp2->velocityBias;\r
+ b -= b2Mul(c->K, a);\r
+\r
+ const float32 k_errorTol = 1e-3f;\r
+ B2_NOT_USED(k_errorTol);\r
+\r
+ for (;;)\r
+ {\r
+ //\r
+ // Case 1: vn = 0\r
+ //\r
+ // 0 = A * x' + b'\r
+ //\r
+ // Solve for x':\r
+ //\r
+ // x' = - inv(A) * b'\r
+ //\r
+ b2Vec2 x = - b2Mul(c->normalMass, b);\r
+\r
+ if (x.x >= 0.0f && x.y >= 0.0f)\r
+ {\r
+ // Resubstitute for the incremental impulse\r
+ b2Vec2 d = x - a;\r
+\r
+ // Apply incremental impulse\r
+ b2Vec2 P1 = d.x * normal;\r
+ b2Vec2 P2 = d.y * normal;\r
+ vA -= invMassA * (P1 + P2);\r
+ wA -= invIA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));\r
+\r
+ vB += invMassB * (P1 + P2);\r
+ wB += invIB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));\r
+\r
+ // Accumulate\r
+ cp1->normalImpulse = x.x;\r
+ cp2->normalImpulse = x.y;\r
+\r
+#if B2_DEBUG_SOLVER == 1\r
+ // Postconditions\r
+ dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);\r
+ dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);\r
+\r
+ // Compute normal velocity\r
+ vn1 = b2Dot(dv1, normal);\r
+ vn2 = b2Dot(dv2, normal);\r
+\r
+ b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol);\r
+ b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol);\r
+#endif\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Case 2: vn1 = 0 and x2 = 0\r
+ //\r
+ // 0 = a11 * x1' + a12 * 0 + b1' \r
+ // vn2 = a21 * x1' + a22 * 0 + b2'\r
+ //\r
+ x.x = - cp1->normalMass * b.x;\r
+ x.y = 0.0f;\r
+ vn1 = 0.0f;\r
+ vn2 = c->K.col1.y * x.x + b.y;\r
+\r
+ if (x.x >= 0.0f && vn2 >= 0.0f)\r
+ {\r
+ // Resubstitute for the incremental impulse\r
+ b2Vec2 d = x - a;\r
+\r
+ // Apply incremental impulse\r
+ b2Vec2 P1 = d.x * normal;\r
+ b2Vec2 P2 = d.y * normal;\r
+ vA -= invMassA * (P1 + P2);\r
+ wA -= invIA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));\r
+\r
+ vB += invMassB * (P1 + P2);\r
+ wB += invIB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));\r
+\r
+ // Accumulate\r
+ cp1->normalImpulse = x.x;\r
+ cp2->normalImpulse = x.y;\r
+\r
+#if B2_DEBUG_SOLVER == 1\r
+ // Postconditions\r
+ dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);\r
+\r
+ // Compute normal velocity\r
+ vn1 = b2Dot(dv1, normal);\r
+\r
+ b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol);\r
+#endif\r
+ break;\r
+ }\r
+\r
+\r
+ //\r
+ // Case 3: vn2 = 0 and x1 = 0\r
+ //\r
+ // vn1 = a11 * 0 + a12 * x2' + b1' \r
+ // 0 = a21 * 0 + a22 * x2' + b2'\r
+ //\r
+ x.x = 0.0f;\r
+ x.y = - cp2->normalMass * b.y;\r
+ vn1 = c->K.col2.x * x.y + b.x;\r
+ vn2 = 0.0f;\r
+\r
+ if (x.y >= 0.0f && vn1 >= 0.0f)\r
+ {\r
+ // Resubstitute for the incremental impulse\r
+ b2Vec2 d = x - a;\r
+\r
+ // Apply incremental impulse\r
+ b2Vec2 P1 = d.x * normal;\r
+ b2Vec2 P2 = d.y * normal;\r
+ vA -= invMassA * (P1 + P2);\r
+ wA -= invIA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));\r
+\r
+ vB += invMassB * (P1 + P2);\r
+ wB += invIB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));\r
+\r
+ // Accumulate\r
+ cp1->normalImpulse = x.x;\r
+ cp2->normalImpulse = x.y;\r
+\r
+#if B2_DEBUG_SOLVER == 1\r
+ // Postconditions\r
+ dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);\r
+\r
+ // Compute normal velocity\r
+ vn2 = b2Dot(dv2, normal);\r
+\r
+ b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol);\r
+#endif\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Case 4: x1 = 0 and x2 = 0\r
+ // \r
+ // vn1 = b1\r
+ // vn2 = b2;\r
+ x.x = 0.0f;\r
+ x.y = 0.0f;\r
+ vn1 = b.x;\r
+ vn2 = b.y;\r
+\r
+ if (vn1 >= 0.0f && vn2 >= 0.0f )\r
+ {\r
+ // Resubstitute for the incremental impulse\r
+ b2Vec2 d = x - a;\r
+\r
+ // Apply incremental impulse\r
+ b2Vec2 P1 = d.x * normal;\r
+ b2Vec2 P2 = d.y * normal;\r
+ vA -= invMassA * (P1 + P2);\r
+ wA -= invIA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));\r
+\r
+ vB += invMassB * (P1 + P2);\r
+ wB += invIB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));\r
+\r
+ // Accumulate\r
+ cp1->normalImpulse = x.x;\r
+ cp2->normalImpulse = x.y;\r
+\r
+ break;\r
+ }\r
+\r
+ // No solution, give up. This is hit sometimes, but it doesn't seem to matter.\r
+ break;\r
+ }\r
+ }\r
+\r
+ bodyA->m_linearVelocity = vA;\r
+ bodyA->m_angularVelocity = wA;\r
+ bodyB->m_linearVelocity = vB;\r
+ bodyB->m_angularVelocity = wB;\r
+ }\r
+}\r
+\r
+void b2ContactSolver::StoreImpulses()\r
+{\r
+ for (int32 i = 0; i < m_constraintCount; ++i)\r
+ {\r
+ b2ContactConstraint* c = m_constraints + i;\r
+ b2Manifold* m = c->manifold;\r
+\r
+ for (int32 j = 0; j < c->pointCount; ++j)\r
+ {\r
+ m->points[j].normalImpulse = c->points[j].normalImpulse;\r
+ m->points[j].tangentImpulse = c->points[j].tangentImpulse;\r
+ }\r
+ }\r
+}\r
+\r
+struct b2PositionSolverManifold\r
+{\r
+ void Initialize(b2ContactConstraint* cc, int32 index)\r
+ {\r
+ b2Assert(cc->pointCount > 0);\r
+\r
+ switch (cc->type)\r
+ {\r
+ case b2Manifold::e_circles:\r
+ {\r
+ b2Vec2 pointA = cc->bodyA->GetWorldPoint(cc->localPoint);\r
+ b2Vec2 pointB = cc->bodyB->GetWorldPoint(cc->points[0].localPoint);\r
+ if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)\r
+ {\r
+ normal = pointB - pointA;\r
+ normal.Normalize();\r
+ }\r
+ else\r
+ {\r
+ normal.Set(1.0f, 0.0f);\r
+ }\r
+\r
+ point = 0.5f * (pointA + pointB);\r
+ separation = b2Dot(pointB - pointA, normal) - cc->radius;\r
+ }\r
+ break;\r
+\r
+ case b2Manifold::e_faceA:\r
+ {\r
+ normal = cc->bodyA->GetWorldVector(cc->localNormal);\r
+ b2Vec2 planePoint = cc->bodyA->GetWorldPoint(cc->localPoint);\r
+\r
+ b2Vec2 clipPoint = cc->bodyB->GetWorldPoint(cc->points[index].localPoint);\r
+ separation = b2Dot(clipPoint - planePoint, normal) - cc->radius;\r
+ point = clipPoint;\r
+ }\r
+ break;\r
+\r
+ case b2Manifold::e_faceB:\r
+ {\r
+ normal = cc->bodyB->GetWorldVector(cc->localNormal);\r
+ b2Vec2 planePoint = cc->bodyB->GetWorldPoint(cc->localPoint);\r
+\r
+ b2Vec2 clipPoint = cc->bodyA->GetWorldPoint(cc->points[index].localPoint);\r
+ separation = b2Dot(clipPoint - planePoint, normal) - cc->radius;\r
+ point = clipPoint;\r
+\r
+ // Ensure normal points from A to B\r
+ normal = -normal;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ b2Vec2 normal;\r
+ b2Vec2 point;\r
+ float32 separation;\r
+};\r
+\r
+// Sequential solver.\r
+bool b2ContactSolver::SolvePositionConstraints(float32 baumgarte)\r
+{\r
+ float32 minSeparation = 0.0f;\r
+\r
+ for (int32 i = 0; i < m_constraintCount; ++i)\r
+ {\r
+ b2ContactConstraint* c = m_constraints + i;\r
+ b2Body* bodyA = c->bodyA;\r
+ b2Body* bodyB = c->bodyB;\r
+\r
+ float32 invMassA = bodyA->m_mass * bodyA->m_invMass;\r
+ float32 invIA = bodyA->m_mass * bodyA->m_invI;\r
+ float32 invMassB = bodyB->m_mass * bodyB->m_invMass;\r
+ float32 invIB = bodyB->m_mass * bodyB->m_invI;\r
+\r
+ // Solve normal constraints\r
+ for (int32 j = 0; j < c->pointCount; ++j)\r
+ {\r
+ b2PositionSolverManifold psm;\r
+ psm.Initialize(c, j);\r
+ b2Vec2 normal = psm.normal;\r
+\r
+ b2Vec2 point = psm.point;\r
+ float32 separation = psm.separation;\r
+\r
+ b2Vec2 rA = point - bodyA->m_sweep.c;\r
+ b2Vec2 rB = point - bodyB->m_sweep.c;\r
+\r
+ // Track max constraint error.\r
+ minSeparation = b2Min(minSeparation, separation);\r
+\r
+ // Prevent large corrections and allow slop.\r
+ float32 C = b2Clamp(baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f);\r
+\r
+ // Compute the effective mass.\r
+ float32 rnA = b2Cross(rA, normal);\r
+ float32 rnB = b2Cross(rB, normal);\r
+ float32 K = invMassA + invMassB + invIA * rnA * rnA + invIB * rnB * rnB;\r
+\r
+ // Compute normal impulse\r
+ float32 impulse = K > 0.0f ? - C / K : 0.0f;\r
+\r
+ b2Vec2 P = impulse * normal;\r
+\r
+ bodyA->m_sweep.c -= invMassA * P;\r
+ bodyA->m_sweep.a -= invIA * b2Cross(rA, P);\r
+ bodyA->SynchronizeTransform();\r
+\r
+ bodyB->m_sweep.c += invMassB * P;\r
+ bodyB->m_sweep.a += invIB * b2Cross(rB, P);\r
+ bodyB->SynchronizeTransform();\r
+ }\r
+ }\r
+\r
+ // We can't expect minSpeparation >= -b2_linearSlop because we don't\r
+ // push the separation above -b2_linearSlop.\r
+ return minSeparation >= -1.5f * b2_linearSlop;\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_CONTACT_SOLVER_H\r
+#define B2_CONTACT_SOLVER_H\r
+\r
+#include <Box2D/Common/b2Math.h>\r
+#include <Box2D/Collision/b2Collision.h>\r
+#include <Box2D/Dynamics/b2Island.h>\r
+\r
+class b2Contact;\r
+class b2Body;\r
+class b2StackAllocator;\r
+\r
+struct b2ContactConstraintPoint\r
+{\r
+ b2Vec2 localPoint;\r
+ b2Vec2 rA;\r
+ b2Vec2 rB;\r
+ float32 normalImpulse;\r
+ float32 tangentImpulse;\r
+ float32 normalMass;\r
+ float32 tangentMass;\r
+ float32 velocityBias;\r
+};\r
+\r
+struct b2ContactConstraint\r
+{\r
+ b2ContactConstraintPoint points[b2_maxManifoldPoints];\r
+ b2Vec2 localNormal;\r
+ b2Vec2 localPoint;\r
+ b2Vec2 normal;\r
+ b2Mat22 normalMass;\r
+ b2Mat22 K;\r
+ b2Body* bodyA;\r
+ b2Body* bodyB;\r
+ b2Manifold::Type type;\r
+ float32 radius;\r
+ float32 friction;\r
+ int32 pointCount;\r
+ b2Manifold* manifold;\r
+};\r
+\r
+class b2ContactSolver\r
+{\r
+public:\r
+ b2ContactSolver(b2Contact** contacts, int32 contactCount,\r
+ b2StackAllocator* allocator, float32 impulseRatio);\r
+\r
+ ~b2ContactSolver();\r
+\r
+ void WarmStart();\r
+ void SolveVelocityConstraints();\r
+ void StoreImpulses();\r
+\r
+ bool SolvePositionConstraints(float32 baumgarte);\r
+\r
+ b2StackAllocator* m_allocator;\r
+ b2ContactConstraint* m_constraints;\r
+ int m_constraintCount;\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h>\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2WorldCallbacks.h>\r
+\r
+#include <new>\r
+\r
+b2Contact* b2PolygonAndCircleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)\r
+{\r
+ void* mem = allocator->Allocate(sizeof(b2PolygonAndCircleContact));\r
+ return new (mem) b2PolygonAndCircleContact(fixtureA, fixtureB);\r
+}\r
+\r
+void b2PolygonAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)\r
+{\r
+ ((b2PolygonAndCircleContact*)contact)->~b2PolygonAndCircleContact();\r
+ allocator->Free(contact, sizeof(b2PolygonAndCircleContact));\r
+}\r
+\r
+b2PolygonAndCircleContact::b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)\r
+: b2Contact(fixtureA, fixtureB)\r
+{\r
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);\r
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);\r
+}\r
+\r
+void b2PolygonAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)\r
+{\r
+ b2CollidePolygonAndCircle( manifold,\r
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,\r
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_POLYGON_AND_CIRCLE_CONTACT_H\r
+#define B2_POLYGON_AND_CIRCLE_CONTACT_H\r
+\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+\r
+class b2BlockAllocator;\r
+\r
+class b2PolygonAndCircleContact : public b2Contact\r
+{\r
+public:\r
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);\r
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);\r
+\r
+ b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);\r
+ ~b2PolygonAndCircleContact() {}\r
+\r
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2PolygonContact.h>\r
+#include <Box2D/Common/b2BlockAllocator.h>\r
+#include <Box2D/Collision/b2TimeOfImpact.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Dynamics/b2WorldCallbacks.h>\r
+\r
+#include <new>\r
+\r
+b2Contact* b2PolygonContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)\r
+{\r
+ void* mem = allocator->Allocate(sizeof(b2PolygonContact));\r
+ return new (mem) b2PolygonContact(fixtureA, fixtureB);\r
+}\r
+\r
+void b2PolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)\r
+{\r
+ ((b2PolygonContact*)contact)->~b2PolygonContact();\r
+ allocator->Free(contact, sizeof(b2PolygonContact));\r
+}\r
+\r
+b2PolygonContact::b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB)\r
+ : b2Contact(fixtureA, fixtureB)\r
+{\r
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);\r
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon);\r
+}\r
+\r
+void b2PolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)\r
+{\r
+ b2CollidePolygons( manifold,\r
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,\r
+ (b2PolygonShape*)m_fixtureB->GetShape(), xfB);\r
+}\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#ifndef B2_POLYGON_CONTACT_H\r
+#define B2_POLYGON_CONTACT_H\r
+\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+\r
+class b2BlockAllocator;\r
+\r
+class b2PolygonContact : public b2Contact\r
+{\r
+public:\r
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);\r
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);\r
+\r
+ b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB);\r
+ ~b2PolygonContact() {}\r
+\r
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*\r
+* Copyright (c) 2006-2010 Erin Catto http://www.gphysics.com\r
+*\r
+* This software is provided 'as-is', without any express or implied\r
+* warranty. In no event will the authors be held liable for any damages\r
+* arising from the use of this software.\r
+* Permission is granted to anyone to use this software for any purpose,\r
+* including commercial applications, and to alter it and redistribute it\r
+* freely, subject to the following restrictions:\r
+* 1. The origin of this software must not be misrepresented; you must not\r
+* claim that you wrote the original software. If you use this software\r
+* in a product, an acknowledgment in the product documentation would be\r
+* appreciated but is not required.\r
+* 2. Altered source versions must be plainly marked as such, and must not be\r
+* misrepresented as being the original software.\r
+* 3. This notice may not be removed or altered from any source distribution.\r
+*/\r
+\r
+#include <Box2D/Dynamics/Contacts/b2TOISolver.h>\r
+#include <Box2D/Dynamics/Contacts/b2Contact.h>\r
+#include <Box2D/Dynamics/b2Body.h>\r
+#include <Box2D/Dynamics/b2Fixture.h>\r
+#include <Box2D/Common/b2StackAllocator.h>\r
+\r
+struct b2TOIConstraint\r
+{\r
+ b2Vec2 localPoints[b2_maxManifoldPoints];\r
+ b2Vec2 localNormal;\r
+ b2Vec2 localPoint;\r
+ b2Manifold::Type type;\r
+ float32 radius;\r
+ int32 pointCount;\r
+ b2Body* bodyA;\r
+ b2Body* bodyB;\r
+};\r
+\r
+b2TOISolver::b2TOISolver(b2StackAllocator* allocator)\r
+{\r
+ m_allocator = allocator;\r
+ m_constraints = NULL;\r
+ m_count = NULL;\r
+ m_toiBody = NULL;\r
+}\r
+\r
+b2TOISolver::~b2TOISolver()\r
+{\r
+ Clear();\r
+}\r
+\r
+void b2TOISolver::Clear()\r
+{\r
+ if (m_allocator && m_constraints)\r
+ {\r
+ m_allocator->Free(m_constraints);\r
+ m_constraints = NULL;\r
+ }\r
+}\r
+\r
+void b2TOISolver::Initialize(b2Contact** contacts, int32 count, b2Body* toiBody)\r
+{\r
+ Clear();\r
+\r
+ m_count = count;\r
+ m_toiBody = toiBody;\r
+\r
+ m_constraints = (b2TOIConstraint*) m_allocator->Allocate(m_count * sizeof(b2TOIConstraint));\r
+\r
+ for (int32 i = 0; i < m_count; ++i)\r
+ {\r
+ b2Contact* contact = contacts[i];\r
+\r
+ b2Fixture* fixtureA = contact->GetFixtureA();\r
+ b2Fixture* fixtureB = contact->GetFixtureB();\r
+ b2Shape* shapeA = fixtureA->GetShape();\r
+ b2Shape* shapeB = fixtureB->GetShape();\r
+ float32 radiusA = shapeA->m_radius;\r
+ float32 radiusB = shapeB->m_radius;\r
+ b2Body* bodyA = fixtureA->GetBody();\r
+ b2Body* bodyB = fixtureB->GetBody();\r
+ b2Manifold* manifold = contact->GetManifold();\r
+\r
+ b2Assert(manifold->pointCount > 0);\r
+\r
+ b2TOIConstraint* constraint = m_constraints + i;\r
+ constraint->bodyA = bodyA;\r
+ constraint->bodyB = bodyB;\r
+ constraint->localNormal = manifold->localNormal;\r
+ constraint->localPoint = manifold->localPoint;\r
+ constraint->type = manifold->type;\r
+ constraint->pointCount = manifold->pointCount;\r
+ constraint->radius = radiusA + radiusB;\r
+\r
+ for (int32 j = 0; j < constraint->pointCount; ++j)\r
+ {\r
+ b2ManifoldPoint* cp = manifold->points + j;\r
+ constraint->localPoints[j] = cp->localPoint;\r
+ }\r
+ }\r
+}\r
+\r
+struct b2TOISolverManifold\r
+{\r
+ void Initialize(b2TOIConstraint* cc, int32 index)\r
+ {\r
+ b2Assert(cc->pointCount > 0);\r
+\r
+ switch (cc->type)\r
+ {\r
+ case b2Manifold::e_circles:\r
+ {\r
+ b2Vec2 pointA = cc->bodyA->GetWorldPoint(cc->localPoint);\r
+ b2Vec2 pointB = cc->bodyB->GetWorldPoint(cc->localPoints[0]);\r
+ if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)\r
+ {\r
+ normal = pointB - pointA;\r
+ normal.Normalize();\r
+ }\r
+ else\r
+ {\r
+ normal.Set(1.0f, 0.0f);\r
+ }\r
+\r
+ point = 0.5f * (pointA + pointB);\r
+ separation = b2Dot(pointB - pointA, normal) - cc->radius;\r
+ }\r
+ break;\r
+\r
+ case b2Manifold::e_faceA:\r
+ {\r
+ normal = cc->bodyA->GetWorldVector(cc->localNormal);\r
+ b2Vec2 planePoint = cc->bodyA->GetWorldPoint(cc->localPoint);\r
+\r
+