예제 #1
0
        /// Remove a rigid body from the simulation.
        public void RemoveBody(cpBody body)
        {
            cp.AssertHard(body != GetStaticBody(), "Cannot remove the designated static body for the space.");
            cp.AssertHard(ContainsBody(body), "Cannot remove a body that was not added to the space. (Removed twice maybe?)");
            //	cpAssertHard(body->shapeList == NULL, "Cannot remove a body from the space before removing the bodies attached to it.");
            //	cpAssertHard(body->constraintList == NULL, "Cannot remove a body from the space before removing the constraints attached to it.");
            cp.AssertSpaceUnlocked(this);

            body.Activate();

            ArrayForBodyType(body.bodyType).Remove(body);

            body.space = null;
        }
예제 #2
0
        /// Add a constraint to the simulation.
        public cpConstraint AddConstraint(cpConstraint constraint)
        {
            cp.AssertHard(constraint.space != this, "You have already added this constraint to this space. You must not add it a second time.");
            cp.AssertHard(constraint.space == null, "You have already added this constraint to another space. You cannot add it to a second.");

            cp.AssertSpaceUnlocked(this);

            cpBody a = constraint.a, b = constraint.b;

            cp.AssertHard(a != null && b != null, "Constraint is attached to a NULL body.");

            a.Activate();
            b.Activate();

            this.constraints.Add(constraint);

            // Push onto the heads of the bodies' constraint lists
            constraint.next_a = a.constraintList; a.constraintList = constraint;
            constraint.next_b = b.constraintList; b.constraintList = constraint;
            constraint.space  = this;

            return(constraint);
        }
예제 #3
0
 public void SetFilter(cpShapeFilter filter)
 {
     body.Activate();
     this.filter = filter;
 }
예제 #4
0
        public void ProcessComponents(float dt)
        {
            var sleep  = (this.sleepTimeThreshold != cp.Infinity);
            var bodies = this.dynamicBodies;

            // These checks can be removed at some stage (if DEBUG == undefined)
            for (var i = 0; i < bodies.Count; i++)
            {
                var body = bodies[i];

                cp.AssertSoft(body.nodeNext == null, "Internal Error: Dangling next pointer detected in contact graph.");
                cp.AssertSoft(body.nodeRoot == null, "Internal Error: Dangling root pointer detected in contact graph.");
            }

            // Calculate the kinetic energy of all the bodies
            if (sleep)
            {
                var dv   = this.idleSpeedThreshold;
                var dvsq = (dv != 0 ? dv * dv : cpVect.cpvlengthsq(this.gravity) * dt * dt);

                for (var i = 0; i < bodies.Count; i++)
                {
                    // TODO should make a separate array for kinematic bodies.
                    if (bodies[i].bodyType != cpBodyType.DYNAMIC)
                    {
                        continue;
                    }

                    // Need to deal with infinite mass objects
                    var keThreshold = (dvsq > 0 ? bodies[i].m * dvsq : 0.0f);
                    bodies[i].nodeIdleTime = (bodies[i].KineticEnergy() > keThreshold ? 0 : bodies[i].nodeIdleTime + dt);
                }
            }

            // Awaken any sleeping bodies found and then push arbiters to the bodies' lists.

            List <cpArbiter> arbiters = this.arbiters; // new List<cpArbiter>();
            var count = arbiters.Count;                //FIX: we cannot read the count values of the array because it changes inside

            for (int i = 0; i < count; i++)
            {
                cpArbiter arb = arbiters[i];
                cpBody    a = arb.body_a, b = arb.body_b;

                if (sleep)
                {
                    if (b.bodyType == cpBodyType.KINEMATIC || a.IsSleeping())
                    {
                        a.Activate();
                    }

                    if (a.bodyType == cpBodyType.KINEMATIC || b.IsSleeping())
                    {
                        b.Activate();
                    }
                }

                a.PushArbiter(arb);
                b.PushArbiter(arb);
            }

            if (sleep)
            {
                // Bodies should be held active if connected by a joint to a non-static rouge body.
                var constraints = this.constraints;
                for (var i = 0; i < constraints.Count; i++)
                {
                    cpConstraint constraint = constraints[i];
                    cpBody       a = constraint.a, b = constraint.b;

                    if (b.bodyType == cpBodyType.KINEMATIC)
                    {
                        a.Activate();
                    }

                    if (a.bodyType == cpBodyType.KINEMATIC)
                    {
                        b.Activate();
                    }
                }

                // Generate components and deactivate sleeping ones
                for (var i = 0; i < bodies.Count;)
                {
                    var body = bodies[i];

                    if (cp.ComponentRoot(body) == null)
                    {
                        // Body not in a component yet. Perform a DFS to flood fill mark
                        // the component in the contact graph using this body as the root.
                        FloodFillComponent(body, body);

                        // Check if the component should be put to sleep.
                        if (!ComponentActive(body, this.sleepTimeThreshold))
                        {
                            this.sleepingComponents.Add(body);
                            //CP_BODY_FOREACH_COMPONENT
                            for (var other = body; other != null; other = other.nodeNext)
                            {
                                this.DeactivateBody(other);
                            }

                            // deactivateBody() removed the current body from the list.
                            // Skip incrementing the index counter.
                            continue;
                        }
                    }

                    i++;

                    // Only sleeping bodies retain their component node pointers.
                    body.nodeRoot = null;
                    body.nodeNext = null;
                }
            }
        }