Example #1
0
        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));
        }
Example #13
0
 //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);
 }
Example #21
0
        /// ///////////////////////////////////////////////////////////////////////////
        // **** Post Step Callback Functions

        static void PostStepDoNothing(cpSpace space, object obj, object data)
        {
        }
Example #22
0
 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);
 }
Example #25
0
 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));
        }