public cpConstraint(cpBody a, cpBody b) { /// The first body connected to this constraint. this.a = a; /// The second body connected to this constraint. this.b = b; this.space = null; this.next_a = null; this.next_b = null; /// The maximum force that this constraint is allowed to use. this.maxForce = cp.Infinity; /// The rate at which joint error is corrected. /// Defaults to pow(1 - 0.1, 60) meaning that it will /// correct 10% of the error every 1/60th of a second. this.errorBias = cp.cpfpow(1f - 0.1f, 60f); /// The maximum rate at which joint error is corrected. this.maxBias = cp.Infinity; this.collideBodies = true; //Not clear preSolve = DefaultPreSolve; postSolve = DefaultPostSolve; }
//public CollisionHandler DefaultHandler { get; set; } #endregion //MARK: Misc Helper Funcs // Default collision functions. static bool DefaultBegin(cpArbiter arb, cpSpace space, object data) { bool retA = arb.CallWildcardBeginA(space); // cpArbiterCallWildcardBeginA(arb, space); bool retB = arb.CallWildcardBeginB(space); // cpArbiterCallWildcardBeginB(arb, space); return(retA && retB); }
//public static cpShapeFilter FILTER_ALL = new cpShapeFilter(cp.NO_GROUP, (int)cpShapeFilterMask.All, (int)cpShapeFilterMask.All); //public static cpShapeFilter FILTER_NONE = new cpShapeFilter(cp.NO_GROUP, (int)cpShapeFilterMask.None, (int)cpShapeFilterMask.None); public cpShape(cpBody body, cpShapeMassInfo massInfo) { /// The rigid body this collision shape is attached to. this.body = body; this.massInfo = massInfo; /// The current bounding box of the shape. /// The current bounding box of the shape. /// //this.bb_l = this.bb_b = this.bb_r = this.bb_t = 0; this.bb = new cpBB(0, 0, 0, 0); //this.hashid = (cp.shapeIDCounter++).ToString(); /// Sensor flag. /// Sensor shapes call collision callbacks but don't produce collisions. this.sensor = false; filter = new cpShapeFilter(cp.NO_GROUP, (int)cpShapeFilterMask.Default, (int)cpShapeFilterMask.Default); /// Coefficient of restitution. (elasticity) this.e = 0; /// Coefficient of friction. this.u = 0; /// Surface velocity used when solving for friction. this.surfaceV = cpVect.Zero; /// Collision type of this shape used when picking collision handlers. this.type = 0; this.space = null; }
static bool DefaultPreSolve(cpArbiter arb, cpSpace space, object data) { bool retA = arb.CallWildcardPreSolveA(space); bool retB = arb.CallWildcardPreSolveB(space); return(retA && retB); }
public void CallWildcardSeparateB(cpSpace space) { cpCollisionHandler handler = this.handlerB; this.swapped = !this.swapped; handler.separateFunc(this, space, handler.userData); this.swapped = !this.swapped; }
public void CallWildcardPostSolveB(cpSpace space) { cpCollisionHandler handler = this.handlerB; this.swapped = !this.swapped; handler.postSolveFunc(this, space, handler.userData); this.swapped = !this.swapped; }
public bool CallWildcardPreSolveB(cpSpace space) { cpCollisionHandler handler = this.handlerB; this.swapped = !this.swapped; bool retval = handler.preSolveFunc(this, space, handler.userData); this.swapped = !this.swapped; return(retval); }
/// <summary> /// CREATES A BODY WITH MASS AND INERTIA /// </summary> /// <param name="mass"></param> /// <param name="moment"></param> public cpBody(float mass, float moment) { transform = new cpTransform(); this.cog = cpVect.Zero; this.space = null; this.shapeList = null; this.arbiterList = null; // These are both wacky linked lists. this.constraintList = null; velocity_func = UpdateVelocity; position_func = UpdatePosition; // This stuff is used to track information on the collision graph. this.nodeRoot = null; this.nodeNext = null; this.nodeIdleTime = 0; /// Position of the rigid body's center of gravity. this.p = cpVect.Zero; /// Velocity of the rigid body's center of gravity. this.v = cpVect.Zero; /// Force acting on the rigid body's center of gravity. this.f = cpVect.Zero; /// Angular velocity of the body around it's center of gravity in radians/second. this.w = 0; /// Torque applied to the body around it's center of gravity. this.t = 0; // This stuff is all private. this.v_bias = cpVect.Zero; //x = this.v_biasy = 0; this.w_bias = 0; this.userData = null; this.SetMass(mass); this.SetMoment(moment); this.SetAngle(0.0f); }
// Defined in cpSpace.c // Wake up a sleeping or idle body. public void Activate() { if (bodyType == cpBodyType.DYNAMIC) { nodeIdleTime = 0.0f; cpBody root = nodeRoot; if (root != null && root.IsSleeping()) { // TODO should cpBodyIsSleeping(root) be an assertion? cp.AssertSoft(root.bodyType == cpBodyType.DYNAMIC, "Internal Error: Non-dynamic body component root detected."); cpSpace space = root.space; cpBody body = root; while (body != null) { cpBody next = body.nodeNext; body.nodeIdleTime = 0.0f; body.nodeRoot = null; body.nodeNext = null; space.ActivateBody(body); body = next; } space.sleepingComponents.Remove(root); } eachArbiter((arb, o) => { // Reset the idle timer of things the body is touching as well. // That way things don't get left hanging in the air. cpBody other = (arb.body_a == this ? arb.body_b : arb.body_a); if (other.bodyType != cpBodyType.STATIC) { other.nodeIdleTime = 0.0f; } }, null); } }
public void CallWildcardSeparateA(cpSpace space) { cpCollisionHandler handler = this.handlerA; handler.separateFunc(this, space, handler.userData); }
public void CallWildcardPostSolveA(cpSpace space) { cpCollisionHandler handler = this.handlerA; handler.postSolveFunc(this, space, handler.userData); }
public bool CallWildcardPreSolveA(cpSpace space) { cpCollisionHandler handler = this.handlerA; return(handler.preSolveFunc(this, space, handler.userData)); }
//Function called after the solver runs. This can be overridden by the user //to customize the constraint. //Use the applied impulse to perform effects like breakable joints. public virtual void DefaultPostSolve(cpSpace space) { }
public static bool AlwaysCollide(cpArbiter arb, cpSpace space, object data) { return(true); }
public static void DefaultSeparate(cpArbiter arb, cpSpace space, object o) { }
public static void DefaultPostSolve(cpArbiter arb, cpSpace space, object o) { }
public static bool DefaultPreSolve(cpArbiter arb, cpSpace space, object o) { return(true); }
public static bool DefaultBegin(cpArbiter arb, cpSpace space, object o) { return(true); }
public void Update(cpCollisionInfo info, cpSpace space) { cpShape a = info.a, b = info.b; // For collisions between two similar primitive types, the order could have been swapped since the last frame. this.a = a; this.body_a = a.body; this.b = b; this.body_b = b.body; // Iterate over the possible pairs to look for hash value matches. for (int i = 0; i < info.count; i++) { cpContact con = info.arr[i]; // r1 and r2 store absolute offsets at init time. // Need to convert them to relative offsets. con.r1 = cpVect.cpvsub(con.r1, a.body.p); con.r2 = cpVect.cpvsub(con.r2, b.body.p); // Cached impulses are not zeroed at init time. con.jnAcc = con.jtAcc = 0.0f; for (int j = 0; j < this.Count; j++) { cpContact old = this.contacts[j]; // This could trigger false positives, but is fairly unlikely nor serious if it does. if (con.hash == old.hash) { // Copy the persistant contact information. con.jnAcc = old.jnAcc; con.jtAcc = old.jtAcc; } } } //TODO: revise this.contacts = info.arr; //this.count = info.count; this.n = info.n; this.e = a.e * b.e; this.u = a.u * b.u; cpVect surface_vr = cpVect.cpvsub(b.surfaceV, a.surfaceV); this.surface_vr = cpVect.cpvsub(surface_vr, cpVect.cpvmult(info.n, cpVect.cpvdot(surface_vr, info.n))); ulong typeA = info.a.type, typeB = info.b.type; cpCollisionHandler defaultHandler = space.defaultHandler; cpCollisionHandler handler = this.handler = space.LookupHandler(typeA, typeB, defaultHandler); // Check if the types match, but don't swap for a default handler which use the wildcard for type A. bool swapped = this.swapped = (typeA != handler.typeA && handler.typeA != cp.WILDCARD_COLLISION_TYPE); if (handler != defaultHandler || space.usesWildcards) { // The order of the main handler swaps the wildcard handlers too. Uffda. this.handlerA = space.LookupHandler(swapped ? typeB : typeA, cp.WILDCARD_COLLISION_TYPE, cpCollisionHandler.cpCollisionHandlerDoNothing); this.handlerB = space.LookupHandler(swapped ? typeA : typeB, cp.WILDCARD_COLLISION_TYPE, cpCollisionHandler.cpCollisionHandlerDoNothing); } // mark it as new if it's been cached if (this.state == cpArbiterState.Cached) { this.state = cpArbiterState.FirstCollision; } }
static void DefaultSeparate(cpArbiter arb, cpSpace space, object data) { arb.CallWildcardSeparateA(space); arb.CallWildcardSeparateB(space); }
/// /////////////////////////////////////////////////////////////////////////// // **** Post Step Callback Functions static void PostStepDoNothing(cpSpace space, object obj, object data) { }
protected XSpaceManager() { mSpace = new cpSpace(); mSpace.SetIterations(10); }
public static void DoNothing(cpArbiter arb, cpSpace space, object data) { }
static void DefaultPostSolve(cpArbiter arb, cpSpace space, object data) { arb.CallWildcardPostSolveA(space); arb.CallWildcardPostSolveB(space); }
public static void AssertSpaceUnlocked(cpSpace space) { AssertSoft(!space.IsLocked, "This addition/removal cannot be done safely during a call to cpSpaceStep() or during a query. Put these calls into a post-step callback."); }
public bool CallWildcardBeginA(cpSpace space) { cpCollisionHandler handler = this.handlerA; return(handler.beginFunc(this, space, handler.userData)); }