Пример #1
0
        public void ClearPairs(cpBBTree tree)
        {
            Pair pair = this.pairs;
            Pair next;

            this.pairs = null;



            while (pair != null)
            {
                if (pair.a.leaf == this)
                {
                    next = pair.a.next;
                    Thread.Unlink(pair.b.prev, pair.b.leaf, pair.b.next);
                }
                else
                {
                    next = pair.b.next;
                    Thread.Unlink(pair.a.prev, pair.a.leaf, pair.a.next);
                }
                tree.PairRecycle(pair);
                pair = next;
            }
        }
Пример #2
0
        /////////////////////////////////////////////////



        public cpBBTree(cpBBTree staticIndex)
        {
            this.staticIndex = staticIndex;

            if (staticIndex != null)
            {
                if (staticIndex.dynamicIndex != null)
                {
                    throw new NotImplementedException("This static index is already associated with a dynamic index.");
                }
                staticIndex.dynamicIndex = this;
            }


            this.velocityFunc = null;

            // This is a hash from object ID -> object for the objects stored in the BBTree.
            leaves = new Dictionary <ulong, Leaf>();

            // elements = new Dictionary<int, object>();
            root = null;

            // A linked list containing an object pool of tree nodes and pairs.
            this.pooledNodes = null;
            this.pooledPairs = null;

            stamp = 0;
        }
Пример #3
0
 public MarkContext(cpBBTree tree, Node staticRoot, cpSpatialIndexQueryFunc func, object data)
 {
     this.tree       = tree;
     this.staticRoot = staticRoot;
     this.func       = func;
     this.data       = data;
 }
Пример #4
0
 public virtual void MarkLeafQuery(Leaf leaf, bool left, cpBBTree tree, cpSpatialIndexQueryFunc func)
 {
     if (cp.bbTreeIntersectsNode(leaf, this))
     {
         this.A.MarkLeafQuery(leaf, left, tree, func);
         this.B.MarkLeafQuery(leaf, left, tree, func);
     }
 }
Пример #5
0
        public Node(Node a, Node b, cpBBTree tree)
        {
            this.obj = null;

            bb = cpBB.Merge(a.bb, b.bb);

            parent = null;

            this.SetA(a);
            this.SetB(b);
        }
Пример #6
0
 // Collide the objects in an index against the objects in a staticIndex using the query callback function.
 public void CollideStatic(cpBBTree staticIndex, cpSpatialIndexQueryFunc func, object data)
 {
     if (staticIndex != null && staticIndex.Count > 0)
     {
         Each((obj) =>
         {
             //	dynamicToStaticContext context = new dynamicToStaticContext(dynamicIndex->bbfunc, staticIndex, func, data);
             staticIndex.Query(staticIndex,
                               new cpBB(obj.bb.l, obj.bb.b, obj.bb.r, obj.bb.t),
                               func, data);
         });
     }
 }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cpBBTree"></param>
        /// <param name="value"></param>

        public Leaf(cpBBTree tree, IObjectBox obj)
            : base()
        {
            this.obj = obj;             //THIS IS THE GENERIC REAL VALUE

            tree.GetBB(obj, this);

            this.parent = null;

            this.STAMP = 1;
            this.PAIRS = null;

            cp.numLeaves++;
        }
Пример #8
0
        public void AddPairs(cpBBTree tree)
        {
            cpBBTree dynamicIndex = tree.dynamicIndex;

            if (dynamicIndex != null)
            {
                var dynamicRoot = dynamicIndex.root;
                if (dynamicRoot != null)
                {
                    dynamicRoot.MarkLeafQuery(this, true, dynamicIndex, null);
                }
            }
            else
            {
                var staticRoot = tree.staticIndex.root;
                this.MarkSubtree(tree, staticRoot, null);
            }
        }
Пример #9
0
        public bool Update(cpBBTree tree)
        {
            var root = tree.root;

            var obj = this.obj;

            if (!this.ContainsObj(obj))
            {
                this.bb = tree.GetBB(this.obj);

                root      = tree.SubtreeRemove(root, this);
                tree.root = tree.SubtreeInsert(root, this);                //tree.root = SubtreeInsert(root, this, tree);
                this.ClearPairs(tree);
                this.stamp = tree.GetStamp();

                return(true);
            }
            return(false);
        }
Пример #10
0
        public override void MarkSubtree(cpBBTree tree, Node staticRoot, cpSpatialIndexQueryFunc func)
        {
            if (this.stamp == tree.GetStamp())
            {
                if (staticRoot != null)
                {
                    staticRoot.MarkLeafQuery(this, false, tree, func);
                }

                for (Node node = this; node.parent != null; node = node.parent)
                {
                    if (node == node.parent.A)
                    {
                        node.parent.B.MarkLeafQuery(this, true, tree, func);
                    }
                    else
                    {
                        node.parent.A.MarkLeafQuery(this, false, tree, func);
                    }
                }
            }
            else
            {
                var pair = this.pairs;
                while (pair != null)
                {
                    if (this == pair.b.leaf)
                    {
                        if (func != null)
                        {
                            func(pair.a.leaf.obj, this.obj, pair.id, null);
                        }

                        pair = pair.b.next;
                    }
                    else
                    {
                        pair = pair.a.next;
                    }
                }
            }
        }
Пример #11
0
        public void ReplaceChild(Node child, Node value, cpBBTree tree)
        {
            cp.AssertSoft(child == this.A || child == this.B, "Node is not a child of parent.");

            if (this.A == child)
            {
                tree.NodeRecycle(this.A);                //.Recycle(tree);
                this.SetA(value);
            }
            else
            {
                tree.NodeRecycle(this.B);
                this.SetB(value);
            }

            for (var node = this; node != null; node = node.parent)
            {
                node.bb = node.A.bb.Merge(node.B.bb);
            }
        }
Пример #12
0
        public override void MarkLeafQuery(Leaf leaf, bool left, cpBBTree tree, cpSpatialIndexQueryFunc func)
        {
            if (cp.bbTreeIntersectsNode(leaf, this))
            {
                if (left)
                {
                    tree.PairInsert(leaf, this);
                }
                else
                {
                    if (this.stamp < leaf.stamp)
                    {
                        tree.PairInsert(this, leaf);
                    }

                    if (func != null)
                    {
                        func(leaf.obj, this.obj, (ulong)leaf.stamp, null);
                    }
                }
            }
        }
Пример #13
0
        public cpBBTree GetMasterTree()
        {
            cpBBTree dynamicTree = this.dynamicIndex;

            return(dynamicTree != null ? dynamicTree : this);
        }
Пример #14
0
 public void Recycle(cpBBTree tree)
 {
     this.a.prev      = tree.pooledPairs;
     tree.pooledPairs = this;
 }
Пример #15
0
 public virtual void Recycle(cpBBTree tree)
 {
     this.parent      = tree.pooledNodes;
     tree.pooledNodes = this;
 }
Пример #16
0
 public override void Recycle(cpBBTree tree)
 {
 }
Пример #17
0
 public virtual void MarkSubtree(cpBBTree tree, Node staticRoot, cpSpatialIndexQueryFunc func)
 {
     this.a.MarkSubtree(tree, staticRoot, func);
     this.b.MarkSubtree(tree, staticRoot, func);
 }
Пример #18
0
        public void SetBodyType(cpBodyType type)
        {
            cpBodyType oldType = bodyType;

            if (oldType == type)
            {
                return;
            }

            // Static bodies have their idle timers set to infinity.
            // Non-static bodies should have their idle timer reset.
            nodeIdleTime = (type == cpBodyType.STATIC ? cp.Infinity : 0.0f);


            if (type == cpBodyType.DYNAMIC)
            {
                this.m     = this.i = 0.0f;
                this.m_inv = this.i_inv = cp.Infinity;

                AccumulateMassFromShapes();
            }
            else
            {
                this.m     = this.i = cp.Infinity;
                this.m_inv = this.i_inv = 0.0f;

                this.v = cpVect.Zero;
                this.w = 0.0f;
            }

            // If the body is added to a space already, we'll need to update some space data structures.

            if (space != null)
            {
                cp.AssertSpaceUnlocked(space);


                if (oldType == cpBodyType.STATIC)
                {
                    // TODO This is probably not necessary
                    //			cpBodyActivateStatic(body, NULL);
                }
                else
                {
                    Activate();
                }

                // Move the bodies to the correct array.
                List <cpBody> fromArray = space.ArrayForBodyType(oldType);
                List <cpBody> toArray   = space.ArrayForBodyType(type);

                if (fromArray != toArray)
                {
                    fromArray.Remove(this);
                    toArray.Add(this);
                }

                // Move the body's shapes to the correct spatial index.
                cpBBTree fromIndex = (oldType == cpBodyType.STATIC ? space.staticShapes : space.dynamicShapes);
                cpBBTree toIndex   = (type == cpBodyType.STATIC ? space.staticShapes : space.dynamicShapes);

                if (fromIndex != toIndex)
                {
                    eachShape((s, o) =>
                    {
                        fromIndex.Remove(s.hashid);
                        toIndex.Insert(s.hashid, s);
                    }, null);
                }
            }
        }
Пример #19
0
        // Used for disposing of collision handlers.
        //static void FreeWrap(void* ptr, void* unused) { cpfree(ptr); }

        //MARK: Memory Management Functions


        public cpSpace()
        {
#if DEBUG
            Console.WriteLine("Initializing cpSpace - Chipmunk v{0} (Debug Enabled)\n", cp.cpVersionString);
            Console.WriteLine("Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks\n");
#endif


            /// Number of iterations to use in the impulse solver to solve contacts.
            this.iterations = 10;

            /// Gravity to pass to rigid bodies when integrating velocity.
            this.gravity = cpVect.Zero;

            /// Damping rate expressed as the fraction of velocity bodies retain each second.
            /// A value of 0.9 would mean that each body's velocity will drop 10% per second.
            /// The default value is 1.0, meaning no damping is applied.
            /// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.
            this.damping = 1;

            /// Amount of encouraged penetration between colliding shapes..
            /// Used to reduce oscillating contacts and keep the collision cache warm.
            /// Defaults to 0.1. If you have poor simulation quality,
            /// increase this number as much as possible without allowing visible amounts of overlap.
            this.collisionSlop = 0.1f;

            /// Determines how fast overlapping shapes are pushed apart.
            /// Expressed as a fraction of the error remaining after each second.
            /// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
            this.collisionBias = cp.cpfpow(1f - 0.1f, 60f);

            /// Number of frames that contact information should persist.
            /// Defaults to 3. There is probably never a reason to change this value.
            this.collisionPersistence = 3;

            this.locked = 0;
            this.stamp  = 0;

            this.staticShapes  = new cpBBTree(null);
            this.dynamicShapes = new cpBBTree(this.staticShapes);

            this.dynamicShapes.SetVelocityFunc(o => ShapeVelocityFunc(o as cpShape));

            this.dynamicBodies      = new List <cpBody>();
            this.staticBodies       = new List <cpBody>();
            this.rousedBodies       = new List <cpBody>();
            this.sleepingComponents = new List <cpBody>();

            /// Time a group of bodies must remain idle in order to fall asleep.
            /// Enabling sleeping also implicitly enables the the contact graph.
            /// The default value of Infinity disables the sleeping algorithm.
            this.sleepTimeThreshold = cp.Infinity;
            /// Speed threshold for a body to be considered idle.
            /// The default value of 0 means to let the space guess a good threshold based on gravity.
            this.idleSpeedThreshold = 0;

            this.arbiters       = new List <cpArbiter>();
            this.cachedArbiters = new Dictionary <ulong, cpArbiter>();

            this.constraints = new List <cpConstraint>();

            this.usesWildcards  = false;
            this.defaultHandler = cpCollisionHandlerDoNothing;

            this.collisionHandlers = new Dictionary <ulong, cpCollisionHandler>();

            this.postStepCallbacks = new List <cpPostStepCallback>();

            this.skipPostStep = false;

            /// The designated static body for this space.
            /// You can modify this body, or replace it with your own static body.
            /// By default it points to a statically allocated cpBody in the cpSpace struct.
            this.staticBody = cpBody.NewStatic();
        }