/// Found Object Tests
        protected override bool _FoundObject(ISceneContainerObject obj, SceneContainerQueryData queryData)
        {
            // Check type on objects
            Assert.Fatal(obj is ISceneObject2D, "Invalid object passed to _FoundObject");
            Assert.Fatal(queryData is T2DSceneContainerQueryData, "Invalid query data object passed to _FoundObject");
            ISceneObject2D sceneObject = (ISceneObject2D)obj; // this is slow due to not inlined properties below, would be better to use T2DSceneObject, but lights can be in the graph and are not scene objects

            T2DSceneContainerQueryData query = (T2DSceneContainerQueryData)queryData;

            if (sceneObject.Visible || query.FindInvisible)
            {
                // Check if the Group / Layer masks match.
                int layerMask = 1 << sceneObject.Layer;
                if ((layerMask & query._layerMask) != 0)
                {
                    // Yes, so fetch Clip Rectangle.
                    if (_IntersectsWith(sceneObject, query))
                        return true;
                }
            }

            return false;
        }
Exemplo n.º 2
0
 private bool _NotInNewList(ISceneContainerObject obj)
 {
     return !_nearbyObjects.Contains(obj);
 }
        protected override void _GetBins(ISceneContainerObject obj, out uint minBinX, out uint minBinY, out uint maxBinX, out uint maxBinY)
        {
            // Check type on object
            Assert.Fatal(obj is ISceneObject2D, "Invalid object passed to _GetBins");
            RectangleF rectangle = ((ISceneObject2D)obj).WorldCollisionClipRectangle;

            _GetBinRange(rectangle.X, rectangle.X + rectangle.Width, out minBinX, out maxBinX);
            _GetBinRange(rectangle.Y, rectangle.Y + rectangle.Height, out minBinY, out maxBinY);
        }
        protected override bool _IntersectsWith(ISceneContainerObject obj, SceneContainerQueryData iQueryData)
        {
            // Check type on objects
            Assert.Fatal(obj is ISceneObject2D, "Invalid object passed to _FoundObject");
            Assert.Fatal(iQueryData is T2DSceneContainerQueryData, "Invalid query data object passed to _FoundObject");
            ISceneObject2D sceneObject = (ISceneObject2D)obj;
            T2DSceneContainerQueryData query = (T2DSceneContainerQueryData)iQueryData;

            return _IntersectsWith(sceneObject, query);
        }
 protected abstract bool _IntersectsWith(ISceneContainerObject obj, SceneContainerQueryData query);
 public void Reset()
 {
     _sceneObject = null;
     _nextBinReference = null;
     _previousBinReference = null;
     _objectLink = null;
 }
 /// Found Object Tests
 protected abstract bool _FoundObject(ISceneContainerObject obj, SceneContainerQueryData query);
 /// Get Bin Range
 protected abstract void _GetBins(ISceneContainerObject obj, out uint minBinX, out uint minBinY, out uint maxBinX, out uint maxBinY);
        protected void _CheckSceneObjectBins(ISceneContainerObject obj, SceneContainerData scd, uint minBinX, uint minBinY, uint maxBinX, uint maxBinY)
        {
            // Check everything is fine!
            Assert.Fatal(obj != null, "Invalid Object");

            // Is the Scene Object in the container?
            if (scd._binReferenceChain == null)
            {
                // No, so add to the Scene Container.
                _AddSceneObject(obj);
                // Finish here.
                return;
            }

            // Check to see if the object has moved outside its allocated bins...

            // Should the bin allocation change?
            if (minBinX != scd._minBinX ||
                    minBinY != scd._minBinY ||
                    maxBinX != scd._maxBinX ||
                    maxBinY != scd._maxBinY)
            {
                // Yes, so remove scene object.
                RemoveSceneObject(obj);
                // Add the scene object back.
                _AddSceneObjectDirect(obj, minBinX, minBinY, maxBinX, maxBinY);
            }
        }
        /// Add Scene Object to Container Directly (via Bin Bounds).
        protected void _AddSceneObjectDirect(ISceneContainerObject obj, uint minX, uint minY, uint maxX, uint maxY)
        {
            // Check everything is fine!
            Assert.Fatal(obj != null, "SceneContainer::addSceneObject() - Invalid Object");
            SceneContainerData scd = obj.SceneContainerData;
            Assert.Fatal(scd._binReferenceChain == null, "SceneContainer::addSceneObject() - Object is already within a Container System!");

            // Update Scene Object.
            scd._minBinX = minX;
            scd._minBinY = minY;
            scd._maxBinX = maxX;
            scd._maxBinY = maxY;

            // Very Large Objects got into the Scene Overflow bin.  Overflow bin?
            if ((maxX - minX + 1) * (maxY - minY + 1) < MaxBinsPerObject)
            {
                // Not in overflow bin
                for (uint y = minY; y <= maxY; y++)
                {
                    // Calculate Bin Position.
                    uint offsetY = (y % _binCount) * _binCount;

                    for (uint x = minX; x <= maxX; x++)
                    {
                        // Calculate Bin Position.
                        uint arrayIndex = offsetY + (x % _binCount);

                        // Allocate Scene Bin Reference.
                        SceneContainerBinReference freeRef = _AllocateSceneBinReference();

                        // Insert into Scene Bin Array.
                        if (_sceneBinArray[arrayIndex] == null)
                            _sceneBinArray[arrayIndex] = _AllocateSceneBinReference();

                        freeRef._sceneObject = obj;
                        freeRef._nextBinReference = _sceneBinArray[arrayIndex]._nextBinReference;
                        freeRef._previousBinReference = _sceneBinArray[arrayIndex];
                        freeRef._objectLink = null;

                        // Finalise the link.
                        if (_sceneBinArray[arrayIndex]._nextBinReference != null)
                            _sceneBinArray[arrayIndex]._nextBinReference._previousBinReference = freeRef;
                        _sceneBinArray[arrayIndex]._nextBinReference = freeRef;

                        // Insert Current Object Reference.
                        // JMQ: note, the following method of insertion results in a
                        // list ordering that is reversed from T2D.  Don't think it matters.
                        if (scd._binReferenceChain == null)
                        {
                            scd._binReferenceChain = freeRef;
                        }
                        else
                        {
                            freeRef._objectLink = scd._binReferenceChain;
                            scd._binReferenceChain = freeRef;
                        }
                    }
                }
            }
            else
            {
                // Yes, so allocate Scene Bin Reference.
                SceneContainerBinReference freeRef = _AllocateSceneBinReference();

                // Insert into Scene Overflow Bin.
                freeRef._sceneObject = obj;
                freeRef._nextBinReference = _sceneOverflowBin._nextBinReference;
                freeRef._previousBinReference = _sceneOverflowBin;
                freeRef._objectLink = null;

                // Finalise the link.
                if (_sceneOverflowBin._nextBinReference != null)
                    _sceneOverflowBin._nextBinReference._previousBinReference = freeRef;
                _sceneOverflowBin._nextBinReference = freeRef;

                // Set Current Object Reference.
                scd._binReferenceChain = freeRef;
            }
        }
        /// Add Scene Object to Container.
        protected void _AddSceneObject(ISceneContainerObject obj)
        {
            // Check everything is fine!
            Assert.Fatal(obj != null, "SceneContainer::addSceneObject() - Invalid Object");
            SceneContainerData scd = obj.SceneContainerData;
            Assert.Fatal(scd._binReferenceChain == null, "SceneContainer::addSceneObject() - Object is already within a Container System!");

            // Find which bins we cover.
            uint minX, minY, maxX, maxY;
            _GetBins(obj, out minX, out minY, out maxX, out maxY);

            // Add the Scene Object Directly.
            _AddSceneObjectDirect(obj, minX, minY, maxX, maxY);
        }
        /// <summary>
        /// Remove Scene Object from Container.
        /// </summary>
        /// <param name="obj">Object to remove.</param>
        public void RemoveSceneObject(ISceneContainerObject obj)
        {
            // Check everything is fine!
            Assert.Fatal(obj != null, "SceneContainer::removeSceneObject() - Invalid Object");

            // Get bin data
            SceneContainerData scd = obj.SceneContainerData;

            // Fetch Bin Chain Reference.
            SceneContainerBinReference refChain = scd._binReferenceChain;

            // Cut Chain from Object.
            scd._binReferenceChain = null;

            // Free Chain Scene Bin References.
            while (refChain != null)
            {
                // Fetch Free Reference.
                SceneContainerBinReference freeRef = refChain;

                // Move to next link.
                refChain = refChain._objectLink;

                // Remove Reference from Chain.
                if (freeRef._nextBinReference != null)
                    freeRef._nextBinReference._previousBinReference = freeRef._previousBinReference;
                freeRef._previousBinReference._nextBinReference = freeRef._nextBinReference;

                // Free Reference.
                _FreeSceneBinReference(freeRef);
            }
        }
        /// <summary>
        /// Checks to make sure the given object is in the right bins and updates the
        /// object if not.
        /// </summary>
        /// <param name="obj">Object to check.</param>
        public void CheckSceneObjectBins(ISceneContainerObject obj)
        {
            // Check everything is fine!
            Assert.Fatal(obj != null, "Invalid Object");

            // Get the object's SceneContainerData
            SceneContainerData scd = obj.SceneContainerData;

            // Find which bins we cover.
            uint minBinX, minBinY, maxBinX, maxBinY;
            _GetBins(obj, out minBinX, out minBinY, out maxBinX, out maxBinY);

            _CheckSceneObjectBins(obj, scd, minBinX, minBinY, maxBinX, maxBinY);
        }